Skip to content

Commit 8e15de5

Browse files
authoredApr 24, 2025··
Fix write detection when using UPDATE/INSERT/DELETE with RETURNING in raw queries (#89)
1 parent 016e341 commit 8e15de5

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed
 

‎packages/drift_sqlite_async/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.2.2
2+
3+
- Fix write detection when using UPDATE/INSERT/DELETE with RETURNING in raw queries.
4+
15
## 0.2.1
26

37
- Fix lints.

‎packages/drift_sqlite_async/lib/src/executor.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import 'package:sqlite_async/sqlite_async.dart';
88
// Ends with " RETURNING *", or starts with insert/update/delete.
99
// Drift-generated queries will always have the RETURNING *.
1010
// The INSERT/UPDATE/DELETE check is for custom queries, and is not exhaustive.
11-
final _returningCheck = RegExp(r'( RETURNING \*;?$)|(^(INSERT|UPDATE|DELETE))',
11+
final _returningCheck = RegExp(
12+
r'( RETURNING \*;?\s*$)|(^\s*(INSERT|UPDATE|DELETE))',
1213
caseSensitive: false);
1314

1415
class _SqliteAsyncDelegate extends _SqliteAsyncQueryDelegate

‎packages/drift_sqlite_async/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: drift_sqlite_async
2-
version: 0.2.1
2+
version: 0.2.2
33
homepage: https://github.com/powersync-ja/sqlite_async.dart
44
repository: https://github.com/powersync-ja/sqlite_async.dart
55
description: Use Drift with a sqlite_async database, allowing both to be used in the same application.

‎packages/drift_sqlite_async/test/basic_test.dart

+25
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:async';
66

77
import 'package:drift/drift.dart';
88
import 'package:drift_sqlite_async/drift_sqlite_async.dart';
9+
import 'package:sqlite3/common.dart';
910
import 'package:sqlite_async/sqlite_async.dart';
1011
import 'package:test/test.dart';
1112

@@ -219,5 +220,29 @@ void main() {
219220
.data,
220221
equals({'count': 1}));
221222
});
223+
224+
test('cannot update database with read', () async {
225+
await expectLater(() => dbu.customSelect('''
226+
-- trick to circumvent regex detecting writes
227+
INSERT INTO test_data(description) VALUES('test data');
228+
''').get(), throwsA(isA<SqliteException>()));
229+
});
230+
231+
test('allows spaces after returning', () async {
232+
// This tests that the statement is forwarded to the write connection
233+
// despite using customSelect(). If it wasn't, we'd get an error about
234+
// the database being read-only.
235+
final row = await dbu.customSelect(
236+
'INSERT INTO test_data(description) VALUES(?) RETURNING * ',
237+
variables: [Variable('Test Data')]).getSingle();
238+
expect(row.data['description'], equals('Test Data'));
239+
});
240+
241+
test('allows spaces before insert', () async {
242+
final row = await dbu.customSelect(
243+
' INSERT INTO test_data(description) VALUES(?) ',
244+
variables: [Variable('Test Data')]).get();
245+
expect(row, isEmpty);
246+
});
222247
});
223248
}

0 commit comments

Comments
 (0)
Please sign in to comment.