From 0af392d63fa7118a8375dc6ff12470e6ff5a5141 Mon Sep 17 00:00:00 2001 From: westito Date: Sat, 21 May 2022 17:58:54 +0200 Subject: [PATCH 1/4] Add synchronised persistence to WasmDatabase --- drift/lib/native.dart | 4 ++-- drift/lib/src/sqlite3/database.dart | 20 +++++++++++++++++--- drift/lib/wasm.dart | 18 ++++++++++++++---- drift/pubspec.yaml | 5 +++++ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drift/lib/native.dart b/drift/lib/native.dart index 27b8a512..21ae6fc3 100644 --- a/drift/lib/native.dart +++ b/drift/lib/native.dart @@ -132,12 +132,12 @@ class NativeDatabase extends DelegatedDatabase { class _NativeDelegate extends Sqlite3Delegate { final File? file; - _NativeDelegate(this.file, DatabaseSetup? setup) : super(setup); + _NativeDelegate(this.file, DatabaseSetup? setup) : super(setup, false); _NativeDelegate.opened( Database db, DatabaseSetup? setup, bool closeUnderlyingWhenClosed) : file = null, - super.opened(db, setup, closeUnderlyingWhenClosed); + super.opened(db, setup, closeUnderlyingWhenClosed, false); @override Database openDatabase() { diff --git a/drift/lib/src/sqlite3/database.dart b/drift/lib/src/sqlite3/database.dart index 522b7133..b3867744 100644 --- a/drift/lib/src/sqlite3/database.dart +++ b/drift/lib/src/sqlite3/database.dart @@ -17,15 +17,18 @@ abstract class Sqlite3Delegate bool _hasCreatedDatabase = false; bool _isOpen = false; + final bool _syncPersistence; final void Function(DB)? _setup; final bool _closeUnderlyingWhenClosed; /// A delegate that will call [openDatabase] to open the database. - Sqlite3Delegate(this._setup) : _closeUnderlyingWhenClosed = true; + Sqlite3Delegate(this._setup, this._syncPersistence) + : _closeUnderlyingWhenClosed = true; - /// A delegate using an underlying sqlite3 database object that has alreaddy + /// A delegate using an underlying sqlite3 database object that has already /// been opened. - Sqlite3Delegate.opened(this._db, this._setup, this._closeUnderlyingWhenClosed) + Sqlite3Delegate.opened(this._db, this._setup, this._closeUnderlyingWhenClosed, + this._syncPersistence) : _hasCreatedDatabase = true { _initializeDatabase(); } @@ -88,6 +91,10 @@ abstract class Sqlite3Delegate stmt.dispose(); } + if (_syncPersistence) { + await _db.flush(); + } + return Future.value(); } @@ -99,6 +106,10 @@ abstract class Sqlite3Delegate stmt.execute(args); stmt.dispose(); } + + if (_syncPersistence) { + await _db.flush(); + } } @override @@ -132,6 +143,9 @@ abstract class Sqlite3Delegate if (_closeUnderlyingWhenClosed) { beforeClose(_db); _db.dispose(); + if (_syncPersistence) { + await _db.flush(); + } } } } diff --git a/drift/lib/wasm.dart b/drift/lib/wasm.dart index a2fd0598..268857bd 100644 --- a/drift/lib/wasm.dart +++ b/drift/lib/wasm.dart @@ -38,13 +38,21 @@ class WasmDatabase extends DelegatedDatabase { /// Creates a wasm database at [path] in the virtual file system of the /// [sqlite3] module. + /// If [synchronizedPersistence] is enabled, the data is guaranteed to be + /// stored in the IndexedDB when the request is complete. Attention! + /// Insert/update queries may be slower when this option enabled. If you want + /// to insert more than one rows, be sure you run in a transaction if + /// possible. factory WasmDatabase({ required CommmonSqlite3 sqlite3, required String path, WasmDatabaseSetup? setup, + bool synchronizedPersistence = false, bool logStatements = false, }) { - return WasmDatabase._(_WasmDelegate(sqlite3, path, setup), logStatements); + return WasmDatabase._( + _WasmDelegate(sqlite3, path, setup, synchronizedPersistence), + logStatements); } /// Creates an in-memory database in the loaded [sqlite3] database. @@ -53,7 +61,8 @@ class WasmDatabase extends DelegatedDatabase { WasmDatabaseSetup? setup, bool logStatements = false, }) { - return WasmDatabase._(_WasmDelegate(sqlite3, null, setup), logStatements); + return WasmDatabase._( + _WasmDelegate(sqlite3, null, setup, false), logStatements); } } @@ -61,8 +70,9 @@ class _WasmDelegate extends Sqlite3Delegate { final CommmonSqlite3 _sqlite3; final String? _path; - _WasmDelegate(this._sqlite3, this._path, WasmDatabaseSetup? setup) - : super(setup); + _WasmDelegate( + this._sqlite3, this._path, WasmDatabaseSetup? setup, bool syncPersistence) + : super(setup, syncPersistence); @override CommonDatabase openDatabase() { diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 9949ef68..40e259e9 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -36,3 +36,8 @@ dependency_overrides: path: ../drift_dev sqlparser: path: ../sqlparser + sqlite3: + git: + url: https://github.com/westito/sqlite3.dart.git + ref: indexeddb-improvements + path: sqlite3 From 0a37736d1bd5213850124101eea749372c311b4d Mon Sep 17 00:00:00 2001 From: westito Date: Sun, 22 May 2022 18:04:02 +0200 Subject: [PATCH 2/4] Add filesystem handling to Drift --- drift/lib/native.dart | 4 ++-- drift/lib/src/sqlite3/database.dart | 20 +++++++--------- .../lib/src/sqlite3/persistence_handler.dart | 5 ++++ drift/lib/wasm.dart | 24 ++++++++++++------- drift/pubspec.yaml | 7 +----- 5 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 drift/lib/src/sqlite3/persistence_handler.dart diff --git a/drift/lib/native.dart b/drift/lib/native.dart index 21ae6fc3..27b8a512 100644 --- a/drift/lib/native.dart +++ b/drift/lib/native.dart @@ -132,12 +132,12 @@ class NativeDatabase extends DelegatedDatabase { class _NativeDelegate extends Sqlite3Delegate { final File? file; - _NativeDelegate(this.file, DatabaseSetup? setup) : super(setup, false); + _NativeDelegate(this.file, DatabaseSetup? setup) : super(setup); _NativeDelegate.opened( Database db, DatabaseSetup? setup, bool closeUnderlyingWhenClosed) : file = null, - super.opened(db, setup, closeUnderlyingWhenClosed, false); + super.opened(db, setup, closeUnderlyingWhenClosed); @override Database openDatabase() { diff --git a/drift/lib/src/sqlite3/database.dart b/drift/lib/src/sqlite3/database.dart index b3867744..d048766c 100644 --- a/drift/lib/src/sqlite3/database.dart +++ b/drift/lib/src/sqlite3/database.dart @@ -1,4 +1,5 @@ @internal +import 'package:drift/src/sqlite3/persistence_handler.dart'; import 'package:meta/meta.dart'; import 'package:sqlite3/common.dart'; @@ -17,18 +18,15 @@ abstract class Sqlite3Delegate bool _hasCreatedDatabase = false; bool _isOpen = false; - final bool _syncPersistence; final void Function(DB)? _setup; final bool _closeUnderlyingWhenClosed; /// A delegate that will call [openDatabase] to open the database. - Sqlite3Delegate(this._setup, this._syncPersistence) - : _closeUnderlyingWhenClosed = true; + Sqlite3Delegate(this._setup) : _closeUnderlyingWhenClosed = true; /// A delegate using an underlying sqlite3 database object that has already /// been opened. - Sqlite3Delegate.opened(this._db, this._setup, this._closeUnderlyingWhenClosed, - this._syncPersistence) + Sqlite3Delegate.opened(this._db, this._setup, this._closeUnderlyingWhenClosed) : _hasCreatedDatabase = true { _initializeDatabase(); } @@ -91,8 +89,8 @@ abstract class Sqlite3Delegate stmt.dispose(); } - if (_syncPersistence) { - await _db.flush(); + if (this is PersistenceHandler) { + await (this as PersistenceHandler).flush(); } return Future.value(); @@ -107,8 +105,8 @@ abstract class Sqlite3Delegate stmt.dispose(); } - if (_syncPersistence) { - await _db.flush(); + if (this is PersistenceHandler) { + await (this as PersistenceHandler).flush(); } } @@ -143,8 +141,8 @@ abstract class Sqlite3Delegate if (_closeUnderlyingWhenClosed) { beforeClose(_db); _db.dispose(); - if (_syncPersistence) { - await _db.flush(); + if (this is PersistenceHandler) { + await (this as PersistenceHandler).flush(); } } } diff --git a/drift/lib/src/sqlite3/persistence_handler.dart b/drift/lib/src/sqlite3/persistence_handler.dart new file mode 100644 index 00000000..d7ffd1d8 --- /dev/null +++ b/drift/lib/src/sqlite3/persistence_handler.dart @@ -0,0 +1,5 @@ +/// +abstract class PersistenceHandler { + /// + Future flush(); +} diff --git a/drift/lib/wasm.dart b/drift/lib/wasm.dart index 268857bd..08c785eb 100644 --- a/drift/lib/wasm.dart +++ b/drift/lib/wasm.dart @@ -14,8 +14,10 @@ @experimental library drift.wasm; +import 'package:drift/src/sqlite3/persistence_handler.dart'; import 'package:meta/meta.dart'; import 'package:sqlite3/common.dart'; +import 'package:sqlite3/wasm.dart'; import 'backends.dart'; import 'src/sqlite3/database.dart'; @@ -38,7 +40,7 @@ class WasmDatabase extends DelegatedDatabase { /// Creates a wasm database at [path] in the virtual file system of the /// [sqlite3] module. - /// If [synchronizedPersistence] is enabled, the data is guaranteed to be + /// If [fileSystem] provided, the data is guaranteed to be /// stored in the IndexedDB when the request is complete. Attention! /// Insert/update queries may be slower when this option enabled. If you want /// to insert more than one rows, be sure you run in a transaction if @@ -47,12 +49,11 @@ class WasmDatabase extends DelegatedDatabase { required CommmonSqlite3 sqlite3, required String path, WasmDatabaseSetup? setup, - bool synchronizedPersistence = false, + IndexedDbFileSystem? fileSystem, bool logStatements = false, }) { return WasmDatabase._( - _WasmDelegate(sqlite3, path, setup, synchronizedPersistence), - logStatements); + _WasmDelegate(sqlite3, path, setup, fileSystem), logStatements); } /// Creates an in-memory database in the loaded [sqlite3] database. @@ -62,17 +63,19 @@ class WasmDatabase extends DelegatedDatabase { bool logStatements = false, }) { return WasmDatabase._( - _WasmDelegate(sqlite3, null, setup, false), logStatements); + _WasmDelegate(sqlite3, null, setup, null), logStatements); } } -class _WasmDelegate extends Sqlite3Delegate { +class _WasmDelegate extends Sqlite3Delegate + implements PersistenceHandler { final CommmonSqlite3 _sqlite3; final String? _path; + final IndexedDbFileSystem? _fileSystem; _WasmDelegate( - this._sqlite3, this._path, WasmDatabaseSetup? setup, bool syncPersistence) - : super(setup, syncPersistence); + this._sqlite3, this._path, WasmDatabaseSetup? setup, this._fileSystem) + : super(setup); @override CommonDatabase openDatabase() { @@ -83,4 +86,9 @@ class _WasmDelegate extends Sqlite3Delegate { return _sqlite3.open(path); } } + + @override + Future flush() async { + await _fileSystem?.flush(); + } } diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 40e259e9..973b83ff 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -35,9 +35,4 @@ dependency_overrides: drift_dev: path: ../drift_dev sqlparser: - path: ../sqlparser - sqlite3: - git: - url: https://github.com/westito/sqlite3.dart.git - ref: indexeddb-improvements - path: sqlite3 + path: ../sqlparser \ No newline at end of file From e2622517a5cbbb525c6ff0b1bc61d22fadf77204 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 23 May 2022 12:11:06 +0200 Subject: [PATCH 3/4] Don't sync in transactions, remove interface --- drift/lib/src/sqlite3/database.dart | 22 ++++++++++++------- .../lib/src/sqlite3/persistence_handler.dart | 5 ----- drift/lib/wasm.dart | 4 +--- 3 files changed, 15 insertions(+), 16 deletions(-) delete mode 100644 drift/lib/src/sqlite3/persistence_handler.dart diff --git a/drift/lib/src/sqlite3/database.dart b/drift/lib/src/sqlite3/database.dart index d048766c..484ad83a 100644 --- a/drift/lib/src/sqlite3/database.dart +++ b/drift/lib/src/sqlite3/database.dart @@ -1,5 +1,6 @@ @internal -import 'package:drift/src/sqlite3/persistence_handler.dart'; +import 'dart:async'; + import 'package:meta/meta.dart'; import 'package:sqlite3/common.dart'; @@ -48,6 +49,12 @@ abstract class Sqlite3Delegate @override Future get isOpen => Future.value(_isOpen); + /// Flush pending writes to the file system on platforms where that is + /// necessary. + /// + /// At the moment, we only support this for the WASM backend. + FutureOr flush() => null; + @override Future open(QueryExecutorUser db) async { if (!_hasCreatedDatabase) { @@ -89,8 +96,8 @@ abstract class Sqlite3Delegate stmt.dispose(); } - if (this is PersistenceHandler) { - await (this as PersistenceHandler).flush(); + if (!isInTransaction) { + await flush(); } return Future.value(); @@ -105,8 +112,8 @@ abstract class Sqlite3Delegate stmt.dispose(); } - if (this is PersistenceHandler) { - await (this as PersistenceHandler).flush(); + if (!isInTransaction) { + await flush(); } } @@ -141,9 +148,8 @@ abstract class Sqlite3Delegate if (_closeUnderlyingWhenClosed) { beforeClose(_db); _db.dispose(); - if (this is PersistenceHandler) { - await (this as PersistenceHandler).flush(); - } + + await flush(); } } } diff --git a/drift/lib/src/sqlite3/persistence_handler.dart b/drift/lib/src/sqlite3/persistence_handler.dart deleted file mode 100644 index d7ffd1d8..00000000 --- a/drift/lib/src/sqlite3/persistence_handler.dart +++ /dev/null @@ -1,5 +0,0 @@ -/// -abstract class PersistenceHandler { - /// - Future flush(); -} diff --git a/drift/lib/wasm.dart b/drift/lib/wasm.dart index 08c785eb..0cc40d76 100644 --- a/drift/lib/wasm.dart +++ b/drift/lib/wasm.dart @@ -14,7 +14,6 @@ @experimental library drift.wasm; -import 'package:drift/src/sqlite3/persistence_handler.dart'; import 'package:meta/meta.dart'; import 'package:sqlite3/common.dart'; import 'package:sqlite3/wasm.dart'; @@ -67,8 +66,7 @@ class WasmDatabase extends DelegatedDatabase { } } -class _WasmDelegate extends Sqlite3Delegate - implements PersistenceHandler { +class _WasmDelegate extends Sqlite3Delegate { final CommmonSqlite3 _sqlite3; final String? _path; final IndexedDbFileSystem? _fileSystem; From c0929772ce6c52579a0535aead8e298e147f7e2f Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 23 May 2022 12:12:35 +0200 Subject: [PATCH 4/4] Bring back trailing newline to pubspec --- drift/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 973b83ff..9949ef68 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -35,4 +35,4 @@ dependency_overrides: drift_dev: path: ../drift_dev sqlparser: - path: ../sqlparser \ No newline at end of file + path: ../sqlparser