Skip to content

Commit c52828e

Browse files
enable table update hooks. using force!
1 parent bf24e5e commit c52828e

File tree

3 files changed

+68
-45
lines changed

3 files changed

+68
-45
lines changed

packages/dev-adapter/src/SQLJSAdapter.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
BaseListener,
23
BaseObserver,
34
BatchedUpdateNotification,
45
DBAdapter,
@@ -30,10 +31,29 @@ export class SQLJSOpenFactory implements SQLOpenFactory {
3031
}
3132
}
3233

34+
(globalThis as any).onSqliteUpdate = (
35+
dbP: number,
36+
operation: string,
37+
database: string,
38+
table: string,
39+
rowId: number
40+
) => {
41+
SQLJSDBAdapter.sharedObserver.iterateListeners((l) => l.tablesUpdated?.(dbP, operation, database, table, rowId));
42+
};
43+
44+
interface TableObserverListener extends BaseListener {
45+
tablesUpdated?: (dpP: number, operation: string, database: string, table: string, rowId: number) => void;
46+
}
47+
class TableObserver extends BaseObserver<TableObserverListener> {}
48+
3349
export class SQLJSDBAdapter extends BaseObserver<DBAdapterListener> implements DBAdapter {
3450
protected initPromise: Promise<SQLJs.Database>;
3551
protected _db: SQLJs.Database | null;
3652
protected tableUpdateCache: Set<string>;
53+
protected dbP: number | null;
54+
55+
static sharedObserver = new TableObserver();
56+
protected disposeListener: () => void;
3757

3858
protected mutex: Mutex;
3959

@@ -51,14 +71,33 @@ export class SQLJSDBAdapter extends BaseObserver<DBAdapterListener> implements D
5171
this._db = null;
5272
this.tableUpdateCache = new Set<string>();
5373
this.mutex = new Mutex();
74+
this.dbP = null;
75+
this.disposeListener = SQLJSDBAdapter.sharedObserver.registerListener({
76+
tablesUpdated: (dbP: number, operation: string, database: string, table: string, rowId: number) => {
77+
if (this.dbP !== dbP) {
78+
// Ignore updates from other databases.
79+
return;
80+
}
81+
this.tableUpdateCache.add(table);
82+
}
83+
});
5484
}
5585

