sqfentity 0.1.0+16 copy "sqfentity: ^0.1.0+16" to clipboard
sqfentity: ^0.1.0+16 copied to clipboard

outdated

SqfEntity ORM for Flutter/Dart lets you build and execute SQL commands easily and quickly with the help of fluent methods similar to .Net Entity Framework.

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
270
likes
0
pub points
90%
popularity

Publisher

verified publisherhuseyintokpinar.com

SqfEntity ORM for Flutter/Dart lets you build and execute SQL commands easily and quickly with the help of fluent methods similar to .Net Entity Framework.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

analyzer, flutter, http, intl, path, sqflite, synchronized

More

Packages that depend on sqfentity