Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/sqlite_async/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Native: Add the `NativeSqliteOpenFactory.beforeOpen` method, which can be overridden to configure
SQLite asynchronously before opening databases.
- Web: Upgrade `package:sqlite3_web` to flush IndexedDB writes automatically, deprecate `flush()`.
- Add `SqliteOptions.preparedStatementCacheSize` to cache prepared statements (disabled by default).

## 0.14.3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ final class NativeSqliteDatabaseImpl extends SqliteDatabaseImpl {
[
for (var i = 0; i < maxReaders; i++) openConnection(isWriter: false)
],
// TODO: Option to enable prepared statement cache.
preparedStatementCacheSize:
openFactory.sqliteOptions.preparedStatementCacheSize,
);
},
);
Expand Down
23 changes: 23 additions & 0 deletions packages/sqlite_async/lib/src/sqlite_options.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/// @docImport 'package:sqlite3/common.dart';
library;

final class WebSqliteOptions {
final String workerUri;
final String wasmUri;
Expand Down Expand Up @@ -43,6 +46,22 @@ final class SqliteOptions {
/// additional readers on the web.
final int maxReaders;

/// The amount of prepared statements to cache.
///
/// For each SQLite connection, up to [preparedStatementCacheSize] statements
/// will be cached in an LRU cache. This allows re-using prepared statements
/// instead of parsing and optimizing them again, which improves performance
/// for frequently-used statements like watched queries.
///
/// Be aware that active prepared statements may alter the operation of the
/// database, for instance because they might keep some database resources
/// locked. Statements are [CommonPreparedStatement.reset] before being stored
/// in the cache, but enabling a statement cache is still something that
/// should be tested carefully.
///
/// This is currently disabled by default (set to `0`).
final int preparedStatementCacheSize;

@Deprecated('Use default SqliteOptions constructor instead')
const factory SqliteOptions.defaults() = SqliteOptions;

Expand All @@ -54,6 +73,7 @@ final class SqliteOptions {
this.lockTimeout = const Duration(seconds: 30),
this.profileQueries = _profileQueriesByDefault,
this.maxReaders = defaultMaxReaders,
this.preparedStatementCacheSize = 0,
});

/// Creates a new options instance by applying overrides from parameters.
Expand All @@ -64,6 +84,7 @@ final class SqliteOptions {
WebSqliteOptions? webSqliteOptions,
bool? profileQueries,
int? maxReaders,
int? preparedStatementCacheSize,
}) {
return SqliteOptions(
journalMode: journalMode,
Expand All @@ -73,6 +94,8 @@ final class SqliteOptions {
lockTimeout: lockTimeout,
profileQueries: profileQueries ?? this.profileQueries,
maxReaders: maxReaders ?? this.maxReaders,
preparedStatementCacheSize:
preparedStatementCacheSize ?? this.preparedStatementCacheSize,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ base class WebSqliteOpenFactory extends InternalOpenFactory {
/// can customize the behavior where needed.
Future<ConnectToRecommendedResult> connectToWorker(
WebSqlite sqlite, String name) {
return sqlite.connectToRecommended(name);
return sqlite.connectToRecommended(name,
preparedStatementCacheSize: sqliteOptions.preparedStatementCacheSize);
}

/// Currently this only uses the SQLite Web WASM implementation.
Expand Down
2 changes: 1 addition & 1 deletion packages/sqlite_async/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ topics:
dependencies:
sqlite3: ^3.5.0
sqlite3_web: ^0.9.4
sqlite3_connection_pool: ^0.2.4
sqlite3_connection_pool: ^0.2.7
async: ^2.10.0
collection: ^1.17.0
meta: ^1.10.0
Expand Down
9 changes: 7 additions & 2 deletions packages/sqlite_async/test/utils/abstract_test_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,24 @@ abstract class AbstractTestUtils {
Future<CommonDatabase> openDatabaseForSingleConnection();

Future<SqliteOpenFactory> testFactory(
{String? path, SqliteOptions options = const SqliteOptions()}) async {
{String? path, SqliteOptions options = defaultTestOptions}) async {
return SqliteOpenFactory(path: path ?? dbPath(), options: options);
}

/// Creates a SqliteDatabaseConnection
Future<SqliteDatabase> setupDatabase({
String? path,
SqliteOptions options = const SqliteOptions(),
SqliteOptions options = defaultTestOptions,
}) async {
final factory = await testFactory(path: path, options: options);
return SqliteDatabase.withFactory(factory);
}

/// Deletes any DB data
Future<void> cleanDb({required String path});

// Enable prepared statement cache in tests, we want to enable that option by
// default eventually.
static const defaultTestOptions =
SqliteOptions(preparedStatementCacheSize: 64);
}
2 changes: 1 addition & 1 deletion packages/sqlite_async/test/utils/web_test_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class TestUtils extends AbstractTestUtils {
@override
Future<SqliteOpenFactory> testFactory({
String? path,
SqliteOptions options = const SqliteOptions(),
SqliteOptions options = AbstractTestUtils.defaultTestOptions,
}) async {
await _isInitialized;
return super.testFactory(
Expand Down