@@ -71,6 +71,10 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
71
71
var SQLITE_BLOB = 4 ;
72
72
// var - Encodings, used for registering functions.
73
73
var SQLITE_UTF8 = 1 ;
74
+ // var - Authorizer Action Codes used to identify change types in updateHook
75
+ var SQLITE_INSERT = 18 ;
76
+ var SQLITE_UPDATE = 23 ;
77
+ var SQLITE_DELETE = 9 ;
74
78
// var - cwrap function
75
79
var sqlite3_open = cwrap ( "sqlite3_open" , "number" , [ "string" , "number" ] ) ;
76
80
var sqlite3_close_v2 = cwrap ( "sqlite3_close_v2" , "number" , [ "number" ] ) ;
@@ -239,6 +243,12 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
239
243
[ "number" ]
240
244
) ;
241
245
246
+ var sqlite3_update_hook = cwrap (
247
+ "sqlite3_update_hook" ,
248
+ "number" ,
249
+ [ "number" , "number" , "number" ]
250
+ ) ;
251
+
242
252
/**
243
253
* @classdesc
244
254
* Represents a prepared statement.
@@ -1383,6 +1393,76 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
1383
1393
return this ;
1384
1394
} ;
1385
1395
1396
+ /** Registers the update hook with SQLite
1397
+ @param {function(operation, tableName, rowId) } callback
1398
+ executed whenever a row in any rowid table is changed
1399
+
1400
+ For each changed row, the callback is called once with the change
1401
+ ('insert', 'update' or 'delete'), the table name where the change
1402
+ happened and the rowid of the row that has been changed.
1403
+
1404
+ rowid is cast to a plain number, if it exceeds Number.MAX_SAFE_INTEGER
1405
+ an error will be thrown.
1406
+
1407
+ The callback MUST NOT modify the database in any way.
1408
+
1409
+ Only a single callback can be registered. Unregister the callback by
1410
+ passing an empty function.
1411
+
1412
+ Not called for some updates like ON REPLACE CONFLICT and TRUNCATE.
1413
+
1414
+ See sqlite docs on sqlite3_update_hook for more details.
1415
+ */
1416
+ Database . prototype [ "updateHook" ] = function updateHook ( callback ) {
1417
+ this . updateHookCallback = callback ;
1418
+
1419
+ // void(*)(void *,int ,char const *,char const *,sqlite3_int64)
1420
+ function wrappedCallback (
1421
+ ignored ,
1422
+ operationCode ,
1423
+ databaseNamePtr ,
1424
+ tableNamePtr ,
1425
+ rowIdBigInt
1426
+ ) {
1427
+ var operation ;
1428
+
1429
+ switch ( operationCode ) {
1430
+ case SQLITE_INSERT :
1431
+ operation = "insert" ;
1432
+ break ;
1433
+ case SQLITE_UPDATE :
1434
+ operation = "update" ;
1435
+ break ;
1436
+ case SQLITE_DELETE :
1437
+ operation = "delete" ;
1438
+ break ;
1439
+ default :
1440
+ throw "unknown operationCode in updateHook callback: "
1441
+ + operationCode ;
1442
+ }
1443
+
1444
+ var tableName = UTF8ToString ( tableNamePtr ) ;
1445
+
1446
+ if ( rowIdBigInt > Number . MAX_SAFE_INTEGER ) {
1447
+ throw "rowId too big to fit inside a Number" ;
1448
+ }
1449
+
1450
+ var rowId = Number ( rowIdBigInt ) ;
1451
+
1452
+ if ( this . updateHookCallback ) {
1453
+ this . updateHookCallback ( operation , tableName , rowId ) ;
1454
+ }
1455
+ }
1456
+
1457
+ var funcPtr = addFunction ( wrappedCallback . bind ( this ) , "viiiij" ) ;
1458
+
1459
+ this . handleError ( sqlite3_update_hook (
1460
+ this . db ,
1461
+ funcPtr ,
1462
+ 0 // passed as the first arg to wrappedCallback
1463
+ ) ) ;
1464
+ } ;
1465
+
1386
1466
// export Database to Module
1387
1467
Module . Database = Database ;
1388
1468
} ;
0 commit comments