Skip to main content

sqflite-common-api

Use when writing Dart code against the sqflite API without depending on Flutter, or when a shared package must work with sqflite (mobile), sqflite_common_ffi (desktop/VM/tests) and sqflite_common_ffi_web: the DatabaseFactory, Database, Transaction, Batch, DatabaseExecutor, OpenDatabaseOptions, ConflictAlgorithm, DatabaseException, QueryCursor types from package:sqflite_common/sqlite_api.dart, the global databaseFactory / openDatabase from sqflite_common/sqflite.dart, sql.dart escapeName, utils/utils.dart firstIntValue, sqflite_logger.dart SqfliteDatabaseFactoryLogger, sandbox(), SqfliteSqlCommand, queryIterate.

Informations de source

Dépôt
tekartik/sqflite
Dernière activité de la source
10 septembre 2026 à 13:15
Langue détectée de SKILL.md
anglais
Étoiles
3 021
Forks
556

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
sqflite-common-api
description
Use when writing Dart code against the sqflite API without depending on Flutter, or when a shared package must work with sqflite (mobile), sqflite_common_ffi (desktop/VM/tests) and sqflite_common_ffi_web: the DatabaseFactory, Database, Transaction, Batch, DatabaseExecutor, OpenDatabaseOptions, ConflictAlgorithm, DatabaseException, QueryCursor types from package:sqflite_common/sqlite_api.dart, the global databaseFactory / openDatabase from sqflite_common/sqflite.dart, sql.dart escapeName, utils/utils.dart firstIntValue, sqflite_logger.dart SqfliteDatabaseFactoryLogger, sandbox(), SqfliteSqlCommand, queryIterate.
# sqflite_common: the pure-Dart sqflite API `package:sqflite_common` defines the whole sqflite API (`DatabaseFactory`, `Database`, `Transaction`, `Batch`, `OpenDatabaseOptions`, ...) and the shared implementation, with no Flutter dependency. It contains no SQLite engine: an implementation package supplies a `DatabaseFactory` (`sqflite` on Android/iOS/macOS, `sqflite_common_ffi` on desktop/VM/tests, `sqflite_common_ffi_web` on the web). Depend on `sqflite_common` in packages that must stay Flutter-free and accept a factory from the caller. ```dart import 'package:sqflite_common/sqlite_api.dart'; class NoteStore { NoteStore(this.factory, this.path); final DatabaseFactory factory; final String path; Future<Database> open() => factory.openDatabase( path, options: OpenDatabaseOptions( version: 1, onCreate: (db, _) => db.execute( 'CREATE TABLE Note (id INTEGER PRIMARY KEY, content TEXT)', ), ), ); } ``` ## Guidelines ### Which import gives what * `package:sqflite_common/sqlite_api.dart`: the types only. `DatabaseFactory` (`openDatabase(path, {options})`, `getDatabasesPath()`, `setDatabasesPath()`, `deleteDatabase()`, `databaseExists()`, `readDatabaseBytes()`, `writeDatabaseBytes()`), `DatabaseExecutor` (`execute`, `rawInsert`/`insert`, `rawQuery`/`query`, `rawQueryCursor`/`queryCursor`, `rawUpdate`/`update`, `rawDelete`/`delete`, `batch()`, `database`), `Database` (`path`, `isOpen`, `close()`, `transaction()`, `readTransaction()`), `Transaction`, `Batch` (`commit`, `apply`, `length`, same mutators as the executor), `QueryCursor`, `OpenDatabaseOptions`, `ConflictAlgorithm`, `DatabaseException`, `inMemoryDatabasePath`, the callback typedefs (`OnDatabaseCreateFn`, `OnDatabaseVersionChangeFn`, `OnDatabaseOpenFn`, `OnDatabaseConfigureFn`), `onDatabaseDowngradeDelete`, `onDatabaseVersionChangeError`, and the extensions `SqfliteDatabaseExecutorExt` (`getVersion`, `setVersion`), `SqfliteDatabaseExt` (`setJournalMode`), `SqfliteDatabaseExecutorIterateExt` (`queryIterate`, `rawQueryIterate`), `SqfliteDatabaseFactorySandboxExtension` (`sandbox`), `SqfliteSqlCommand` + `SqfliteSqlCommandExecutorExt`, `sqfliteLogLevel*` constants. Use this import in libraries. * `package:sqflite_common/sqflite.dart`: everything above plus the global `databaseFactory` getter/setter, `databaseFactoryOrNull`, and the global functions `openDatabase`, `openReadOnlyDatabase`, `getDatabasesPath`, `deleteDatabase`, `databaseExists` that forward to `databaseFactory`. Only applications should rely on the global; a library that reads it forces the app to have set it. `package:sqflite/sqflite.dart` and `package:sqflite_common_ffi/sqflite_ffi.dart` both re-export this library, so do not import it next to them (`unnecessary_import`). * `package:sqflite_common/sql.dart`: `ConflictAlgorithm`, `escapeName`, `unescapeName`. * `package:sqflite_common/utils/utils.dart`: `firstIntValue(rows)`, `firstStringValue(rows)`, `hex(bytes)`, `setLockWarningInfo(duration:, callback:)`, `sqlCountColumn` (`'COUNT(*)'`). There is no `Sqflite` class here; that class lives in `package:sqflite`. * `package:sqflite_common/sqflite_logger.dart`: `SqfliteDatabaseFactoryLogger` (its constructor is `@experimental`, expect an `experimental_member_use` analyzer warning), `SqfliteLoggerOptions`, `SqfliteDatabaseFactoryLoggerType` (`all`, `invoke`), the event classes (`SqfliteLoggerSqlEvent`, `SqfliteLoggerBatchEvent`, `SqfliteLoggerDatabaseOpenEvent`, `SqfliteLoggerDatabaseCloseEvent`, `SqfliteLoggerDatabaseDeleteEvent`, `SqfliteLoggerInvokeEvent`), `SqfliteLoggerEventExt.dump()` and `DatabaseFactoryLoggerDebugExt.debugQuickLoggerWrapper()`. * `package:sqflite_common/sqflite_dev.dart`: deprecated dev-only `setLogLevel` / `setOptions` (`SqfliteDatabaseFactoryDev`) and `SqfliteOptions`. Do not ship code that uses it. * Never import `package:sqflite_common/src/...` from user code. ### Designing a Flutter-free package * Take a `DatabaseFactory` (or a `Database`) as a constructor or function parameter. The Flutter app passes `databaseFactory` from `package:sqflite`, the CLI or test passes `databaseFactoryFfi` from `sqflite_common_ffi`. * Take the database `path` as a parameter too: `getDatabasesPath()` is only meaningful for the sqflite plugin; on other implementations the app should compute a location (`path_provider`, a CLI argument, a temp dir). `inMemoryDatabasePath` (`':memory:'`) works everywhere. * Type your SQL-facing functions on `DatabaseExecutor` so they work with both a `Database` and a `Transaction`. * Opening returns the same instance for the same path while `singleInstance` is true (default); it is forced to false for in-memory databases. * `databaseFactory` throws `StateError('databaseFactory not initialized')` until an implementation sets it; the setter rejects factories that are not sqflite implementations (`ArgumentError`) and prints a warning when changing an already set factory. * `factory.sandbox(path: root)` returns a `DatabaseFactory` restricted to `root` (relative paths resolved under it, absolute paths must be inside, `getDatabasesPath()` returns `root`); it works over any implementation and is never nested twice. ### Statements, transactions, batches (shared semantics) * One statement per call; bind with `?` and an argument list; values are `int`, `num`, `String`, `Uint8List` or `null` (`bool`, `DateTime`, `List`, `Map` are not supported). Results are read-only maps. * `db.transaction((txn) async {...})` commits when the callback returns and rolls back (and rethrows) when it throws. Use only `txn` inside. Callbacks `onCreate` / `onUpgrade` / `onDowngrade` are already in a transaction. * `db.batch()` collects operations and `commit()` runs them in one call in a transaction (`noResult: true`, `continueOnError: true`); a batch created from a `Transaction` is committed with it. * `queryIterate` / `rawQueryIterate` (or `queryCursor` + `moveNext()` + `close()`) stream large results with a `bufferSize` (default 100). * `DatabaseException` helpers: `isNoSuchTableError`, `isSyntaxError`, `isUniqueConstraintError`, `isNotNullConstraintError`, `isDuplicateColumnError`, `isOpenFailedError`, `isDatabaseClosedError`, `isReadOnlyError`, `getResultCode()`. ## Examples ### Shared repository, used from Flutter and from a Dart test ```dart // package my_data (depends on sqflite_common only) import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common/utils/utils.dart'; class TodoRepository { TodoRepository({required this.factory, required this.path}); final DatabaseFactory factory; final String path; Future<Database>? _db; Future<Database> get db => _db ??= factory.openDatabase( path, options: OpenDatabaseOptions( version: 1, onConfigure: (db) => db.execute('PRAGMA foreign_keys = ON'), onCreate: (db, _) => db.execute( 'CREATE TABLE Todo (id INTEGER PRIMARY KEY, title TEXT NOT NULL, done INTEGER NOT NULL DEFAULT 0)', ), ), ); Future<int> add(String title) async => (await db).insert('Todo', {'title': title}); Future<int> count(DatabaseExecutor executor) async => firstIntValue(await executor.query('Todo', columns: [sqlCountColumn])) ?? 0; Future<void> markAllDone() async { final database = await db; await database.transaction((txn) async { final pending = await count(txn); if (pending > 0) { await txn.update('Todo', {'done': 1}); } }); } Future<void> close() async { await (await db).close(); _db = null; } } ``` ```dart // test/todo_repository_test.dart (dev_dependency: sqflite_common_ffi) // sqflite_ffi.dart re-exports the sqflite_common API (inMemoryDatabasePath...). import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:test/test.dart'; import 'package:my_data/todo_repository.dart'; void main() { setUpAll(sqfliteFfiInit); test('count and markAllDone', () async { final repo = TodoRepository( factory: databaseFactoryFfi, path: inMemoryDatabasePath, ); await repo.add('a'); expect(await repo.count(await repo.db), 1); await repo.markAllDone(); expect(await (await repo.db).query('Todo', where: 'done = 1'), hasLength(1)); await repo.close(); }); } ``` In the Flutter app: `TodoRepository(factory: databaseFactory, path: join(await getDatabasesPath(), 'todo.db'))` with `package:sqflite/sqflite.dart`. ### Using the global factory in an application ```dart import 'package:sqflite_common/sqflite.dart'; /// The app (not a library) sets databaseFactory first, e.g. /// `databaseFactory = databaseFactoryFfi;` from sqflite_common_ffi. Future<int> countRows(String table) async { final db = await openDatabase(inMemoryDatabasePath); try { await db.execute('CREATE TABLE $table (id INTEGER PRIMARY KEY)'); final rows = await db.rawQuery('SELECT COUNT(*) FROM $table'); return rows.first.values.first as int; } finally { await db.close(); } } ``` ### Sandboxed factory for tests or per-user data ```dart import 'package:sqflite_common/sqlite_api.dart'; Future<Database> openUserDb(DatabaseFactory factory, String userRoot) async { final userFactory = factory.sandbox(path: userRoot); // Relative to userRoot; '/etc/x.db' would throw ArgumentError. return userFactory.openDatabase('cache.db'); } ``` ### Logging every statement of any factory ```dart import 'package:sqflite_common/sqflite_logger.dart'; import 'package:sqflite_common/sqlite_api.dart'; // ignore: experimental_member_use DatabaseFactory withLogs(DatabaseFactory factory) => SqfliteDatabaseFactoryLogger( factory, options: SqfliteLoggerOptions( type: SqfliteDatabaseFactoryLoggerType.all, log: (event) { if (event is SqfliteLoggerSqlEvent) { print('${event.type.name}: ${event.sql} ${event.arguments ?? ''}' '${event.error != null ? ' error: ${event.error}' : ''}'); } else if (event is SqfliteLoggerBatchEvent) { for (final op in event.operations) { print('batch ${op.type.name}: ${op.sql} ${op.arguments ?? ''}'); } } else { event.dump(); } }, ), ); ``` ### Prepared commands and iteration ```dart import 'package:sqflite_common/sqlite_api.dart'; final _byDone = SqfliteSqlCommand.query('Todo', where: 'done = ?', whereArgs: [0]); final _insert = SqfliteSqlCommand.insert('Todo', {'title': 'x', 'done': 0}); Future<List<String>> pendingTitles(DatabaseExecutor executor) async { final titles = <String>[]; await _byDone.iterate(executor, bufferSize: 50, onRow: (row) { titles.add(row['title'] as String); return true; }); return titles; } Future<int> insertOne(DatabaseExecutor executor) => _insert.insert(executor); Future<void> walk(DatabaseExecutor executor) => executor.queryIterate( 'Todo', orderBy: 'id', onRow: (row) async { print(row); return row['id'] != 100; // stop at id 100 }, ); ``` ### Reading the schema version and enabling WAL ```dart import 'package:sqflite_common/sqlite_api.dart'; Future<Database> openWithWal(DatabaseFactory factory, String path) => factory.openDatabase( path, options: OpenDatabaseOptions( version: 2, onConfigure: (db) async { await db.setJournalMode('WAL'); if (await db.getVersion() == 0) { // New file: settings that must precede table creation. await db.execute('PRAGMA auto_vacuum = 2'); } }, onCreate: (db, v) => db.execute('CREATE TABLE T (id INTEGER PRIMARY KEY)'), onUpgrade: (db, old, _) async { if (old < 2) await db.execute('ALTER TABLE T ADD name TEXT'); }, onDowngrade: onDatabaseDowngradeDelete, ), ); ``` ## Common mistakes * Depending on `package:sqflite` in a package that also runs on the Dart VM or in `dart test`; depend on `sqflite_common` and inject the factory. * Importing `package:sqflite_common/sqflite.dart` in a library only for the types; use `sqlite_api.dart` so the library does not read the global.
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub