@@ -176,6 +176,10 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
176176 var SQLITE_BLOB = 4 ;
177177 // var - Encodings, used for registering functions.
178178 var SQLITE_UTF8 = 1 ;
179+ // var - Authorizer Action Codes used to identify change types in updateHook
180+ var SQLITE_INSERT = 18 ;
181+ var SQLITE_UPDATE = 23 ;
182+ var SQLITE_DELETE = 9 ;
179183 // var - cwrap function
180184 var sqlite3_open = cwrap ( "sqlite3_open" , "number" , [ "string" , "number" ] ) ;
181185 var sqlite3_close_v2 = cwrap ( "sqlite3_close_v2" , "number" , [ "number" ] ) ;
@@ -344,6 +348,12 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
344348 [ "number" ]
345349 ) ;
346350
351+ var sqlite3_update_hook = cwrap (
352+ "sqlite3_update_hook" ,
353+ "number" ,
354+ [ "number" , "number" , "number" ]
355+ ) ;
356+
347357 /**
348358 * @classdesc
349359 * Represents a prepared statement.
@@ -1219,6 +1229,12 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
12191229 } ) ;
12201230 Object . values ( this . functions ) . forEach ( removeFunction ) ;
12211231 this . functions = { } ;
1232+
1233+ if ( this . updateHookFunctionPtr ) {
1234+ removeFunction ( this . updateHookFunctionPtr ) ;
1235+ this . updateHookFunctionPtr = undefined ;
1236+ }
1237+
12221238 this . handleError ( sqlite3_close_v2 ( this . db ) ) ;
12231239 FS . unlink ( "/" + this . filename ) ;
12241240 this . db = null ;
@@ -1488,6 +1504,87 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
14881504 return this ;
14891505 } ;
14901506
1507+ /** Registers the update hook with SQLite
1508+ @param {function(operation, database, table, rowId) | null } callback
1509+ executed whenever a row in any rowid table is changed
1510+
1511+ For each changed row, the callback is called once with the change
1512+ ('insert', 'update' or 'delete'), the database name and table name
1513+ where the change happened and the rowid of the row that has been
1514+ changed.
1515+
1516+ rowid is cast to a plain number, if it exceeds Number.MAX_SAFE_INTEGER
1517+ an error will be thrown.
1518+
1519+ The callback MUST NOT modify the database in any way.
1520+
1521+ Only a single callback can be registered. Unregister the callback by
1522+ passing null.
1523+
1524+ Not called for some updates like ON REPLACE CONFLICT and TRUNCATE (a
1525+ DELETE FROM without a WHERE clause).
1526+
1527+ See sqlite docs on sqlite3_update_hook for more details.
1528+ */
1529+ Database . prototype [ "updateHook" ] = function updateHook ( callback ) {
1530+ if ( this . updateHookFunctionPtr ) {
1531+ // unregister and cleanup a previously registered update hook
1532+ sqlite3_update_hook ( this . db , 0 , 0 ) ;
1533+ removeFunction ( this . updateHookFunctionPtr ) ;
1534+ this . updateHookFunctionPtr = undefined ;
1535+ }
1536+
1537+ if ( ! callback ) {
1538+ // no new callback to register
1539+ return ;
1540+ }
1541+
1542+ // void(*)(void *,int ,char const *,char const *,sqlite3_int64)
1543+ function wrappedCallback (
1544+ ignored ,
1545+ operationCode ,
1546+ databaseNamePtr ,
1547+ tableNamePtr ,
1548+ rowIdBigInt
1549+ ) {
1550+ var operation ;
1551+
1552+ switch ( operationCode ) {
1553+ case SQLITE_INSERT :
1554+ operation = "insert" ;
1555+ break ;
1556+ case SQLITE_UPDATE :
1557+ operation = "update" ;
1558+ break ;
1559+ case SQLITE_DELETE :
1560+ operation = "delete" ;
1561+ break ;
1562+ default :
1563+ throw "unknown operationCode in updateHook callback: "
1564+ + operationCode ;
1565+ }
1566+
1567+ var databaseName = UTF8ToString ( databaseNamePtr ) ;
1568+ var tableName = UTF8ToString ( tableNamePtr ) ;
1569+
1570+ if ( rowIdBigInt > Number . MAX_SAFE_INTEGER ) {
1571+ throw "rowId too big to fit inside a Number" ;
1572+ }
1573+
1574+ var rowId = Number ( rowIdBigInt ) ;
1575+
1576+ callback ( operation , databaseName , tableName , rowId ) ;
1577+ }
1578+
1579+ this . updateHookFunctionPtr = addFunction ( wrappedCallback , "viiiij" ) ;
1580+
1581+ sqlite3_update_hook (
1582+ this . db ,
1583+ this . updateHookFunctionPtr ,
1584+ 0 // passed as the first arg to wrappedCallback
1585+ ) ;
1586+ } ;
1587+
14911588 // export Database to Module
14921589 Module . Database = Database ;
14931590} ;
@@ -6443,6 +6540,7 @@ var _sqlite3_normalized_sql = Module['_sqlite3_normalized_sql'] = createExportWr
64436540var _sqlite3_changes = Module [ '_sqlite3_changes' ] = createExportWrapper ( 'sqlite3_changes' , 1 ) ;
64446541var _sqlite3_close_v2 = Module [ '_sqlite3_close_v2' ] = createExportWrapper ( 'sqlite3_close_v2' , 1 ) ;
64456542var _sqlite3_create_function_v2 = Module [ '_sqlite3_create_function_v2' ] = createExportWrapper ( 'sqlite3_create_function_v2' , 9 ) ;
6543+ var _sqlite3_update_hook = Module [ '_sqlite3_update_hook' ] = createExportWrapper ( 'sqlite3_update_hook' , 3 ) ;
64466544var _sqlite3_open = Module [ '_sqlite3_open' ] = createExportWrapper ( 'sqlite3_open' , 2 ) ;
64476545var _strerror = createExportWrapper ( 'strerror' , 1 ) ;
64486546var _malloc = Module [ '_malloc' ] = createExportWrapper ( 'malloc' , 1 ) ;
0 commit comments