From 4b5607625b1d3f37d6f1610ec562f7be2a79ec86 Mon Sep 17 00:00:00 2001 From: Jorge Sardina Date: Fri, 20 Jun 2025 12:52:04 +0200 Subject: [PATCH 1/4] Allow transforming table updates from sqlite_async. --- packages/drift_sqlite_async/CHANGELOG.md | 4 ++++ .../lib/src/connection.dart | 20 ++++++++++++++----- packages/drift_sqlite_async/pubspec.yaml | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/drift_sqlite_async/CHANGELOG.md b/packages/drift_sqlite_async/CHANGELOG.md index b101ac4..fa769a1 100644 --- a/packages/drift_sqlite_async/CHANGELOG.md +++ b/packages/drift_sqlite_async/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.3 + +- Allow transforming table updates from sqlite_async. + ## 0.2.2 - Fix write detection when using UPDATE/INSERT/DELETE with RETURNING in raw queries. diff --git a/packages/drift_sqlite_async/lib/src/connection.dart b/packages/drift_sqlite_async/lib/src/connection.dart index a1af55a..bcde1bf 100644 --- a/packages/drift_sqlite_async/lib/src/connection.dart +++ b/packages/drift_sqlite_async/lib/src/connection.dart @@ -15,12 +15,22 @@ import 'package:sqlite_async/sqlite_async.dart'; class SqliteAsyncDriftConnection extends DatabaseConnection { late StreamSubscription _updateSubscription; - SqliteAsyncDriftConnection(SqliteConnection db, {bool logStatements = false}) - : super(SqliteAsyncQueryExecutor(db, logStatements: logStatements)) { + SqliteAsyncDriftConnection( + SqliteConnection db, { + bool logStatements = false, + Set Function(UpdateNotification)? transformTableUpdate, + }) : super(SqliteAsyncQueryExecutor(db, logStatements: logStatements)) { _updateSubscription = (db as SqliteQueries).updates!.listen((event) { - var setUpdates = {}; - for (var tableName in event.tables) { - setUpdates.add(TableUpdate(tableName)); + final Set setUpdates; + // This is useful to map local table names from PowerSync that are backed by a view name + // which is the entity that the user interacts with. + if (transformTableUpdate != null) { + setUpdates = transformTableUpdate(event); + } else { + setUpdates = {}; + for (var tableName in event.tables) { + setUpdates.add(TableUpdate(tableName)); + } } super.streamQueries.handleTableUpdates(setUpdates); }); diff --git a/packages/drift_sqlite_async/pubspec.yaml b/packages/drift_sqlite_async/pubspec.yaml index 62a64da..c17e833 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.2 +version: 0.2.3 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. From a2b6c4cd2226f867569b03d25318b87d6aea6fde Mon Sep 17 00:00:00 2001 From: David Martos Date: Sun, 22 Jun 2025 12:35:16 +0200 Subject: [PATCH 2/4] typo --- packages/drift_sqlite_async/lib/src/connection.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/drift_sqlite_async/lib/src/connection.dart b/packages/drift_sqlite_async/lib/src/connection.dart index bcde1bf..fa56e2e 100644 --- a/packages/drift_sqlite_async/lib/src/connection.dart +++ b/packages/drift_sqlite_async/lib/src/connection.dart @@ -18,14 +18,14 @@ class SqliteAsyncDriftConnection extends DatabaseConnection { SqliteAsyncDriftConnection( SqliteConnection db, { bool logStatements = false, - Set Function(UpdateNotification)? transformTableUpdate, + Set Function(UpdateNotification)? transformTableUpdates, }) : super(SqliteAsyncQueryExecutor(db, logStatements: logStatements)) { _updateSubscription = (db as SqliteQueries).updates!.listen((event) { final Set setUpdates; // This is useful to map local table names from PowerSync that are backed by a view name // which is the entity that the user interacts with. - if (transformTableUpdate != null) { - setUpdates = transformTableUpdate(event); + if (transformTableUpdates != null) { + setUpdates = transformTableUpdates(event); } else { setUpdates = {}; for (var tableName in event.tables) { From d76435962555b05f472ae0d2aa2621f0ead38004 Mon Sep 17 00:00:00 2001 From: David Martos Date: Fri, 19 Sep 2025 12:11:17 +0200 Subject: [PATCH 3/4] update doc --- packages/drift_sqlite_async/lib/src/connection.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/drift_sqlite_async/lib/src/connection.dart b/packages/drift_sqlite_async/lib/src/connection.dart index fa56e2e..6c34ed4 100644 --- a/packages/drift_sqlite_async/lib/src/connection.dart +++ b/packages/drift_sqlite_async/lib/src/connection.dart @@ -15,6 +15,8 @@ import 'package:sqlite_async/sqlite_async.dart'; class SqliteAsyncDriftConnection extends DatabaseConnection { late StreamSubscription _updateSubscription; + /// [transformTableUpdates] is useful to map local table names from PowerSync that are backed by a view name + /// which is the entity that the user interacts with. SqliteAsyncDriftConnection( SqliteConnection db, { bool logStatements = false, @@ -22,8 +24,6 @@ class SqliteAsyncDriftConnection extends DatabaseConnection { }) : super(SqliteAsyncQueryExecutor(db, logStatements: logStatements)) { _updateSubscription = (db as SqliteQueries).updates!.listen((event) { final Set setUpdates; - // This is useful to map local table names from PowerSync that are backed by a view name - // which is the entity that the user interacts with. if (transformTableUpdates != null) { setUpdates = transformTableUpdates(event); } else { From 09b841ba9b34a1e309504808e399695239e08c17 Mon Sep 17 00:00:00 2001 From: David Martos Date: Fri, 19 Sep 2025 14:14:10 +0200 Subject: [PATCH 4/4] add test --- .../drift_sqlite_async/test/basic_test.dart | 40 +++++++++++++++++++ .../test/generated/database.dart | 2 + 2 files changed, 42 insertions(+) diff --git a/packages/drift_sqlite_async/test/basic_test.dart b/packages/drift_sqlite_async/test/basic_test.dart index 339cc04..dd7a159 100644 --- a/packages/drift_sqlite_async/test/basic_test.dart +++ b/packages/drift_sqlite_async/test/basic_test.dart @@ -11,6 +11,7 @@ import 'package:sqlite_async/sqlite_async.dart'; import 'package:test/test.dart'; import './utils/test_utils.dart'; +import 'generated/database.dart'; class EmptyDatabase extends GeneratedDatabase { EmptyDatabase(super.executor); @@ -245,4 +246,43 @@ INSERT INTO test_data(description) VALUES('test data'); expect(row, isEmpty); }); }); + + test('transform table updates', () async { + final path = dbPath(); + await cleanDb(path: path); + + final db = await setupDatabase(path: path); + final connection = SqliteAsyncDriftConnection( + db, + // tables with the local_ prefix are mapped to the name without the prefix + transformTableUpdates: (event) { + final updates = {}; + + for (final originalTableName in event.tables) { + final effectiveName = originalTableName.startsWith("local_") + ? originalTableName.substring(6) + : originalTableName; + updates.add(TableUpdate(effectiveName)); + } + + return updates; + }, + ); + + // Create table with a different name than drift. (Mimicking a table name backed by a view in PowerSync with the optional sync strategy) + await db.execute( + 'CREATE TABLE local_todos(id INTEGER PRIMARY KEY AUTOINCREMENT, description TEXT)', + ); + + final dbu = TodoDatabase.fromSqliteAsyncConnection(connection); + + final tableUpdatesFut = + dbu.tableUpdates(TableUpdateQuery.onTableName("todos")).first; + + // This insert will trigger the sqlite_async "updates" stream + await db.execute("INSERT INTO local_todos(description) VALUES('Test 1')"); + + expect(await tableUpdatesFut.timeout(const Duration(seconds: 2)), + {TableUpdate("todos")}); + }); } diff --git a/packages/drift_sqlite_async/test/generated/database.dart b/packages/drift_sqlite_async/test/generated/database.dart index 928c7dd..b8a5109 100644 --- a/packages/drift_sqlite_async/test/generated/database.dart +++ b/packages/drift_sqlite_async/test/generated/database.dart @@ -15,6 +15,8 @@ class TodoItems extends Table { @DriftDatabase(tables: [TodoItems]) class TodoDatabase extends _$TodoDatabase { TodoDatabase(SqliteConnection db) : super(SqliteAsyncDriftConnection(db)); + + TodoDatabase.fromSqliteAsyncConnection(SqliteAsyncDriftConnection super.conn); @override int get schemaVersion => 1;