5686
protected async init(): Promise<SQLJs.Database> {
5787
console.log('Initializing SQL.js database with options');
58-
const SQL = await SQLJs({ locateFile: (filename: any) => `../dist/${filename}` });
88+
const SQL = await SQLJs({
89+
locateFile: (filename: any) => `../dist/${filename}`,
90+
print: (text) => {
91+
console.log('[stdout]', text);
92+
},
93+
printErr: (text) => {
94+
console.warn('[stderr]', text);
95+
}
96+
});
5997
console.log('SQL.js loaded:');
6098
const existing = await this.options.persister.readFile();
6199
const db = new SQL.Database(existing);
100+
this.dbP = db['db'];
62101
// debugger;
63102
// (db as any).updateHook(function (operation, database, table, rowId) {
64103
// console.log(`Update Hook: ${operation} on ${table}`);
@@ -70,6 +109,7 @@ export class SQLJSDBAdapter extends BaseObserver<DBAdapterListener> implements D
70109

71110
async close() {
72111
const db = await this.getDB();
112+
this.disposeListener();
73113
db.close();
74114
}
75115

packages/sqljs/patches/powersync-update.patch

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,34 @@
11
diff --git a/src/update.c b/src/update.c
22
new file mode 100644
3-
index 0000000..a025f71
3+
index 0000000..c7e8a23
44
--- /dev/null
55
+++ b/src/update.c
6-
@@ -0,0 +1,24 @@
7-
+#include "sqlite3.h"
6+
@@ -0,0 +1,28 @@
7+
+#include "sqlite3ext.h"
8+
+SQLITE_EXTENSION_INIT1
9+
+
810
+#include <emscripten.h>
11+
+#include <stdio.h>
12+
+#include <stdint.h>
913
+
10-
+// Declare a JS function to be callable from C
11-
+// JS hook only receives type, db name, and table name
12-
+EM_JS(void, call_js_update_hook, (int type, const char* db_name, const char* table_name), {
13-
+ console.log('update from sqlite hook');
14+
+EM_JS(void, call_js_update_hook, (int db_p, int type, const char* db_name, const char* table_name), {
1415
+ if (typeof onSqliteUpdate === "function") {
15-
+ onSqliteUpdate(type, UTF8ToString(db_name), UTF8ToString(table_name));
16+
+ onSqliteUpdate(db_p, type, UTF8ToString(db_name), UTF8ToString(table_name));
1617
+ } else {
1718
+ console.error("onSqliteUpdate is not defined");
1819
+ }
1920
+});
2021
+
21-
+void EMSCRIPTEN_KEEPALIVE sqlite_update_callback(void* pArg, int type, const char* db, const char* table, sqlite3_int64 rowid) {
22-
+ EM_ASM({ console.log("got an update"); });
23-
+ call_js_update_hook(type, db, table);
22+
+static void sqlite_update_callback(void* pArg, int type, const char* db, const char* table, sqlite3_int64 rowid) {
23+
+ call_js_update_hook((int)(intptr_t)pArg, type, db, table);
24+
+}
25+
+
26+
+static int register_update_hook_on_open(sqlite3* db, const char** pzErrMsg, const sqlite3_api_routines* pApi) {
27+
+ SQLITE_EXTENSION_INIT2(pApi);
28+
+ sqlite3_update_hook(db, sqlite_update_callback, db);
29+
+ return SQLITE_OK;
2430
+}
2531
+
26-
+// Attach this to a sqlite3* connection:
27-
+void EMSCRIPTEN_KEEPALIVE register_sqlite_update_hook(sqlite3* db) {
28-
+ EM_ASM({ console.log("register_sqlite_update_hook: OK"); });
29-
+ sqlite3_update_hook(db, sqlite_update_callback, NULL);
32+
+void register_update_hook_extension(void) {
33+
+ sqlite3_auto_extension((void(*)(void))register_update_hook_on_open);
3034
+}
31-
\ No newline at end of file

packages/sqljs/patches/powersync.patch

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -86,49 +86,29 @@ index 4530653..5ac01a0 100644
8686
clean:
8787
rm -f out/* dist/* cache/*
8888
diff --git a/src/api.js b/src/api.js
89-
index c7f102b..df7e901 100644
89+
index c7f102b..4c20316 100644
9090
--- a/src/api.js
9191
+++ b/src/api.js
92-
@@ -72,6 +72,8 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
92+
@@ -72,6 +72,10 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
9393
var SQLITE_UPDATE = 23;
9494
var SQLITE_DELETE = 9;
9595
// var - cwrap function
9696
+ Module['ccall']('powersync_init_static', 'int', []);
97+
+ Module['ccall']('register_update_hook_extension', 'void', []);
98+
+
9799
+
98100
var sqlite3_open = cwrap("sqlite3_open", "number", ["string", "number"]);
99101
var sqlite3_close_v2 = cwrap("sqlite3_close_v2", "number", ["number"]);
100102
var sqlite3_exec = cwrap(
101-
@@ -122,6 +124,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
103+
@@ -122,6 +126,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
102104
"number",
103105
["number", "string"]
104106
);
105107
+ var sqlite3_last_insert_rowid = cwrap("sqlite3_last_insert_rowid", "number", ["number"]);
106108
var sqlite3_step = cwrap("sqlite3_step", "number", ["number"]);
107109
var sqlite3_errmsg = cwrap("sqlite3_errmsg", "string", ["number"]);
108110
var sqlite3_column_count = cwrap(
109-
@@ -239,6 +242,12 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
110-
["number"]
111-
);
112-
113-
+ var registerUpdateHook = cwrap(
114-
+ "register_sqlite_update_hook",
115-
+ "void",
116-
+ ["number"]
117-
+ );
118-
+
119-
var sqlite3_update_hook = cwrap(
120-
"sqlite3_update_hook",
121-
"number",
122-
@@ -833,6 +842,8 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
123-
}
124-
this.handleError(sqlite3_open(this.filename, apiTemp));
125-
this.db = getValue(apiTemp, "i32");
126-
+ registerUpdateHook(this.db)
127-
+ // Module['ccall']('register_sqlite_update_hook', 'void', ['number'], [apiTemp]);
128-
registerExtensionFunctions(this.db);
129-
// A list of all prepared statements of the database
130-
this.statements = {};
131-
@@ -1155,6 +1166,13 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
111+
@@ -1155,6 +1160,13 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
132112
return sqlite3_changes(this.db);
133113
};
134114

@@ -143,7 +123,7 @@ index c7f102b..df7e901 100644
143123
var size = sqlite3_value_bytes(ptr);
144124
var blob_ptr = sqlite3_value_blob(ptr);
145125
diff --git a/src/exported_functions.json b/src/exported_functions.json
146-
index 3be2595..d1c0037 100644
126+
index 3be2595..709bc5c 100644
147127
--- a/src/exported_functions.json
148128
+++ b/src/exported_functions.json
149129
@@ -1,47 +1,50 @@
@@ -240,7 +220,7 @@ index 3be2595..d1c0037 100644
240220
+ "_sqlite3_last_insert_rowid",
241221
+ "_sqlite3_update_hook",
242222
+ "_powersync_init_static",
243-
+ "_register_sqlite_update_hook"
223+
+ "_register_update_hook_extension"
244224
]
245225
diff --git a/src/exported_runtime_methods.json b/src/exported_runtime_methods.json
246226
index f099056..b1712fc 100644

0 commit comments

Comments
 (0)