/
lazy_database.dart
83 lines (67 loc) · 2.32 KB
/
lazy_database.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import 'dart:async';
import 'package:drift/backends.dart';
import 'package:drift/drift.dart';
/// Signature of a function that opens a database connection when instructed to.
typedef DatabaseOpener = FutureOr<QueryExecutor> Function();
/// A special database executor that delegates work to another [QueryExecutor].
/// The other executor is lazily opened by a [DatabaseOpener].
class LazyDatabase extends QueryExecutor {
late QueryExecutor _delegate;
bool _delegateAvailable = false;
Completer<void>? _openDelegate;
/// The function that will open the database when this [LazyDatabase] gets
/// opened for the first time.
final DatabaseOpener opener;
/// Declares a [LazyDatabase] that will run [opener] when the database is
/// first requested to be opened.
LazyDatabase(this.opener);
Future<void> _awaitOpened() {
if (_delegateAvailable) {
return Future.value();
} else if (_openDelegate != null) {
return _openDelegate!.future;
} else {
final delegate = _openDelegate = Completer();
Future.value(opener()).then((database) {
_delegate = database;
_delegateAvailable = true;
delegate.complete();
});
return delegate.future;
}
}
@override
TransactionExecutor beginTransaction() => _delegate.beginTransaction();
@override
Future<bool> ensureOpen(QueryExecutorUser user) {
return _awaitOpened().then((_) => _delegate.ensureOpen(user));
}
@override
Future<void> runBatched(BatchedStatements statements) =>
_delegate.runBatched(statements);
@override
Future<void> runCustom(String statement, [List<Object?>? args]) =>
_delegate.runCustom(statement, args);
@override
Future<int> runDelete(String statement, List<Object?> args) =>
_delegate.runDelete(statement, args);
@override
Future<int> runInsert(String statement, List<Object?> args) =>
_delegate.runInsert(statement, args);
@override
Future<List<Map<String, Object?>>> runSelect(
String statement, List<Object?> args) {
return _delegate.runSelect(statement, args);
}
@override
Future<int> runUpdate(String statement, List<Object?> args) =>
_delegate.runUpdate(statement, args);
@override
Future<void> close() {
if (_delegateAvailable) {
return _delegate.close();
} else {
return Future.value();
}
}
}