sqfentity 0.1.0+20

sqfentity #

Sqf Entity ORM Preview

Getting Started #

SqfEntity is based on SQFlite plugin and lets you build and execute SQL commands easily and quickly with the help of fluent methods similar to .Net Entity Framework

Leave the job to SqfEntitiy for CRUD operations. Do easily and faster adding tables, adding columns, defining multiple tables, soft deleting, recovery, syncronize data from the web and more with the help of SqfEntityTable class.

If you have a bundled database, you can use it or EntityBase will create a new database automatically for you.

What Can I Do With SqfEntity? #

  1. Create Database Model (supports multiple databases & models)
  2. Creating Model (Table) Class
  3. Basic methods for CRUD operations ex: toSingle(), toList(), getById(), save(), saveAll(), delete(), recover() (only softdelete was activated) and Update Batch/Multiple row
  4. DISTINCT
  5. GROUP BY with Aggregate and Scalar functions (MIN,MAX,SUM,AVG..)
  6. Object Relational Mapping (Child to Parent, get Childs of Parent)
  7. Syncronize data from JSON (on the web)

How Can I Use SqfEntity? #

Define sqfentity in the dependencies section of your pubscpec.yaml

dependencies: #

dependencies:
  sqfentity: any

Create a new Database Model #

First, create your dbmodel.dart file to define your model and import SqfEntityBase.dart

import 'package:sqfentity/sqfentity.dart';

STEP 1: define your tables as shown in the example Classes below. For example, we have created 3 tables for category,product and todo that extended from "SqfEntityTable" as follows:

Table 1: Category

class TableCategory extends SqfEntityTable {
TableCategory() {
// declare properties of EntityTable
tableName = "category";
modelName = null; // If the modelName (class name) is null then EntityBase uses TableName instead of modelName
primaryKeyName = "id";
primaryKeyisIdentity = true;
useSoftDeleting = true;

// declare fields
fields = [
  SqfEntityField("name", DbType.text),
  SqfEntityField("isActive", DbType.bool, defaultValue: "true")
];

super.init();
}
static SqfEntityTable _instance;
  static SqfEntityTable get getInstance {
    if (_instance == null) {
      _instance = TableCategory();
    }
    return _instance;
  }
}

If useSoftDeleting is true then, The builder engine creates a field named "isDeleted" on the table. When item was deleted then this field value is changed to "1" (does not hard delete) in this case it is possible to recover a deleted item using the recover() method. If the modelName (class name) is null then EntityBase uses TableName instead of modelName

Table 2: Product

class TableProduct extends SqfEntityTable {
TableProduct() {
// declare properties of EntityTable
tableName = "product";
primaryKeyName = "id";
primaryKeyisIdentity = true;
useSoftDeleting = true;
// when useSoftDeleting is true, creates a field named "isDeleted" on the table, and set to "1" this field when item deleted (does not hard delete)

// declare fields
fields = [
  SqfEntityField("name", DbType.text),
  SqfEntityField("description", DbType.text),
  SqfEntityField("price", DbType.real, defaultValue: "0"),
  SqfEntityField("isActive", DbType.bool, defaultValue: "true"),
  SqfEntityFieldRelationship(TableCategory.getInstance, DeleteRule.CASCADE,
      defaultValue: "0"), // Relationship column for CategoryId of Product
  SqfEntityField("rownum", DbType.integer, defaultValue: "0"),
];
super.init();
}
static SqfEntityTable _instance;
static SqfEntityTable get getInstance {
if (_instance == null) {
  _instance = TableProduct();
}
return _instance;
}}

If this table (Product) is the child of a parent table (Category), you must declare the SqfEntityFieldRelationship column into fields for Object Relational Mapping. You can choose one of the following for DeleteRule: CASCADE, NO ACTION, SET NULL, SET DEFAULT VALUE

Table 3: Todo

This table is for creating a synchronization with json data from the web url

class TableTodo extends SqfEntityTable {
TableTodo() {
// declare properties of EntityTable
tableName = "todos";
modelName =
    null; // when the modelName (class name) is null then EntityBase uses TableName instead of modelName
primaryKeyName = "id";
useSoftDeleting =
    false; // when useSoftDeleting is true, creates a field named "isDeleted" on the table, and set to "1" this field when item deleted (does not hard delete)
primaryKeyisIdentity = false;
defaultJsonUrl =
    "https://jsonplaceholder.typicode.com/todos"; // optional: to synchronize your table with json data from webUrl

// declare fields
fields = [
  SqfEntityField("userId", DbType.integer),
  SqfEntityField("title", DbType.text),
  SqfEntityField("completed", DbType.bool, defaultValue: "false")
];

super.init();
}
static SqfEntityTable __instance;
static SqfEntityTable get getInstance {
if (__instance == null) {
  __instance = TableTodo();
}
return __instance;
}}

2. Add your table objects you defined above to your dbModel #

STEP 2: Create your Database Model to be extended from SqfEntityModel Note: SqfEntity provides support for the use of multiple databases. So you can create many Database Models and use them in your application.

class MyDbModel extends SqfEntityModel {
MyDbModel() {
databaseName = "sampleORM.db";
databaseTables = [
  TableProduct.getInstance,
  TableCategory.getInstance,
  TableTodo.getInstance,
]; // put defined tables into the list. ex: [TableProduct.getInstance, TableCategory.getInstance]
bundledDatabasePath =
    null; // "assets/sample.db"; // This value is optional. When bundledDatabasePath is empty then EntityBase creats a new database when initializing the database
}}

That's all.. one more step left for create models.dart file. #

bundledDatabasePath is optional. When bundledDatabasePath is empty then EntityBase creats a new database when initializing the database

ATTENTION: Defining the tables here provides automatic processing for database configuration only. Use the following function to create your model and use it in your project

To get the your classes (models) from the clipboard, just type

MyDbModel.createModel(); 

This function sets the Clipboard text that includes your classes (After debugging, press Ctrl+V to paste the model from the Clipboard) That's all.. You can paste your model in your .dart file by pressing Ctrl+V for PC or Command+V for Mac and reference it where you wish to use.

Database initializer async method #

When the software/app is started, you must check the database was it initialized. If needed, initilizeDb method runs that CREATE TABLE / ALTER TABLE ADD COLUMN queries for you.

final bool isInitialized = await MyDbModel().initializeDB();
  if (isInitialized == true)
  {
    runSamples();
    // TO DO
    // ex: runApp(MyApp());
  } 
  else {
   // If the database is not initialized, something went wrong. Check DEBUG CONSOLE for alerts
   // TO DO
  }
}

If result is true, the database is ready to use

That's Great! now we can use our created new models #

Let's add some record to the "Category" table

Note: save() method returns the primary id of the added record

final notebookCategoryId = await Category(name: "Notebooks", isActive: true).save();

// or another way to define a category is Category.withField
final ultrabookCategoryId = await Category.withFields("Ultrabooks", true, false).save();

Let's add some record to the "Product" table #

You can add record as follow:

final product = Product();
product.name = "Notebook 12\"";
product.description = "128 GB SSD i7";
product.price = 6899;
product.categoryId = notebookCategoryId;
await product.save();

You can also add records quickly as follows:

await Product.withFields( "Notebook 12\"", "128 GB SSD i7", 6899, true, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 12\"", "256 GB SSD i7", 8244, true, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 12\"", "512 GB SSD i7", 9214, true, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 13\"", "128 GB SSD", 8500, true, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 13\"", "256 GB SSD", 9900, true, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 13\"", "512 GB SSD", 11000, null, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 15\"", "128 GB SSD", 8999, null, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 15\"", "256 GB SSD", 10499, null, notebookCategoryId, 0, false).save();
await Product.withFields( "Notebook 15\"", "512 GB SSD", 11999, true, notebookCategoryId, 0, false).save();

await Product.withFields( "Ultrabook 13\"", "128 GB SSD i5", 9954, true, ultrabookCategoryId, 0, false).save();
await Product.withFields( "Ultrabook 13\"", "256 GB SSD i5", 11154, true, ultrabookCategoryId, 0, false).save();
await Product.withFields( "Ultrabook 13\"", "512 GB SSD i5", 13000, true, ultrabookCategoryId, 0, false).save();
await Product.withFields( "Ultrabook 15\"", "128 GB SSD i7", 11000, true, ultrabookCategoryId, 0, false).save();
await Product.withFields( "Ultrabook 15\"", "256 GB SSD i7", 12000, true, ultrabookCategoryId, 0, false).save();
await Product.withFields( "Ultrabook 15\"", "512 GB SSD i7", 14000, true, ultrabookCategoryId, 0, false).save();

See sample usage of sqf below #

To run this statement "SELECT * FROM PRODUCTS" Try below:

final productList = await Product().select().toList();

for (int i = 0; i < productList.length; i++) {
    print(productList[i].toMap());
}

   

To run this statement "SELECT * FROM PRODUCTS WHERE id=5" There are two way for this statement

The First is:

   var product = await Product().getById(5);
  

Second one is:

  var product = await Product().Select().id.equals(5).toSingle();


SELECT FIELDS, ORDER BY EXAMPLES #

EXAMPLE 1.2: ORDER BY FIELDS ex: SELECT * FROM PRODUCTS ORDER BY name, price DESC, id 
        -> await Product().select().orderBy("name").orderByDesc("price").orderBy("id").toList()

EXAMPLE 1.3: SELECT SPECIFIC FIELDS ex: SELECT name,price FROM PRODUCTS ORDER BY price DESC 
        -> await Product().select(columnsToSelect: ["name","price"]).orderByDesc("price").toList()
        

SELECT AND FILTER EXAMPLES: #

EXAMPLE 2.1: EQUALS ex: SELECT * FROM PRODUCTS WHERE isActive=1 
->  await Product().select().isActive.equals(true).toList()

EXAMPLE 2.2: WHERE field IN (VALUES) ex: SELECT * FROM PRODUCTS WHERE ID IN (3,6,9) 
-> await Product().select().id.inValues([3,6,9]).toList()

EXAMPLE 2.3: BRACKETS ex: SELECT TOP 1 * FROM PRODUCTS WHERE price>10000 AND (description LIKE '%256%' OR description LIKE '512%') 
-> await  Product().select()
  .price
  .greaterThan(10000)
  .and.startBlock.description.contains("256").or.description.startsWith("512").endBlock
  .toSingle();

EXAMPLE 2.4: BRACKETS 2: SELECT name,price FROM PRODUCTS WHERE price<=10000 AND (description LIKE '%128%' OR description LIKE '%GB') 
->  await Product().select(columnsToSelect:["name","price"])
   .price.lessThanOrEquals(10000)
   .and.startBlock.description.contains("128").or.description.endsWith("GB").endBlock
   .toList();

EXAMPLE 2.5: NOT EQUALS ex: SELECT * FROM PRODUCTS WHERE ID <> 11 
-> await Product().select().id.not.equals(11).toList();
        
EXAMPLE 2.6: GREATERTHEN OR EQUALS, LESSTHAN OR EQUALS ex: SELECT * FROM PRODUCTS WHERE price>=10000 AND price<=13000 
-> await Product().select().price.greaterThanOrEquals(10000).and.price.lessThanOrEquals(13000).toList();        

EXAMPLE 2.7: BETWEEN ex: SELECT * FROM PRODUCTS WHERE price BETWEEN 8000 AND 14000 
-> await Product().select().price.between(8000,14000).orderBy("price").toList();

EXAMPLE 2.8: 'NOT' KEYWORD ex: SELECT * FROM PRODUCTS WHERE NOT id>5 
-> await Product().select().id.not.greaterThan(5).toList();

WRITE CUSTOM SQL FILTER #

EXAMPLE 2.9: WRITING CUSTOM FILTER IN WHERE CLAUSE ex: SELECT * FROM PRODUCTS WHERE id IN (3,6,9) OR price>8000 
-> await Product().select().where("id IN (3,6,9) OR price>8000").toList()

EXAMPLE 2.10: Build filter and query from values from the form
-> await Product().select()
   .price.between(minPrice, maxPrice)
   .and.name.contains(nameFilter)
   .and.description.contains(descFilter)
   .toList()

SELECT WITH DELETED ITEMS (SOFT DELETE WHEN USED) #

EXAMPLE 2.11: EXAMPLE 1.13: Select products with deleted items
-> await Product().select(getIsDeleted: true).toList()

EXAMPLE 2.12: Select products only deleted items 
-> await Product().select(getIsDeleted: true).isDeleted.equals(true).toList()

LIMITATION, PAGING #

EXAMPLE 3.1: LIMITATION SELECT TOP 3 * FROM PRODUCTS ORDER BY price DESC 
-> await Product().select().orderByDesc("price").top(3).toList()

EXAMPLE 3.2: PAGING: PRODUCTS in 3. page (5 items per page) 
-> await Product().select().page(3,5).toList()


DISTINCT #

