Skip to content

Commit bacc1c5

Browse files
[Feature] Update WA-SQLite (#290)
1 parent d72ac11 commit bacc1c5

File tree

13 files changed

+379
-465
lines changed

13 files changed

+379
-465
lines changed

.changeset/nice-impalas-speak.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/web': minor
3+
---
4+
5+
Updated WA-SQLite to `@journeyapps/wa-sqlite@1.0.0`. Note that WA-SQLite performed some changes to the virtual filesystem structure in this update. An automatic migration will be executed when upgrading, however no down-migration is available. Downgrading to `@journeyapps/wa-sqlite < 1.0.0` will require the IndexDB storage to be erased.

demos/angular-supabase-todolist/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@angular/platform-browser-dynamic": "^18.1.1",
2222
"@angular/router": "^18.1.1",
2323
"@angular/service-worker": "^18.1.1",
24-
"@journeyapps/wa-sqlite": "^0.4.2",
24+
"@journeyapps/wa-sqlite": "^1.0.0",
2525
"@powersync/web": "workspace:*",
2626
"@supabase/supabase-js": "^2.44.4",
2727
"rxjs": "~7.8.1",

demos/example-capacitor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@capacitor/core": "latest",
2424
"@capacitor/ios": "^6.0.0",
2525
"@capacitor/splash-screen": "latest",
26-
"@journeyapps/wa-sqlite": "^0.4.2",
26+
"@journeyapps/wa-sqlite": "^1.0.0",
2727
"@powersync/react": "workspace:*",
2828
"@powersync/web": "workspace:*",
2929
"js-logger": "^1.6.1",

demos/example-electron/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"dependencies": {
2222
"@emotion/react": "^11.13.0",
2323
"@emotion/styled": "^11.13.0",
24-
"@journeyapps/wa-sqlite": "^0.4.2",
24+
"@journeyapps/wa-sqlite": "^1.0.0",
2525
"@mui/icons-material": "^5.15.16",
2626
"@mui/material": "^5.15.16",
2727
"@mui/x-data-grid": "^6.19.11",

demos/example-nextjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@emotion/react": "^11.11.4",
1515
"@emotion/styled": "^11.11.5",
1616
"@fontsource/roboto": "^5.0.13",
17-
"@journeyapps/wa-sqlite": "^0.4.2",
17+
"@journeyapps/wa-sqlite": "^1.0.0",
1818
"@lexical/react": "^0.15.0",
1919
"@mui/icons-material": "^5.15.18",
2020
"@mui/material": "^5.15.18",

demos/react-multi-client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"test:build": "pnpm build"
1111
},
1212
"dependencies": {
13-
"@journeyapps/wa-sqlite": "^0.4.2",
13+
"@journeyapps/wa-sqlite": "^1.0.0",
1414
"@powersync/react": "workspace:*",
1515
"@powersync/web": "workspace:*",
1616
"@supabase/supabase-js": "^2.43.1",

demos/react-supabase-todolist/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@powersync/web": "workspace:*",
1414
"@emotion/react": "11.11.4",
1515
"@emotion/styled": "11.11.5",
16-
"@journeyapps/wa-sqlite": "^0.4.2",
16+
"@journeyapps/wa-sqlite": "^1.0.0",
1717
"@mui/icons-material": "^5.15.12",
1818
"@mui/material": "^5.15.12",
1919
"@mui/x-data-grid": "^6.19.6",

demos/yjs-react-supabase-text-collab/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@fontsource/roboto": "^5.0.12",
1515
"@powersync/react": "workspace:*",
1616
"@powersync/web": "workspace:*",
17-
"@journeyapps/wa-sqlite": "^0.4.2",
17+
"@journeyapps/wa-sqlite": "^1.0.0",
1818
"@lexical/react": "^0.11.3",
1919
"@mui/icons-material": "^5.15.12",
2020
"@mui/material": "^5.15.12",

packages/kysely-driver/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
},
3434
"devDependencies": {
3535
"@powersync/web": "workspace:*",
36-
"@journeyapps/wa-sqlite": "^0.4.2",
36+
"@journeyapps/wa-sqlite": "^1.0.0",
3737
"@types/node": "^20.17.6",
3838
"@vitest/browser": "^2.1.4",
3939
"ts-loader": "^9.5.1",

packages/web/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"author": "JOURNEYAPPS",
5757
"license": "Apache-2.0",
5858
"peerDependencies": {
59-
"@journeyapps/wa-sqlite": "^0.4.2",
59+
"@journeyapps/wa-sqlite": "^1.0.0",
6060
"@powersync/common": "workspace:^1.21.0"
6161
},
6262
"dependencies": {
@@ -67,7 +67,7 @@
6767
"js-logger": "^1.6.1"
6868
},
6969
"devDependencies": {
70-
"@journeyapps/wa-sqlite": "^0.4.2",
70+
"@journeyapps/wa-sqlite": "^1.0.0",
7171
"@types/uuid": "^9.0.6",
7272
"@vitest/browser": "^2.1.4",
7373
"crypto-browserify": "^3.12.0",

packages/web/src/shared/open-db.ts

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import * as SQLite from '@journeyapps/wa-sqlite';
21
import '@journeyapps/wa-sqlite';
2+
import * as SQLite from '@journeyapps/wa-sqlite';
3+
import { BatchedUpdateNotification } from '@powersync/common';
4+
import { Mutex } from 'async-mutex';
35
import * as Comlink from 'comlink';
46
import type { DBFunctionsInterface, OnTableChangeCallback, WASQLExecuteResult } from './types';
5-
import { Mutex } from 'async-mutex';
6-
import { BatchedUpdateNotification } from '@powersync/common';
77

88
let nextId = 1;
99

@@ -15,8 +15,14 @@ export async function _openDB(
1515
const module = await moduleFactory();
1616
const sqlite3 = SQLite.Factory(module);
1717

18+
/**
19+
* Register the PowerSync core SQLite extension
20+
*/
21+
module.ccall('powersync_init_static', 'int', []);
22+
1823
const { IDBBatchAtomicVFS } = await import('@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js');
19-
const vfs = new IDBBatchAtomicVFS(dbFileName);
24+
// @ts-expect-error The types for this static method are missing upstream
25+
const vfs = await IDBBatchAtomicVFS.create(dbFileName, module, { lockPolicy: 'exclusive' });
2026
sqlite3.vfs_register(vfs, true);
2127

2228
const db = await sqlite3.open_v2(dbFileName);
@@ -37,7 +43,10 @@ export async function _openDB(
3743
Array.from(listeners.values()).forEach((l) => l(event));
3844
}
3945

40-
sqlite3.register_table_onchange_hook(db, (opType: number, tableName: string, rowId: number) => {
46+
sqlite3.update_hook(db, (updateType: number, dbName: string | null, tableName: string | null) => {
47+
if (!tableName) {
48+
return;
49+
}
4150
updatedTables.add(tableName);
4251
if (updateTimer == null) {
4352
updateTimer = setTimeout(fireUpdates, 0);
@@ -134,52 +143,48 @@ export async function _openDB(
134143
return _acquireExecuteLock(async (): Promise<WASQLExecuteResult> => {
135144
let affectedRows = 0;
136145

137-
const str = sqlite3.str_new(db, sql);
138-
const query = sqlite3.str_value(str);
139146
try {
140147
await executeSingleStatement('BEGIN TRANSACTION');
141148

142-
//Prepare statement once
143-
const prepared = await sqlite3.prepare_v2(db, query);
144-
if (prepared === null) {
145-
return {
146-
rowsAffected: 0,
147-
rows: { _array: [], length: 0 }
148-
};
149-
}
150149
const wrappedBindings = bindings ? bindings : [];
151-
for (const binding of wrappedBindings) {
152-
// TODO not sure why this is needed currently, but booleans break
153-
for (let i = 0; i < binding.length; i++) {
154-
const b = binding[i];
155-
if (typeof b == 'boolean') {
156-
binding[i] = b ? 1 : 0;
157-
}
150+
for await (const stmt of sqlite3.statements(db, sql)) {
151+
if (stmt === null) {
152+
return {
153+
rowsAffected: 0,
154+
rows: { _array: [], length: 0 }
155+
};
158156
}
159157

160-
//Reset bindings
161-
sqlite3.reset(prepared.stmt);
162-
if (bindings) {
163-
sqlite3.bind_collection(prepared.stmt, binding);
164-
}
158+
//Prepare statement once
159+
for (const binding of wrappedBindings) {
160+
// TODO not sure why this is needed currently, but booleans break
161+
for (let i = 0; i < binding.length; i++) {
162+
const b = binding[i];
163+
if (typeof b == 'boolean') {
164+
binding[i] = b ? 1 : 0;
165+
}
166+
}
165167

166-
const result = await sqlite3.step(prepared.stmt);
167-
if (result === SQLite.SQLITE_DONE) {
168-
//The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
169-
affectedRows += sqlite3.changes(db);
168+
if (bindings) {
169+
sqlite3.bind_collection(stmt, binding);
170+
}
171+
const result = await sqlite3.step(stmt);
172+
if (result === SQLite.SQLITE_DONE) {
173+
//The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
174+
affectedRows += sqlite3.changes(db);
175+
}
176+
177+
sqlite3.reset(stmt);
170178
}
171179
}
172-
//Finalize prepared statement
173-
await sqlite3.finalize(prepared.stmt);
180+
174181
await executeSingleStatement('COMMIT');
175182
} catch (err) {
176183
await executeSingleStatement('ROLLBACK');
177184
return {
178185
rowsAffected: 0,
179186
rows: { _array: [], length: 0 }
180187
};
181-
} finally {
182-
sqlite3.str_finish(str);
183188
}
184189
const result = {
185190
rowsAffected: affectedRows,

0 commit comments

Comments
 (0)