From f6fb858d39a1d2b0df766327d6090fc1982877b8 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Sun, 22 Jun 2025 16:02:34 -0400 Subject: [PATCH 1/4] Reset cached statements after using them --- .github/workflows/tests.yml | 2 +- Cargo.lock | 7 -- crates/core/Cargo.toml | 1 - crates/core/src/sync/storage_adapter.rs | 51 +++++------- crates/core/src/sync/streaming_sync.rs | 3 +- crates/core/src/sync/sync_status.rs | 20 ++--- dart/pubspec.lock | 92 ++++++++++++++++------ dart/pubspec.yaml | 10 +++ dart/test/js_key_encoding_test.dart | 6 +- dart/test/sync_local_performance_test.dart | 6 +- dart/test/sync_test.dart | 14 +++- dart/test/utils/native_test_utils.dart | 25 +----- 12 files changed, 130 insertions(+), 107 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3d771bde..2ce13b5b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -58,5 +58,5 @@ jobs: run: | cd dart dart pub get - dart test + dart --enable-experiment=native-assets test dart analyze diff --git a/Cargo.lock b/Cargo.lock index 4c081087..5f37d73d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,7 +252,6 @@ dependencies = [ "serde", "serde_json", "sqlite_nostd", - "streaming-iterator", "uuid", ] @@ -418,12 +417,6 @@ dependencies = [ "sqlite3_capi", ] -[[package]] -name = "streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" - [[package]] name = "syn" version = "1.0.109" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index a4bc4d18..e39d2b72 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -22,7 +22,6 @@ serde = { version = "1.0", default-features = false, features = ["alloc", "deriv const_format = "0.2.34" futures-lite = { version = "2.6.0", default-features = false, features = ["alloc"] } rustc-hash = { version = "2.1", default-features = false } -streaming-iterator = { version = "0.1.9", default-features = false, features = ["alloc"] } [dependencies.uuid] version = "1.4.1" diff --git a/crates/core/src/sync/storage_adapter.rs b/crates/core/src/sync/storage_adapter.rs index ed71b79b..c2d0fdea 100644 --- a/crates/core/src/sync/storage_adapter.rs +++ b/crates/core/src/sync/storage_adapter.rs @@ -3,7 +3,6 @@ use core::{assert_matches::debug_assert_matches, fmt::Display}; use alloc::{string::ToString, vec::Vec}; use serde::Serialize; use sqlite_nostd::{self as sqlite, Connection, ManagedStmt, ResultCode}; -use streaming_iterator::StreamingIterator; use crate::{ error::SQLiteError, @@ -25,7 +24,7 @@ use super::{ /// used frequently as an optimization, but we're not taking advantage of that yet. pub struct StorageAdapter { pub db: *mut sqlite::sqlite3, - progress_stmt: ManagedStmt, + pub progress_stmt: ManagedStmt, time_stmt: ManagedStmt, } @@ -78,37 +77,22 @@ impl StorageAdapter { Ok(()) } - pub fn local_progress( - &self, - ) -> Result< - impl StreamingIterator>, - ResultCode, - > { - self.progress_stmt.reset()?; - - fn step(stmt: &ManagedStmt) -> Result, ResultCode> { - if stmt.step()? == ResultCode::ROW { - let bucket = stmt.column_text(0)?; - let count_at_last = stmt.column_int64(1); - let count_since_last = stmt.column_int64(2); - - return Ok(Some(PersistedBucketProgress { - bucket, - count_at_last, - count_since_last, - })); - } - + pub fn step_progress(&self) -> Result, ResultCode> { + if self.progress_stmt.step()? == ResultCode::ROW { + let bucket = self.progress_stmt.column_text(0)?; + let count_at_last = self.progress_stmt.column_int64(1); + let count_since_last = self.progress_stmt.column_int64(2); + + Ok(Some(PersistedBucketProgress { + bucket, + count_at_last, + count_since_last, + })) + } else { + // Done + self.progress_stmt.reset()?; Ok(None) } - - Ok(streaming_iterator::from_fn(|| { - match step(&self.progress_stmt) { - Err(e) => Some(Err(e)), - Ok(Some(other)) => Some(Ok(other)), - Ok(None) => None, - } - })) } pub fn reset_progress(&self) -> Result<(), ResultCode> { @@ -239,10 +223,11 @@ impl StorageAdapter { } pub fn now(&self) -> Result { - self.time_stmt.reset()?; self.time_stmt.step()?; + let res = Timestamp(self.time_stmt.column_int64(0)); + self.time_stmt.reset()?; - Ok(Timestamp(self.time_stmt.column_int64(0))) + Ok(res) } } diff --git a/crates/core/src/sync/streaming_sync.rs b/crates/core/src/sync/streaming_sync.rs index d5f2f516..1c74a587 100644 --- a/crates/core/src/sync/streaming_sync.rs +++ b/crates/core/src/sync/streaming_sync.rs @@ -425,11 +425,10 @@ impl StreamingSyncIteration { &self, checkpoint: &OwnedCheckpoint, ) -> Result { - let local_progress = self.adapter.local_progress()?; let SyncProgressFromCheckpoint { progress, needs_counter_reset, - } = SyncDownloadProgress::for_checkpoint(checkpoint, local_progress)?; + } = SyncDownloadProgress::for_checkpoint(checkpoint, &self.adapter)?; if needs_counter_reset { self.adapter.reset_progress()?; diff --git a/crates/core/src/sync/sync_status.rs b/crates/core/src/sync/sync_status.rs index e6744fa7..95340950 100644 --- a/crates/core/src/sync/sync_status.rs +++ b/crates/core/src/sync/sync_status.rs @@ -3,11 +3,12 @@ use core::{cell::RefCell, hash::BuildHasher}; use rustc_hash::FxBuildHasher; use serde::Serialize; use sqlite_nostd::ResultCode; -use streaming_iterator::StreamingIterator; + +use crate::sync::storage_adapter::StorageAdapter; use super::{ bucket_priority::BucketPriority, interface::Instruction, line::DataLine, - storage_adapter::PersistedBucketProgress, streaming_sync::OwnedCheckpoint, + streaming_sync::OwnedCheckpoint, }; /// Information about a progressing download. @@ -187,9 +188,7 @@ pub struct SyncProgressFromCheckpoint { impl SyncDownloadProgress { pub fn for_checkpoint<'a>( checkpoint: &OwnedCheckpoint, - mut local_progress: impl StreamingIterator< - Item = Result, ResultCode>, - >, + adapter: &StorageAdapter, ) -> Result { let mut buckets = BTreeMap::::new(); let mut needs_reset = false; @@ -206,12 +205,11 @@ impl SyncDownloadProgress { ); } - while let Some(row) = local_progress.next() { - let row = match row { - Ok(row) => row, - Err(e) => return Err(*e), - }; + // Go through local bucket states to detect pending progress from previous sync iterations + // that may have been interrupted. + adapter.progress_stmt.reset()?; + while let Some(row) = adapter.step_progress()? { let Some(progress) = buckets.get_mut(row.bucket) else { continue; }; @@ -232,6 +230,8 @@ impl SyncDownloadProgress { } } + adapter.progress_stmt.reset()?; + Ok(SyncProgressFromCheckpoint { progress: Self { buckets }, needs_counter_reset: needs_reset, diff --git a/dart/pubspec.lock b/dart/pubspec.lock index 5000e7e8..5834abf2 100644 --- a/dart/pubspec.lock +++ b/dart/pubspec.lock @@ -13,10 +13,18 @@ packages: dependency: transitive description: name: analyzer - sha256: "13c1e6c6fd460522ea840abec3f677cc226f5fec7872c04ad7b425517ccf54f7" + sha256: "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0" url: "https://pub.dev" source: hosted - version: "7.4.4" + version: "7.4.5" + archive: + dependency: transitive + description: + name: archive + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + url: "https://pub.dev" + source: hosted + version: "4.0.7" args: dependency: transitive description: @@ -45,10 +53,10 @@ packages: dependency: "direct main" description: name: bson - sha256: "9b761248a3494fea594aecf5d6f369b5f04d7b082aa2b8c06579ade77f1a7e47" + sha256: f8c80be7a62a88f4add7c48cc83567c36a77532de107224df8328ef71f125045 url: "https://pub.dev" source: hosted - version: "5.0.6" + version: "5.0.7" cli_config: dependency: transitive description: @@ -85,10 +93,10 @@ packages: dependency: transitive description: name: coverage - sha256: "9086475ef2da7102a0c0a4e37e1e30707e7fb7b6d28c209f559a9c5f8ce42016" + sha256: aa07dbe5f2294c827b7edb9a87bba44a9c15a3cc81bc8da2ca19b37322d30080 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.14.1" crypto: dependency: transitive description: @@ -101,10 +109,10 @@ packages: dependency: transitive description: name: decimal - sha256: "28239b8b929c1bd8618702e6dbc96e2618cf99770bbe9cb040d6cf56a11e4ec3" + sha256: "6c2041df7caefc9393ae0b0dcc4abc700831014a2c252dd10e3952499673f0b2" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" fake_async: dependency: "direct dev" description: @@ -153,6 +161,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" http_multi_server: dependency: transitive description: @@ -213,10 +229,10 @@ packages: dependency: "direct dev" description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -225,6 +241,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + native_assets_cli: + dependency: transitive + description: + name: native_assets_cli + sha256: "298ba641e47b44f039601141ab26f6865186b5d05b7f313d45797513d7205b3d" + url: "https://pub.dev" + source: hosted + version: "0.14.0" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: e5b14abd4309f820817a48701dfd40d1fbd80a1d5fa2ce6838b758e952ea46d9 + url: "https://pub.dev" + source: hosted + version: "0.11.0" node_preamble: dependency: transitive description: @@ -265,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + posix: + dependency: transitive + description: + name: posix + sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62 + url: "https://pub.dev" + source: hosted + version: "6.0.2" power_extensions: dependency: transitive description: @@ -361,6 +401,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.6" + sqlite3_native_assets: + dependency: "direct main" + description: + name: sqlite3_native_assets + sha256: "0b379f37a642b20905e86fba43940bb429e44bed1d0fc6149076090815d450a7" + url: "https://pub.dev" + source: hosted + version: "0.0.4" sqlite3_test: dependency: "direct dev" description: @@ -405,26 +453,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" + sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" url: "https://pub.dev" source: hosted - version: "1.25.15" + version: "1.26.2" test_api: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" test_core: dependency: transitive description: name: test_core - sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" + sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" url: "https://pub.dev" source: hosted - version: "0.6.8" + version: "0.6.11" typed_data: dependency: transitive description: @@ -445,18 +493,18 @@ packages: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "15.0.2" watcher: dependency: transitive description: name: watcher - sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" + sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" web: dependency: transitive description: @@ -469,10 +517,10 @@ packages: dependency: transitive description: name: web_socket - sha256: bfe6f435f6ec49cb6c01da1e275ae4228719e59a6b067048c51e72d9d63bcc4b + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" web_socket_channel: dependency: transitive description: diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 40b46486..8f973bb0 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -7,6 +7,7 @@ environment: dependencies: sqlite3: ^2.7.6 bson: ^5.0.5 + sqlite3_native_assets: ^0.0.4 dev_dependencies: test: ^1.25.0 @@ -15,3 +16,12 @@ dev_dependencies: fake_async: ^1.3.3 convert: ^3.1.2 meta: ^1.16.0 + +hooks: + user_defines: + sqlite3_native_assets: + defines: + defines: + # We use the sqlite_stmt virtual table in tests to assert that the core extension is properly + # returning all statements it starts. + - SQLITE_ENABLE_STMTVTAB diff --git a/dart/test/js_key_encoding_test.dart b/dart/test/js_key_encoding_test.dart index dd86e062..3d818e1f 100644 --- a/dart/test/js_key_encoding_test.dart +++ b/dart/test/js_key_encoding_test.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:file/local.dart'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/sqlite3.dart'; +import 'package:sqlite3/native_assets.dart'; import 'package:sqlite3_test/sqlite3_test.dart'; import 'package:test/test.dart'; @@ -16,9 +16,9 @@ void main() { setUpAll(() { loadExtension(); - sqlite3.registerVirtualFileSystem(vfs, makeDefault: false); + sqlite3Native.registerVirtualFileSystem(vfs, makeDefault: false); }); - tearDownAll(() => sqlite3.unregisterVirtualFileSystem(vfs)); + tearDownAll(() => sqlite3Native.unregisterVirtualFileSystem(vfs)); setUp(() async { db = openTestDatabase(vfs: vfs) diff --git a/dart/test/sync_local_performance_test.dart b/dart/test/sync_local_performance_test.dart index 94411382..10fe074e 100644 --- a/dart/test/sync_local_performance_test.dart +++ b/dart/test/sync_local_performance_test.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/sqlite3.dart'; +import 'package:sqlite3/native_assets.dart'; import 'package:test/test.dart'; import 'utils/native_test_utils.dart'; @@ -32,13 +32,13 @@ void testFilesystemOperations( // Needs an unique name per test file to avoid concurrency issues vfs = new TrackingFileSystem( parent: new InMemoryFileSystem(), name: 'perf-test-vfs'); - sqlite3.registerVirtualFileSystem(vfs, makeDefault: false); + sqlite3Native.registerVirtualFileSystem(vfs, makeDefault: false); db = openTestDatabase(vfs: vfs, fileName: 'test.db'); }); tearDown(() { db.dispose(); - sqlite3.unregisterVirtualFileSystem(vfs); + sqlite3Native.unregisterVirtualFileSystem(vfs); }); setUp(() { diff --git a/dart/test/sync_test.dart b/dart/test/sync_test.dart index fe786660..40e6dfcf 100644 --- a/dart/test/sync_test.dart +++ b/dart/test/sync_test.dart @@ -7,7 +7,7 @@ import 'package:fake_async/fake_async.dart'; import 'package:file/local.dart'; import 'package:meta/meta.dart'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/sqlite3.dart'; +import 'package:sqlite3/native_assets.dart'; import 'package:sqlite3_test/sqlite3_test.dart'; import 'package:test/test.dart'; import 'package:path/path.dart'; @@ -28,9 +28,9 @@ void main() { setUpAll(() { loadExtension(); - sqlite3.registerVirtualFileSystem(vfs, makeDefault: false); + sqlite3Native.registerVirtualFileSystem(vfs, makeDefault: false); }); - tearDownAll(() => sqlite3.unregisterVirtualFileSystem(vfs)); + tearDownAll(() => sqlite3Native.unregisterVirtualFileSystem(vfs)); group('text lines', () { _syncTests(vfs: vfs, isBson: false); @@ -52,6 +52,14 @@ void _syncTests({ db.execute('begin'); final [row] = db.select('SELECT powersync_control(?, ?)', [operation, data]); + + // Make sure that powersync_control doesn't leave any busy statements + // behind. + final busy = db.select( + 'SELECT * FROM sqlite_stmt WHERE busy AND sql NOT LIKE ?;', + ['%sqlite_stmt%']); + expect(busy, isEmpty); + db.execute('commit'); return jsonDecode(row.columnAt(0)); } diff --git a/dart/test/utils/native_test_utils.dart b/dart/test/utils/native_test_utils.dart index e65c7531..8c724aa0 100644 --- a/dart/test/utils/native_test_utils.dart +++ b/dart/test/utils/native_test_utils.dart @@ -1,8 +1,7 @@ import 'dart:ffi'; -import 'dart:io'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/open.dart' as sqlite_open; +import 'package:sqlite3/native_assets.dart'; import 'package:sqlite3/sqlite3.dart'; import 'package:path/path.dart' as p; @@ -11,37 +10,19 @@ const defaultSqlitePath = 'libsqlite3.so.0'; const libPath = '../target/debug'; var didLoadExtension = false; -void applyOpenOverride() { - sqlite_open.open.overrideFor(sqlite_open.OperatingSystem.linux, () { - return DynamicLibrary.open('libsqlite3.so.0'); - }); - sqlite_open.open.overrideFor(sqlite_open.OperatingSystem.macOS, () { - // Prefer using Homebrew's SQLite which allows loading extensions. - const fromHomebrew = '/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib'; - if (File(fromHomebrew).existsSync()) { - return DynamicLibrary.open(fromHomebrew); - } - - return DynamicLibrary.open('libsqlite3.dylib'); - }); -} - CommonDatabase openTestDatabase( {VirtualFileSystem? vfs, String fileName = ':memory:'}) { - applyOpenOverride(); if (!didLoadExtension) { loadExtension(); } - return sqlite3.open(fileName, vfs: vfs?.name); + return sqlite3Native.open(fileName, vfs: vfs?.name); } void loadExtension() { - applyOpenOverride(); - var lib = DynamicLibrary.open(getLibraryForPlatform(path: libPath)); var extension = SqliteExtension.inLibrary(lib, 'sqlite3_powersync_init'); - sqlite3.ensureExtensionLoaded(extension); + sqlite3Native.ensureExtensionLoaded(extension); didLoadExtension = true; } From 5aa29704bb408d4714d1d77824cc1e71b1261f4a Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Sun, 22 Jun 2025 16:08:35 -0400 Subject: [PATCH 2/4] Simplify statement --- dart/test/sync_test.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dart/test/sync_test.dart b/dart/test/sync_test.dart index 40e6dfcf..1accdfff 100644 --- a/dart/test/sync_test.dart +++ b/dart/test/sync_test.dart @@ -55,9 +55,8 @@ void _syncTests({ // Make sure that powersync_control doesn't leave any busy statements // behind. - final busy = db.select( - 'SELECT * FROM sqlite_stmt WHERE busy AND sql NOT LIKE ?;', - ['%sqlite_stmt%']); + const statement = 'SELECT * FROM sqlite_stmt WHERE busy AND sql != ?;'; + final busy = db.select(statement, [statement]); expect(busy, isEmpty); db.execute('commit'); From ccf2cdad578cef57225d32d0c84c3157bc4cb3f8 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 23 Jun 2025 07:33:07 -0400 Subject: [PATCH 3/4] Revert Dart testing changes --- dart/pubspec.lock | 92 ++++++---------------- dart/pubspec.yaml | 10 --- dart/test/js_key_encoding_test.dart | 6 +- dart/test/sync_local_performance_test.dart | 6 +- dart/test/sync_test.dart | 13 +-- dart/test/utils/native_test_utils.dart | 25 +++++- 6 files changed, 57 insertions(+), 95 deletions(-) diff --git a/dart/pubspec.lock b/dart/pubspec.lock index 5834abf2..5000e7e8 100644 --- a/dart/pubspec.lock +++ b/dart/pubspec.lock @@ -13,18 +13,10 @@ packages: dependency: transitive description: name: analyzer - sha256: "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0" + sha256: "13c1e6c6fd460522ea840abec3f677cc226f5fec7872c04ad7b425517ccf54f7" url: "https://pub.dev" source: hosted - version: "7.4.5" - archive: - dependency: transitive - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" + version: "7.4.4" args: dependency: transitive description: @@ -53,10 +45,10 @@ packages: dependency: "direct main" description: name: bson - sha256: f8c80be7a62a88f4add7c48cc83567c36a77532de107224df8328ef71f125045 + sha256: "9b761248a3494fea594aecf5d6f369b5f04d7b082aa2b8c06579ade77f1a7e47" url: "https://pub.dev" source: hosted - version: "5.0.7" + version: "5.0.6" cli_config: dependency: transitive description: @@ -93,10 +85,10 @@ packages: dependency: transitive description: name: coverage - sha256: aa07dbe5f2294c827b7edb9a87bba44a9c15a3cc81bc8da2ca19b37322d30080 + sha256: "9086475ef2da7102a0c0a4e37e1e30707e7fb7b6d28c209f559a9c5f8ce42016" url: "https://pub.dev" source: hosted - version: "1.14.1" + version: "1.12.0" crypto: dependency: transitive description: @@ -109,10 +101,10 @@ packages: dependency: transitive description: name: decimal - sha256: "6c2041df7caefc9393ae0b0dcc4abc700831014a2c252dd10e3952499673f0b2" + sha256: "28239b8b929c1bd8618702e6dbc96e2618cf99770bbe9cb040d6cf56a11e4ec3" url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.1" fake_async: dependency: "direct dev" description: @@ -161,14 +153,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" - http: - dependency: transitive - description: - name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" - url: "https://pub.dev" - source: hosted - version: "1.4.0" http_multi_server: dependency: transitive description: @@ -229,10 +213,10 @@ packages: dependency: "direct dev" description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.16.0" mime: dependency: transitive description: @@ -241,22 +225,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" - native_assets_cli: - dependency: transitive - description: - name: native_assets_cli - sha256: "298ba641e47b44f039601141ab26f6865186b5d05b7f313d45797513d7205b3d" - url: "https://pub.dev" - source: hosted - version: "0.14.0" - native_toolchain_c: - dependency: transitive - description: - name: native_toolchain_c - sha256: e5b14abd4309f820817a48701dfd40d1fbd80a1d5fa2ce6838b758e952ea46d9 - url: "https://pub.dev" - source: hosted - version: "0.11.0" node_preamble: dependency: transitive description: @@ -297,14 +265,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - posix: - dependency: transitive - description: - name: posix - sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62 - url: "https://pub.dev" - source: hosted - version: "6.0.2" power_extensions: dependency: transitive description: @@ -401,14 +361,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.6" - sqlite3_native_assets: - dependency: "direct main" - description: - name: sqlite3_native_assets - sha256: "0b379f37a642b20905e86fba43940bb429e44bed1d0fc6149076090815d450a7" - url: "https://pub.dev" - source: hosted - version: "0.0.4" sqlite3_test: dependency: "direct dev" description: @@ -453,26 +405,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" url: "https://pub.dev" source: hosted - version: "1.26.2" + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.4" test_core: dependency: transitive description: name: test_core - sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" url: "https://pub.dev" source: hosted - version: "0.6.11" + version: "0.6.8" typed_data: dependency: transitive description: @@ -493,18 +445,18 @@ packages: dependency: transitive description: name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 url: "https://pub.dev" source: hosted - version: "15.0.2" + version: "15.0.0" watcher: dependency: transitive description: name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" web: dependency: transitive description: @@ -517,10 +469,10 @@ packages: dependency: transitive description: name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + sha256: bfe6f435f6ec49cb6c01da1e275ae4228719e59a6b067048c51e72d9d63bcc4b url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.0" web_socket_channel: dependency: transitive description: diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 8f973bb0..40b46486 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -7,7 +7,6 @@ environment: dependencies: sqlite3: ^2.7.6 bson: ^5.0.5 - sqlite3_native_assets: ^0.0.4 dev_dependencies: test: ^1.25.0 @@ -16,12 +15,3 @@ dev_dependencies: fake_async: ^1.3.3 convert: ^3.1.2 meta: ^1.16.0 - -hooks: - user_defines: - sqlite3_native_assets: - defines: - defines: - # We use the sqlite_stmt virtual table in tests to assert that the core extension is properly - # returning all statements it starts. - - SQLITE_ENABLE_STMTVTAB diff --git a/dart/test/js_key_encoding_test.dart b/dart/test/js_key_encoding_test.dart index 3d818e1f..dd86e062 100644 --- a/dart/test/js_key_encoding_test.dart +++ b/dart/test/js_key_encoding_test.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:file/local.dart'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/native_assets.dart'; +import 'package:sqlite3/sqlite3.dart'; import 'package:sqlite3_test/sqlite3_test.dart'; import 'package:test/test.dart'; @@ -16,9 +16,9 @@ void main() { setUpAll(() { loadExtension(); - sqlite3Native.registerVirtualFileSystem(vfs, makeDefault: false); + sqlite3.registerVirtualFileSystem(vfs, makeDefault: false); }); - tearDownAll(() => sqlite3Native.unregisterVirtualFileSystem(vfs)); + tearDownAll(() => sqlite3.unregisterVirtualFileSystem(vfs)); setUp(() async { db = openTestDatabase(vfs: vfs) diff --git a/dart/test/sync_local_performance_test.dart b/dart/test/sync_local_performance_test.dart index 10fe074e..94411382 100644 --- a/dart/test/sync_local_performance_test.dart +++ b/dart/test/sync_local_performance_test.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/native_assets.dart'; +import 'package:sqlite3/sqlite3.dart'; import 'package:test/test.dart'; import 'utils/native_test_utils.dart'; @@ -32,13 +32,13 @@ void testFilesystemOperations( // Needs an unique name per test file to avoid concurrency issues vfs = new TrackingFileSystem( parent: new InMemoryFileSystem(), name: 'perf-test-vfs'); - sqlite3Native.registerVirtualFileSystem(vfs, makeDefault: false); + sqlite3.registerVirtualFileSystem(vfs, makeDefault: false); db = openTestDatabase(vfs: vfs, fileName: 'test.db'); }); tearDown(() { db.dispose(); - sqlite3Native.unregisterVirtualFileSystem(vfs); + sqlite3.unregisterVirtualFileSystem(vfs); }); setUp(() { diff --git a/dart/test/sync_test.dart b/dart/test/sync_test.dart index 1accdfff..a55c6a09 100644 --- a/dart/test/sync_test.dart +++ b/dart/test/sync_test.dart @@ -7,7 +7,7 @@ import 'package:fake_async/fake_async.dart'; import 'package:file/local.dart'; import 'package:meta/meta.dart'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/native_assets.dart'; +import 'package:sqlite3/sqlite3.dart'; import 'package:sqlite3_test/sqlite3_test.dart'; import 'package:test/test.dart'; import 'package:path/path.dart'; @@ -28,9 +28,9 @@ void main() { setUpAll(() { loadExtension(); - sqlite3Native.registerVirtualFileSystem(vfs, makeDefault: false); + sqlite3.registerVirtualFileSystem(vfs, makeDefault: false); }); - tearDownAll(() => sqlite3Native.unregisterVirtualFileSystem(vfs)); + tearDownAll(() => sqlite3.unregisterVirtualFileSystem(vfs)); group('text lines', () { _syncTests(vfs: vfs, isBson: false); @@ -55,9 +55,10 @@ void _syncTests({ // Make sure that powersync_control doesn't leave any busy statements // behind. - const statement = 'SELECT * FROM sqlite_stmt WHERE busy AND sql != ?;'; - final busy = db.select(statement, [statement]); - expect(busy, isEmpty); + // TODO: Re-enable after we can guarantee sqlite_stmt being available + // const statement = 'SELECT * FROM sqlite_stmt WHERE busy AND sql != ?;'; + // final busy = db.select(statement, [statement]); + // expect(busy, isEmpty); db.execute('commit'); return jsonDecode(row.columnAt(0)); diff --git a/dart/test/utils/native_test_utils.dart b/dart/test/utils/native_test_utils.dart index 8c724aa0..e65c7531 100644 --- a/dart/test/utils/native_test_utils.dart +++ b/dart/test/utils/native_test_utils.dart @@ -1,7 +1,8 @@ import 'dart:ffi'; +import 'dart:io'; import 'package:sqlite3/common.dart'; -import 'package:sqlite3/native_assets.dart'; +import 'package:sqlite3/open.dart' as sqlite_open; import 'package:sqlite3/sqlite3.dart'; import 'package:path/path.dart' as p; @@ -10,19 +11,37 @@ const defaultSqlitePath = 'libsqlite3.so.0'; const libPath = '../target/debug'; var didLoadExtension = false; +void applyOpenOverride() { + sqlite_open.open.overrideFor(sqlite_open.OperatingSystem.linux, () { + return DynamicLibrary.open('libsqlite3.so.0'); + }); + sqlite_open.open.overrideFor(sqlite_open.OperatingSystem.macOS, () { + // Prefer using Homebrew's SQLite which allows loading extensions. + const fromHomebrew = '/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib'; + if (File(fromHomebrew).existsSync()) { + return DynamicLibrary.open(fromHomebrew); + } + + return DynamicLibrary.open('libsqlite3.dylib'); + }); +} + CommonDatabase openTestDatabase( {VirtualFileSystem? vfs, String fileName = ':memory:'}) { + applyOpenOverride(); if (!didLoadExtension) { loadExtension(); } - return sqlite3Native.open(fileName, vfs: vfs?.name); + return sqlite3.open(fileName, vfs: vfs?.name); } void loadExtension() { + applyOpenOverride(); + var lib = DynamicLibrary.open(getLibraryForPlatform(path: libPath)); var extension = SqliteExtension.inLibrary(lib, 'sqlite3_powersync_init'); - sqlite3Native.ensureExtensionLoaded(extension); + sqlite3.ensureExtensionLoaded(extension); didLoadExtension = true; } From fdda3a204fe86bf591e6ef2a196eba93436f4ef7 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 23 Jun 2025 07:54:47 -0400 Subject: [PATCH 4/4] Don't enable experiment --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2ce13b5b..3d771bde 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -58,5 +58,5 @@ jobs: run: | cd dart dart pub get - dart --enable-experiment=native-assets test + dart test dart analyze