Skip to content

Commit 27004b3

Browse files
authored
Web: Flush IndexedDB after transactions and RETURNING statements (#3865)
The COMMIT statement runs while isInTransaction is still set, so changes made in a transaction were never flushed. Check sqlite3's autocommit state instead, and also flush after selects since they can write too.
1 parent 00d2f2e commit 27004b3

5 files changed

Lines changed: 62 additions & 7 deletions

File tree

‎drift/CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.35.1-dev
2+
3+
- Web: Fix writes made in transactions or through `RETURNING` statements not being persisted to IndexedDB (#3864).
4+
15
## 2.35.0
26

37
- Add support for FTS5 queries in the Dart API: `match`, `matchExp`, `highlight`, `snippet`, `bm25` and `rank` are now available as extension methods on FTS5 tables from `package:drift/extensions/fts5.dart` (#3843).

‎drift/lib/wasm.dart‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,27 @@ class _WasmDelegate extends Sqlite3Delegate<CommonDatabase> {
359359
await _fileSystem?.flush();
360360
}
361361

362+
Future<void> _flushIfOutsideOfTransaction() async {
363+
// Checking isInTransaction isn't enough here: The flag is only reset after
364+
// the COMMIT statement has completed, so relying on it would never flush
365+
// the changes made in a transaction.
366+
if (database.autocommit) {
367+
await _flush();
368+
}
369+
}
370+
362371
Future _runWithArgs(String statement, List<Object?> args) async {
363372
runWithArgsSync(statement, args);
373+
await _flushIfOutsideOfTransaction();
374+
}
364375

365-
if (!isInTransaction) {
366-
await _flush();
367-
}
376+
@override
377+
Future<QueryResult> runSelect(String statement, List<Object?> args) async {
378+
final result = await super.runSelect(statement, args);
379+
// Selects can write too (e.g. with a RETURNING clause). Flushing without
380+
// pending writes is cheap.
381+
await _flushIfOutsideOfTransaction();
382+
return result;
368383
}
369384

370385
@override
@@ -387,10 +402,7 @@ class _WasmDelegate extends Sqlite3Delegate<CommonDatabase> {
387402
@override
388403
Future<void> runBatched(BatchedStatements statements) async {
389404
runBatchSync(statements);
390-
391-
if (!isInTransaction) {
392-
await _flush();
393-
}
405+
await _flushIfOutsideOfTransaction();
394406
}
395407

396408
@override

‎extras/integration_tests/web_wasm/lib/driver.dart‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,14 @@ class DriftWebDriver {
166166
await driver.executeAsync('insert("", arguments[0])', []);
167167
}
168168

169+
Future<void> insertInTransaction() async {
170+
await driver.executeAsync('insert_in_transaction("", arguments[0])', []);
171+
}
172+
173+
Future<void> insertReturning() async {
174+
await driver.executeAsync('insert_returning("", arguments[0])', []);
175+
}
176+
169177
Future<void> runExclusiveBlock() async {
170178
await driver.executeAsync('do_exclusive("", arguments[0])', []);
171179
}

‎extras/integration_tests/web_wasm/test/drift_wasm_test.dart‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,21 @@ final class _TestConfiguration {
290290
await driver.openDatabase();
291291
expect(await driver.hasTable, isFalse);
292292
});
293+
294+
test('persists writes from transactions and RETURNING', () async {
295+
await driver.openDatabase(implementation: entry);
296+
await driver.insertInTransaction();
297+
await driver.insertReturning();
298+
expect(await driver.amountOfRows, 2);
299+
300+
// No delay before reloading: the writes must have been persisted
301+
// by the time they complete.
302+
await driver.driver.refresh();
303+
await driver.waitReady();
304+
305+
await driver.openDatabase(implementation: entry);
306+
expect(await driver.amountOfRows, 2);
307+
});
293308
}
294309

295310
group(

‎extras/integration_tests/web_wasm/web/main.dart‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ void main() {
5050
return null;
5151
});
5252
_addCallbackForWebDriver('insert', _insert);
53+
_addCallbackForWebDriver('insert_in_transaction', (arg) async {
54+
final db = openedDatabase!;
55+
await db.transaction(() async {
56+
await db
57+
.into(db.testTable)
58+
.insert(TestTableCompanion.insert(content: 'from transaction'));
59+
});
60+
return null;
61+
});
62+
_addCallbackForWebDriver('insert_returning', (arg) async {
63+
final db = openedDatabase!;
64+
await db
65+
.into(db.testTable)
66+
.insertReturning(TestTableCompanion.insert(content: 'returning'));
67+
return null;
68+
});
5369
_addCallbackForWebDriver('get_rows', _getRows);
5470
_addCallbackForWebDriver('has_table', _hasTables);
5571
_addCallbackForWebDriver('wait_for_update', _waitForUpdate);

0 commit comments

Comments
 (0)