@@ -532,6 +532,50 @@ export function Factory(Module) {
532532 } ;
533533 } ) ( ) ;
534534
535+ sqlite3 . register_table_onchange_hook = function ( db , callback ) {
536+ // Register hooks for this DB as a global hook
537+ // It will call the global handler above
538+ Module . ccall ( 'register_table_update_hook' , 'int' , [ 'number' ] , [ db ] ) ;
539+
540+ onTableChangeCallbacks [ db ] = function ( opType , tableNamePtr , rowId ) {
541+ // Need to get the string from the pointer
542+ // const tableName = Module.UTF8ToString(Module.getValue(tableNamePtr, '*'));
543+ const memory = new DataView ( Module . HEAPU8 . buffer ) ;
544+
545+ // Find the null terminator to determine the string length
546+ let length = 0 ;
547+ while ( memory . getUint8 ( tableNamePtr + length ) !== 0 ) {
548+ length ++ ;
549+ }
550+
551+ // Extract the string content
552+ const stringBytes = new Uint8Array ( Module . HEAPU8 . buffer , tableNamePtr , length ) ;
553+ const tableName = new TextDecoder ( ) . decode ( stringBytes ) ;
554+
555+ /**
556+ * Call the callback inside a setTimeout to avoid blocking SQLite.
557+ * We use a setTimeout only after fetching data from the heap to avoid
558+ * accessing memory which has been freed.
559+ */
560+ setTimeout ( ( ) => callback ( opType , tableName , rowId ) , 0 )
561+ } ;
562+ } ;
563+
564+ sqlite3 . prepare_v2 = ( function ( ) {
565+ const fname = 'sqlite3_prepare_v2' ;
566+ const f = Module . cwrap ( fname , ...decl ( 'nnnnn:n' ) , { async } ) ;
567+ return async function ( db , sql ) {
568+ const result = await f ( db , sql , - 1 , tmpPtr [ 0 ] , tmpPtr [ 1 ] ) ;
569+ check ( fname , result , db ) ;
570+
571+ const stmt = Module . getValue ( tmpPtr [ 0 ] , '*' ) ;
572+ if ( stmt ) {
573+ mapStmtToDB . set ( stmt , db ) ;
574+ return { stmt, sql : Module . getValue ( tmpPtr [ 1 ] , '*' ) } ;
575+ }
576+ return null ;
577+ } ;
578+ } ) ( ) ;
535579
536580 sqlite3 . progress_handler = function ( db , nProgressOps , handler , userData ) {
537581 verifyDatabase ( db ) ;
0 commit comments