EXAMPLE 4.1: DISTINCT: SELECT DISTINCT name FROM PRODUCTS WHERE price > 3000 
-> await Product().distinct(columnsToSelect:["name").price.greaterThan(3000).toList();

GROUP BY #

EXAMPLE 4.2: GROUP BY WITH SCALAR OR AGGREGATE FUNCTIONS
SELECT name, COUNT(id) AS Count, MIN(price) AS minPrice, MAX(price) AS maxPrice, AVG(price) AS
avgPrice, SUM(price) AS sumPrice FROM PRODUCTS GROUP BY name 
-> await Product()
    .select(columnsToSelect: [
    ProductFields.name.toString(),
    ProductFields.id.count("Count"),
    ProductFields.price.min("minPrice"),
    ProductFields.price.max("maxPrice"),
    ProductFields.price.avg("avgPrice"),
    ProductFields.price.sum("sumPrice"),
  ])
  .groupBy(ProductFields.name.toString() /*also you can use this .groupBy("name")*/)
  .toListObject();
   
   

RELATIONSHIPS #

EXAMPLE 7.1: goto Category from Product 

final product = await Product().getById(1);
final category = await product.getCategory();
print(category.toMap());

Results:
{id: 1, name: Notebooks, isActive: true, isDeleted: false}


EXAMPLE 7.2: Products of 'Notebooks Category' listing 

final category = await Category().getById(1);
final productList = await category.getProducts();

for(var product in productList) {
   print(product.toMap());
   }

Results: Products of 'Notebooks' listing 9 matches found:
{id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 1, isDeleted: false}
{id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
....


These were just a few samples. You can download and review dozens of examples written below

save() Method for insert or update (for both) #

await Product({name:"test product"}).save(); // inserts a new record if id is null or equals to zero
await Product({id:1, name:"test product"}).save(); // updates record

saveAll() Method for insert or update List (for both) #

var productList= List<Product>();
// TO DO.. add products to list

// Save All products in the List
 final results = await Product().saveAll(productList);
 
print(" List<BoolResult> result of saveAll method is following:");
for (var result in results) {
   print(result.toString());
}

upsertAll() Method for insert or update List (for both) #

Note: upsertAll() method is faster then saveAll() method. upsertAll() should be used when you are sure that the primary key is greater than zero

var productList= List<Product>();
// TO DO.. add products to list with ID (ID>0) (primary key must be greater then 0)

// Upsert All products in the List
final results = await Product().upsertAll(productList);
for (var result in results) {
    print(result.toString());  
}

UPDATE multiple records with query #

EXAMPLE 5.1: UPDATE PRODUCT SET isActive=0 WHERE ID>=10

final result = await Product().select().id.greaterThan(10).update({"isActive": 0});
print(result.toString());

DELETE multiple records with query #

EXAMPLE 6.4: DELETE PRODUCT WHERE ID>17

final result = await Product().select().id.greaterThan(17).delete();
print(result.toString());
  

Syncronize data from the web #

EXAMPLE 8.2: Fill List from web with Url (JSON data) and saveAll Todo.fromWebUrl("URL",(todosList){}) method gets json data from the web and loads into the todosList and then Todo().saveAll(todosList) method saves all data in your local database

 todosList = await Todo.fromWebUrl("https://jsonplaceholder.typicode.com/todos");
  final results = await Todo().upsertAll(todosList);

  // print upsert Results
  for (var res in results) {
    print(res.toString()); 
  }

  todosList = await Todo().select().top(10).toList();
  print(todosList.length.toString() + " matches found\n");
  for (var todo in todosList) {
    print(todo.toMap());
  }

See the following examples in main.dart for sample model use #

  // SELECT AND ORDER PRODUCTS BY FIELDS
  samples1();

  // FILTERS: SOME FILTERS ON PRODUCTS
  samples2();

  // LIMITATIONS: PAGING, TOP X ROW
  samples3();

  // DISTINCT, GROUP BY with SQL AGGREGATE FUNCTIONS,
  samples4();

  // UPDATE BATCH, UPDATE OBJECT
  samples5();

  // DELETE BATCH, DELETE OBJECT
  samples6();

main.dart includes a lot of samples that you need #

For more information about the SqfEntity and download sample application Click here

Running the main.dart should show the following result at DEBUG CONSOLE: #

flutter >>>>>>>>>>>>>>>>>>>>>>>>>>>> SqfEntityTable of 'category' initialized successfuly
flutter >>>>>>>>>>>>>>>>>>>>>>>>>>>> SqfEntityTable of 'product' initialized successfuly
flutter >>>>>>>>>>>>>>>>>>>>>>>>>>>> SqfEntityTable of 'todos' initialized successfuly
D/EGL_emulation( 6184): eglMakeCurrent: 0xe6ed49a0: ver 3 0 (tinfo 0xcf020470)
flutter SQFENTITIY: [databaseTables] Model was created successfully. Create models.dart file in your project and press Ctrl+V to paste the model from the Clipboard
flutter sampleORMx01.db created successfully
flutter SQFENTITIY: Table named 'product' was initialized successfuly with create new table
flutter SQFENTITIY: alterTableIndexesQuery => [CREATE INDEX IF NOT EXISTS IDXCategorycategoryId ON product (categoryId ASC)]
flutter SQFENTITIY: Table named 'category' was initialized successfuly with create new table
flutter SQFENTITIY: Table named 'todos' was initialized successfuly with create new table
flutter SQFENTITIY: The database is ready for use
flutter
flutter
flutter added 15 new products
flutter added 5 dummy products
flutter
flutter
flutter LISTING CATEGORIES -> Category().select().toList()
flutter 2 matches found:
flutter {id: 1, name: Notebooks, isActive: true, isDeleted: false}
flutter {id: 2, name: Ultrabooks, isActive: true, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.1: SELECT ALL ROWS WITHOUT FILTER ex: SELECT * FROM PRODUCTS
flutter  -> Product().select().toList()
flutter 20 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 16, name: Product 1, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 17, name: Product 2, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 18, name: Product 3, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 19, name: Product 4, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 20, name: Product 5, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.2: ORDER BY FIELDS ex: SELECT * FROM PRODUCTS ORDER BY name, price DESC, id
flutter -> Product().select().orderBy("name").orderByDesc("price").orderBy("id").toList()
flutter 20 matches found:
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 16, name: Product 1, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 17, name: Product 2, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 18, name: Product 3, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 19, name: Product 4, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 20, name: Product 5, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter EXAMPLE 1.3: SELECT SPECIFIC FIELDS ex: SELECT name,price FROM PRODUCTS ORDER BY price DESC
flutter -> Product().select(columnsToSelect: ["name","price"]).orderByDesc("price").toList()
flutter
flutter
flutter 20 matches found:
flutter {name: Ultrabook 15", price: 14000.0}
flutter {name: Ultrabook 13", price: 13000.0}
flutter {name: Ultrabook 15", price: 12000.0}
flutter {name: Notebook 15", price: 11999.0}
flutter {name: Ultrabook 13", price: 11154.0}
flutter {name: Notebook 13", price: 11000.0}
flutter {name: Ultrabook 15", price: 11000.0}
flutter {name: Notebook 15", price: 10499.0}
flutter {name: Ultrabook 13", price: 9954.0}
flutter {name: Notebook 13", price: 9900.0}
flutter {name: Notebook 12", price: 9214.0}
flutter {name: Notebook 15", price: 8999.0}
flutter {name: Notebook 13", price: 8500.0}
flutter {name: Notebook 12", price: 8244.0}
flutter {name: Notebook 12", price: 6899.0}
flutter {name: Product 1, price: 0.0}
flutter {name: Product 2, price: 0.0}
flutter {name: Product 3, price: 0.0}
flutter {name: Product 4, price: 0.0}
flutter {name: Product 5, price: 0.0}
flutter ---------------------------------------------------------------
flutter
flutter
flutter EXAMPLE 1.4: EQUALS ex: SELECT * FROM PRODUCTS WHERE isActive=1
flutter ->  Product().select().isActive.equals(true).toList()
flutter 17 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 16, name: Product 1, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 17, name: Product 2, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 18, name: Product 3, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 19, name: Product 4, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 20, name: Product 5, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.5: WHERE field IN (VALUES) ex: SELECT * FROM PRODUCTS WHERE ID IN (3,6,9)
flutter  -> Product().select().id.inValues([3,6,9]).toList()
flutter 3 matches found:
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.6: BRACKETS ex: SELECT TOP 1 * FROM PRODUCTS WHERE price>10000 AND (description LIKE '%256%' OR description LIKE '512%')
flutter  -> Product().select().price.greaterThan(10000).and.startBlock.description.contains("256").or.description.startsWith("512").endBlock.toSingle((product){ // TO DO })
flutter Toplam 1 sonuç listeleniyor:
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.7: BRACKETS 2 ex: SELECT name,price FROM PRODUCTS WHERE price <=10000 AND (description LIKE '%128%' OR description LIKE '%GB')
flutter  -> Product().select(columnsToSelect:["name","price"]).price.lessThanOrEquals(10000).and.startBlock.description.contains("128").or.description.endsWith("GB").endBlock.toList();
flutter 4 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.8: NOT EQUALS ex: SELECT * FROM PRODUCTS WHERE ID <> 11
flutter  -> Product().select().id.not.equals(11).toList();
flutter 19 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 16, name: Product 1, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 17, name: Product 2, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 18, name: Product 3, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 19, name: Product 4, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 20, name: Product 5, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.9: GREATERTHEN OR EQUALS, LESSTHAN OR EQUALS ex: SELECT * FROM PRODUCTS WHERE price>=10000 AND price<=13000
flutter  -> Product().select().price.greaterThanOrEquals(10000).and.price.lessThanOrEquals(13000).toList();
flutter 7 matches found:
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.10: BETWEEN ex: SELECT * FROM PRODUCTS WHERE price BETWEEN 8000 AND 14000
flutter  -> Product().select().price.between(8000,14000).orderBy("price").toList();
flutter 14 matches found:
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.11: 'NOT' KEYWORD ex: SELECT * FROM PRODUCTS WHERE NOT id>5
flutter  -> Product().select().id.not.greaterThan(5).toList();
flutter 5 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.12: WRITING CUSTOM FILTER IN WHERE CLAUSE ex: SELECT * FROM PRODUCTS WHERE id IN (3,6,9) OR price>8000
flutter  -> Product().select().where("id IN (3,6,9) OR price>8000").toList()
flutter 14 matches found:
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.13: Product().select().price.between(8000, 10000).and.name.contains("13").and.description.contains("SSD").toList()
flutter 3 matches found:
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.14: EXAMPLE 1.13: Select products with deleted items
flutter  -> Product().select(getIsDeleted: true).toList()
flutter 20 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: false, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 16, name: Product 1, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 17, name: Product 2, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 18, name: Product 3, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 19, name: Product 4, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter {id: 20, name: Product 5, description: , price: 0.0, isActive: true, categoryId: 0, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 1.15: Select products only deleted items
flutter  -> Product().select(getIsDeleted: true).isDeleted.equals(true).toList()
flutter 0 matches found:
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 3.1: LIMITATION ex: SELECT TOP 3 * FROM PRODUCTS ORDER BY price DESC
flutter  -> Product().select().orderByDesc("price").top(3).toList()
flutter 3 matches found:
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 3.2: SAMPLE PAGING ex: PRODUCTS in 3. page (5 items per page)
flutter  -> Product().select().page(3,5).toList()
flutter 5 matches found:
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7, price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 4.1: DISTINCT ex: SELECT DISTINCT name FROM PRODUCTS WHERE price > 3000
flutter  -> Product().distinct(columnsToSelect:["name").price.greaterThan(3000).toList();
flutter 5 matches found:
flutter {name: Notebook 12"}
flutter {name: Notebook 13"}
flutter {name: Notebook 15"}
flutter {name: Ultrabook 13"}
flutter {name: Ultrabook 15"}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 4.2: GROUP BY WITH SCALAR OR AGGREGATE FUNCTIONS ex: SELECT name, COUNT(id) AS Count, MIN(price) AS minPrice, MAX(price) AS maxPrice, AVG(price) AS avgPrice,ProductFields.price.sum("sumPrice") FROM PRODUCTS GROUP BY name
flutter -> Product().select(columnsToSelect: [ProductFields.name.toString(), ProductFields.id.count("Count"), ProductFields.price.min("minPrice"), ProductFields.price.max("maxPrice"), ProductFields.price.avg("avgPrice")).groupBy(ProductFields.name.toString()).toListObject()
flutter 10 matches found:
flutter {name: Notebook 12", Count: 3, minPrice: 6899.0, maxPrice: 9214.0, avgPrice: 8119.0, sumPrice: 24357.0}
flutter {name: Notebook 13", Count: 3, minPrice: 8500.0, maxPrice: 11000.0, avgPrice: 9800.0, sumPrice: 29400.0}
flutter {name: Notebook 15", Count: 3, minPrice: 8999.0, maxPrice: 11999.0, avgPrice: 10499.0, sumPrice: 31497.0}
flutter {name: Product 1, Count: 1, minPrice: 0.0, maxPrice: 0.0, avgPrice: 0.0, sumPrice: 0.0}
flutter {name: Product 2, Count: 1, minPrice: 0.0, maxPrice: 0.0, avgPrice: 0.0, sumPrice: 0.0}
flutter {name: Product 3, Count: 1, minPrice: 0.0, maxPrice: 0.0, avgPrice: 0.0, sumPrice: 0.0}
flutter {name: Product 4, Count: 1, minPrice: 0.0, maxPrice: 0.0, avgPrice: 0.0, sumPrice: 0.0}
flutter {name: Product 5, Count: 1, minPrice: 0.0, maxPrice: 0.0, avgPrice: 0.0, sumPrice: 0.0}
flutter {name: Ultrabook 13", Count: 3, minPrice: 9954.0, maxPrice: 13000.0, avgPrice: 11369.333333333334, sumPrice: 34108.0}
flutter {name: Ultrabook 15", Count: 3, minPrice: 11000.0, maxPrice: 14000.0, avgPrice: 12333.333333333334, sumPrice: 37000.0}
flutter ---------------------------------------------------------------
flutter EXAMPLE 5.1: Update multiple records with query
flutter  -> Product().select().id.greaterThan(10).update({"isActive": 0});
flutter 10 items updated
flutter ---------------------------------------------------------------
flutter
flutter EXAMPLE 5.2: uUpdate multiple records with query
flutter  -> Product().select().id.lessThanOrEquals(10).update({"isActive": 1});
flutter 10 items updated
flutter ---------------------------------------------------------------
flutter
flutter EXAMPLE 5.3: id=15 Product item updated: {id: 15, name: Ultrabook 15", description: 512 GB SSD i7 (updated), price: 14000.0, isActive: true, categoryId: 2, rownum: 0, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter
flutter EXAMPLE 5.4: update some filtered products with saveAll method
flutter  -> Product().saveAll(productList){});
flutter  List<BoolResult> result of saveAll method is following:
flutter id=1 upserted successfuly
flutter id=2 upserted successfuly
flutter id=3 upserted successfuly
flutter id=4 upserted successfuly
flutter id=5 upserted successfuly
flutter id=6 upserted successfuly
flutter id=7 upserted successfuly
flutter id=8 upserted successfuly
flutter id=9 upserted successfuly
flutter id=10 upserted successfuly
flutter id=11 upserted successfuly
flutter id=12 upserted successfuly
flutter id=13 upserted successfuly
flutter id=14 upserted successfuly
flutter id=15 upserted successfuly
flutter id=16 upserted successfuly
flutter id=17 upserted successfuly
flutter id=18 upserted successfuly
flutter id=19 upserted successfuly
flutter id=20 upserted successfuly
flutter ---------------------------------------------------------------
flutter EXAMPLE 5.4: listing saved products (set rownum=i) with saveAll method;
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 1, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 2, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 3, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 4, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 5, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: true, categoryId: 1, rownum: 6, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: true, categoryId: 1, rownum: 7, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: true, categoryId: 1, rownum: 8, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 9, isDeleted: false}
flutter {id: 10, name: Ultrabook 13", description: 128 GB SSD i5, price: 9954.0, isActive: true, categoryId: 2, rownum: 10, isDeleted: false}
flutter {id: 11, name: Ultrabook 13", description: 256 GB SSD i5, price: 11154.0, isActive: false, categoryId: 2, rownum: 11, isDeleted: false}
flutter {id: 12, name: Ultrabook 13", description: 512 GB SSD i5, price: 13000.0, isActive: false, categoryId: 2, rownum: 12, isDeleted: false}
flutter {id: 13, name: Ultrabook 15", description: 128 GB SSD i7, price: 11000.0, isActive: false, categoryId: 2, rownum: 13, isDeleted: false}
flutter {id: 14, name: Ultrabook 15", description: 256 GB SSD i7, price: 12000.0, isActive: false, categoryId: 2, rownum: 14, isDeleted: false}
flutter {id: 15, name: Ultrabook 15", description: 512 GB SSD i7 (updated), price: 14000.0, isActive: true, categoryId: 2, rownum: 15, isDeleted: false}
flutter {id: 16, name: Product 1, description: , price: 0.0, isActive: false, categoryId: 0, rownum: 16, isDeleted: false}
flutter {id: 17, name: Product 2, description: , price: 0.0, isActive: false, categoryId: 0, rownum: 17, isDeleted: false}
flutter {id: 18, name: Product 3, description: , price: 0.0, isActive: false, categoryId: 0, rownum: 18, isDeleted: false}
flutter {id: 19, name: Product 4, description: , price: 0.0, isActive: false, categoryId: 0, rownum: 19, isDeleted: false}
flutter {id: 20, name: Product 5, description: , price: 0.0, isActive: false, categoryId: 0, rownum: 20, isDeleted: false}
flutter ---------------------------------------------------------------
flutter EXAMPLE 6.2: delete product by query filder
flutter  -> Product().select().id.equals(16).delete();
flutter 1 items updated
flutter ---------------------------------------------------------------
flutter
flutter SQFENTITIY: delete Product invoked (id=17)
flutter EXAMPLE 6.3: delete product if exist
flutter  -> if (product != null) Product.delete();
flutter 1 items updated
flutter ---------------------------------------------------------------
flutter
flutter EXAMPLE 6.4: Delete many products by filter
flutter  -> Product().select().id.greaterThan(17).delete()
flutter 3 items updated
flutter ---------------------------------------------------------------
flutter
flutter SQFENTITIY: recover Product batch invoked
flutter EXAMPLE 6.6: Recover many products by filter
flutter  -> Product().select().id.greaterThan(17).recover()
flutter 3 items updated
flutter ---------------------------------------------------------------
flutter
flutter EXAMPLE 7.1: goto Category Object from Product
flutter -> Product.getCategory();
flutter The category of 'Notebook 12"' is: {id: 1, name: Notebooks, isActive: true, isDeleted: false}
flutter
flutter
flutter EXAMPLE 7.2.1: Products of 'Notebooks' listing
flutter -> category.getProducts((productList) {});
flutter 9 matches found:
flutter {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 1, isDeleted: false}
flutter {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 2, isDeleted: false}
flutter {id: 3, name: Notebook 12", description: 512 GB SSD i7, price: 9214.0, isActive: true, categoryId: 1, rownum: 3, isDeleted: false}
flutter {id: 4, name: Notebook 13", description: 128 GB SSD, price: 8500.0, isActive: true, categoryId: 1, rownum: 4, isDeleted: false}
flutter {id: 5, name: Notebook 13", description: 256 GB SSD, price: 9900.0, isActive: true, categoryId: 1, rownum: 5, isDeleted: false}
flutter {id: 6, name: Notebook 13", description: 512 GB SSD, price: 11000.0, isActive: true, categoryId: 1, rownum: 6, isDeleted: false}
flutter {id: 7, name: Notebook 15", description: 128 GB SSD, price: 8999.0, isActive: true, categoryId: 1, rownum: 7, isDeleted: false}
flutter {id: 8, name: Notebook 15", description: 256 GB SSD, price: 10499.0, isActive: true, categoryId: 1, rownum: 8, isDeleted: false}
flutter {id: 9, name: Notebook 15", description: 512 GB SSD, price: 11999.0, isActive: true, categoryId: 1, rownum: 9, isDeleted: false}
flutter ---------------------------------------------------------------
flutter
flutter
flutter EXAMPLE 8.1: Fill List from web (JSON data) and upsertAll
flutter  -> Todo.fromWeb((todosList) {}
flutter 10 matches found
flutter {id: 1, userId: 1, title: delectus aut autem, completed: false}
flutter {id: 2, userId: 1, title: quis ut nam facilis et officia qui, completed: false}
flutter {id: 3, userId: 1, title: fugiat veniam minus, completed: false}
flutter {id: 4, userId: 1, title: et porro tempora, completed: false}
flutter {id: 5, userId: 1, title: laboriosam mollitia et enim quasi adipisci quia provident illum, completed: false}
flutter {id: 6, userId: 1, title: qui ullam ratione quibusdam voluptatem quia omnis, completed: false}
flutter {id: 7, userId: 1, title: illo expedita consequatur quia in, completed: false}
flutter {id: 8, userId: 1, title: quo adipisci enim quam ut ab, completed: false}
flutter {id: 9, userId: 1, title: molestiae perspiciatis ipsa, completed: false}
flutter {id: 10, userId: 1, title: illo est ratione doloremque quia maiores aut, completed: false}
flutter ---------------------------------------------------------------
flutter
flutter EXAMPLE 8.2: upsertAll result
flutter  -> final results = await Todo().upsertAll(todosList);
flutter
flutter
flutter EXAMPLE 8.2: Fill List from web with Url (JSON data) and upsertAll
flutter  -> Todo.fromWebUrl("https://jsonplaceholder.typicode.com/todos", (todosList) {}
flutter 10 matches found
flutter {id: 1, userId: 1, title: delectus aut autem, completed: false}
flutter {id: 2, userId: 1, title: quis ut nam facilis et officia qui, completed: false}
flutter {id: 3, userId: 1, title: fugiat veniam minus, completed: false}
flutter {id: 4, userId: 1, title: et porro tempora, completed: false}
flutter {id: 5, userId: 1, title: laboriosam mollitia et enim quasi adipisci quia provident illum, completed: false}
flutter {id: 6, userId: 1, title: qui ullam ratione quibusdam voluptatem quia omnis, completed: false}
flutter {id: 7, userId: 1, title: illo expedita consequatur quia in, completed: false}
flutter {id: 8, userId: 1, title: quo adipisci enim quam ut ab, completed: false}
flutter {id: 9, userId: 1, title: molestiae perspiciatis ipsa, completed: false}
flutter {id: 10, userId: 1, title: illo est ratione doloremque quia maiores aut, completed: false}
flutter ---------------------------------------------------------------

0.1.0+20 #

dependencies modified

0.1.0+18 #

recover() and delete() methods updated

0.1.0+13 #

create_model.dart modified

0.1.0+12 #

README.md and example/main.dart modified

0.1.0+11 #

README.md and example/main.dart modified

0.1.0+10 #

README.md and example/main.dart modified

0.1.0+9 #

README.md and example/main.dart modified

0.1.0+8 #

README.md and example/main.dart modified

0.1.0+7 #

README.md and example/main.dart modified

0.1.0+6 #

README.md modified

0.1.0+5 #

README.md modified

0.0.5+5 #

README.md modified

0.0.5+4 #

README.md modified

0.0.5+3 #

README.md modified

0.0.5+2 #

README.md modified

0.0.5+1 #

  • toList(), toSingle(), getById(), initializeDb(), fromWeb().. etc methods are replaced with async method

0.0.4+1 #

README.md modified

0.0.3+1 #

README.md modified

0.0.2+1 #

README.md modified

0.0.1 #

  • Initial experimentation

example/main.dart

import 'dart:async';
import 'dart:convert';
import 'dart:ui';
import 'package:http/http.dart' as http;

// STEP 1: import sqfentity package.
import 'package:sqfentity/sqfentity.dart';

// STEP 2: define your tables as shown in the example Classes below.
// Define the "TableCategory" sample table as extended from "SqfEntityTable".
class TableCategory extends SqfEntityTable {
  TableCategory() {
    // declare properties of EntityTable
    tableName = "category";
    modelName =
        null; // If the modelName (class name) is null then EntityBase uses TableName instead of modelName
    primaryKeyName = "id";
    primaryKeyisIdentity = true;
    useSoftDeleting = true;

    // declare fields
    fields = [
      SqfEntityField("name", DbType.text),
      SqfEntityField("isActive", DbType.bool, defaultValue: "true")
    ];

    super.init();
  }
  static SqfEntityTable _instance;
  static SqfEntityTable get getInstance {
    if (_instance == null) {
      _instance = TableCategory();
    }
    return _instance;
  }
}

// Define the "TableProduct"  sample table as extended from "SqfEntityTable".
class TableProduct extends SqfEntityTable {
  TableProduct() {
    // declare properties of EntityTable
    tableName = "product";
    primaryKeyName = "id";
    primaryKeyisIdentity = true;
    useSoftDeleting = true;
    // when useSoftDeleting is true, creates a field named "isDeleted" on the table, and set to "1" this field when item deleted (does not hard delete)

    // declare fields
    fields = [
      SqfEntityField("name", DbType.text),
      SqfEntityField("description", DbType.text),
      SqfEntityField("price", DbType.real, defaultValue: "0"),
      SqfEntityField("isActive", DbType.bool, defaultValue: "true"),
      SqfEntityFieldRelationship(TableCategory.getInstance, DeleteRule.CASCADE,
          defaultValue: "0"), // Relationship column for CategoryId of Product
      SqfEntityField("rownum", DbType.integer, defaultValue: "0"),
    ];
    super.init();
  }
  static SqfEntityTable _instance;
  static SqfEntityTable get getInstance {
    if (_instance == null) {
      _instance = TableProduct();
    }
    return _instance;
  }
}

class TableTodo extends SqfEntityTable {
  TableTodo() {
    // declare properties of EntityTable
    tableName = "todos";
    modelName =
        null; // when the modelName (class name) is null then EntityBase uses TableName instead of modelName
    primaryKeyName = "id";
    useSoftDeleting =
        false; // when useSoftDeleting is true, creates a field named "isDeleted" on the table, and set to "1" this field when item deleted (does not hard delete)
    primaryKeyisIdentity = false;
    defaultJsonUrl =
        "https://jsonplaceholder.typicode.com/todos"; // optional: to synchronize your table with json data from webUrl

    // declare fields
    fields = [
      SqfEntityField("userId", DbType.integer),
      SqfEntityField("title", DbType.text),
      SqfEntityField("completed", DbType.bool, defaultValue: "false")
    ];

    super.init();
  }
  static SqfEntityTable __instance;
  static SqfEntityTable get getInstance {
    if (__instance == null) {
      __instance = TableTodo();
    }
    return __instance;
  }
}

// STEP 3: Create your Database Model to be extended from SqfEntityModel
// Note: SqfEntity provides support for the use of multiple databases. So you can create many Database Models and use them in the application.
class MyDbModel extends SqfEntityModel {
  MyDbModel() {
    databaseName = "sampleORM.db";
    databaseTables = [
      TableProduct.getInstance,
      TableCategory.getInstance,
      TableTodo.getInstance,
    ]; // put defined tables into the list. ex: [TableProduct.getInstance, TableCategory.getInstance]
    bundledDatabasePath =
        null; // "assets/sample.db"; // This value is optional. When bundledDatabasePath is empty then EntityBase creats a new database when initializing the database
  }
}

void main(List<String> args) async {
  // 1- creates a simple  Model named product and sets the clipboard for paste into your models.dart file
  // This function sets the Clipboard text that includes your classes
  MyDbModel().createModel();
  // After debugging, press Ctrl+V to paste the model from the Clipboard
  // That's all.. You can paste your model in your .dart file by pressing Ctrl+V for PC or Command+V for Mac and reference it where you wish to use.

  // 2- run Entity Model samples
  // ATTENTION! when the software/app is started, you must check the database was it initialized.
  // If needed, initilizeDb method runs CREATE / ALTER TABLE query for you.
  final bool isInitialized = await MyDbModel().initializeDB();
  if (isInitialized == false) {
    // If the database is not initialized, something went wrong. Check DEBUG CONSOLE for alerts
    // TO DO
    return;
  }

//That's Great! now we can use our created new models
//Let's add some record to the "Category" table
//Note: save() method returns the primary id of the added record

  final notebookCategoryId =
      await Category(name: "Notebooks", isActive: true).save();

// or another way to define a category is Category.withField
  final ultrabookCategoryId =
      await Category.withFields("Ultrabooks", true, false).save();

//Let's add some record to the "Product" table
//You can add record as follow:

  var product = Product();
  product.name = "Notebook 12\"";
  product.description = "128 GB SSD i7";
  product.price = 6899;
  product.categoryId = notebookCategoryId;
  await product.save();

//You can also add records quickly as follows:

  await Product.withFields("Notebook 12\"", "128 GB SSD i7", 6899, true,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 12\"", "256 GB SSD i7", 8244, true,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 12\"", "512 GB SSD i7", 9214, true,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 13\"", "128 GB SSD", 8500, true,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 13\"", "256 GB SSD", 9900, true,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 13\"", "512 GB SSD", 11000, null,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 15\"", "128 GB SSD", 8999, null,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 15\"", "256 GB SSD", 10499, null,
          notebookCategoryId, 0, false)
      .save();
  await Product.withFields("Notebook 15\"", "512 GB SSD", 11999, true,
          notebookCategoryId, 0, false)
      .save();

  await Product.withFields("Ultrabook 13\"", "128 GB SSD i5", 9954, true,
          ultrabookCategoryId, 0, false)
      .save();
  await Product.withFields("Ultrabook 13\"", "256 GB SSD i5", 11154, true,
          ultrabookCategoryId, 0, false)
      .save();
  await Product.withFields("Ultrabook 13\"", "512 GB SSD i5", 13000, true,
          ultrabookCategoryId, 0, false)
      .save();
  await Product.withFields("Ultrabook 15\"", "128 GB SSD i7", 11000, true,
          ultrabookCategoryId, 0, false)
      .save();
  await Product.withFields("Ultrabook 15\"", "256 GB SSD i7", 12000, true,
          ultrabookCategoryId, 0, false)
      .save();
  await Product.withFields("Ultrabook 15\"", "512 GB SSD i7", 14000, true,
          ultrabookCategoryId, 0, false)
      .save();

// See sample usage of sqf below
// To run this statement "SELECT * FROM PRODUCTS" Try below:

  var productList = await Product().select().toList();

  for (int i = 0; i < productList.length; i++) {
    print(productList[i].toMap());
  }

// To run this statement "SELECT * FROM PRODUCTS WHERE id=5" There are two way for this statement

// The First is:

  product = await Product().getById(5);

// Second one is:

  product = await Product().select().id.equals(5).toSingle();

// SELECT FIELDS, ORDER BY EXAMPLES
// EXAMPLE 1.2: ORDER BY FIELDS ex: SELECT * FROM PRODUCTS ORDER BY name, price DESC, id
  await Product()
      .select()
      .orderBy("name")
      .orderByDesc("price")
      .orderBy("id")
      .toList();

// EXAMPLE 1.3: SELECT SPECIFIC FIELDS ex: SELECT name,price FROM PRODUCTS ORDER BY price DESC
  await Product()
      .select(columnsToSelect: ["name", "price"])
      .orderByDesc("price")
      .toList();

// SELECT AND FILTER EXAMPLES:
// EXAMPLE 2.1: EQUALS ex: SELECT * FROM PRODUCTS WHERE isActive=1
  await Product().select().isActive.equals(true).toList();

// EXAMPLE 2.2: WHERE field IN (VALUES) ex: SELECT * FROM PRODUCTS WHERE ID IN (3,6,9)
  await Product().select().id.inValues([3, 6, 9]).toList();

// EXAMPLE 2.3: BRACKETS ex: SELECT TOP 1 * FROM PRODUCTS WHERE price>10000 AND (description LIKE '%256%' OR description LIKE '512%')
  await Product()
      .select()
      .price
      .greaterThan(10000)
      .and
      .startBlock
      .description
      .contains("256")
      .or
      .description
      .startsWith("512")
      .endBlock
      .toSingle();

// EXAMPLE 2.4: BRACKETS 2: SELECT name,price FROM PRODUCTS WHERE price<=10000 AND (description LIKE '%128%' OR description LIKE '%GB')
  await Product()
      .select(columnsToSelect: ["name", "price"])
      .price
      .lessThanOrEquals(10000)
      .and
      .startBlock
      .description
      .contains("128")
      .or
      .description
      .endsWith("GB")
      .endBlock
      .toList();

// EXAMPLE 2.5: NOT EQUALS ex: SELECT * FROM PRODUCTS WHERE ID <> 11
  await Product().select().id.not.equals(11).toList();

// EXAMPLE 2.6: GREATERTHEN OR EQUALS, LESSTHAN OR EQUALS ex: SELECT * FROM PRODUCTS WHERE price>=10000 AND price<=13000
  await Product()
      .select()
      .price
      .greaterThanOrEquals(10000)
      .and
      .price
      .lessThanOrEquals(13000)
      .toList();

// EXAMPLE 2.7: BETWEEN ex: SELECT * FROM PRODUCTS WHERE price BETWEEN 8000 AND 14000
  await Product().select().price.between(8000, 14000).orderBy("price").toList();

// EXAMPLE 2.8: 'NOT' KEYWORD ex: SELECT * FROM PRODUCTS WHERE NOT id>5
  await Product().select().id.not.greaterThan(5).toList();

// WRITE CUSTOM SQL FILTER
// EXAMPLE 2.9: WRITING CUSTOM FILTER IN WHERE CLAUSE ex: SELECT * FROM PRODUCTS WHERE id IN (3,6,9) OR price>8000
  await Product().select().where("id IN (3,6,9) OR price>8000").toList();

// EXAMPLE 2.10: Build filter and query from values from the form
  final minPrice = 6000;
  final maxPrice = 10000;
  final nameFilter = "Notebook";
  final descFilter = "512";
  await Product()
      .select()
      .price
      .between(minPrice, maxPrice)
      .and
      .name
      .contains(nameFilter)
      .and
      .description
      .contains(descFilter)
      .toList();

// SELECT WITH DELETED ITEMS (SOFT DELETE WHEN USED)
// EXAMPLE 2.11: Select products with deleted items
  await Product().select(getIsDeleted: true).toList();

// EXAMPLE 2.12: Select products only deleted items
  await Product().select(getIsDeleted: true).isDeleted.equals(true).toList();

// LIMITATION, PAGING
// EXAMPLE 3.1: LIMITATION SELECT TOP 3 * FROM PRODUCTS ORDER BY price DESC
  await Product().select().orderByDesc("price").top(3).toList();

// EXAMPLE 3.2: PAGING: PRODUCTS in 3. page (5 items per page)
  await Product().select().page(3, 5).toList();

// DISTINCT
// EXAMPLE 4.1: DISTINCT: SELECT DISTINCT name FROM PRODUCTS WHERE price > 3000
  await Product()
      .distinct(columnsToSelect: ["name"])
      .price
      .greaterThan(3000)
      .toList();

// GROUP BY
// EXAMPLE 4.2: GROUP BY WITH SCALAR OR AGGREGATE FUNCTIONS
// SELECT name, COUNT(id) AS Count, MIN(price) AS minPrice, MAX(price) AS maxPrice, AVG(price) AS
// avgPrice, SUM(price) AS sumPrice FROM PRODUCTS GROUP BY name
  await Product()
      .select(columnsToSelect: [
        ProductFields.name.toString(),
        ProductFields.id.count("Count"),
        ProductFields.price.min("minPrice"),
        ProductFields.price.max("maxPrice"),
        ProductFields.price.avg("avgPrice"),
        ProductFields.price.sum("sumPrice"),
      ])
      .groupBy(ProductFields.name
          .toString() /*also you can use this .groupBy("name")*/)
      .toListObject();

// RELATIONSHIPS
// EXAMPLE 7.1: goto Category from Product

  product = await Product().getById(1);
  var category = await product.getCategory();
  print(category.toMap());

// Results:
// {id: 1, name: Notebooks, isActive: true, isDeleted: false}

// EXAMPLE 7.2: Products of 'Notebooks Category' listing

  category = await Category().getById(1);
  productList = await category.getProducts();

  for (var product in productList) {
    print(product.toMap());
  }

// Results: Products of 'Notebooks' listing 9 matches found:
// {id: 1, name: Notebook 12", description: 128 GB SSD i7, price: 6899.0, isActive: true, categoryId: 1, rownum: 1, isDeleted: false}
// {id: 2, name: Notebook 12", description: 256 GB SSD i7, price: 8244.0, isActive: true, categoryId: 1, rownum: 0, isDeleted: false}

// These were just a few samples. You can download and review dozens of examples written below

// save() Method for insert or update (for both)
  await Product(name: "test product")
      .save(); // inserts a new record if id is null or equals to zero
  await Product(id: 1, name: "test product").save(); // updates record

// saveAll() Method for insert or update List (for both)
  productList = List<Product>();
// TO DO.. add products to list

// Save All products in the List
  var results = await Product().saveAll(productList);

  print(" List<BoolResult> result of saveAll method is following:");
  for (var result in results) {
    print(result.toString());
  }

// upsertAll() Method for insert or update List (for both)
//  Note: upsertAll() method is faster then saveAll() method. upsertAll() should be used when you are sure that the primary key is greater than zero

  productList = List<Product>();
// TO DO.. add products to list with ID (ID>0) (primary key must be greater then 0)

// Upsert All products in the List
  results = await Product().upsertAll(productList);
  for (var result in results) {
    print(result.toString());
  }

// UPDATE multiple records with query
// EXAMPLE 5.1: UPDATE PRODUCT SET isActive=0 WHERE ID>=10

  var result =
      await Product().select().id.greaterThan(10).update({"isActive": 0});
  print(result.toString());

// DELETE multiple records with query
// EXAMPLE 6.4: DELETE PRODUCT WHERE ID>17

  result = await Product().select().id.greaterThan(17).delete();
  print(result.toString());

// Syncronize data from the web
// EXAMPLE 8.2: Fill List from web with Url (JSON data) and saveAll Todo.fromWebUrl("URL",(todosList){}) method gets json data from the web and loads into the todosList and then Todo().saveAll(todosList) method saves all data in your local database

  var todosList =
      await Todo.fromWebUrl("https://jsonplaceholder.typicode.com/todos");
  results = await Todo().upsertAll(todosList);

  // print upsert Results
  for (var res in results) {
    print(res.toString());
  }

  todosList = await Todo().select().top(10).toList();
  print(todosList.length.toString() + " matches found\n");
  for (var todo in todosList) {
    print(todo.toMap());
  }
}

/*
      These classes was generated by SqfEntity
      To use these SqfEntity classes do following: 
      - import Product.dart into where to use
      - start typing Product().select()... (add a few filters with fluent methods)...(add orderBy/orderBydesc if you want)...
      - and then just put end of filters / or end of only select()  toSingle(product) / or toList(productList) 
      - you can select one Product or List<Product> by your filters and orders
      - also you can batch update or batch delete by using delete/update methods instead of tosingle/tolist methods
        Enjoy.. Huseyin Tokpunar
      */
// region Product
class Product {
  Product(
      {this.id,
      this.name,
      this.description,
      this.price,
      this.isActive,
      this.categoryId,
      this.rownum,
      this.isDeleted}) {
    setDefaultValues();
  }
  Product.withFields(this.name, this.description, this.price, this.isActive,
      this.categoryId, this.rownum, this.isDeleted) {
    setDefaultValues();
  }
  Product.withId(this.id, this.name, this.description, this.price,
      this.isActive, this.categoryId, this.rownum, this.isDeleted) {
    setDefaultValues();
  }
  Product.fromMap(Map<String, dynamic> o) {
    id = o["id"] as int;
    name = o["name"] as String;
    description = o["description"] as String;
    price = o["price"] as double;
    isActive = o["isActive"] != null ? o["isActive"] == 1 : null;
    categoryId = o["categoryId"] as int;
    rownum = o["rownum"] as int;
    isDeleted = o["isDeleted"] != null ? o["isDeleted"] == 1 : null;
  }
  // FIELDS
  int id;
  String name;
  String description;
  double price;
  bool isActive;
  int categoryId;
  int rownum;
  bool isDeleted;
  // end FIELDS

// RELATIONSHIPS
  Future<Category> getCategory([VoidCallback category(Category o)]) async {
    final obj = await Category().getById(categoryId);
    if (category != null) {
      category(obj);
    }
    return obj;
  }
  // END RELATIONSHIPS

  static const bool _softDeleteActivated = true;
  ProductManager __mnProduct;
  ProductFilterBuilder _select;

  ProductManager get _mnProduct {
    if (__mnProduct == null) __mnProduct = ProductManager();
    return __mnProduct;
  }

  // methods
  Map<String, dynamic> toMap({bool forQuery = false}) {
    final map = Map<String, dynamic>();
    if (id != null) {
      map["id"] = id;
    }
    if (name != null) {
      map["name"] = name;
    }
    if (description != null) {
      map["description"] = description;
    }
    if (price != null) {
      map["price"] = price;
    }
    if (isActive != null) {
      map["isActive"] = forQuery ? (isActive ? 1 : 0) : isActive;
    }
    if (categoryId != null) {
      map["categoryId"] = categoryId;
    }
    if (rownum != null) {
      map["rownum"] = rownum;
    }
    if (isDeleted != null) {
      map["isDeleted"] = forQuery ? (isDeleted ? 1 : 0) : isDeleted;
    }

    return map;
  }

  List<dynamic> toArgs() {
    return [
      id,
      name,
      description,
      price,
      isActive,
      categoryId,
      rownum,
      isDeleted
    ];
  }

  static Future<List<Product>> fromWebUrl(String url,
      [VoidCallback productList(List<Product> o)]) async {
    var objList = List<Product>();
    final response = await http.get(url);
    final Iterable list = json.decode(response.body) as Iterable;
    try {
      objList = list
          .map((product) => Product.fromMap(product as Map<String, dynamic>))
          .toList();
      if (productList != null) {
        productList(objList);
      }
      return objList;
    } catch (e) {
      print("SQFENTITY ERROR Product.fromWeb: ErrorMessage:" + e.toString());
      return null;
    }
  }

  static Future<List<Product>> fromObjectList(Future<List<dynamic>> o) async {
    final productsList = List<Product>();
    final data = await o;
    for (int i = 0; i < data.length; i++) {
      productsList.add(Product.fromMap(data[i] as Map<String, dynamic>));
    }
    return productsList;
  }

  static List<Product> fromMapList(List<Map<String, dynamic>> query) {
    final List<Product> products = List<Product>();
    for (Map map in query) {
      products.add(Product.fromMap(map as Map<String, dynamic>));
    }
    return products;
  }

  /// returns Product by ID if exist, otherwise returns null
  /// <param name="id">Primary Key Value</param>
  /// <returns>returns Product if exist, otherwise returns null</returns>
  Future<Product> getById(int id) async {
    Product productObj;
    final data = await _mnProduct.getById(id);
    if (data.length != 0) {
      productObj = Product.fromMap(data[0] as Map<String, dynamic>);
    } else {
      productObj = null;
    }
    return productObj;
  }

  /// <summary>
  /// Saves the object. If the id field is null, saves as a new record and returns new id, if id is not null then updates record
  /// </summary>
  /// <returns>Returns id</returns>
  Future<int> save() async {
    if (id == null || id == 0) {
      id = await _mnProduct.insert(Product.withFields(
          name, description, price, isActive, categoryId, rownum, isDeleted));
    } else {
      id = await _upsert();
    }
    return id;
  }

  /// <summary>
  /// saveAll method saves the sent List<Product> as a batch in one transaction
  /// </summary>
  /// <returns> Returns a <List<BoolResult>> </returns>
  Future<List<BoolResult>> saveAll(List<Product> products) async {
    final results = _mnProduct.saveAll(
        "INSERT OR REPLACE INTO product (id, name,description,price,isActive,categoryId,rownum,isDeleted)  VALUES (?,?,?,?,?,?,?,?)",
        products);
    return results;
  }

  /// <summary>
  /// Updates if the record exists, otherwise adds a new row
  /// </summary>
  /// <returns>Returns id</returns>
  Future<int> _upsert() async {
    id = await _mnProduct.rawInsert(
        "INSERT OR REPLACE INTO product (id, name,description,price,isActive,categoryId,rownum,isDeleted)  VALUES (?,?,?,?,?,?,?,?)",
        [
          id,
          name,
          description,
          price,
          isActive,
          categoryId,
          rownum,
          isDeleted
        ]);
    return id;
  }

  /// <summary>
  /// inserts or replaces the sent List<Todo> as a batch in one transaction.
  /// upsertAll() method is faster then saveAll() method. upsertAll() should be used when you are sure that the primary key is greater than zero
  /// </summary>
  /// <returns> Returns a <List<BoolResult>> </returns>
  Future<List<BoolResult>> upsertAll(List<Product> products) async {
    final results = await _mnProduct.rawInsertAll(
        "INSERT OR REPLACE INTO product (id, name,description,price,isActive,categoryId,rownum,isDeleted)  VALUES (?,?,?,?,?,?,?,?)",
        products);
    return results;
  }

  /// <summary>
  /// saveAs Product. Returns a new Primary Key value of Product
  /// </summary>
  /// <returns>Returns a new Primary Key value of Product</returns>
  Future<int> saveAs() async {
    id = await _mnProduct.insert(Product.withFields(
        name, description, price, isActive, categoryId, rownum, isDeleted));
    return id;
  }

  /// <summary>
  /// Deletes Product
  /// </summary>
  /// <returns>BoolResult res.success=Deleted, not res.success=Can not deleted</returns>
  Future<BoolResult> delete() async {
    print("SQFENTITIY: delete Product invoked (id=$id)");
    if (!_softDeleteActivated) {
      return _mnProduct.delete(QueryParams(whereString: "id=$id"));
    } else {
      return _mnProduct
          .updateBatch(QueryParams(whereString: "id=$id"), {"isDeleted": 1});
    }
  }

  /// <summary>
  /// Recover Product
  /// </summary>
  /// <returns>BoolResult res.success=Recovered, not res.success=Can not recovered</returns>
  Future<BoolResult> recover() async {
    print("SQFENTITIY: recover Product invoked (id=$id)");
    {
      return _mnProduct
          .updateBatch(QueryParams(whereString: "id=$id"), {"isDeleted": 0});
    }
  }

  //private ProductFilterBuilder _Select;
  ProductFilterBuilder select(
      {List<String> columnsToSelect, bool getIsDeleted}) {
    _select = ProductFilterBuilder(this);
    _select._getIsDeleted = getIsDeleted == true;
    _select.qparams.selectColumns = columnsToSelect;
    return _select;
  }

  ProductFilterBuilder distinct(
      {List<String> columnsToSelect, bool getIsDeleted}) {
    final ProductFilterBuilder _distinct = ProductFilterBuilder(this);
    _distinct._getIsDeleted = getIsDeleted == true;
    _distinct.qparams.selectColumns = columnsToSelect;
    _distinct.qparams.distinct = true;
    return _distinct;
  }

  void setDefaultValues() {
    if (price == null) price = 0;
    if (isActive == null) isActive = false;
    if (categoryId == null) categoryId = 0;
    if (rownum == null) rownum = 0;
    if (isDeleted == null) isDeleted = false;
  }
  //end methods
}
// endregion product

// region ProductField
class ProductField extends SearchCriteria {
  ProductField(this.productFB) {
    param = DbParameter();
  }
  DbParameter param;
  String _waitingNot = "";
  ProductFilterBuilder productFB;

  ProductField get not {
    _waitingNot = " NOT ";
    return this;
  }

  ProductFilterBuilder equals(var pValue) {
    param.expression = "=";
    productFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, productFB.parameters, param, SqlSyntax.EQuals,
            productFB._addedBlocks)
        : setCriteria(pValue, productFB.parameters, param, SqlSyntax.NotEQuals,
            productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder isNull() {
    productFB._addedBlocks = setCriteria(
        0,
        productFB.parameters,
        param,
        SqlSyntax.IsNULL.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder contains(dynamic pValue) {
    productFB._addedBlocks = setCriteria(
        "%" + pValue.toString() + "%",
        productFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder startsWith(dynamic pValue) {
    productFB._addedBlocks = setCriteria(
        pValue.toString() + "%",
        productFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder endsWith(dynamic pValue) {
    productFB._addedBlocks = setCriteria(
        "%" + pValue.toString(),
        productFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder between(dynamic pFirst, dynamic pLast) {
    if (pFirst != null && pLast != null) {
      productFB._addedBlocks = setCriteria(
          pFirst,
          productFB.parameters,
          param,
          SqlSyntax.Between.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
          productFB._addedBlocks,
          pLast);
    } else if (pFirst != null) {
      if (_waitingNot != "") {
        productFB._addedBlocks = setCriteria(pFirst, productFB.parameters,
            param, SqlSyntax.LessThan, productFB._addedBlocks);
      } else {
        productFB._addedBlocks = setCriteria(pFirst, productFB.parameters,
            param, SqlSyntax.GreaterThanOrEquals, productFB._addedBlocks);
      }
    } else if (pLast != null) {
      if (_waitingNot != "") {
        productFB._addedBlocks = setCriteria(pLast, productFB.parameters, param,
            SqlSyntax.GreaterThan, productFB._addedBlocks);
      } else {
        productFB._addedBlocks = setCriteria(pLast, productFB.parameters, param,
            SqlSyntax.LessThanOrEquals, productFB._addedBlocks);
      }
    }
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder greaterThan(dynamic pValue) {
    param.expression = ">";
    productFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, productFB.parameters, param,
            SqlSyntax.GreaterThan, productFB._addedBlocks)
        : setCriteria(pValue, productFB.parameters, param,
            SqlSyntax.LessThanOrEquals, productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder lessThan(dynamic pValue) {
    param.expression = "<";
    productFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, productFB.parameters, param, SqlSyntax.LessThan,
            productFB._addedBlocks)
        : setCriteria(pValue, productFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder greaterThanOrEquals(dynamic pValue) {
    param.expression = ">=";
    productFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, productFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, productFB._addedBlocks)
        : setCriteria(pValue, productFB.parameters, param, SqlSyntax.LessThan,
            productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder lessThanOrEquals(dynamic pValue) {
    param.expression = "<=";
    productFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, productFB.parameters, param,
            SqlSyntax.LessThanOrEquals, productFB._addedBlocks)
        : setCriteria(pValue, productFB.parameters, param,
            SqlSyntax.GreaterThan, productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }

  ProductFilterBuilder inValues(var pValue) {
    productFB._addedBlocks = setCriteria(
        pValue,
        productFB.parameters,
        param,
        SqlSyntax.IN.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        productFB._addedBlocks);
    _waitingNot = "";
    productFB._addedBlocks.needEndBlock[productFB._blockIndex] =
        productFB._addedBlocks.retVal;
    return productFB;
  }
}
// endregion ProductField

// region ProductFilterBuilder
class ProductFilterBuilder extends SearchCriteria {
  ProductFilterBuilder(Product obj) {
    whereString = "";
    qparams = QueryParams();
    parameters = List<DbParameter>();
    orderByList = List<String>();
    groupByList = List<String>();
    _addedBlocks = AddedBlocks(List<bool>(), List<bool>());
    _addedBlocks.needEndBlock.add(false);
    _addedBlocks.waitingStartBlock.add(false);
    _pagesize = 0;
    _page = 0;
    _obj = obj;
  }
  AddedBlocks _addedBlocks;
  int _blockIndex = 0;
  List<DbParameter> parameters;
  List<String> orderByList;
  Product _obj;
  QueryParams qparams;
  int _pagesize;
  int _page;

  ProductFilterBuilder get and {
    if (parameters.isNotEmpty) {
      parameters[parameters.length - 1].wOperator = " AND ";
    }
    return this;
  }

  ProductFilterBuilder get or {
    if (parameters.isNotEmpty) {
      parameters[parameters.length - 1].wOperator = " OR ";
    }
    return this;
  }

  ProductFilterBuilder get startBlock {
    _addedBlocks.waitingStartBlock.add(true);
    _addedBlocks.needEndBlock.add(false);
    _blockIndex++;
    if (_blockIndex > 1) _addedBlocks.needEndBlock[_blockIndex - 1] = true;
    return this;
  }

  ProductFilterBuilder where(String whereCriteria) {
    if (whereCriteria != null && whereCriteria != "") {
      final DbParameter param = DbParameter();
      _addedBlocks = setCriteria(
          0, parameters, param, "(" + whereCriteria + ")", _addedBlocks);
      _addedBlocks.needEndBlock[_blockIndex] = _addedBlocks.retVal;
    }
    return this;
  }

  ProductFilterBuilder page(int page, int pagesize) {
    if (page > 0) _page = page;
    if (pagesize > 0) _pagesize = pagesize;
    return this;
  }

  ProductFilterBuilder top(int count) {
    if (count > 0) {
      _pagesize = count;
    }
    return this;
  }

  ProductFilterBuilder get endBlock {
    if (_addedBlocks.needEndBlock[_blockIndex]) {
      parameters[parameters.length - 1].whereString += " ) ";
    }
    _addedBlocks.needEndBlock.removeAt(_blockIndex);
    _addedBlocks.waitingStartBlock.removeAt(_blockIndex);
    _blockIndex--;
    return this;
  }

  ProductFilterBuilder orderBy(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        orderByList.add(argFields);
      } else {
        for (String s in argFields) {
          if (s != null && s != "") orderByList.add(" $s ");
        }
      }
    }
    return this;
  }

  ProductFilterBuilder orderByDesc(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        orderByList.add("$argFields desc ");
      } else {
        for (String s in argFields) {
          if (s != null && s != "") orderByList.add(" $s desc ");
        }
      }
    }
    return this;
  }

  ProductFilterBuilder groupBy(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        groupByList.add(" $argFields ");
      } else {
        for (String s in argFields) {
          if (s != null && s != "") groupByList.add(" $s ");
        }
      }
    }
    return this;
  }

  ProductField setField(ProductField field, String colName, DbType dbtype) {
    field = ProductField(this);
    field.param = DbParameter(
        dbType: dbtype,
        columnName: colName,
        wStartBlock: _addedBlocks.waitingStartBlock[_blockIndex]);
    return field;
  }

  ProductField _id;
  ProductField get id {
    _id = setField(_id, "id", DbType.integer);
    return _id;
  }

  ProductField _name;
  ProductField get name {
    _name = setField(_name, "name", DbType.text);
    return _name;
  }

  ProductField _description;
  ProductField get description {
    _description = setField(_description, "description", DbType.text);
    return _description;
  }

  ProductField _price;
  ProductField get price {
    _price = setField(_price, "price", DbType.real);
    return _price;
  }

  ProductField _isActive;
  ProductField get isActive {
    _isActive = setField(_isActive, "isActive", DbType.bool);
    return _isActive;
  }

  ProductField _categoryId;
  ProductField get categoryId {
    _categoryId = setField(_categoryId, "categoryId", DbType.integer);
    return _categoryId;
  }

  ProductField _rownum;
  ProductField get rownum {
    _rownum = setField(_rownum, "rownum", DbType.integer);
    return _rownum;
  }

  ProductField _isDeleted;
  ProductField get isDeleted {
    _isDeleted = setField(_isDeleted, "isDeleted", DbType.bool);
    return _isDeleted;
  }

  bool _getIsDeleted;

  void _buildParameters() {
    if (_page > 0 && _pagesize > 0) {
      qparams.limit = _pagesize;
      qparams.offset = (_page - 1) * _pagesize;
    } else {
      qparams.limit = _pagesize;
      qparams.offset = _page;
    }
    for (DbParameter param in parameters) {
      if (param.columnName != null) {
        if (param.value is List) {
          param.value = param.value
              .toString()
              .replaceAll("[", "")
              .replaceAll("]", "")
              .toString();
          whereString += param.whereString
              .replaceAll("{field}", param.columnName)
              .replaceAll("?", param.value.toString());
          param.value = null;
        } else {
          whereString +=
              param.whereString.replaceAll("{field}", param.columnName);
        }
        switch (param.dbType) {
          case DbType.bool:
            if (param.value != null) param.value = param.value == true ? 1 : 0;
            break;
          default:
        }

        if (param.value != null) whereArguments.add(param.value);
        if (param.value2 != null) whereArguments.add(param.value2);
      } else {
        whereString += param.whereString;
      }
    }
    if (Product._softDeleteActivated) {
      if (whereString != "") {
        whereString = (!_getIsDeleted ? "ifnull(isDeleted,0)=0 AND" : "") +
            " ($whereString)";
      } else if (!_getIsDeleted) {
        whereString = "ifnull(isDeleted,0)=0";
      }
    }

    if (whereString != "") {
      qparams.whereString = whereString;
    }
    qparams.whereArguments = whereArguments;
    qparams.groupBy = groupByList.join(',');
    qparams.orderBy = orderByList.join(',');
  }

  /// <summary>
  /// Deletes List<Product> batch by query
  /// </summary>
  /// <returns>BoolResult res.success=Deleted, not res.success=Can not deleted</returns>
  Future<BoolResult> delete() async {
    _buildParameters();
    var r = BoolResult();
    if (Product._softDeleteActivated) {
      r = await _obj._mnProduct.updateBatch(qparams, {"isDeleted": 1});
    } else {
      r = await _obj._mnProduct.delete(qparams);
    }
    return r;
  }

  Future<BoolResult> recover() async {
    _getIsDeleted = true;
    _buildParameters();
    print("SQFENTITIY: recover Product batch invoked");
    return _obj._mnProduct.updateBatch(qparams, {"isDeleted": 0});
  }

  Future<BoolResult> update(Map<String, dynamic> values) {
    _buildParameters();
    return _obj._mnProduct.updateBatch(qparams, values);
  }

  /// This method always returns ProductObj if exist, otherwise returns null
  /// <returns>List<Product></returns>
  Future<Product> toSingle([VoidCallback product(Product o)]) async {
    _pagesize = 1;
    _buildParameters();
    final objFuture = _obj._mnProduct.toList(qparams);
    final data = await objFuture;
    Product retVal;
    if (data.isNotEmpty) {
      retVal = Product.fromMap(data[0] as Map<String, dynamic>);
    } else {
      retVal = null;
    }
    if (product != null) {
      product(retVal);
    }
    return retVal;
  }

  /// This method always returns int.
  /// <returns>int</returns>
  Future<BoolResult> toCount(VoidCallback productCount(int c)) async {
    _buildParameters();
    qparams.selectColumns = ["COUNT(1) AS CNT"];
    final productsFuture = await _obj._mnProduct.toList(qparams);
    final int count = productsFuture[0]["CNT"] as int;
    productCount(count);
    return BoolResult(
        success: count > 0,
        successMessage: count > 0 ? "toCount(): $count items found" : "",
        errorMessage: count > 0 ? "" : "toCount(): no items found");
  }

  /// This method always returns List<Product>.
  /// <returns>List<Product></returns>
  Future<List<Product>> toList(
      [VoidCallback productList(List<Product> o)]) async {
    _buildParameters();
    final productsFuture = _obj._mnProduct.toList(qparams);
    final List<Product> productsData = List<Product>();
    final data = await productsFuture;
    final int count = data.length;
    for (int i = 0; i < count; i++) {
      productsData.add(Product.fromMap(data[i] as Map<String, dynamic>));
    }
    if (productList != null) productList(productsData);
    return productsData;
  }

  /// This method always returns Primary Key List<int>.
  /// <returns>List<int></returns>
  Future<List<int>> toListPrimaryKey(
      [VoidCallback idList(List<int> o), bool buildParameters = true]) async {
    if (buildParameters) _buildParameters();
    final List<int> idData = List<int>();
    qparams.selectColumns = ["id"];
    final idFuture = await _obj._mnProduct.toList(qparams);

    final int count = idFuture.length;
    for (int i = 0; i < count; i++) {
      idData.add(idFuture[i]["id"] as int);
    }
    if (idList != null) {
      idList(idData);
    }
    return idData;
  }

  Future<List<dynamic>> toListObject(
      [VoidCallback listObject(List<dynamic> o)]) async {
    _buildParameters();

    final objectFuture = _obj._mnProduct.toList(qparams);

    final List<dynamic> objectsData = List<dynamic>();
    final data = await objectFuture;
    final int count = data.length;
    for (int i = 0; i < count; i++) {
      objectsData.add(data[i]);
    }
    if (listObject != null) {
      listObject(objectsData);
    }
    return objectsData;
  }
}
// endregion ProductFilterBuilder

// region ProductFields
class ProductFields {
  static TableField _fId;
  static TableField get id {
    _fId = SqlSyntax.setField(_fId, "id", DbType.integer);
    return _fId;
  }

  static TableField _fName;
  static TableField get name {
    _fName = SqlSyntax.setField(_fName, "name", DbType.text);
    return _fName;
  }

  static TableField _fDescription;
  static TableField get description {
    _fDescription =
        SqlSyntax.setField(_fDescription, "description", DbType.text);
    return _fDescription;
  }

  static TableField _fPrice;
  static TableField get price {
    _fPrice = SqlSyntax.setField(_fPrice, "price", DbType.real);
    return _fPrice;
  }

  static TableField _fIsActive;
  static TableField get isActive {
    _fIsActive = SqlSyntax.setField(_fIsActive, "isActive", DbType.bool);
    return _fIsActive;
  }

  static TableField _fCategoryId;
  static TableField get categoryId {
    _fCategoryId =
        SqlSyntax.setField(_fCategoryId, "categoryId", DbType.integer);
    return _fCategoryId;
  }

  static TableField _fRownum;
  static TableField get rownum {
    _fRownum = SqlSyntax.setField(_fRownum, "rownum", DbType.integer);
    return _fRownum;
  }

  static TableField _fIsDeleted;
  static TableField get isDeleted {
    _fIsDeleted = SqlSyntax.setField(_fIsDeleted, "isDeleted", DbType.integer);
    return _fIsDeleted;
  }
}
// endregion ProductFields

//region ProductManager
class ProductManager extends SqfEntityProvider {
  ProductManager() : super(MyDbModel(), tableName: _tableName, colId: _colId);
  static String _tableName = "product";
  static String _colId = "id";
}
//endregion ProductManager

/*
      These classes was generated by SqfEntity
      To use these SqfEntity classes do following: 
      - import Category.dart into where to use
      - start typing Category().select()... (add a few filters with fluent methods)...(add orderBy/orderBydesc if you want)...
      - and then just put end of filters / or end of only select()  toSingle(category) / or toList(categoryList) 
      - you can select one Category or List<Category> by your filters and orders
      - also you can batch update or batch delete by using delete/update methods instead of tosingle/tolist methods
        Enjoy.. Huseyin Tokpunar
      */
// region Category
class Category {
  Category({this.id, this.name, this.isActive, this.isDeleted}) {
    setDefaultValues();
  }
  Category.withFields(this.name, this.isActive, this.isDeleted) {
    setDefaultValues();
  }
  Category.withId(this.id, this.name, this.isActive, this.isDeleted) {
    setDefaultValues();
  }
  Category.fromMap(Map<String, dynamic> o) {
    id = o["id"] as int;
    name = o["name"] as String;
    isActive = o["isActive"] != null ? o["isActive"] == 1 : null;
    isDeleted = o["isDeleted"] != null ? o["isDeleted"] == 1 : null;
  }
  // FIELDS
  int id;
  String name;
  bool isActive;
  bool isDeleted;
  // end FIELDS

// COLLECTIONS
  Future<List<Product>> getProducts(
      [VoidCallback productList(List<Product> o)]) async {
    final objList = await Product().select().categoryId.equals(id).toList();
    if (productList != null) {
      productList(objList);
    }
    return objList;
  }
  // END COLLECTIONS

  static const bool _softDeleteActivated = true;
  CategoryManager __mnCategory;
  CategoryFilterBuilder _select;

  CategoryManager get _mnCategory {
    if (__mnCategory == null) __mnCategory = CategoryManager();
    return __mnCategory;
  }

  // methods
  Map<String, dynamic> toMap({bool forQuery = false}) {
    final map = Map<String, dynamic>();
    if (id != null) {
      map["id"] = id;
    }
    if (name != null) {
      map["name"] = name;
    }
    if (isActive != null) {
      map["isActive"] = forQuery ? (isActive ? 1 : 0) : isActive;
    }
    if (isDeleted != null) {
      map["isDeleted"] = forQuery ? (isDeleted ? 1 : 0) : isDeleted;
    }

    return map;
  }

  List<dynamic> toArgs() {
    return [id, name, isActive, isDeleted];
  }

  static Future<List<Category>> fromWebUrl(String url,
      [VoidCallback categoryList(List<Category> o)]) async {
    var objList = List<Category>();
    final response = await http.get(url);
    final Iterable list = json.decode(response.body) as Iterable;
    try {
      objList = list
          .map((category) => Category.fromMap(category as Map<String, dynamic>))
          .toList();
      if (categoryList != null) {
        categoryList(objList);
      }
      return objList;
    } catch (e) {
      print("SQFENTITY ERROR Category.fromWeb: ErrorMessage:" + e.toString());
      return null;
    }
  }

  static Future<List<Category>> fromObjectList(Future<List<dynamic>> o) async {
    final categorysList = List<Category>();
    final data = await o;
    for (int i = 0; i < data.length; i++) {
      categorysList.add(Category.fromMap(data[i] as Map<String, dynamic>));
    }
    return categorysList;
  }

  static List<Category> fromMapList(List<Map<String, dynamic>> query) {
    final List<Category> categorys = List<Category>();
    for (Map map in query) {
      categorys.add(Category.fromMap(map as Map<String, dynamic>));
    }
    return categorys;
  }

  /// returns Category by ID if exist, otherwise returns null
  /// <param name="id">Primary Key Value</param>
  /// <returns>returns Category if exist, otherwise returns null</returns>
  Future<Category> getById(int id) async {
    Category categoryObj;
    final data = await _mnCategory.getById(id);
    if (data.length != 0) {
      categoryObj = Category.fromMap(data[0] as Map<String, dynamic>);
    } else {
      categoryObj = null;
    }
    return categoryObj;
  }

  /// <summary>
  /// Saves the object. If the id field is null, saves as a new record and returns new id, if id is not null then updates record
  /// </summary>
  /// <returns>Returns id</returns>
  Future<int> save() async {
    if (id == null || id == 0) {
      id = await _mnCategory
          .insert(Category.withFields(name, isActive, isDeleted));
    } else {
      id = await _upsert();
    }
    return id;
  }

  /// <summary>
  /// saveAll method saves the sent List<Category> as a batch in one transaction
  /// </summary>
  /// <returns> Returns a <List<BoolResult>> </returns>
  Future<List<BoolResult>> saveAll(List<Category> categories) async {
    final results = _mnCategory.saveAll(
        "INSERT OR REPLACE INTO category (id, name,isActive,isDeleted)  VALUES (?,?,?,?)",
        categories);
    return results;
  }

  /// <summary>
  /// Updates if the record exists, otherwise adds a new row
  /// </summary>
  /// <returns>Returns id</returns>
  Future<int> _upsert() async {
    id = await _mnCategory.rawInsert(
        "INSERT OR REPLACE INTO category (id, name,isActive,isDeleted)  VALUES (?,?,?,?)",
        [id, name, isActive, isDeleted]);
    return id;
  }

  /// <summary>
  /// inserts or replaces the sent List<Todo> as a batch in one transaction.
  /// upsertAll() method is faster then saveAll() method. upsertAll() should be used when you are sure that the primary key is greater than zero
  /// </summary>
  /// <returns> Returns a <List<BoolResult>> </returns>
  Future<List<BoolResult>> upsertAll(List<Category> categories) async {
    final results = await _mnCategory.rawInsertAll(
        "INSERT OR REPLACE INTO category (id, name,isActive,isDeleted)  VALUES (?,?,?,?)",
        categories);
    return results;
  }

  /// <summary>
  /// saveAs Category. Returns a new Primary Key value of Category
  /// </summary>
  /// <returns>Returns a new Primary Key value of Category</returns>
  Future<int> saveAs() async {
    id = await _mnCategory
        .insert(Category.withFields(name, isActive, isDeleted));
    return id;
  }

  /// <summary>
  /// Deletes Category
  /// </summary>
  /// <returns>BoolResult res.success=Deleted, not res.success=Can not deleted</returns>
  Future<BoolResult> delete() async {
    print("SQFENTITIY: delete Category invoked (id=$id)");
    var result = BoolResult();
    result = await Product().select().categoryId.equals(id).delete();
    if (!result.success) {
      return result;
    } else if (!_softDeleteActivated) {
      return _mnCategory.delete(QueryParams(whereString: "id=$id"));
    } else {
      return _mnCategory
          .updateBatch(QueryParams(whereString: "id=$id"), {"isDeleted": 1});
    }
  }

  /// <summary>
  /// Recover Product
  /// </summary>
  /// <returns>BoolResult res.success=Recovered, not res.success=Can not recovered</returns>
  Future<BoolResult> recover() async {
    print("SQFENTITIY: recover Category invoked (id=$id)");
    var result = BoolResult();
    result = await Product()
        .select(getIsDeleted: true)
        .isDeleted
        .equals(true)
        .and
        .categoryId
        .equals(id)
        .update({"isDeleted": 0});
    if (!result.success) {
      return result;
    } else {
      return _mnCategory
          .updateBatch(QueryParams(whereString: "id=$id"), {"isDeleted": 0});
    }
  }

  //private CategoryFilterBuilder _Select;
  CategoryFilterBuilder select(
      {List<String> columnsToSelect, bool getIsDeleted}) {
    _select = CategoryFilterBuilder(this);
    _select._getIsDeleted = getIsDeleted == true;
    _select.qparams.selectColumns = columnsToSelect;
    return _select;
  }

  CategoryFilterBuilder distinct(
      {List<String> columnsToSelect, bool getIsDeleted}) {
    final CategoryFilterBuilder _distinct = CategoryFilterBuilder(this);
    _distinct._getIsDeleted = getIsDeleted == true;
    _distinct.qparams.selectColumns = columnsToSelect;
    _distinct.qparams.distinct = true;
    return _distinct;
  }

  void setDefaultValues() {
    if (isActive == null) isActive = false;
    if (isDeleted == null) isDeleted = false;
  }
  //end methods
}
// endregion category

// region CategoryField
class CategoryField extends SearchCriteria {
  CategoryField(this.categoryFB) {
    param = DbParameter();
  }
  DbParameter param;
  String _waitingNot = "";
  CategoryFilterBuilder categoryFB;

  CategoryField get not {
    _waitingNot = " NOT ";
    return this;
  }

  CategoryFilterBuilder equals(var pValue) {
    param.expression = "=";
    categoryFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, categoryFB.parameters, param, SqlSyntax.EQuals,
            categoryFB._addedBlocks)
        : setCriteria(pValue, categoryFB.parameters, param, SqlSyntax.NotEQuals,
            categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder isNull() {
    categoryFB._addedBlocks = setCriteria(
        0,
        categoryFB.parameters,
        param,
        SqlSyntax.IsNULL.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder contains(dynamic pValue) {
    categoryFB._addedBlocks = setCriteria(
        "%" + pValue.toString() + "%",
        categoryFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder startsWith(dynamic pValue) {
    categoryFB._addedBlocks = setCriteria(
        pValue.toString() + "%",
        categoryFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder endsWith(dynamic pValue) {
    categoryFB._addedBlocks = setCriteria(
        "%" + pValue.toString(),
        categoryFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder between(dynamic pFirst, dynamic pLast) {
    if (pFirst != null && pLast != null) {
      categoryFB._addedBlocks = setCriteria(
          pFirst,
          categoryFB.parameters,
          param,
          SqlSyntax.Between.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
          categoryFB._addedBlocks,
          pLast);
    } else if (pFirst != null) {
      if (_waitingNot != "") {
        categoryFB._addedBlocks = setCriteria(pFirst, categoryFB.parameters,
            param, SqlSyntax.LessThan, categoryFB._addedBlocks);
      } else {
        categoryFB._addedBlocks = setCriteria(pFirst, categoryFB.parameters,
            param, SqlSyntax.GreaterThanOrEquals, categoryFB._addedBlocks);
      }
    } else if (pLast != null) {
      if (_waitingNot != "") {
        categoryFB._addedBlocks = setCriteria(pLast, categoryFB.parameters,
            param, SqlSyntax.GreaterThan, categoryFB._addedBlocks);
      } else {
        categoryFB._addedBlocks = setCriteria(pLast, categoryFB.parameters,
            param, SqlSyntax.LessThanOrEquals, categoryFB._addedBlocks);
      }
    }
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder greaterThan(dynamic pValue) {
    param.expression = ">";
    categoryFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, categoryFB.parameters, param,
            SqlSyntax.GreaterThan, categoryFB._addedBlocks)
        : setCriteria(pValue, categoryFB.parameters, param,
            SqlSyntax.LessThanOrEquals, categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder lessThan(dynamic pValue) {
    param.expression = "<";
    categoryFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, categoryFB.parameters, param, SqlSyntax.LessThan,
            categoryFB._addedBlocks)
        : setCriteria(pValue, categoryFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder greaterThanOrEquals(dynamic pValue) {
    param.expression = ">=";
    categoryFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, categoryFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, categoryFB._addedBlocks)
        : setCriteria(pValue, categoryFB.parameters, param, SqlSyntax.LessThan,
            categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder lessThanOrEquals(dynamic pValue) {
    param.expression = "<=";
    categoryFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, categoryFB.parameters, param,
            SqlSyntax.LessThanOrEquals, categoryFB._addedBlocks)
        : setCriteria(pValue, categoryFB.parameters, param,
            SqlSyntax.GreaterThan, categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }

  CategoryFilterBuilder inValues(var pValue) {
    categoryFB._addedBlocks = setCriteria(
        pValue,
        categoryFB.parameters,
        param,
        SqlSyntax.IN.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        categoryFB._addedBlocks);
    _waitingNot = "";
    categoryFB._addedBlocks.needEndBlock[categoryFB._blockIndex] =
        categoryFB._addedBlocks.retVal;
    return categoryFB;
  }
}
// endregion CategoryField

// region CategoryFilterBuilder
class CategoryFilterBuilder extends SearchCriteria {
  CategoryFilterBuilder(Category obj) {
    whereString = "";
    qparams = QueryParams();
    parameters = List<DbParameter>();
    orderByList = List<String>();
    groupByList = List<String>();
    _addedBlocks = AddedBlocks(List<bool>(), List<bool>());
    _addedBlocks.needEndBlock.add(false);
    _addedBlocks.waitingStartBlock.add(false);
    _pagesize = 0;
    _page = 0;
    _obj = obj;
  }
  AddedBlocks _addedBlocks;
  int _blockIndex = 0;
  List<DbParameter> parameters;
  List<String> orderByList;
  Category _obj;
  QueryParams qparams;
  int _pagesize;
  int _page;

  CategoryFilterBuilder get and {
    if (parameters.isNotEmpty) {
      parameters[parameters.length - 1].wOperator = " AND ";
    }
    return this;
  }

  CategoryFilterBuilder get or {
    if (parameters.isNotEmpty) {
      parameters[parameters.length - 1].wOperator = " OR ";
    }
    return this;
  }

  CategoryFilterBuilder get startBlock {
    _addedBlocks.waitingStartBlock.add(true);
    _addedBlocks.needEndBlock.add(false);
    _blockIndex++;
    if (_blockIndex > 1) _addedBlocks.needEndBlock[_blockIndex - 1] = true;
    return this;
  }

  CategoryFilterBuilder where(String whereCriteria) {
    if (whereCriteria != null && whereCriteria != "") {
      final DbParameter param = DbParameter();
      _addedBlocks = setCriteria(
          0, parameters, param, "(" + whereCriteria + ")", _addedBlocks);
      _addedBlocks.needEndBlock[_blockIndex] = _addedBlocks.retVal;
    }
    return this;
  }

  CategoryFilterBuilder page(int page, int pagesize) {
    if (page > 0) _page = page;
    if (pagesize > 0) _pagesize = pagesize;
    return this;
  }

  CategoryFilterBuilder top(int count) {
    if (count > 0) {
      _pagesize = count;
    }
    return this;
  }

  CategoryFilterBuilder get endBlock {
    if (_addedBlocks.needEndBlock[_blockIndex]) {
      parameters[parameters.length - 1].whereString += " ) ";
    }
    _addedBlocks.needEndBlock.removeAt(_blockIndex);
    _addedBlocks.waitingStartBlock.removeAt(_blockIndex);
    _blockIndex--;
    return this;
  }

  CategoryFilterBuilder orderBy(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        orderByList.add(argFields);
      } else {
        for (String s in argFields) {
          if (s != null && s != "") orderByList.add(" $s ");
        }
      }
    }
    return this;
  }

  CategoryFilterBuilder orderByDesc(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        orderByList.add("$argFields desc ");
      } else {
        for (String s in argFields) {
          if (s != null && s != "") orderByList.add(" $s desc ");
        }
      }
    }
    return this;
  }

  CategoryFilterBuilder groupBy(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        groupByList.add(" $argFields ");
      } else {
        for (String s in argFields) {
          if (s != null && s != "") groupByList.add(" $s ");
        }
      }
    }
    return this;
  }

  CategoryField setField(CategoryField field, String colName, DbType dbtype) {
    field = CategoryField(this);
    field.param = DbParameter(
        dbType: dbtype,
        columnName: colName,
        wStartBlock: _addedBlocks.waitingStartBlock[_blockIndex]);
    return field;
  }

  CategoryField _id;
  CategoryField get id {
    _id = setField(_id, "id", DbType.integer);
    return _id;
  }

  CategoryField _name;
  CategoryField get name {
    _name = setField(_name, "name", DbType.text);
    return _name;
  }

  CategoryField _isActive;
  CategoryField get isActive {
    _isActive = setField(_isActive, "isActive", DbType.bool);
    return _isActive;
  }

  CategoryField _isDeleted;
  CategoryField get isDeleted {
    _isDeleted = setField(_isDeleted, "isDeleted", DbType.bool);
    return _isDeleted;
  }

  bool _getIsDeleted;

  void _buildParameters() {
    if (_page > 0 && _pagesize > 0) {
      qparams.limit = _pagesize;
      qparams.offset = (_page - 1) * _pagesize;
    } else {
      qparams.limit = _pagesize;
      qparams.offset = _page;
    }
    for (DbParameter param in parameters) {
      if (param.columnName != null) {
        if (param.value is List) {
          param.value = param.value
              .toString()
              .replaceAll("[", "")
              .replaceAll("]", "")
              .toString();
          whereString += param.whereString
              .replaceAll("{field}", param.columnName)
              .replaceAll("?", param.value.toString());
          param.value = null;
        } else {
          whereString +=
              param.whereString.replaceAll("{field}", param.columnName);
        }
        switch (param.dbType) {
          case DbType.bool:
            if (param.value != null) param.value = param.value == true ? 1 : 0;
            break;
          default:
        }

        if (param.value != null) whereArguments.add(param.value);
        if (param.value2 != null) whereArguments.add(param.value2);
      } else {
        whereString += param.whereString;
      }
    }
    if (Category._softDeleteActivated) {
      if (whereString != "") {
        whereString = (!_getIsDeleted ? "ifnull(isDeleted,0)=0 AND" : "") +
            " ($whereString)";
      } else if (!_getIsDeleted) {
        whereString = "ifnull(isDeleted,0)=0";
      }
    }

    if (whereString != "") {
      qparams.whereString = whereString;
    }
    qparams.whereArguments = whereArguments;
    qparams.groupBy = groupByList.join(',');
    qparams.orderBy = orderByList.join(',');
  }

  /// <summary>
  /// Deletes List<Category> batch by query
  /// </summary>
  /// <returns>BoolResult res.success=Deleted, not res.success=Can not deleted</returns>
  Future<BoolResult> delete() async {
    _buildParameters();
    var r = BoolResult();
    final idList = await toListPrimaryKey(null, false);
    await Product().select().categoryId.inValues(idList).delete();

    if (Category._softDeleteActivated) {
      r = await _obj._mnCategory.updateBatch(qparams, {"isDeleted": 1});
    } else {
      r = await _obj._mnCategory.delete(qparams);
    }
    return r;
  }

  Future<BoolResult> recover() async {
    _getIsDeleted = true;
    _buildParameters();
    print("SQFENTITIY: recover Category batch invoked");
    final idList = await toListPrimaryKey(null, false);
    await Product()
        .select(getIsDeleted: true)
        .isDeleted
        .equals(true)
        .and
        .categoryId
        .inValues(idList)
        .update({"isDeleted": 0});
    return _obj._mnCategory.updateBatch(qparams, {"isDeleted": 0});
  }

  Future<BoolResult> update(Map<String, dynamic> values) {
    _buildParameters();
    return _obj._mnCategory.updateBatch(qparams, values);
  }

  /// This method always returns CategoryObj if exist, otherwise returns null
  /// <returns>List<Category></returns>
  Future<Category> toSingle([VoidCallback category(Category o)]) async {
    _pagesize = 1;
    _buildParameters();
    final objFuture = _obj._mnCategory.toList(qparams);
    final data = await objFuture;
    Category retVal;
    if (data.isNotEmpty) {
      retVal = Category.fromMap(data[0] as Map<String, dynamic>);
    } else {
      retVal = null;
    }
    if (category != null) {
      category(retVal);
    }
    return retVal;
  }

  /// This method always returns int.
  /// <returns>int</returns>
  Future<BoolResult> toCount(VoidCallback categoryCount(int c)) async {
    _buildParameters();
    qparams.selectColumns = ["COUNT(1) AS CNT"];
    final categoriesFuture = await _obj._mnCategory.toList(qparams);
    final int count = categoriesFuture[0]["CNT"] as int;
    categoryCount(count);
    return BoolResult(
        success: count > 0,
        successMessage: count > 0 ? "toCount(): $count items found" : "",
        errorMessage: count > 0 ? "" : "toCount(): no items found");
  }

  /// This method always returns List<Category>.
  /// <returns>List<Category></returns>
  Future<List<Category>> toList(
      [VoidCallback categoryList(List<Category> o)]) async {
    _buildParameters();
    final categoriesFuture = _obj._mnCategory.toList(qparams);
    final List<Category> categoriesData = List<Category>();
    final data = await categoriesFuture;
    final int count = data.length;
    for (int i = 0; i < count; i++) {
      categoriesData.add(Category.fromMap(data[i] as Map<String, dynamic>));
    }
    if (categoryList != null) categoryList(categoriesData);
    return categoriesData;
  }

  /// This method always returns Primary Key List<int>.
  /// <returns>List<int></returns>
  Future<List<int>> toListPrimaryKey(
      [VoidCallback idList(List<int> o), bool buildParameters = true]) async {
    if (buildParameters) _buildParameters();
    final List<int> idData = List<int>();
    qparams.selectColumns = ["id"];
    final idFuture = await _obj._mnCategory.toList(qparams);

    final int count = idFuture.length;
    for (int i = 0; i < count; i++) {
      idData.add(idFuture[i]["id"] as int);
    }
    if (idList != null) {
      idList(idData);
    }
    return idData;
  }

  Future<List<dynamic>> toListObject(
      VoidCallback listObject(List<dynamic> o)) async {
    _buildParameters();

    final objectFuture = _obj._mnCategory.toList(qparams);

    final List<dynamic> objectsData = List<dynamic>();
    final data = await objectFuture;
    final int count = data.length;
    for (int i = 0; i < count; i++) {
      objectsData.add(data[i]);
    }
    if (listObject != null) {
      listObject(objectsData);
    }
    return objectsData;
  }
}
// endregion CategoryFilterBuilder

// region CategoryFields
class CategoryFields {
  static TableField _fId;
  static TableField get id {
    _fId = SqlSyntax.setField(_fId, "id", DbType.integer);
    return _fId;
  }

  static TableField _fName;
  static TableField get name {
    _fName = SqlSyntax.setField(_fName, "name", DbType.text);
    return _fName;
  }

  static TableField _fIsActive;
  static TableField get isActive {
    _fIsActive = SqlSyntax.setField(_fIsActive, "isActive", DbType.bool);
    return _fIsActive;
  }

  static TableField _fIsDeleted;
  static TableField get isDeleted {
    _fIsDeleted = SqlSyntax.setField(_fIsDeleted, "isDeleted", DbType.integer);
    return _fIsDeleted;
  }
}
// endregion CategoryFields

//region CategoryManager
class CategoryManager extends SqfEntityProvider {
  CategoryManager() : super(MyDbModel(), tableName: _tableName, colId: _colId);
  static String _tableName = "category";
  static String _colId = "id";
}
//endregion CategoryManager

/*
      These classes was generated by SqfEntity
      To use these SqfEntity classes do following: 
      - import Todo.dart into where to use
      - start typing Todo().select()... (add a few filters with fluent methods)...(add orderBy/orderBydesc if you want)...
      - and then just put end of filters / or end of only select()  toSingle(todo) / or toList(todoList) 
      - you can select one Todo or List<Todo> by your filters and orders
      - also you can batch update or batch delete by using delete/update methods instead of tosingle/tolist methods
        Enjoy.. Huseyin Tokpunar
      */
// region Todo
class Todo {
  Todo({this.id, this.userId, this.title, this.completed}) {
    setDefaultValues();
  }
  Todo.withFields(this.userId, this.title, this.completed) {
    setDefaultValues();
  }
  Todo.withId(this.id, this.userId, this.title, this.completed) {
    setDefaultValues();
  }
  Todo.fromMap(Map<String, dynamic> o) {
    id = o["id"] as int;
    userId = o["userId"] as int;
    title = o["title"] as String;
    completed = o["completed"] != null ? o["completed"] == 1 : null;
  }
  // FIELDS
  int id;
  int userId;
  String title;
  bool completed;
  // end FIELDS

  static const bool _softDeleteActivated = false;
  TodoManager __mnTodo;
  TodoFilterBuilder _select;

  TodoManager get _mnTodo {
    if (__mnTodo == null) __mnTodo = TodoManager();
    return __mnTodo;
  }

  // methods
  Map<String, dynamic> toMap({bool forQuery = false}) {
    final map = Map<String, dynamic>();
    if (id != null) {
      map["id"] = id;
    }
    if (userId != null) {
      map["userId"] = userId;
    }
    if (title != null) {
      map["title"] = title;
    }
    if (completed != null) {
      map["completed"] = forQuery ? (completed ? 1 : 0) : completed;
    }

    return map;
  }

  List<dynamic> toArgs() {
    return [id, userId, title, completed];
  }

  static Future<List<Todo>> fromWeb(
      [VoidCallback todoList(List<Todo> o)]) async {
    final objList =
        await fromWebUrl("https://jsonplaceholder.typicode.com/todos");
    if (todoList != null) {
      todoList(objList);
    }
    return objList;
  }

  static Future<List<Todo>> fromWebUrl(String url,
      [VoidCallback todoList(List<Todo> o)]) async {
    var objList = List<Todo>();
    final response = await http.get(url);
    final Iterable list = json.decode(response.body) as Iterable;
    try {
      objList = list
          .map((todo) => Todo.fromMap(todo as Map<String, dynamic>))
          .toList();
      if (todoList != null) {
        todoList(objList);
      }
      return objList;
    } catch (e) {
      print("SQFENTITY ERROR Todo.fromWeb: ErrorMessage:" + e.toString());
      return null;
    }
  }

  static Future<List<Todo>> fromObjectList(Future<List<dynamic>> o) async {
    final todosList = List<Todo>();
    final data = await o;
    for (int i = 0; i < data.length; i++) {
      todosList.add(Todo.fromMap(data[i] as Map<String, dynamic>));
    }
    return todosList;
  }

  static List<Todo> fromMapList(List<Map<String, dynamic>> query) {
    final List<Todo> todos = List<Todo>();
    for (Map map in query) {
      todos.add(Todo.fromMap(map as Map<String, dynamic>));
    }
    return todos;
  }

  /// returns Todo by ID if exist, otherwise returns null
  /// <param name="id">Primary Key Value</param>
  /// <returns>returns Todo if exist, otherwise returns null</returns>
  Future<Todo> getById(int id) async {
    Todo todoObj;
    final data = await _mnTodo.getById(id);
    if (data.length != 0) {
      todoObj = Todo.fromMap(data[0] as Map<String, dynamic>);
    } else {
      todoObj = null;
    }
    return todoObj;
  }

  /// <summary>
  /// Saves the object. If the id field is null, saves as a new record and returns new id, if id is not null then updates record
  /// </summary>
  /// <returns>Returns id</returns>
  Future<int> save() async {
    if (id == null || id == 0) {
      id = await _mnTodo.insert(Todo.withFields(userId, title, completed));
    } else {
      id = await _upsert();
    }
    return id;
  }

  /// <summary>
  /// saveAll method saves the sent List<Todo> as a batch in one transaction
  /// </summary>
  /// <returns> Returns a <List<BoolResult>> </returns>
  Future<List<BoolResult>> saveAll(List<Todo> todos) async {
    final results = _mnTodo.saveAll(
        "INSERT OR REPLACE INTO todos (id, userId,title,completed)  VALUES (?,?,?,?)",
        todos);
    return results;
  }

  /// <summary>
  /// Updates if the record exists, otherwise adds a new row
  /// </summary>
  /// <returns>Returns id</returns>
  Future<int> _upsert() async {
    id = await _mnTodo.rawInsert(
        "INSERT OR REPLACE INTO todos (id, userId,title,completed)  VALUES (?,?,?,?)",
        [id, userId, title, completed]);
    return id;
  }

  /// <summary>
  /// inserts or replaces the sent List<Todo> as a batch in one transaction.
  /// upsertAll() method is faster then saveAll() method. upsertAll() should be used when you are sure that the primary key is greater than zero
  /// </summary>
  /// <returns> Returns a <List<BoolResult>> </returns>
  Future<List<BoolResult>> upsertAll(List<Todo> todos) async {
    final results = await _mnTodo.rawInsertAll(
        "INSERT OR REPLACE INTO todos (id, userId,title,completed)  VALUES (?,?,?,?)",
        todos);
    return results;
  }

  /// <summary>
  /// saveAs Todo. Returns a new Primary Key value of Todo
  /// </summary>
  /// <returns>Returns a new Primary Key value of Todo</returns>
  Future<int> saveAs() async {
    id = await _mnTodo.insert(Todo.withFields(userId, title, completed));
    return id;
  }

  /// <summary>
  /// Deletes Todo
  /// </summary>
  /// <returns>BoolResult res.success=Deleted, not res.success=Can not deleted</returns>
  Future<BoolResult> delete() async {
    print("SQFENTITIY: delete Todo invoked (id=$id)");
    if (!_softDeleteActivated) {
      return _mnTodo.delete(QueryParams(whereString: "id=$id"));
    } else {
      return _mnTodo
          .updateBatch(QueryParams(whereString: "id=$id"), {"isDeleted": 1});
    }
  }

  //private TodoFilterBuilder _Select;
  TodoFilterBuilder select({List<String> columnsToSelect, bool getIsDeleted}) {
    _select = TodoFilterBuilder(this);
    _select._getIsDeleted = getIsDeleted == true;
    _select.qparams.selectColumns = columnsToSelect;
    return _select;
  }

  TodoFilterBuilder distinct(
      {List<String> columnsToSelect, bool getIsDeleted}) {
    final TodoFilterBuilder _distinct = TodoFilterBuilder(this);
    _distinct._getIsDeleted = getIsDeleted == true;
    _distinct.qparams.selectColumns = columnsToSelect;
    _distinct.qparams.distinct = true;
    return _distinct;
  }

  void setDefaultValues() {
    if (completed == null) completed = false;
  }
  //end methods
}
// endregion todo

// region TodoField
class TodoField extends SearchCriteria {
  TodoField(this.todoFB) {
    param = DbParameter();
  }
  DbParameter param;
  String _waitingNot = "";
  TodoFilterBuilder todoFB;

  TodoField get not {
    _waitingNot = " NOT ";
    return this;
  }

  TodoFilterBuilder equals(var pValue) {
    param.expression = "=";
    todoFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, todoFB.parameters, param, SqlSyntax.EQuals,
            todoFB._addedBlocks)
        : setCriteria(pValue, todoFB.parameters, param, SqlSyntax.NotEQuals,
            todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder isNull() {
    todoFB._addedBlocks = setCriteria(
        0,
        todoFB.parameters,
        param,
        SqlSyntax.IsNULL.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder contains(dynamic pValue) {
    todoFB._addedBlocks = setCriteria(
        "%" + pValue.toString() + "%",
        todoFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder startsWith(dynamic pValue) {
    todoFB._addedBlocks = setCriteria(
        pValue.toString() + "%",
        todoFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder endsWith(dynamic pValue) {
    todoFB._addedBlocks = setCriteria(
        "%" + pValue.toString(),
        todoFB.parameters,
        param,
        SqlSyntax.Contains.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder between(dynamic pFirst, dynamic pLast) {
    if (pFirst != null && pLast != null) {
      todoFB._addedBlocks = setCriteria(
          pFirst,
          todoFB.parameters,
          param,
          SqlSyntax.Between.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
          todoFB._addedBlocks,
          pLast);
    } else if (pFirst != null) {
      if (_waitingNot != "") {
        todoFB._addedBlocks = setCriteria(pFirst, todoFB.parameters, param,
            SqlSyntax.LessThan, todoFB._addedBlocks);
      } else {
        todoFB._addedBlocks = setCriteria(pFirst, todoFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, todoFB._addedBlocks);
      }
    } else if (pLast != null) {
      if (_waitingNot != "") {
        todoFB._addedBlocks = setCriteria(pLast, todoFB.parameters, param,
            SqlSyntax.GreaterThan, todoFB._addedBlocks);
      } else {
        todoFB._addedBlocks = setCriteria(pLast, todoFB.parameters, param,
            SqlSyntax.LessThanOrEquals, todoFB._addedBlocks);
      }
    }
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder greaterThan(dynamic pValue) {
    param.expression = ">";
    todoFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, todoFB.parameters, param, SqlSyntax.GreaterThan,
            todoFB._addedBlocks)
        : setCriteria(pValue, todoFB.parameters, param,
            SqlSyntax.LessThanOrEquals, todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder lessThan(dynamic pValue) {
    param.expression = "<";
    todoFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, todoFB.parameters, param, SqlSyntax.LessThan,
            todoFB._addedBlocks)
        : setCriteria(pValue, todoFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder greaterThanOrEquals(dynamic pValue) {
    param.expression = ">=";
    todoFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, todoFB.parameters, param,
            SqlSyntax.GreaterThanOrEquals, todoFB._addedBlocks)
        : setCriteria(pValue, todoFB.parameters, param, SqlSyntax.LessThan,
            todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder lessThanOrEquals(dynamic pValue) {
    param.expression = "<=";
    todoFB._addedBlocks = _waitingNot == ""
        ? setCriteria(pValue, todoFB.parameters, param,
            SqlSyntax.LessThanOrEquals, todoFB._addedBlocks)
        : setCriteria(pValue, todoFB.parameters, param, SqlSyntax.GreaterThan,
            todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }

  TodoFilterBuilder inValues(var pValue) {
    todoFB._addedBlocks = setCriteria(
        pValue,
        todoFB.parameters,
        param,
        SqlSyntax.IN.replaceAll(SqlSyntax.NOT_KEYWORD, _waitingNot),
        todoFB._addedBlocks);
    _waitingNot = "";
    todoFB._addedBlocks.needEndBlock[todoFB._blockIndex] =
        todoFB._addedBlocks.retVal;
    return todoFB;
  }
}
// endregion TodoField

// region TodoFilterBuilder
class TodoFilterBuilder extends SearchCriteria {
  TodoFilterBuilder(Todo obj) {
    whereString = "";
    qparams = QueryParams();
    parameters = List<DbParameter>();
    orderByList = List<String>();
    groupByList = List<String>();
    _addedBlocks = AddedBlocks(List<bool>(), List<bool>());
    _addedBlocks.needEndBlock.add(false);
    _addedBlocks.waitingStartBlock.add(false);
    _pagesize = 0;
    _page = 0;
    _obj = obj;
  }
  AddedBlocks _addedBlocks;
  int _blockIndex = 0;
  List<DbParameter> parameters;
  List<String> orderByList;
  Todo _obj;
  QueryParams qparams;
  int _pagesize;
  int _page;

  TodoFilterBuilder get and {
    if (parameters.isNotEmpty) {
      parameters[parameters.length - 1].wOperator = " AND ";
    }
    return this;
  }

  TodoFilterBuilder get or {
    if (parameters.isNotEmpty) {
      parameters[parameters.length - 1].wOperator = " OR ";
    }
    return this;
  }

  TodoFilterBuilder get startBlock {
    _addedBlocks.waitingStartBlock.add(true);
    _addedBlocks.needEndBlock.add(false);
    _blockIndex++;
    if (_blockIndex > 1) _addedBlocks.needEndBlock[_blockIndex - 1] = true;
    return this;
  }

  TodoFilterBuilder where(String whereCriteria) {
    if (whereCriteria != null && whereCriteria != "") {
      final DbParameter param = DbParameter();
      _addedBlocks = setCriteria(
          0, parameters, param, "(" + whereCriteria + ")", _addedBlocks);
      _addedBlocks.needEndBlock[_blockIndex] = _addedBlocks.retVal;
    }
    return this;
  }

  TodoFilterBuilder page(int page, int pagesize) {
    if (page > 0) _page = page;
    if (pagesize > 0) _pagesize = pagesize;
    return this;
  }

  TodoFilterBuilder top(int count) {
    if (count > 0) {
      _pagesize = count;
    }
    return this;
  }

  TodoFilterBuilder get endBlock {
    if (_addedBlocks.needEndBlock[_blockIndex]) {
      parameters[parameters.length - 1].whereString += " ) ";
    }
    _addedBlocks.needEndBlock.removeAt(_blockIndex);
    _addedBlocks.waitingStartBlock.removeAt(_blockIndex);
    _blockIndex--;
    return this;
  }

  TodoFilterBuilder orderBy(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        orderByList.add(argFields);
      } else {
        for (String s in argFields) {
          if (s != null && s != "") orderByList.add(" $s ");
        }
      }
    }
    return this;
  }

  TodoFilterBuilder orderByDesc(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        orderByList.add("$argFields desc ");
      } else {
        for (String s in argFields) {
          if (s != null && s != "") orderByList.add(" $s desc ");
        }
      }
    }
    return this;
  }

  TodoFilterBuilder groupBy(var argFields) {
    if (argFields != null) {
      if (argFields is String) {
        groupByList.add(" $argFields ");
      } else {
        for (String s in argFields) {
          if (s != null && s != "") groupByList.add(" $s ");
        }
      }
    }
    return this;
  }

  TodoField setField(TodoField field, String colName, DbType dbtype) {
    field = TodoField(this);
    field.param = DbParameter(
        dbType: dbtype,
        columnName: colName,
        wStartBlock: _addedBlocks.waitingStartBlock[_blockIndex]);
    return field;
  }

  TodoField _id;
  TodoField get id {
    _id = setField(_id, "id", DbType.integer);
    return _id;
  }

  TodoField _userId;
  TodoField get userId {
    _userId = setField(_userId, "userId", DbType.integer);
    return _userId;
  }

  TodoField _title;
  TodoField get title {
    _title = setField(_title, "title", DbType.text);
    return _title;
  }

  TodoField _completed;
  TodoField get completed {
    _completed = setField(_completed, "completed", DbType.bool);
    return _completed;
  }

  bool _getIsDeleted;

  void _buildParameters() {
    if (_page > 0 && _pagesize > 0) {
      qparams.limit = _pagesize;
      qparams.offset = (_page - 1) * _pagesize;
    } else {
      qparams.limit = _pagesize;
      qparams.offset = _page;
    }
    for (DbParameter param in parameters) {
      if (param.columnName != null) {
        if (param.value is List) {
          param.value = param.value
              .toString()
              .replaceAll("[", "")
              .replaceAll("]", "")
              .toString();
          whereString += param.whereString
              .replaceAll("{field}", param.columnName)
              .replaceAll("?", param.value.toString());
          param.value = null;
        } else {
          whereString +=
              param.whereString.replaceAll("{field}", param.columnName);
        }
        switch (param.dbType) {
          case DbType.bool:
            if (param.value != null) param.value = param.value == true ? 1 : 0;
            break;
          default:
        }

        if (param.value != null) whereArguments.add(param.value);
        if (param.value2 != null) whereArguments.add(param.value2);
      } else {
        whereString += param.whereString;
      }
    }
    if (Todo._softDeleteActivated) {
      if (whereString != "") {
        whereString = (!_getIsDeleted ? "ifnull(isDeleted,0)=0 AND" : "") +
            " ($whereString)";
      } else if (!_getIsDeleted) {
        whereString = "ifnull(isDeleted,0)=0";
      }
    }

    if (whereString != "") {
      qparams.whereString = whereString;
    }
    qparams.whereArguments = whereArguments;
    qparams.groupBy = groupByList.join(',');
    qparams.orderBy = orderByList.join(',');
  }

  /// <summary>
  /// Deletes List<Todo> batch by query
  /// </summary>
  /// <returns>BoolResult res.success=Deleted, not res.success=Can not deleted</returns>
  Future<BoolResult> delete() async {
    _buildParameters();
    var r = BoolResult();
    if (Todo._softDeleteActivated) {
      r = await _obj._mnTodo.updateBatch(qparams, {"isDeleted": 1});
    } else {
      r = await _obj._mnTodo.delete(qparams);
    }
    return r;
  }

  Future<BoolResult> update(Map<String, dynamic> values) {
    _buildParameters();
    return _obj._mnTodo.updateBatch(qparams, values);
  }

  /// This method always returns TodoObj if exist, otherwise returns null
  /// <returns>List<Todo></returns>
  Future<Todo> toSingle([VoidCallback todo(Todo o)]) async {
    _pagesize = 1;
    _buildParameters();
    final objFuture = _obj._mnTodo.toList(qparams);
    final data = await objFuture;
    Todo retVal;
    if (data.isNotEmpty) {
      retVal = Todo.fromMap(data[0] as Map<String, dynamic>);
    } else {
      retVal = null;
    }
    if (todo != null) {
      todo(retVal);
    }
    return retVal;
  }

  /// This method always returns int.
  /// <returns>int</returns>
  Future<BoolResult> toCount(VoidCallback todoCount(int c)) async {
    _buildParameters();
    qparams.selectColumns = ["COUNT(1) AS CNT"];
    final todosFuture = await _obj._mnTodo.toList(qparams);
    final int count = todosFuture[0]["CNT"] as int;
    todoCount(count);
    return BoolResult(
        success: count > 0,
        successMessage: count > 0 ? "toCount(): $count items found" : "",
        errorMessage: count > 0 ? "" : "toCount(): no items found");
  }

  /// This method always returns List<Todo>.
  /// <returns>List<Todo></returns>
  Future<List<Todo>> toList([VoidCallback todoList(List<Todo> o)]) async {
    _buildParameters();
    final todosFuture = _obj._mnTodo.toList(qparams);
    final List<Todo> todosData = List<Todo>();
    final data = await todosFuture;
    final int count = data.length;
    for (int i = 0; i < count; i++) {
      todosData.add(Todo.fromMap(data[i] as Map<String, dynamic>));
    }
    if (todoList != null) todoList(todosData);
    return todosData;
  }

  /// This method always returns Primary Key List<int>.
  /// <returns>List<int></returns>
  Future<List<int>> toListPrimaryKey(
      [VoidCallback idList(List<int> o), bool buildParameters = true]) async {
    if (buildParameters) _buildParameters();
    final List<int> idData = List<int>();
    qparams.selectColumns = ["id"];
    final idFuture = await _obj._mnTodo.toList(qparams);

    final int count = idFuture.length;
    for (int i = 0; i < count; i++) {
      idData.add(idFuture[i]["id"] as int);
    }
    if (idList != null) {
      idList(idData);
    }
    return idData;
  }

  Future<List<dynamic>> toListObject(
      VoidCallback listObject(List<dynamic> o)) async {
    _buildParameters();

    final objectFuture = _obj._mnTodo.toList(qparams);

    final List<dynamic> objectsData = List<dynamic>();
    final data = await objectFuture;
    final int count = data.length;
    for (int i = 0; i < count; i++) {
      objectsData.add(data[i]);
    }
    if (listObject != null) {
      listObject(objectsData);
    }
    return objectsData;
  }
}
// endregion TodoFilterBuilder

// region TodoFields
class TodoFields {
  static TableField _fId;
  static TableField get id {
    _fId = SqlSyntax.setField(_fId, "id", DbType.integer);
    return _fId;
  }

  static TableField _fUserId;
  static TableField get userId {
    _fUserId = SqlSyntax.setField(_fUserId, "userId", DbType.integer);
    return _fUserId;
  }

  static TableField _fTitle;
  static TableField get title {
    _fTitle = SqlSyntax.setField(_fTitle, "title", DbType.text);
    return _fTitle;
  }

  static TableField _fCompleted;
  static TableField get completed {
    _fCompleted = SqlSyntax.setField(_fCompleted, "completed", DbType.bool);
    return _fCompleted;
  }
}
// endregion TodoFields

//region TodoManager
class TodoManager extends SqfEntityProvider {
  TodoManager() : super(MyDbModel(), tableName: _tableName, colId: _colId);
  static String _tableName = "todos";
  static String _colId = "id";
}
//endregion TodoManager

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  sqfentity: ^0.1.0+20

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:sqfentity/sqfentity.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
62
Health:
Code health derived from static analysis. [more]
99
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
81
Learn more about scoring.

We analyzed this package on Aug 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19
  • Flutter: 1.7.8+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Health issues and suggestions

Document public APIs. (-0.88 points)

239 out of 240 API elements have no dartdoc comment.Providing good documentation for libraries, classes, functions, and other API elements improves code readability and helps developers find and use your API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.68.0 <3.0.0
flutter 0.0.0
http ^0.12.0+1 0.12.0+2
path ^1.6.2 1.6.4
sqflite ^1.1.6+3 1.1.6+3
synchronized ^2.1.0+1 2.1.0+1
Transitive dependencies
async 2.3.0
charcode 1.1.2
collection 1.14.11 1.14.12
http_parser 3.1.3
meta 1.1.6 1.1.7
pedantic 1.8.0+1
sky_engine 0.0.99
source_span 1.5.5
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
vector_math 2.0.8