@@ -71,6 +71,10 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
7171 var SQLITE_BLOB = 4 ;
7272 // var - Encodings, used for registering functions.
7373 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 ;
7478 // var - cwrap function
7579 var sqlite3_open = cwrap ( "sqlite3_open" , "number" , [ "string" , "number" ] ) ;
7680 var sqlite3_close_v2 = cwrap ( "sqlite3_close_v2" , "number" , [ "number" ] ) ;
@@ -239,6 +243,12 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
239243 [ "number" ]
240244 ) ;
241245
246+ var sqlite3_update_hook = cwrap (
247+ "sqlite3_update_hook" ,
248+ "number" ,
249+ [ "number" , "number" , "number" ]
250+ ) ;
251+
242252 /**
243253 * @classdesc
244254 * Represents a prepared statement.
@@ -1383,6 +1393,76 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
13831393 return this ;
13841394 } ;
13851395
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+
13861466 // export Database to Module
13871467 Module . Database = Database ;
13881468} ;
0 commit comments