mirror of https://github.com/AMT-Cheif/drift.git
Rollback if commit fails (#1589)
This commit is contained in:
parent
36b23942f4
commit
41825e058e
|
@ -1,3 +1,7 @@
|
|||
## unreleased
|
||||
|
||||
- Rollback transactions when a commit fails.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
- Add the `references` method to `BuildColumn` to reference a column declared
|
||||
|
|
|
@ -434,8 +434,13 @@ abstract class DatabaseConnectionUser {
|
|||
rethrow;
|
||||
} finally {
|
||||
if (success) {
|
||||
// complete() will also take care of committing the transaction
|
||||
try {
|
||||
await transaction.complete();
|
||||
} catch (e) {
|
||||
// Couldn't commit -> roll back then.
|
||||
await transactionExecutor.rollback();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
await transaction.disposeChildStreams();
|
||||
}
|
||||
|
|
|
@ -13,12 +13,8 @@ class Lock {
|
|||
final blockCompleted = Completer<void>();
|
||||
_last = blockCompleted.future;
|
||||
|
||||
Future<T> callBlockAndComplete() async {
|
||||
try {
|
||||
return await block();
|
||||
} finally {
|
||||
blockCompleted.complete();
|
||||
}
|
||||
Future<T> callBlockAndComplete() {
|
||||
return Future.sync(block).whenComplete(blockCompleted.complete);
|
||||
}
|
||||
|
||||
if (previous != null) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
test('a failing commit does not block the whole database', () async {
|
||||
final db = _Database(NativeDatabase.memory());
|
||||
addTearDown(db.close);
|
||||
|
||||
await db.customStatement('''
|
||||
CREATE TABLE IF NOT EXISTS todo_items (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL, content TEXT NULL,
|
||||
category_id INTEGER NOT NULL
|
||||
REFERENCES todo_categories (id) DEFERRABLE INITIALLY DEFERRED,
|
||||
generated_text TEXT NULL
|
||||
GENERATED ALWAYS AS (title || ' (' || content || ')') VIRTUAL
|
||||
);
|
||||
''');
|
||||
await db.customStatement('''
|
||||
CREATE TABLE IF NOT EXISTS todo_categories (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
''');
|
||||
await db.customStatement('PRAGMA foreign_keys = ON;');
|
||||
|
||||
await expectLater(
|
||||
db.transaction(() async {
|
||||
// Thanks to the deferrable clause, this statement will only cause a
|
||||
// failing COMMIT.
|
||||
await db.customStatement(
|
||||
'INSERT INTO todo_items (title, category_id) VALUES (?, ?);',
|
||||
['a', 100]);
|
||||
}),
|
||||
throwsA(isA<SqliteException>()),
|
||||
);
|
||||
|
||||
expect(
|
||||
db.customSelect('SELECT * FROM todo_items').get(), completion(isEmpty));
|
||||
});
|
||||
}
|
||||
|
||||
class _Database extends GeneratedDatabase {
|
||||
_Database(QueryExecutor executor)
|
||||
: super(SqlTypeSystem.defaultInstance, executor);
|
||||
|
||||
@override
|
||||
Iterable<TableInfo<Table, dynamic>> get allTables => const Iterable.empty();
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
}
|
|
@ -1,3 +1,7 @@
|
|||
## unreleased
|
||||
|
||||
- Improve error handling around custom row classes.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
- Consider `drift`-named files when generating schema migrations ([#1486](https://github.com/simolus3/moor/issues/1486))
|
||||
|
|
Loading…
Reference in New Issue