-
Notifications
You must be signed in to change notification settings - Fork 367
/
executor.dart
165 lines (136 loc) · 6.03 KB
/
executor.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:drift/backends.dart';
import 'package:drift/drift.dart' show OpeningDetails;
/// A query executor is responsible for executing statements on a database and
/// return their results in a raw form.
///
/// This is an internal api of drift, which can break often. If you want to
/// implement custom database backends, consider using the new `backends` API.
/// The [NativeDatabase implementation](https://github.com/simolus3/drift/blob/develop/drift/lib/src/ffi/database.dart)
/// might be useful as a reference. If you want to write your own database
/// engine to use with drift and run into issues, please consider creating an
/// issue.
abstract class QueryExecutor {
/// The [SqlDialect] to use for this database engine.
SqlDialect get dialect;
/// Opens the executor, if it has not yet been opened.
Future<bool> ensureOpen(QueryExecutorUser user);
/// Runs a select statement with the given variables and returns the raw
/// results.
Future<List<Map<String, Object?>>> runSelect(
String statement, List<Object?> args);
/// Runs an insert statement with the given variables. Returns the row id or
/// the auto_increment id of the inserted row.
Future<int> runInsert(String statement, List<Object?> args);
/// Runs an update statement with the given variables and returns how many
/// rows where affected.
Future<int> runUpdate(String statement, List<Object?> args);
/// Runs an delete statement and returns how many rows where affected.
Future<int> runDelete(String statement, List<Object?> args);
/// Runs a custom SQL statement without any variables. The result of that
/// statement will be ignored.
Future<void> runCustom(String statement, [List<Object?>? args]);
/// Prepares and runs [statements].
///
/// Running them doesn't need to happen in a transaction. When using drift's
/// batch api, drift will call this method from a transaction either way. This
/// method mainly exists to save duplicate parsing costs, allowing each
/// statement to be prepared only once.
Future<void> runBatched(BatchedStatements statements);
/// Starts a [TransactionExecutor].
TransactionExecutor beginTransaction();
/// Closes this database connection and releases all resources associated with
/// it. Implementations should also handle [close] calls in a state where the
/// database isn't open.
Future<void> close() async {
// no-op per default for backwards compatibility
}
}
/// Callbacks passed to [QueryExecutor.ensureOpen] to run schema migrations when
/// the database is first opened.
abstract class QueryExecutorUser {
/// The schema version to set on the database when it's opened.
int get schemaVersion;
/// A callbacks that runs after the database connection has been established,
/// but before any other query is sent.
///
/// The query executor will wait for this future to complete before running
/// any other query. Queries running on the [executor] are an exception to
/// this, they can be used to run migrations.
/// No matter how often [QueryExecutor.ensureOpen] is called, this method will
/// not be called more than once.
Future<void> beforeOpen(QueryExecutor executor, OpeningDetails details);
}
const _equality = ListEquality();
/// Stores information needed to run batched statements in the order they were
/// issued without preparing statements multiple times.
class BatchedStatements {
/// All sql statements that need to be prepared.
///
/// A statement might run multiple times with different arguments.
final List<String> statements;
/// Stores which sql statement should be run with what arguments.
final List<ArgumentsForBatchedStatement> arguments;
/// Creates a collection of batched statements by splitting the sql and the
/// bound arguments.
BatchedStatements(this.statements, this.arguments);
@override
int get hashCode {
return Object.hash(_equality.hash(statements), _equality.hash(arguments));
}
@override
bool operator ==(Object other) {
return other is BatchedStatements &&
_equality.equals(other.statements, statements) &&
_equality.equals(other.arguments, arguments);
}
@override
String toString() {
return 'BatchedStatements($statements, $arguments)';
}
}
/// Instruction to run a batched sql statement with the arguments provided.
class ArgumentsForBatchedStatement {
/// Index of the sql statement in the [BatchedStatements.statements] of the
/// [BatchedStatements] containing this argument set.
final int statementIndex;
/// Bound arguments for the referenced statement.
final List<Object?> arguments;
/// Used internally by drift.
ArgumentsForBatchedStatement(this.statementIndex, this.arguments);
@override
int get hashCode {
return Object.hash(statementIndex, _equality);
}
@override
bool operator ==(Object other) {
return other is ArgumentsForBatchedStatement &&
other.statementIndex == statementIndex &&
_equality.equals(other.arguments, arguments);
}
@override
String toString() {
return 'ArgumentsForBatchedStatement($statementIndex, $arguments)';
}
}
/// A [QueryExecutor] that runs multiple queries atomically.
abstract class TransactionExecutor extends QueryExecutor {
/// Whether this transaction executor supports nesting transactions by calling
/// [beginTransaction] on it.
bool get supportsNestedTransactions;
/// Completes the transaction. No further queries may be sent to to this
/// [QueryExecutor] after this method was called.
///
/// This may be called before [ensureOpen] was awaited, implementations must
/// support this. That state implies that no query was sent, so it should be
/// a no-op.
Future<void> send();
/// Cancels this transaction. No further queries may be sent ot this
/// [QueryExecutor] after this method was called.
///
/// This may be called before [ensureOpen] was awaited, implementations must
/// support this. That state implies that no query was sent, so it should be
/// a no-op.
Future<void> rollback();
}