]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Expose sqlite3_commit/rollback/update_hook() to JS API.
authorstephan <stephan@noemail.net>
Tue, 27 Dec 2022 12:13:01 +0000 (12:13 +0000)
committerstephan <stephan@noemail.net>
Tue, 27 Dec 2022 12:13:01 +0000 (12:13 +0000)
FossilOrigin-Name: f99f8e3ecfe205337996ee61c0b9f139d3e8788b14f32e26560888b3a16564de

ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api
ext/wasm/api/sqlite3-api-glue.js
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid

index 8ba6e515c5e0bc611ffd23615619a5a205942898..93ab8b7950aab526a82fca0afb5a96b0c26cc779 100644 (file)
@@ -31,6 +31,7 @@ _sqlite3_column_name
 _sqlite3_column_text
 _sqlite3_column_type
 _sqlite3_column_value
+_sqlite3_commit_hook
 _sqlite3_compileoption_get
 _sqlite3_compileoption_used
 _sqlite3_complete
@@ -98,6 +99,7 @@ _sqlite3_result_subtype
 _sqlite3_result_text
 _sqlite3_result_zeroblob
 _sqlite3_result_zeroblob64
+_sqlite3_rollback_hook
 _sqlite3_serialize
 _sqlite3_set_authorizer
 _sqlite3_set_auxdata
@@ -120,6 +122,7 @@ _sqlite3_total_changes
 _sqlite3_total_changes64
 _sqlite3_trace_v2
 _sqlite3_txn_state
+_sqlite3_update_hook
 _sqlite3_uri_boolean
 _sqlite3_uri_int64
 _sqlite3_uri_key
index ddb4a58fa6ae3d3d3a9fb72b2a007680af180330..e8fe5aba6bd5003d85c025f46bdb27c80c56a25e 100644 (file)
@@ -103,6 +103,15 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     ["sqlite3_column_text","string", "sqlite3_stmt*", "int"],
     ["sqlite3_column_type","int", "sqlite3_stmt*", "int"],
     ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"],
+    ["sqlite3_commit_hook", "void*", [
+      "sqlite3*",
+      new wasm.xWrap.FuncPtrAdapter({
+        name: 'sqlite3_commit_hook',
+        signature: 'i(p)',
+        contextKey: (argv)=>argv[0/* sqlite3* */]
+      }),
+      '*'
+    ]],
     ["sqlite3_compileoption_get", "string", "int"],
     ["sqlite3_compileoption_used", "int", "string"],
     ["sqlite3_complete", "int", "string:flexible"],
@@ -206,6 +215,15 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"],
     ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"],
     ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"],
+    ["sqlite3_rollback_hook", "void*", [
+      "sqlite3*",
+      new wasm.xWrap.FuncPtrAdapter({
+        name: 'sqlite3_rollback_hook',
+        signature: 'v(p)',
+        contextKey: (argv)=>argv[0/* sqlite3* */]
+      }),
+      '*'
+    ]],
     ["sqlite3_set_authorizer", "int", [
       "sqlite3*",
       new wasm.xWrap.FuncPtrAdapter({
@@ -327,6 +345,20 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]],
     ["sqlite3_status64", "int", "int", "*", "*", "int"],
     ["sqlite3_total_changes64", "i64", ["sqlite3*"]],
+    ["sqlite3_update_hook", "*", [
+      "sqlite3*",
+      new wasm.xWrap.FuncPtrAdapter({
+        name: 'sqlite3_update_hook',
+        signature: "v(iippj)",
+        contextKey: (argv)=>argv[0/* sqlite3* */],
+        callProxy: (callback)=>{
+          return (p,op,z0,z1,rowid)=>{
+            callback(p, op, wasm.cstrToJs(z0), wasm.cstrToJs(z1), rowid);
+          };
+        }
+      }),
+      "*"
+    ]],
     ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]],
     ["sqlite3_value_int64","i64", "sqlite3_value*"],
     ["sqlite3_vtab_collation","string","sqlite3_index_info*","int"],
@@ -704,7 +736,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
           message = message || ''+resultCode;
           resultCode = (resultCode.resultCode || capi.SQLITE_ERROR);
         }
