diff --git a/packages/drift_sqlite_async/CHANGELOG.md b/packages/drift_sqlite_async/CHANGELOG.md
index d39db6f..b101ac4 100644
--- a/packages/drift_sqlite_async/CHANGELOG.md
+++ b/packages/drift_sqlite_async/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.2
+
+- Fix write detection when using UPDATE/INSERT/DELETE with RETURNING in raw queries.
+
 ## 0.2.1
 
 - Fix lints.
diff --git a/packages/drift_sqlite_async/lib/src/executor.dart b/packages/drift_sqlite_async/lib/src/executor.dart
index dbd4c96..41886f3 100644
--- a/packages/drift_sqlite_async/lib/src/executor.dart
+++ b/packages/drift_sqlite_async/lib/src/executor.dart
@@ -8,7 +8,8 @@ import 'package:sqlite_async/sqlite_async.dart';
 // Ends with " RETURNING *", or starts with insert/update/delete.
 // Drift-generated queries will always have the RETURNING *.
 // The INSERT/UPDATE/DELETE check is for custom queries, and is not exhaustive.
-final _returningCheck = RegExp(r'( RETURNING \*;?$)|(^(INSERT|UPDATE|DELETE))',
+final _returningCheck = RegExp(
+    r'( RETURNING \*;?\s*$)|(^\s*(INSERT|UPDATE|DELETE))',
     caseSensitive: false);
 
 class _SqliteAsyncDelegate extends _SqliteAsyncQueryDelegate
diff --git a/packages/drift_sqlite_async/pubspec.yaml b/packages/drift_sqlite_async/pubspec.yaml
index 98eb766..62a64da 100644
--- a/packages/drift_sqlite_async/pubspec.yaml
+++ b/packages/drift_sqlite_async/pubspec.yaml
@@ -1,5 +1,5 @@
 name: drift_sqlite_async
-version: 0.2.1
+version: 0.2.2
 homepage: https://github.com/powersync-ja/sqlite_async.dart
 repository: https://github.com/powersync-ja/sqlite_async.dart
 description: Use Drift with a sqlite_async database, allowing both to be used in the same application.
diff --git a/packages/drift_sqlite_async/test/basic_test.dart b/packages/drift_sqlite_async/test/basic_test.dart
index 371c149..339cc04 100644
--- a/packages/drift_sqlite_async/test/basic_test.dart
+++ b/packages/drift_sqlite_async/test/basic_test.dart
@@ -6,6 +6,7 @@ import 'dart:async';
 
 import 'package:drift/drift.dart';
 import 'package:drift_sqlite_async/drift_sqlite_async.dart';
+import 'package:sqlite3/common.dart';
 import 'package:sqlite_async/sqlite_async.dart';
 import 'package:test/test.dart';
 
@@ -219,5 +220,29 @@ void main() {
               .data,
           equals({'count': 1}));
     });
+
+    test('cannot update database with read', () async {
+      await expectLater(() => dbu.customSelect('''
+-- trick to circumvent regex detecting writes
+INSERT INTO test_data(description) VALUES('test data');
+''').get(), throwsA(isA<SqliteException>()));
+    });
+
+    test('allows spaces after returning', () async {
+      // This tests that the statement is forwarded to the write connection
+      // despite using customSelect(). If it wasn't, we'd get an error about
+      // the database being read-only.
+      final row = await dbu.customSelect(
+          'INSERT INTO test_data(description) VALUES(?) RETURNING *   ',
+          variables: [Variable('Test Data')]).getSingle();
+      expect(row.data['description'], equals('Test Data'));
+    });
+
+    test('allows spaces before insert', () async {
+      final row = await dbu.customSelect(
+          '  INSERT INTO test_data(description) VALUES(?)   ',
+          variables: [Variable('Test Data')]).get();
+      expect(row, isEmpty);
+    });
   });
 }