11import 'dart:async' ;
2- import 'dart:collection' ;
32import 'dart:isolate' ;
43
54import 'package:sqlite3/sqlite3.dart' as sqlite;
6- import 'package:sqlite_async/src/port_channel.dart' ;
75
6+ import 'isolate_completer.dart' ;
87import 'mutex.dart' ;
8+ import 'port_channel.dart' ;
99import 'sqlite_connection.dart' ;
10- import 'sqlite_connection_factory .dart' ;
10+ import 'sqlite_open_factory .dart' ;
1111import 'sqlite_queries.dart' ;
1212import 'update_notification.dart' ;
1313
@@ -16,31 +16,42 @@ typedef TxCallback<T> = Future<T> Function(sqlite.Database db);
1616/// Implements a SqliteConnection using a separate isolate for the database
1717/// operations.
1818class SqliteConnectionImpl with SqliteQueries implements SqliteConnection {
19- final SqliteConnectionFactory _factory;
20-
2119 /// Private to this connection
2220 final SimpleMutex _connectionMutex = SimpleMutex ();
21+ final Mutex _writeMutex;
2322
2423 @override
2524 final Stream <UpdateNotification >? updates;
2625 final PortClient _dbIsolate = PortClient ();
2726 final String ? debugName;
2827 final bool readOnly;
2928
30- SqliteConnectionImpl (this ._factory,
31- {this .updates, this .debugName, this .readOnly = false }) {
32- _open ();
29+ SqliteConnectionImpl (
30+ {required SqliteOpenFactory openFactory,
31+ required Mutex mutex,
32+ required SendPort upstreamPort,
33+ this .updates,
34+ this .debugName,
35+ this .readOnly = false ,
36+ bool primary = false })
37+ : _writeMutex = mutex {
38+ _open (openFactory, primary: primary, upstreamPort: upstreamPort);
3339 }
3440
3541 Future <void > get ready async {
3642 await _dbIsolate.ready;
3743 }
3844
39- Future <void > _open () async {
45+ Future <void > _open (SqliteOpenFactory openFactory,
46+ {required bool primary, required SendPort upstreamPort}) async {
4047 await _connectionMutex.lock (() async {
4148 var isolate = await Isolate .spawn (
4249 _sqliteConnectionIsolate,
43- _SqliteConnectionParams (_factory, _dbIsolate.server (),
50+ _SqliteConnectionParams (
51+ openFactory: openFactory,
52+ port: upstreamPort,
53+ primary: primary,
54+ portServer: _dbIsolate.server (),
4455 readOnly: readOnly),
4556 debugName: debugName,
4657 paused: true );
@@ -88,7 +99,7 @@ class SqliteConnectionImpl with SqliteQueries implements SqliteConnection {
8899 stopWatch.stop ();
89100 }
90101 // DB lock so that only one write happens at a time
91- return await _factory.mutex .lock (() async {
102+ return await _writeMutex .lock (() async {
92103 final ctx = _TransactionContext (_dbIsolate);
93104 try {
94105 return await callback (ctx);
@@ -173,7 +184,7 @@ class _TransactionContext implements SqliteWriteContext {
173184 @override
174185 Future <void > executeBatch (String sql, List <List <Object ?>> parameterSets) {
175186 return computeWithDatabase ((db) async {
176- final statement = db.prepare (sql);
187+ final statement = db.prepare (sql, checkNoTail : true );
177188 try {
178189 for (var parameters in parameterSets) {
179190 statement.execute (parameters);
@@ -186,15 +197,24 @@ class _TransactionContext implements SqliteWriteContext {
186197}
187198
188199void _sqliteConnectionIsolate (_SqliteConnectionParams params) async {
189- final db = await params.factory .openRawDatabase (readOnly: params.readOnly);
190- final port = params.factory .port;
200+ final port = params.port;
201+ if (! params.primary) {
202+ // Wait until the primary connection has been initialized.
203+ // The primary connection is responsible for configuring journal mode,
204+ // running migrations, and other setup.
205+ var initialized = IsolateResult <void >();
206+ port.send (['init-db' , initialized.completer]);
207+ await initialized.future;
208+ }
209+ final db = await params.openFactory.open (SqliteOpenOptions (
210+ primaryConnection: params.primary, readOnly: params.readOnly));
191211
192212 final server = params.portServer;
193213 final commandPort = ReceivePort ();
194214
195215 Set <String > updatedTables = {};
196- int ? txId = null ;
197- Object ? txError = null ;
216+ int ? txId;
217+ Object ? txError;
198218
199219 db.updates.listen ((event) {
200220 updatedTables.add (event.tableName);
@@ -261,12 +281,19 @@ void _sqliteConnectionIsolate(_SqliteConnectionParams params) async {
261281}
262282
263283class _SqliteConnectionParams {
264- SqliteConnectionFactory factory ;
265- PortServer portServer;
266- bool readOnly;
284+ final PortServer portServer;
285+ final bool readOnly;
286+
287+ final SendPort port;
288+ final bool primary;
289+ final SqliteOpenFactory openFactory;
267290
268- _SqliteConnectionParams (this .factory , this .portServer,
269- {required this .readOnly});
291+ _SqliteConnectionParams (
292+ {required this .openFactory,
293+ required this .portServer,
294+ required this .port,
295+ required this .readOnly,
296+ required this .primary});
270297}
271298
272299class _SqliteIsolateStatement {
0 commit comments