Skip to content

Commit 18ee0b4

Browse files
committed
add executeMultiple for multi-statement strings
1 parent b8b9a65 commit 18ee0b4

File tree

8 files changed

+88
-0
lines changed

8 files changed

+88
-0
lines changed

packages/sqlite_async/lib/src/common/connection/sync_sqlite_connection.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,20 @@ final class _UnsafeSyncContext extends UnscopedContext {
164164
}
165165
}, sql: sql);
166166
}
167+
168+
@override
169+
Future<void> executeMultiple(String sql) async {
170+
task.timeSync('executeBatch', () {
171+
final statements = db.prepareMultiple(sql);
172+
try {
173+
for (var statement in statements) {
174+
task.timeSync('iteration', () => statement.execute());
175+
}
176+
} finally {
177+
for (var statement in statements) {
178+
statement.dispose();
179+
}
180+
}
181+
}, sql: sql);
182+
}
167183
}

packages/sqlite_async/lib/src/impl/context.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import '../sqlite_connection.dart';
1212
abstract base class UnscopedContext implements SqliteReadContext {
1313
Future<ResultSet> execute(String sql, List<Object?> parameters);
1414
Future<void> executeBatch(String sql, List<List<Object?>> parameterSets);
15+
Future<void> executeMultiple(String sql);
1516

1617
/// Returns an [UnscopedContext] useful as the outermost transaction.
1718
///
@@ -143,6 +144,12 @@ final class ScopedWriteContext extends ScopedReadContext
143144
return await _context.executeBatch(sql, parameterSets);
144145
}
145146

147+
@override
148+
Future<void> executeMultiple(String sql) {
149+
_checkNotLocked();
150+
return _context.executeMultiple(sql);
151+
}
152+
146153
@override
147154
Future<T> writeTransaction<T>(
148155
Future<T> Function(SqliteWriteContext tx) callback) async {

packages/sqlite_async/lib/src/native/database/native_sqlite_connection_impl.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,22 @@ final class _UnsafeContext extends UnscopedContext {
275275
}
276276
});
277277
}
278+
279+
@override
280+
Future<void> executeMultiple(String sql) async {
281+
return computeWithDatabase((db) async {
282+
final statements = db.prepareMultiple(sql);
283+
try {
284+
for (var statement in statements) {
285+
statement.execute();
286+
}
287+
} finally {
288+
for (var statement in statements) {
289+
statement.dispose();
290+
}
291+
}
292+
});
293+
}
278294
}
279295

280296
void _sqliteConnectionIsolate(_SqliteConnectionParams params) async {

packages/sqlite_async/lib/src/sqlite_connection.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ abstract interface class SqliteWriteContext extends SqliteReadContext {
7676
/// parameter set.
7777
Future<void> executeBatch(String sql, List<List<Object?>> parameterSets);
7878

79+
// Execute multiple SQL statements from a single string, sequentially.
80+
Future<void> executeMultiple(String sql);
81+
7982
/// Open a read-write transaction on this write context.
8083
///
8184
/// When called on a [SqliteConnection], this takes a global lock - only one

packages/sqlite_async/lib/src/sqlite_queries.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ mixin SqliteQueries implements SqliteWriteContext, SqliteConnection {
136136
});
137137
}
138138

139+
@override
140+
Future<void> executeMultiple(String sql) {
141+
return writeTransaction((tx) async {
142+
return tx.executeMultiple(sql);
143+
});
144+
}
145+
139146
@override
140147
Future<void> refreshSchema() {
141148
return getAll("PRAGMA table_info('sqlite_master')");

packages/sqlite_async/lib/src/web/database.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,19 @@ final class _UnscopedContext extends UnscopedContext {
293293
});
294294
}
295295

296+
@override
297+
Future<void> executeMultiple(String sql) {
298+
return _task.timeAsync('executeMultiple', sql: sql, () {
299+
return wrapSqliteException(() async {
300+
await _database._database.executeMultiple(
301+
sql,
302+
token: _lock,
303+
checkInTransaction: _checkInTransaction,
304+
);
305+
});
306+
});
307+
}
308+
296309
@override
297310
UnscopedContext interceptOutermostTransaction() {
298311
// All execute calls done in the callback will be checked for the

packages/sqlite_async/pubspec.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ repository: https://github.com/powersync-ja/sqlite_async.dart
55
environment:
66
sdk: ">=3.5.0 <4.0.0"
77

8+
# TODO : Remove this override when the changes are merged and published.
9+
dependency_overrides:
10+
sqlite3_web:
11+
git:
12+
url: https://github.com/stevenctl/sqlite3.dart
13+
ref: stevenctl/execute-multi-support
14+
path: sqlite3_web
15+
16+
817
topics:
918
- sqlite
1019
- async

packages/sqlite_async/test/basic_test.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,23 @@ void main() {
303303
)
304304
});
305305

306+
test('executeMultiple inserts multiple rows', () async {
307+
final db = await testUtils.setupDatabase(path: path);
308+
await createTables(db);
309+
310+
await db.executeMultiple('''
311+
INSERT INTO test_data(description) VALUES('row1');
312+
INSERT INTO test_data(description) VALUES('row2');
313+
''');
314+
315+
final results = await db.getAll('SELECT description FROM test_data ORDER BY id');
316+
expect(results.length, equals(2));
317+
expect(results.rows[0], equals(['row1']));
318+
expect(results.rows[1], equals(['row2']));
319+
320+
await db.close();
321+
}, skip: _isWeb ? 'executeMultiple is not supported on web' : null);
322+
306323
test('with all connections', () async {
307324
final maxReaders = _isWeb ? 0 : 3;
308325

0 commit comments

Comments
 (0)