Skip to content

Commit 2c8ff27

Browse files
committed
Prefer existing database
1 parent 8e998be commit 2c8ff27

File tree

5 files changed

+81
-45
lines changed

5 files changed

+81
-45
lines changed

sqlite3_web/lib/src/client.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ final class DatabaseClient implements WebSqlite {
535535
}
536536

537537
final result = CompatibilityResult.fromJS(response.response as JSObject);
538+
existing.addAll(result.existingDatabases);
538539

539540
if (result.canUseIndexedDb) {
540541
workersReportedIndexedDbSupport = true;

sqlite3_web/lib/src/shared.dart

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import 'dart:async';
66
import 'dart:js_interop';
77
import 'dart:js_interop_unsafe';
88

9+
// ignore: implementation_imports
10+
import 'package:sqlite3/src/wasm/js_interop/new_file_system_access.dart';
911
import 'package:web/web.dart';
1012

1113
/// Checks whether IndexedDB is working in the current browser.
@@ -87,6 +89,47 @@ class Lock {
8789
}
8890
}
8991

92+
/// Collects all drift OPFS databases.
93+
Future<List<String>> opfsDatabases() async {
94+
final storage = storageManager;
95+
if (storage == null) return const [];
96+
97+
var directory = await storage.directory;
98+
try {
99+
directory = await directory.getDirectory('drift_db');
100+
} on Object {
101+
// The drift_db folder doesn't exist, so there aren't any databases.
102+
return const [];
103+
}
104+
105+
return [
106+
await for (final entry in directory.list())
107+
if (entry.isDirectory) entry.name,
108+
];
109+
}
110+
111+
/// Constructs the path used by drift to store a database in the origin-private
112+
/// section of the agent's file system.
113+
String pathForOpfs(String databaseName) {
114+
return 'drift_db/$databaseName';
115+
}
116+
117+
/// Deletes the OPFS folder storing a database with the given [databaseName] if
118+
/// such folder exists.
119+
Future<void> deleteDatabaseInOpfs(String databaseName) async {
120+
final storage = storageManager;
121+
if (storage == null) return;
122+
123+
var directory = await storage.directory;
124+
try {
125+
directory = await directory.getDirectory('drift_db');
126+
await directory.remove(databaseName, recursive: true);
127+
} on Object {
128+
// fine, an error probably means that the database didn't exist in the first
129+
// place.
130+
}
131+
}
132+
90133
extension CompleteIdbRequest on IDBRequest {
91134
Future<T> complete<T extends JSAny?>() {
92135
final completer = Completer<T>.sync();

sqlite3_web/lib/src/worker.dart

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,7 @@ final class WorkerRunner {
705705

706706
var supportsOpfs = false;
707707
var opfsSupportsReadWriteUnsafe = false;
708+
final databaseName = check.databaseName;
708709
if (check.shouldCheckOpfsCompatibility) {
709710
(
710711
basicSupport: supportsOpfs,
@@ -717,14 +718,15 @@ final class WorkerRunner {
717718
: false;
718719

719720
var sharedCanSpawnDedicated = false;
721+
final existingDatabases = <ExistingDatabase>{};
720722

721723
if (check.type == MessageType.sharedCompatibilityCheck) {
722724
if (globalContext.has('Worker')) {
723725
sharedCanSpawnDedicated = true;
724726

725727
final worker = useOrSpawnInnerWorker();
726728
CompatibilityCheck(
727-
databaseName: check.databaseName,
729+
databaseName: databaseName,
728730
type: MessageType.dedicatedInSharedCompatibilityCheck,
729731
requestId: 0,
730732
).sendToWorker(worker);
@@ -735,11 +737,23 @@ final class WorkerRunner {
735737

736738
supportsOpfs = result.canUseOpfs;
737739
opfsSupportsReadWriteUnsafe = result.opfsSupportsReadWriteUnsafe;
740+
existingDatabases.addAll(result.existingDatabases);
741+
}
742+
}
743+
744+
if (supportsOpfs) {
745+
for (final database in await opfsDatabases()) {
746+
existingDatabases.add((StorageMode.opfs, database));
747+
}
748+
}
749+
if (supportsIndexedDb && databaseName != null) {
750+
if (await checkIndexedDbExists(databaseName)) {
751+
existingDatabases.add((StorageMode.indexedDb, databaseName));
738752
}
739753
}
740754

741755
return CompatibilityResult(
742-
existingDatabases: const [], // todo
756+
existingDatabases: existingDatabases.toList(),
743757
sharedCanSpawnDedicated: sharedCanSpawnDedicated,
744758
canUseOpfs: supportsOpfs,
745759
opfsSupportsReadWriteUnsafe: opfsSupportsReadWriteUnsafe,
@@ -878,44 +892,3 @@ Future<(bool, FileSystemSyncAccessHandle)> _tryOpeningWithReadWriteUnsafe(
878892
return (false, sync);
879893
}
880894
}
881-
882-
/// Collects all drift OPFS databases.
883-
Future<List<String>> opfsDatabases() async {
884-
final storage = storageManager;
885-
if (storage == null) return const [];
886-
887-
var directory = await storage.directory;
888-
try {
889-
directory = await directory.getDirectory('drift_db');
890-
} on Object {
891-
// The drift_db folder doesn't exist, so there aren't any databases.
892-
return const [];
893-
}
894-
895-
return [
896-
await for (final entry in directory.list())
897-
if (entry.isDirectory) entry.name,
898-
];
899-
}
900-
901-
/// Constructs the path used by drift to store a database in the origin-private
902-
/// section of the agent's file system.
903-
String pathForOpfs(String databaseName) {
904-
return 'drift_db/$databaseName';
905-
}
906-
907-
/// Deletes the OPFS folder storing a database with the given [databaseName] if
908-
/// such folder exists.
909-
Future<void> deleteDatabaseInOpfs(String databaseName) async {
910-
final storage = storageManager;
911-
if (storage == null) return;
912-
913-
var directory = await storage.directory;
914-
try {
915-
directory = await directory.getDirectory('drift_db');
916-
await directory.remove(databaseName, recursive: true);
917-
} on Object {
918-
// fine, an error probably means that the database didn't exist in the first
919-
// place.
920-
}
921-
}

sqlite3_web/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: sqlite3_web
22
description: Utilities to simplify accessing sqlite3 on the web, with automated feature detection.
3-
version: 0.3.2
3+
version: 0.4.0
44
homepage: https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3_web
55
repository: https://github.com/simolus3/sqlite3.dart
66

@@ -9,7 +9,7 @@ environment:
99

1010
dependencies:
1111
meta: ^1.17.0
12-
sqlite3: ^2.7.0
12+
sqlite3: ^2.9.4
1313
stream_channel: ^2.1.2
1414
web: ^1.0.0
1515

sqlite3_web/test/integration_test.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,5 +254,24 @@ final class _TestConfiguration {
254254
test('can share databases', () async {
255255
await driver.testSecond();
256256
});
257+
258+
test('re-uses IndexedDB after OPFS becomes available', () async {
259+
// In 0.4.0, we've added a new OPFS implementation that would be used by
260+
// default on browsers that previously only supported IndexedDB.
261+
await driver.openDatabase(
262+
implementation: DatabaseImplementation.indexedDbShared);
263+
await driver.execute('CREATE TABLE foo (bar TEXT);');
264+
await driver.closeDatabase();
265+
266+
await driver.driver.refresh();
267+
await driver.waitReady();
268+
269+
final features = await driver.probeImplementations();
270+
expect(features.existing, [(StorageMode.indexedDb, 'database')]);
271+
272+
final actualImplementation = await driver.openDatabase();
273+
expect(actualImplementation.storage, StorageMode.indexedDb);
274+
await driver.execute('INSERT INTO foo DEFAULT VALUES');
275+
});
257276
}
258277
}

0 commit comments

Comments
 (0)