### Alternative GitHub Actions Linux Setup Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/troubleshooting.md If you are certain the environment is Linux, you can directly use `sudo apt-get` to install `libsqlite3-dev`. ```shell - run: sudo apt-get -y install libsqlite3-dev ``` -------------------------------- ### Linux setup script Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/README.md Run this script on Ubuntu for a one-time setup of required Linux packages. ```bash dart tool/linux_setup.dart ``` -------------------------------- ### Setup sqlite3 lib for GitHub Actions Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/troubleshooting.md In GitHub Actions, use this run step to install `libsqlite3-dev` on Linux environments. This command is safe to use on all platforms. ```shell ... # Setup sqlite3 lib (done for linux only but works safely on all platform) - name: Install libsqlite3-dev run: | dart pub global activate --source git https://github.com/tekartik/ci.dart --git-path ci dart pub global run tekartik_ci:setup_sqlite3lib ... ``` -------------------------------- ### Setup sqflite_common_ffi_web Binaries Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web/README.md Run the setup command to download and place necessary SQLite3 WASM binaries and the sqflite shared worker script into your web directory. ```bash $ dart run sqflite_common_ffi_web:setup ``` ```bash $ dart run sqflite_common_ffi_web:setup --force ``` -------------------------------- ### Setup and Run Web Tests Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web_test/README.md Execute these commands to set up the web environment and run the tests. ```bash dart run tool/setup_web_force.dart ``` ```bash dart run tool/run_web_tests.dart ``` -------------------------------- ### Switch to Flutter Beta Channel and Run Example Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md Instructions to switch to the beta channel, upgrade Flutter, clone the sqflite repository, and run the example app for iOS. This is useful for testing with a specific Flutter version. ```bash # Switch to beta flutter channel beta flutter upgrade # Get the project and build/run the example git clone https://github.com/tekartik/sqflite.git cd sqflite/example flutter packages get # build for iOS flutter build ios # run! flutter run ``` -------------------------------- ### Switch to Flutter Master Channel and Run Example Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md Instructions to switch to the master channel, upgrade Flutter, clone the sqflite repository, and run the example app for iOS. This is useful for testing with the latest development version. ```bash # Switch to master flutter channel master flutter upgrade # Get the project and build/run the example git clone https://github.com/tekartik/sqflite.git cd sqflite/example flutter packages get # build for iOS flutter build ios # run! flutter run ``` -------------------------------- ### Run Sqflite Example on Linux Source: https://github.com/tekartik/sqflite/blob/master/packages_flutter/sqflite_example_common/README.md Create and run the sqflite example on a Linux environment using Flutter. ```bash flutter create -p linux flutter run -d linux --target=lib/main_ffi.dart ``` -------------------------------- ### Install Linux packages manually Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/README.md Alternatively, manually install the required Linux packages using apt-get. ```bash sudo apt-get -y install libsqlite3-0 libsqlite3-dev ``` -------------------------------- ### Example SQLite Version Output Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md This is an example of the output when querying the SQLite version. The actual version depends on the operating system. ```text 3.22.0 ``` -------------------------------- ### Setup and Run Flutter Web Support Source: https://github.com/tekartik/sqflite/blob/master/sqflite_test_app/README.md Commands to create a Flutter project with web support, set up necessary binaries, and run the application on Chrome. ```bash # Create the project flutter create --platforms web . # Setup the binaries flutter pub run sqflite_common_ffi_web:setup # Run it flutter run -d chrome ``` -------------------------------- ### Setup and Run Sqflite Web App Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_test_app_web/README.md Commands to set up the necessary binaries and run the sqflite test application in a Chrome browser. ```bash # Setup the binaries flutter pub run sqflite_common_ffi_web:setup ``` ```bash # Run it flutter run -d chrome ``` -------------------------------- ### Install libsqlite3-dev on Linux Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/troubleshooting.md If you encounter 'libsqlite3.so: cannot open shared object file' on Linux, install the `sqlite3-dev` package using apt-get. ```shell sudo apt-get -y install libsqlite3-dev ``` -------------------------------- ### Sqflite FFI application example Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/README.md Demonstrates opening an in-memory database, creating a table, inserting data, querying it, and closing the database. ```dart import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; Future main() async { // Init ffi loader if needed. sqfliteFfiInit(); var databaseFactory = databaseFactoryFfi; var db = await databaseFactory.openDatabase(inMemoryDatabasePath); await db.execute(''' CREATE TABLE Product ( id INTEGER PRIMARY KEY, title TEXT ) '''); await db.insert('Product', {'title': 'Product 1'}); await db.insert('Product', {'title': 'Product 1'}); var result = await db.query('Product'); print(result); // prints [{id: 1, title: Product 1}, {id: 2, title: Product 1}] await db.close(); } ``` -------------------------------- ### Run Native Tests with Flutter Driver Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/sqflite_dev_guide.md Command to run native tests from the example folder using Flutter Driver. This requires navigating to the example directory first. ```bash flutter driver test_driver/main.dart ``` -------------------------------- ### Sqflite FFI with path_provider example Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/README.md Shows how to use sqflite_common_ffi with path_provider to open a database file in the application's documents directory. ```dart import 'dart:io' as io; import 'package:path/path.dart' as p; import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:path_provider/path_provider.dart'; Future main() async { // Init ffi loader if needed. sqfliteFfiInit(); var databaseFactory = databaseFactoryFfi; final io.Directory appDocumentsDir = await getApplicationDocumentsDirectory(); //Create path for database String dbPath = p.join(appDocumentsDir.path, "databases", "myDb.db"); var db = await databaseFactory.openDatabase( dbPath, ); await db.execute(''' CREATE TABLE Product ( id INTEGER PRIMARY KEY, title TEXT ) '''); await db.insert('Product', {'title': 'Product 1'}); await db.insert('Product', {'title': 'Product 1'}); var result = await db.query('Product'); print(result); // prints [{id: 1, title: Product 1}, {id: 2, title: Product 1}] await db.close(); } ``` -------------------------------- ### Basic Sqflite Logger Setup Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/sqflite_logger.md Sets up a basic logger to print SQL statements and batch operations. It checks the event type and logs relevant information. ```dart import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; import 'package:path/path.dart'; import 'package:sqflite_common/sqflite_dev.dart'; import 'package:sqflite_common/sqflite_logger.dart'; import 'package:sqflite_common/utils/utils.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:test/test.dart'; Future main() async { // Init ffi loader if needed. sqfliteFfiInit(); test('logger', () async { /// Log sql commands void _logger(SqfliteLoggerEvent event) { /// Check the event type if (event is SqfliteLoggerSqlEvent) { print( 'sql: ${event.sql}${event.arguments != null ? ' ${event.arguments}' : ''}'); } else if (event is SqfliteLoggerBatchEvent) { /// The batch contains a list of operations for (var operation in event.operations) { print( 'sql(batch): ${operation.sql}${operation.arguments != null ? ' ${operation.arguments}' : ''}'); } } } final factoryWithLogs = SqfliteDatabaseFactoryLogger( databaseFactoryFfi, options: SqfliteLoggerOptions( log: _logger, type: SqfliteDatabaseFactoryLoggerType.all, ), ); var db = await factoryWithLogs.openDatabase(inMemoryDatabasePath); // Ok await db.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY)'); var batch = db.batch(); batch.insert('Test', {'id': 1}); batch.insert('Test', {'id': 2}); await batch.commit(); await db.query('Test'); await db.close(); }); } ``` -------------------------------- ### Transaction v1 - Begin Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/method_call_protocol.md Defines the input for starting a transaction in version 1 (up to 2022-10-21). ```json in: BEGIN TRANSACTION: inTransaction: true ``` -------------------------------- ### Open Encrypted Database with SQLCipher Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/encryption_support.md Example demonstrating how to open an encrypted database using SQLCipher. The password is set via `PRAGMA KEY` in `onConfigure`. ```dart import 'dart:ffi'; import 'dart:io'; import 'dart:math'; import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:sqlite3/open.dart'; Future main(List arguments) async { final dbFactory = createDatabaseFactoryFfi(ffiInit: ffiInit); final db = await dbFactory.openDatabase( Directory.current.path + "/db_pass_1234.db", options: OpenDatabaseOptions( version: 1, onConfigure: (db) async { // This is the part where we pass the "password" await db.rawQuery("PRAGMA KEY='1234'"); }, onCreate: (db, version) async { db.execute("CREATE TABLE t (i INTEGER)"); }, ), ); print(await db.rawQuery("PRAGMA cipher_version")); print(await db.rawQuery("SELECT * FROM sqlite_master")); print(db.path); await db.close(); } void ffiInit() { open.overrideForAll(sqlcipherOpen); } DynamicLibrary sqlcipherOpen() { // Taken from https://github.com/simolus3/sqlite3.dart/blob/e66702c5bec7faec2bf71d374c008d5273ef2b3b/sqlite3/lib/src/load_library.dart#L24 if (Platform.isLinux || Platform.isAndroid) { try { return DynamicLibrary.open('libsqlcipher.so'); } catch (_) { if (Platform.isAndroid) { // On some (especially old) Android devices, we somehow can't dlopen // libraries shipped with the apk. We need to find the full path of the // library (/data/data//lib/libsqlite3.so) and open that one. // For details, see https://github.com/simolus3/moor/issues/420 final appIdAsBytes = File('/proc/self/cmdline').readAsBytesSync(); // app id ends with the first \0 character in here. final endOfAppId = max(appIdAsBytes.indexOf(0), 0); final appId = String.fromCharCodes(appIdAsBytes.sublist(0, endOfAppId)); return DynamicLibrary.open('/data/data/$appId/lib/libsqlcipher.so'); } rethrow; } } if (Platform.isIOS) { return DynamicLibrary.process(); } if (Platform.isMacOS) { // TODO: Unsure what the path is in macos return DynamicLibrary.open('/usr/lib/libsqlite3.dylib'); } if (Platform.isWindows) { // TODO: This dll should be the one that gets generated after compiling SQLcipher on Windows return DynamicLibrary.open('sqlite3.dll'); } throw UnsupportedError('Unsupported platform: ${Platform.operatingSystem}'); } ``` -------------------------------- ### Transaction v2 - Begin Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/method_call_protocol.md Input for starting a transaction using the new mechanism (as of 2022-10-21). Includes a transaction ID. ```json in: BEGIN TRANSACTION: 'inTransaction': true 'transactionId': null // This tells ``` -------------------------------- ### Add sqflite_example_common Dependency Source: https://github.com/tekartik/sqflite/blob/master/packages_flutter/sqflite_example_common/README.md Add this dependency to your pubspec.yaml file to include the sqflite example common package. ```yaml dependencies: sqflite_example_common: git: url: https://github.com/tekartik/sqflite path: packages_flutter/sqflite_example_common ``` -------------------------------- ### Setup sqflite_common_ffi for Flutter Unit Tests Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/testing.md Initialize sqflite_common_ffi and set the database factory in a `setUpAll` method for Flutter unit tests. This allows your existing sqflite code to run in a test environment. ```dart import 'package:flutter_test/flutter_test.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:sqflite/sqflite.dart'; Future main() async { // Setup sqflite_common_ffi for flutter test setUpAll(() { // Initialize FFI sqfliteFfiInit(); // Change the default factory databaseFactory = databaseFactoryFfi; }); test('Simple test', () async { var db = await openDatabase(inMemoryDatabasePath, version: 1, onCreate: (db, version) async { await db .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, value TEXT)'); }); // Insert some data await db.insert('Test', {'value': 'my_value'}); // Check content expect(await db.query('Test'), [ {'id': 1, 'value': 'my_value'} ]); await db.close(); }); } ``` -------------------------------- ### Call Function to Open Asset Database Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md Example of how to call the `copyIfNeededAndOpenAssetDatabase` function. Ensure that `getDatabasesPath()` is available and correctly configured. ```dart var db = await copyIfNeededAndOpenAssetDatabase( databasesPath: await getDatabasesPath(), // The asset database filename. dbFilename: 'my_asset_database.db', // The version num. versionNumFilename: 'db_version_num.txt'); ``` -------------------------------- ### Register SqflitePlugin on iOS Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md Example of how to register the SqflitePlugin in AppDelegate.m for iOS. ```objective-c [SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]]; ``` -------------------------------- ### Register SqflitePlugin on Android Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md Example of how to register the SqflitePlugin in MainActivity.java for Android. ```java SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin")); ``` -------------------------------- ### SQL Helpers and Data Model Example Source: https://github.com/tekartik/sqflite/blob/master/sqflite/README.md Defines a data model (Todo) and a provider class (TodoProvider) to interact with an SQLite database using helper methods for common operations like opening, inserting, querying, updating, and deleting records. ```dart final String tableTodo = 'todo'; final String columnId = '_id'; final String columnTitle = 'title'; final String columnDone = 'done'; class Todo { int id; String title; bool done; Map toMap() { var map = { columnTitle: title, columnDone: done == true ? 1 : 0 }; if (id != null) { map[columnId] = id; } return map; } Todo(); Todo.fromMap(Map map) { id = map[columnId]; title = map[columnTitle]; done = map[columnDone] == 1; } } class TodoProvider { Database db; Future open(String path) async { db = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { await db.execute(''' create table $tableTodo ( $columnId integer primary key autoincrement, $columnTitle text not null, $columnDone integer not null) '''); }); } Future insert(Todo todo) async { todo.id = await db.insert(tableTodo, todo.toMap()); return todo; } Future getTodo(int id) async { List maps = await db.query(tableTodo, columns: [columnId, columnDone, columnTitle], where: '$columnId = ?', whereArgs: [id]); if (maps.length > 0) { return Todo.fromMap(maps.first); } return null; } Future delete(int id) async { return await db.delete(tableTodo, where: '$columnId = ?', whereArgs: [id]); } Future update(Todo todo) async { return await db.update(tableTodo, todo.toMap(), where: '$columnId = ?', whereArgs: [todo.id]); } Future close() async => db.close(); } ``` -------------------------------- ### Setup sqflite_common_ffi for Dart VM Unit Tests Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/testing.md Use `sqflite_common_ffi` to write regular Dart tests. Instead of `openDatabase`, use `databaseFactoryFfi.openDatabase` for the Dart VM. ```dart @TestOn('vm') library sqflite_common_ffi.test.sqflite_ffi_doc_test; import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:test/test.dart'; void main() { // Init ffi loader if needed. sqfliteFfiInit(); test('Simple test', () async { var factory = databaseFactoryFfi; var db = await factory.openDatabase(inMemoryDatabasePath, options: OpenDatabaseOptions( version: 1, onCreate: (db, version) async { await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, value TEXT)'); })); // Insert some data await db.insert('Test', {'value': 'my_value'}); // Check content expect(await db.query('Test'), [{'id': 1, 'value': 'my_value'}]); await db.close(); }); } ``` -------------------------------- ### Run Flutter Driver Test Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/testing.md Execute Flutter driver tests for integration testing. This command starts the driver and runs tests defined in the specified file. ```bash flutter driver --target=test_driver/main.dart ``` -------------------------------- ### Create and Run Flutter Project Source: https://github.com/tekartik/sqflite/blob/master/sqflite_test_app/README.md Basic commands to create a new Flutter project and run it in the current directory. ```bash flutter create . flutter run ``` -------------------------------- ### Configure Database with onConfigure Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md Opens a database and configures it using the onConfigure callback. This is useful for setting pragmas like foreign_keys. ```dart _onConfigure(Database db) async { // Add support for cascade delete await db.execute("PRAGMA foreign_keys = ON"); } var db = await openDatabase(path, onConfigure: _onConfigure); ``` -------------------------------- ### Perform Raw SQL Queries Source: https://github.com/tekartik/sqflite/blob/master/sqflite/README.md Demonstrates opening a database, creating a table, inserting, updating, querying, and deleting records using raw SQL commands. Includes transaction handling and basic assertions. ```dart var databasesPath = await getDatabasesPath(); String path = join(databasesPath, 'demo.db'); // Delete the database await deleteDatabase(path); // open the database Database database = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { // When creating the db, create the table await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); }); // Insert some records in a transaction await database.transaction((txn) async { int id1 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)'); print('inserted1: $id1'); int id2 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)', ['another name', 12345678, 3.1416]); print('inserted2: $id2'); }); // Update some record int count = await database.rawUpdate( 'UPDATE Test SET name = ?, value = ? WHERE name = ?', ['updated name', '9876', 'some name']); print('updated: $count'); // Get the records List list = await database.rawQuery('SELECT * FROM Test'); List expectedList = [ {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, {'name': 'another name', 'id': 2, 'value': 12345678, 'num': 3.1416} ]; print(list); print(expectedList); assert(const DeepCollectionEquality().equals(list, expectedList)); // Count the records count = Sqflite .firstIntValue(await database.rawQuery('SELECT COUNT(*) FROM Test')); assert(count == 2); // Delete a record count = await database .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']); assert(count == 1); // Close the database await database.close(); ``` -------------------------------- ### Open Database with Version 2 and Migrations Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/migration_example.md Opens the database with version 2, configuring foreign keys, handling initial creation in onCreate, and performing schema upgrades in onUpgrade. ```dart // 2nd version of the database db = await factory.openDatabase(path, options: OpenDatabaseOptions( version: 2, onConfigure: onConfigure, onCreate: (db, version) async { var batch = db.batch(); // We create all the tables _createTableCompanyV2(batch); _createTableEmployeeV2(batch); await batch.commit(); }, onUpgrade: (db, oldVersion, newVersion) async { var batch = db.batch(); if (oldVersion == 1) { // We update existing table and create the new tables _updateTableCompanyV1toV2(batch); _createTableEmployeeV2(batch); } await batch.commit(); }, onDowngrade: onDatabaseDowngradeDelete)); ``` -------------------------------- ### Unsupported Nested Map Example Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md Illustrates a nested map structure that is not directly supported by Sqflite. ```dart { "title": "Table", "size": {"width": 80, "height": 80} } ``` -------------------------------- ### Enable WAL mode using execute (fallback) Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/dev_tips.md This method can be used in onConfigure to enable WAL mode. It is a fallback if the manifest setting is not used. ```db await db.execute('PRAGMA journal_mode=WAL') ``` -------------------------------- ### Simple Insert Without Error Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/conflict_algorithm.md Demonstrates basic insertion of product and product image data without encountering constraint violations. ```dart int recordId = await db.insert('Product', {'title': 'Example 1'}); await db.insert('ProductImage', {'productId': recordId, 'imageUrl': 'someUrlHere'}); ``` -------------------------------- ### Enable WAL mode using execute Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/dev_tips.md Use this method in onConfigure to enable WAL mode if manifest setting is not used. It attempts 'execute' first, then 'rawQuery' as a fallback. ```dart try { await db.execute('PRAGMA journal_mode=WAL'); } catch (e) { await db.rawQuery('PRAGMA journal_mode=WAL'); } ``` -------------------------------- ### Enable WAL mode using rawQuery (fallback) Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/dev_tips.md This method can be used in onConfigure to enable WAL mode. It is a fallback if the manifest setting is not used and execute fails. ```db await db.rawQuery('PRAGMA journal_mode=WAL') ``` -------------------------------- ### Post Open Callback with onOpen Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md Opens a database and executes the onOpen callback after the database is ready and its version is set. This is useful for actions that need to be performed immediately after opening, like logging the database version. ```dart _onOpen(Database db) async { // Database is open, print its version print('db version ${await db.getVersion()}'); } var db = await openDatabase( path, onOpen: _onOpen, ); ``` -------------------------------- ### Get Database Path Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md Retrieves the default database path for the current platform (Android or iOS). This path is used to construct the full database file path. ```dart var databasesPath = await getDatabasesPath(); var path = join(databasesPath, dbName); // Make sure the directory exists try { await Directory(databasesPath).create(recursive: true); } catch (_) {} ``` -------------------------------- ### Always Copy Asset Database Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md Deletes any existing database and copies the asset database every time the application starts. This ensures a fresh copy but is less performant. ```dart var databasesPath = await getDatabasesPath(); var path = join(databasesPath, "demo_always_copy_asset_example.db"); // delete existing if any await deleteDatabase(path); // Make sure the parent directory exists try { await Directory(dirname(path)).create(recursive: true); } catch (_) {} // Copy from asset ByteData data = await rootBundle.load(url.join("assets", "example.db")); List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await new File(path).writeAsBytes(bytes, flush: true); // open the database var db = await openDatabase(path, readOnly: true); ``` -------------------------------- ### Handle Database Migrations with onCreate, onUpgrade, onDowngrade Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md Opens a database with version management. It defines onCreate for initial creation, onUpgrade for schema changes when the version increases, and onDowngrade for schema changes when the version decreases. onDatabaseDowngradeDelete is used to recreate the database on downgrade. ```dart _onCreate(Database db, int version) async { // Database is created, create the table await db.execute( "CREATE TABLE Test (id INTEGER PRIMARY KEY, value TEXT)"); } _onUpgrade(Database db, int oldVersion, int newVersion) async { // Database version is updated, alter the table await db.execute("ALTER TABLE Test ADD name TEXT"); } // Special callback used for onDowngrade here to recreate the database var db = await openDatabase(path, version: 1, onCreate: _onCreate, onUpgrade: _onUpgrade, onDowngrade: onDatabaseDowngradeDelete); ``` -------------------------------- ### Create Flutter Project for macOS and iOS Source: https://github.com/tekartik/sqflite/blob/master/sqflite_darwin/example/README.md Use this command to create a new Flutter project with support for macOS and iOS platforms. ```bash flutter create --platforms=macos,ios . ``` -------------------------------- ### Get SQLite Version with Sqflite Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/version.md Query the database to retrieve the SQLite version string. The result is a list of maps, and the version is typically the first value in the first map. ```dart print((await db.rawQuery('SELECT sqlite_version()')).first.values.first); ``` -------------------------------- ### Build and Run Windows App in Release Mode Source: https://github.com/tekartik/sqflite/blob/master/sqflite_test_app/README.md Commands to build a Flutter Windows application in release mode, copy the necessary DLL, and run the executable. ```bash # Build flutter build windows # Copy sqlite3.dll cp ..\sqflite_common_ffi\lib\src\windows\sqlite3.dll .\build\windows\runner\Release # Run it .\build\windows\runner\Release\sqflite_test_app.exe ``` -------------------------------- ### Configure Shared Worker File Name in pubspec.yaml Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web/doc/dev_info.md Override the default shared worker file name by specifying 'sw_js_file' in your pubspec.yaml. Rerun setup and update 'sharedWorkerUri' options in the client. ```yaml sqflite: # Update for force changing file name for shared worker # to force an app update until a better solution is found # default being sqflite_sw.js # # Could be sqflite_sw_v1.js, sqflite_sw_v2.js,... # # Re run setup then and change the sharedWorkerUri options in the client. # sqflite_common_ffi_web: sw_js_file: sqflite_sw_v1.js ``` -------------------------------- ### Preload Data during onCreate Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md Opens a database with a specified version and provides an onCreate callback to create tables and populate initial data when the database is first created. ```dart _onCreate(Database db, int version) async { // Database is created, create the table await db.execute( "CREATE TABLE Test (id INTEGER PRIMARY KEY, value TEXT)"); // populate data await db.insert(...); } // Open the database, specifying a version and an onCreate callback var db = await openDatabase(path, version: 1, onCreate: _onCreate); ``` -------------------------------- ### Query with Escaped Column Name Source: https://github.com/tekartik/sqflite/blob/master/sqflite/README.md When using SQLite keywords as table or column names, they must be escaped with double quotes. This example queries a table named 'table' and filters by a column named 'group'. ```dart db.query('table', columns: ['group'], where: '"group" = ?', whereArgs: ['my_group']); ``` -------------------------------- ### Run Flutter App Source: https://github.com/tekartik/sqflite/blob/master/sqflite_android/example/README.md Execute this command to run the Flutter application. ```bash flutter run ``` -------------------------------- ### Run Flutter Tests Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_test/README.md Execute this command in your project's root directory to run the Flutter tests after setting up the sqflite server and port forwarding. ```bash flutter test ``` -------------------------------- ### Basic Database Helper Class Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md A simple helper class to manage database opening. Note the potential race condition if `openDatabase` is called multiple times concurrently. ```dart class Helper { final String path; Helper(this.path); Database _db; Future getDb() async { if (_db == null) { _db = await openDatabase(path); } return _db; } } ``` -------------------------------- ### Open Database Protocol Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/method_call_protocol.md Defines the input and output for opening a database. Parameters include path, read-only status, and single instance preference. ```json in: path: database path (String) readOnly: singleInstance: out: id: database id (int) clientId: recoveredInTransaction: ``` -------------------------------- ### Sqflite FFI Initialization for Tests Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/testing.md Initialize sqflite_common_ffi for running tests on desktop. This sets up the FFI implementation and the global database factory. ```dart import 'package:flutter_test/flutter_test.dart'; import 'package:sqflite/sqflite.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; /// Initialize sqflite for test. void sqfliteTestInit() { // Initialize ffi implementation sqfliteFfiInit(); // Set global factory databaseFactory = databaseFactoryFfi; } Future main() async { sqfliteTestInit(); test('simple', () async { var db = await openDatabase(inMemoryDatabasePath); await db.execute(''' CREATE TABLE Product ( id INTEGER PRIMARY KEY, title TEXT ) '''); await db.insert('Product', {'title': 'Product 1'}); await db.insert('Product', {'title': 'Product 2'}); var result = await db.query('Product'); expect(result, [ {'id': 1, 'title': 'Product 1'}, {'id': 2, 'title': 'Product 2'} ]); await db.close(); }); } ``` -------------------------------- ### SQL Table Creation Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/conflict_algorithm.md Defines the schema for the Product and ProductImage tables. ```sql CREATE TABLE Product ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT) ``` ```sql CREATE TABLE ProductImage ( productId INTEGER PRIMARY KEY, imageUrl TEXT) ``` -------------------------------- ### Open Database Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md Standard method to open a database file using its path. ```dart // open the database Database db = await openDatabase(path); ``` -------------------------------- ### Transaction v2 - Begin Output Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/method_call_protocol.md Output indicating the implementation supports the new transaction model and providing a transaction ID. ```json out: // This tells that the implementation supports the new transaction model transactionId: ``` -------------------------------- ### AppDelegate.m for GeneratedPluginRegistrant Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md Ensure AppDelegate.m calls GeneratedPluginRegistrant.registerWithRegistry(self) in its application:didFinishLaunchingWithOptions: method. ```objective-c - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } ``` -------------------------------- ### Android Tests with Sqflite Source: https://github.com/tekartik/sqflite/blob/master/sqflite_android/example/README.md Navigate to the android directory and run Gradle commands for testing. This includes Java unit tests and connected Android tests with an emulator. ```bash cd android # Java unit test ./gradlew test # With a emulator running ./gradlew connectedAndroidTest ``` -------------------------------- ### Use sqflite_common_ffi_web Factory Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web/README.md In web applications, use the databaseFactoryFfiWeb to open a database. This factory utilizes IndexedDB for persistence. ```dart // Use the ffi web factory in web apps (flutter or dart) var factory = databaseFactoryFfiWeb; var db = await factory.openDatabase('my_db.db'); var sqliteVersion = (await db.rawQuery('select sqlite_version()')).first.values.first; print(sqliteVersion); // should print 3.39.3 ``` -------------------------------- ### Import Asset Database on Web Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web/doc/opening_asset_db_web.md Use this snippet to copy an asset database to a file path on web platforms. Ensure the 'url' variable points to your asset and 'path' is the desired destination. ```dart final data = await rootBundle.load(url.join('assets', 'example.db')); final bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await databaseFactory.writeDatabaseBytes(path, bytes); ``` -------------------------------- ### Quick Logger Wrapper Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/dev_tips.md A convenient method to quickly wrap an existing factory with a debug logger for immediate feedback. ```dart var factoryWithLogs = factory.debugQuickLoggerWrapper(); ``` ```dart databaseFactory = databaseFactory.debugQuickLoggerWrapper(); ``` -------------------------------- ### Create SqfliteSqlCommand using Raw Factories Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/sqflite_sql_command.md Use raw factories to create SqfliteSqlCommand instances directly from SQL strings and arguments. Suitable for complex or dynamic SQL. ```dart final queryCmd = SqfliteSqlCommand.rawQuery('SELECT * FROM Test WHERE id = ?', [1]); ``` ```dart final insertCmd = SqfliteSqlCommand.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item']); ``` ```dart final updateCmd = SqfliteSqlCommand.rawUpdate('UPDATE Test SET name = ? WHERE id = ?', ['new name', 1]); ``` ```dart final deleteCmd = SqfliteSqlCommand.rawDelete('DELETE FROM Test WHERE id = ?', [1]); ``` ```dart final executeCmd = SqfliteSqlCommand.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); ``` -------------------------------- ### Add Asset to pubspec.yaml Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md Specify the database file in the `assets` section of your `pubspec.yaml` file. ```yaml flutter: assets: - assets/example.db ``` -------------------------------- ### Initialize sqflite_ffi and Set Factory Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/using_ffi_instead_of_sqflite.md Initialize the FFI implementation and set the database factory before running your application. This is particularly important for Windows and Linux. On iOS/Android, this step might be optional if not using `sqlite_flutter_lib`. ```dart import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:sqflite/sqflite.dart'; Future main() async { if (Platform.isWindows || Platform.isLinux) { // Initialize FFI sqfliteFfiInit(); } // Change the default factory. On iOS/Android, if not using `sqlite_flutter_lib` you can forget // this step, it will use the sqlite version available on the system. databaseFactory = databaseFactoryFfi; runApp(MyApp()); } ``` -------------------------------- ### Perf 10000 item (Background Thread) Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/perf.md Tests performance for inserting 10000 items in batches and performing various select operations. Includes batch inserts and different types of SELECT queries. ```text TEST Running Perf 10000 item sw 0:00:03.638205 insert 10000 items batch sw 0:00:00.483061 SELECT * From Test : 10000 items sw 0:00:00.521089 SELECT * FROM Test WHERE name LIKE %item% 10000 items sw 0:00:00.011873 SELECT * FROM Test WHERE name LIKE %dummy% 0 items TEST Done Perf 10000 item ``` -------------------------------- ### Sqflite Unit Testing with FFI Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/dev_tips.md Set up unit tests for database logic using sqflite_common_ffi for FFI support. This allows testing database interactions outside of a device or emulator. ```yaml dev_dependencies: sqflite_common_ffi: ``` ```dart import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:test/test.dart'; void main() { // Init ffi loader if needed. sqfliteFfiInit(); test('MyUnitTest', () async { var factory = databaseFactoryFfi; var db = await factory.openDatabase(inMemoryDatabasePath); // Should fail table does not exists try { await db.query('Test'); } on DatabaseException catch (e) { // no such table: Test expect(e.isNoSuchTableError('Test'), isTrue); print(e.toString()); } // Ok await db.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY)'); await db.execute('ALTER TABLE Test ADD COLUMN name TEXT'); // should succeed, but empty expect(await db.query('Test'), []); await db.close(); }); } ``` -------------------------------- ### Basic sqflite FFI unit test Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/README.md A simple unit test demonstrating the initialization and basic usage of sqflite_common_ffi with an in-memory database. ```dart import 'package:test/test.dart'; import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; void main() { // Init ffi loader if needed. sqfliteFfiInit(); test('simple sqflite example', () async { var db = await databaseFactoryFfi.openDatabase(inMemoryDatabasePath); expect(await db.getVersion(), 0); await db.close(); }); } ``` -------------------------------- ### Declare Database Path and Instance Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/migration_example.md Declare variables for the database path and the database instance. These are typically defined at the class or file level. ```dart // Our database path String path; // Our database once opened Database db; ``` -------------------------------- ### Create Company Table (Version 2) Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/migration_example.md Defines the SQL statement to create the 'Company' table with 'id', 'name', and 'description' columns for version 2. ```dart /// Create Company table V2 void _createTableCompanyV2(Batch batch) { batch.execute('DROP TABLE IF EXISTS Company'); batch.execute('''CREATE TABLE Company ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT )'''); } ``` -------------------------------- ### Create Table with sqflite execute Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/sql.md Use `execute` for SQL commands that do not return values, such as table creation. Only a single SQL statement is supported per call. ```dart await db.execute('CREATE TABLE my_table (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, type TEXT)'); ``` -------------------------------- ### Recreate Windows Project for Flutter Source: https://github.com/tekartik/sqflite/blob/master/sqflite_test_app/README.md Optional commands to delete and recreate the Windows project directory for a Flutter application. ```powershell # Delete existing windows project if needed rmdir -Recurse -Force windows # Recreate the project flutter create --platforms windows . ``` -------------------------------- ### Use sqflite_common_ffi_web with sqlite3 v2 Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web/doc/troubleshooting.md If you need to use sqlite3 v2 (pre-3.0.0), specify an older version of sqflite_common_ffi_web. ```yaml dependencives: sqflite_common_ffi_web: ^1.0.2 ``` -------------------------------- ### Run Dart Build Hooks Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common_ffi/doc/troubleshooting.md For Dart projects (not Flutter), execute build scripts using `dart run` to ensure build hooks are properly invoked. This is crucial for setting up dynamic libraries. ```shell dart run xxxx.dart ``` -------------------------------- ### query Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/method_call_protocol.md Executes a SELECT SQL query with optional arguments and supports cursor-based pagination. ```APIDOC ## query ### Description Executes a `SELECT` SQL query. Supports binding parameters and optionally returns a cursor for paginated results. ### Method (Implicitly a method call) ### Parameters #### Request Body - **sql** (String) - Required - The SQL query to execute. - **arguments** (List) - Optional - A list of parameters to bind to the query. - **cursorPageSize** (int) - Optional - If provided, enables cursor-based pagination with the specified page size. Defaults to null (fetch all results). ### Response #### Success Response - **columns** (List) - A list of column names returned by the query. - **rows** (List>) - A list of rows, where each row is a list of values corresponding to the columns. - **cursorId** (int) - An optional cursor ID if `cursorPageSize` was used. `null` if all results have been fetched. ``` -------------------------------- ### Insert with SQL Parameters Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/sql.md Use '?' as placeholders for values in raw SQL insert statements to prevent SQL injection. Ensure the number of placeholders matches the number of arguments provided in the list. ```dart int recordId = await db.rawInsert('INSERT INTO my_table(name, year) VALUES (?, ?)', ['my_name', 2019]); ``` -------------------------------- ### Use sqflite_common_ffi_web with sqlite3 v3 Source: https://github.com/tekartik/sqflite/blob/master/packages_web/sqflite_common_ffi_web/doc/troubleshooting.md To use sqlite3 v3, ensure your sqflite_common_ffi_web dependency is at least version 1.1.0. ```yaml dependencives: sqflite_common_ffi_web: ^1.1.0 ``` -------------------------------- ### Create Employee Table (Version 2) Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/migration_example.md Defines the SQL statement to create the 'Employee' table with 'id', 'name', 'companyId', and a foreign key constraint referencing 'Company'. ```dart /// Create Employee table V2 void _createTableEmployeeV2(Batch batch) { batch.execute('DROP TABLE IF EXISTS Employee'); batch.execute('''CREATE TABLE Employee ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, companyId INTEGER, FOREIGN KEY (companyId) REFERENCES Company(id) ON DELETE CASCADE )'''); } ``` -------------------------------- ### Analysis Options for Strict Mode Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/troubleshooting.md Configure analysis_options.yaml to enable strong mode and disable implicit casts for better code analysis. ```yaml analyzer: language: strict-casts: true strict-inference: true ``` -------------------------------- ### Create Company Table (Version 1) Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/migration_example.md Defines the SQL statement to create the 'Company' table with an 'id' and 'name' column for the initial database version. ```dart /// Create tables void _createTableCompanyV1(Batch batch) { batch.execute('DROP TABLE IF EXISTS Company'); batch.execute('''CREATE TABLE Company ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT )'''); } // First version of the database db = await factory.openDatabase(path, options: OpenDatabaseOptions( version: 1, onCreate: (db, version) async { var batch = db.batch(); _createTableCompanyV1(batch); await batch.commit(); }, onDowngrade: onDatabaseDowngradeDelete)); ``` -------------------------------- ### Usage of SqfliteSqlCommand in Transactions Source: https://github.com/tekartik/sqflite/blob/master/sqflite_common/doc/sqflite_sql_command.md Define a list of commands and execute them sequentially within a database transaction. This ensures atomicity for multiple operations. ```dart final commands = [ SqfliteSqlCommand.insert('Test', {'id': 1, 'name': 'item 1'}), SqfliteSqlCommand.insert('Test', {'id': 2, 'name': 'item 2'}), ]; await db.transaction((txn) async { for (final cmd in commands) { await cmd.insert(txn); } }); ``` -------------------------------- ### Run Flutter Driver Test with Specific Device Source: https://github.com/tekartik/sqflite/blob/master/sqflite_test_app/README.md Command to execute Flutter driver tests on a specific Android emulator. ```bash flutter driver --target=test_driver/main.dart -d emulator-5554 ``` -------------------------------- ### Copy Asset Database If Needed and Open Source: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md Copies the asset database if the version number indicates an update is needed. It checks an external version file, reads the asset version, and copies the database and version file if the asset version is greater. Ensure the 'assets' folder is correctly configured in your project. ```dart /// Copy the asset database if needed and open it. /// /// It uses an external version file to keep track of the asset version. Future copyIfNeededAndOpenAssetDatabase( {required String databasesPath, required String versionNumFilename, required String dbFilename}) async { var dbPath = join(databasesPath, dbFilename); // First check the currently installed version var versionNumFile = File(join(databasesPath, versionNumFilename)); var existingVersionNum = 0; if (versionNumFile.existsSync()) { existingVersionNum = int.parse(await versionNumFile.readAsString()); } // Read the asset version var assetVersionNum = int.parse( (await rootBundle.loadString(url.join('assets', versionNumFilename))).trim()); // Compare them. print('existing/asset: $existingVersionNum/$assetVersionNum'); // If needed, copy the asset database if (existingVersionNum < assetVersionNum) { print('copying new version $assetVersionNum'); // Make sure the parent directory exists try { await Directory(databasesPath).create(recursive: true); } catch (_) {} // Copy from asset var data = await rootBundle.load(url.join('assets', dbFilename)); var bytes = Uint8List.sublistView(data); // Write and flush the database bytes written await File(dbPath).writeAsBytes(bytes, flush: true); // Write and flush the version file await versionNumFile.writeAsString('$assetVersionNum', flush: true); } var db = await openDatabase(dbPath); return db; } ``` -------------------------------- ### Alternative Flutter Driver Test Execution Source: https://github.com/tekartik/sqflite/blob/master/sqflite_test_app/README.md Alternative command to run Flutter driver tests using a Dart script. ```bash dart tool/run_flutter_driver_test.dart ``` -------------------------------- ### Reading Query Results Source: https://github.com/tekartik/sqflite/blob/master/sqflite/README.md Demonstrates how to query data from a table and access the results. Note that map items returned from a query are read-only; create a new map if modifications are needed. ```dart List> records = await db.query('my_table'); ``` ```dart // get the first record Map mapRead = records.first; // Update it in memory...this will throw an exception mapRead['my_column'] = 1; // Crash... `mapRead` is read-only ``` ```dart // get the first record Map map = Map.from(mapRead); // Update it in memory now map['my_column'] = 1; ```