-        return __db_err(pDb, resultCode, message);
+        return pDb ? __db_err(pDb, resultCode, message) : resultCode;
       };
     }else{
       util.sqlite3_wasm_db_error = function(pDb,errCode,msg){
@@ -891,9 +923,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        installed for pDb.
     */
     try{capi.sqlite3_busy_handler(pDb, 0, 0)} catch(e){/*ignored*/}
+    try{capi.sqlite3_commit_hook(pDb, 0, 0)} catch(e){/*ignored*/}
     try{capi.sqlite3_progress_handler(pDb, 0, 0, 0)} catch(e){/*ignored*/}
-    try{capi.sqlite3_trace_v2(pDb, 0, 0, 0, 0)} catch(e){/*ignored*/}
+    try{capi.sqlite3_rollback_hook(pDb, 0, 0)} catch(e){/*ignored*/}
     try{capi.sqlite3_set_authorizer(pDb, 0, 0)} catch(e){/*ignored*/}
+    try{capi.sqlite3_trace_v2(pDb, 0, 0, 0, 0)} catch(e){/*ignored*/}
+    try{capi.sqlite3_update_hook(pDb, 0, 0)} catch(e){/*ignored*/}
     const m = __dbCleanupMap(pDb, 0);
     if(!m) return;
     if(m.collation){
index 7cb6c260ebf603d939af7002cd6330e8ded465ac..2f085650c5e6329f60b3653363349ceeae5cd0d7 100644 (file)
@@ -2687,6 +2687,88 @@ self.sqlite3InitModule = sqlite3InitModule;
     }/*OPFS util sanity checks*/)
   ;/* end OPFS tests */
 
+  ////////////////////////////////////////////////////////////////////////
+  T.g('Hook APIs')
+    .t({
+      name: "Commit/update/rollback hooks.",
+      predicate: ()=>wasm.bigIntEnabled || "Update hook requires int64",
+      test: function(sqlite3){
+        let countCommit = 0, countRollback = 0;;
+        const db = new sqlite3.oo1.DB(':memory:',1 ? 'c' : 'ct');
+        let rc = capi.sqlite3_commit_hook(db, (p)=>{
+          ++countCommit;
+          return (1 === p) ? 0 : capi.SQLITE_ERROR;
+        }, 1);
+        T.assert( 0 === rc /*void pointer*/ );
+
+        // Commit hook...
+        db.exec("BEGIN; SELECT 1; COMMIT");
+        T.assert(0 === countCommit,
+                 "No-op transactions (mostly) do not trigger commit hook.");
+        db.exec("BEGIN EXCLUSIVE; SELECT 1; COMMIT");
+        T.assert(1 === countCommit,
+                 "But EXCLUSIVE transactions do.");
+        db.transaction((d)=>{d.exec("create table t(a)");});
+        T.assert(2 === countCommit);
+
+        // Rollback hook:
+        rc = capi.sqlite3_rollback_hook(db, (p)=>{
+          ++countRollback;
+          T.assert( 2 === p );
+        }, 2);
+        T.assert( 0 === rc /*void pointer*/ );
+        T.mustThrowMatching(()=>{
+          db.transaction('drop table t',()=>{})
+        }, (e)=>{
+          return (capi.SQLITE_MISUSE === e.resultCode)
+            && ( e.message.indexOf('Invalid argument') > 0 );
+        });
+        T.assert(0 === countRollback, "Transaction was not started.");
+        T.mustThrowMatching(()=>{
+          db.transaction('immediate', ()=>{
+            sqlite3.SQLite3Error.toss(capi.SQLITE_FULL,'testing rollback hook');
+          });
+        }, (e)=>{
+          return capi.SQLITE_FULL === e.resultCode
+        });
+        T.assert(1 === countRollback);
+
+        // Update hook...
+        const countUpdate = Object.create(null);
+        capi.sqlite3_update_hook(db, (p,op,db,tbl,rowid)=>{
+          switch(op){
+              case capi.SQLITE_INSERT:
+              case capi.SQLITE_UPDATE:
+              case capi.SQLITE_DELETE:
+                countUpdate[op] = (countUpdate[op]||0) + 1;
+                break;
+              default: return;
+          }
+          T.assert(3===p).assert('bigint' === typeof rowid);
+        }, 3);
+        db.transaction((d)=>{
+          d.exec([
+            "insert into t(a) values(1);",
+            "update t set a=2;",
+            "update t set a=3;",
+            "delete from t where a=3"
+            // update hook is not called for an unqualified DELETE
+          ]);
+        });
+        T.assert(1 === countRollback)
+          .assert(3 === countCommit)
+          .assert(1 === countUpdate[capi.SQLITE_INSERT])
+          .assert(2 === countUpdate[capi.SQLITE_UPDATE])
+          .assert(1 === countUpdate[capi.SQLITE_DELETE]);
+        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
+        T.assert(1 === capi.sqlite3_commit_hook(db, 0, 0));
+        T.assert(2 === capi.sqlite3_rollback_hook(db, 0, 0));
+        T.assert(3 === capi.sqlite3_update_hook(db, 0, 0));
+        //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
+        db.close();
+      }
+    });
+
   ////////////////////////////////////////////////////////////////////////
   T.g('Auto-extension API')
     .t({
index 90f98310f7dc325de0102c57c3fc04ffa5725f5d..59b4ef7d55233dcf958ed0983780e5df2514ae10 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\san\soptional\sargument\sto\soo1.DB.transaction()\sto\sspecify\san\sexplicit\sBEGIN\squalifier.
-D 2022-12-27T11:40:05.031
+C Expose\ssqlite3_commit/rollback/update_hook()\sto\sJS\sAPI.
+D 2022-12-27T12:13:01.660
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -494,7 +494,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
 F ext/wasm/GNUmakefile ffe0e9818a3b6b36c85a1d10dab76b220a8f5cd83439c62e50223a7970b3d68a
 F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
 F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
-F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 1e61a3ff4085974080ecf782d4defea6b7d443eaa98f9aea773b5f5b416b417c
+F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 445ae63749f47c50c251de53388ca2d1247f06b62f71289d3d2b9c3cee014575
 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
 F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
 F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d
@@ -503,7 +503,7 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
 F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
 F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
-F ext/wasm/api/sqlite3-api-glue.js b55e13aadf33a037e9a6950f370d16e2b0e858b74a2070faa2c87d7cde48c80c
+F ext/wasm/api/sqlite3-api-glue.js 7d619834cc0d378e9f46afc1eab0587f8f097944936aff5723da7243f36bc787
 F ext/wasm/api/sqlite3-api-oo1.js e9fba119e9b1716b3f731838ed1ab18741401bcf4c51d2a4a6e9d1d23cf9d771
 F ext/wasm/api/sqlite3-api-prologue.js e862e5b79d565bd79c8ff59ebb6618a07ecb1a0262a1560dc6a10aa0f4d6f531
 F ext/wasm/api/sqlite3-api-worker1.js c9ef8865f072e61251260b218aa4ed614a21a25e9e3cc6f22acf81794d32fc0b
@@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
 F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
 F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
 F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
-F ext/wasm/tester1.c-pp.js 93e3ebae7f0caa1b54265447f76b0485d4a28799e02b7c2a3cc92883aa84fda6
+F ext/wasm/tester1.c-pp.js e183830a1c09e9535fea0f28ad8ed60049797d0461450e590f39e61aee48ae81
 F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
 F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 52b229d11d82bfb81c8b63e252c51c57a34dc50498dd685451588c185873c628
-R 907b947f3596b78852af2b253c74cbfb
+P 507335c12b1dbe21d180cf6f0a0deb4cc737417acb44c8f1d8fac98b86f62b01
+R 1861a6bdb0fe2e8302265dde3d3ce972
 U stephan
-Z 14582b10a3620eea75adde1bd5a1eeb7
+Z 65af223f5379fb35b8546fe3024152a5
 # Remove this line to create a well-formed Fossil manifest.
index a86e29ff1398131bf298d2459de5b6b0fa2e23b3..6fc68debea21dd949ccafe3fa232ac6d2346ef4b 100644 (file)
@@ -1 +1 @@
-507335c12b1dbe21d180cf6f0a0deb4cc737417acb44c8f1d8fac98b86f62b01
\ No newline at end of file
+f99f8e3ecfe205337996ee61c0b9f139d3e8788b14f32e26560888b3a16564de
\ No newline at end of file