1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Expose sqlite3_preupdate_hook() and friends to the JS API.

FossilOrigin-Name: cc02783a1210a083683320fae1ec1519e45b8e3003a9e32809d808513a2ce06b
This commit is contained in:
stephan
2022-12-27 14:34:32 +00:00
parent 4e013284a0
commit 294968e030
6 changed files with 137 additions and 24 deletions

View File

@ -79,6 +79,12 @@ _sqlite3_open_v2
_sqlite3_overload_function _sqlite3_overload_function
_sqlite3_prepare_v2 _sqlite3_prepare_v2
_sqlite3_prepare_v3 _sqlite3_prepare_v3
_sqlite3_preupdate_blobwrite
_sqlite3_preupdate_count
_sqlite3_preupdate_depth
_sqlite3_preupdate_hook
_sqlite3_preupdate_new
_sqlite3_preupdate_old
_sqlite3_progress_handler _sqlite3_progress_handler
_sqlite3_randomness _sqlite3_randomness
_sqlite3_realloc _sqlite3_realloc

View File

@ -338,6 +338,26 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
["sqlite3_malloc64", "*","i64"], ["sqlite3_malloc64", "*","i64"],
["sqlite3_msize", "i64", "*"], ["sqlite3_msize", "i64", "*"],
["sqlite3_overload_function", "int", ["sqlite3*","string","int"]], ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]],
["sqlite3_preupdate_blobwrite", "int", "sqlite3*"],
["sqlite3_preupdate_count", "int", "sqlite3*"],
["sqlite3_preupdate_depth", "int", "sqlite3*"],
["sqlite3_preupdate_hook", "*", [
"sqlite3*",
new wasm.xWrap.FuncPtrAdapter({
name: 'sqlite3_preupdate_hook',
signature: "v(ppippjj)",
contextKey: (argv)=>argv[0/* sqlite3* */],
callProxy: (callback)=>{
return (p,db,op,zDb,zTbl,iKey1,iKey2)=>{
callback(p, db, op, wasm.cstrToJs(zDb), wasm.cstrToJs(zTbl),
iKey1, iKey2);
};
}
}),
"*"
]],
["sqlite3_preupdate_new", "int", ["sqlite3*", "int", "**"]],
["sqlite3_preupdate_old", "int", ["sqlite3*", "int", "**"]],
["sqlite3_realloc64", "*","*", "i64"], ["sqlite3_realloc64", "*","*", "i64"],
["sqlite3_result_int64", undefined, "*", "i64"], ["sqlite3_result_int64", undefined, "*", "i64"],
["sqlite3_result_zeroblob64", "int", "*", "i64"], ["sqlite3_result_zeroblob64", "int", "*", "i64"],
@ -895,7 +915,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
Intended to be called _only_ from sqlite3_close_v2(), Intended to be called _only_ from sqlite3_close_v2(),
passed its non-0 db argument. passed its non-0 db argument.
This function freees up certain automatically-installed WASM This function frees up certain automatically-installed WASM
function bindings which were installed on behalf of the given db, function bindings which were installed on behalf of the given db,
as those may otherwise leak. as those may otherwise leak.
@ -914,7 +934,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
*/ */
__dbCleanupMap.cleanup = function(pDb){ __dbCleanupMap.cleanup = function(pDb){
pDb = __argPDb(pDb); pDb = __argPDb(pDb);
wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false; //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
/** /**
Installing NULL functions in the C API will remove those Installing NULL functions in the C API will remove those
bindings. The FuncPtrAdapter which sits between us and the C bindings. The FuncPtrAdapter which sits between us and the C
@ -922,13 +942,26 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
wasm.uninstallFunction() any WASM function bindings it has wasm.uninstallFunction() any WASM function bindings it has
installed for pDb. installed for pDb.
*/ */
try{capi.sqlite3_busy_handler(pDb, 0, 0)} catch(e){/*ignored*/} const closeArgs = [pDb];
try{capi.sqlite3_commit_hook(pDb, 0, 0)} catch(e){/*ignored*/} for(const name of [
try{capi.sqlite3_progress_handler(pDb, 0, 0, 0)} catch(e){/*ignored*/} 'sqlite3_busy_handler',
try{capi.sqlite3_rollback_hook(pDb, 0, 0)} catch(e){/*ignored*/} 'sqlite3_commit_hook',
try{capi.sqlite3_set_authorizer(pDb, 0, 0)} catch(e){/*ignored*/} 'sqlite3_preupdate_hook',
try{capi.sqlite3_trace_v2(pDb, 0, 0, 0, 0)} catch(e){/*ignored*/} 'sqlite3_progress_handler',
try{capi.sqlite3_update_hook(pDb, 0, 0)} catch(e){/*ignored*/} 'sqlite3_rollback_hook',
'sqlite3_set_authorizer',
'sqlite3_trace_v2',
'sqlite3_update_hook'
]) {
const x = wasm.exports[name];
closeArgs.length = x.length/*==argument count*/
/* recall that undefined entries translate to 0 when passed to
WASM. */;
try{ capi[name](...closeArgs) }
catch(e){
console.warn("close-time call of",name+"(",closeArgs,") threw:",e);
}
}
const m = __dbCleanupMap(pDb, 0); const m = __dbCleanupMap(pDb, 0);
if(!m) return; if(!m) return;
if(m.collation){ if(m.collation){

View File

@ -139,7 +139,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
main thread (aborts via a failed assert() if it's attempted), main thread (aborts via a failed assert() if it's attempted),
which eliminates any(?) benefit to supporting it. */ false; which eliminates any(?) benefit to supporting it. */ false;
/** /**
The main sqlite3 binding API gets installed into this object, The main sqlite3 binding API gets installed into this object,
mimicking the C API as closely as we can. The numerous members mimicking the C API as closely as we can. The numerous members
names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as
@ -1779,6 +1779,36 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
return (0===v) ? undefined : capi.sqlite3_value_to_js(v, throwIfCannotConvert); return (0===v) ? undefined : capi.sqlite3_value_to_js(v, throwIfCannotConvert);
}; };
/**
Internal impl of sqlite3_preupdate_new_js() and
sqlite3_preupdate_old_js().
*/
const __preupdateNewOld = function(pDb, iCol, impl){
impl = capi[impl];
if(!this.ptr) this.ptr = wasm.allocPtr();
else wasm.pokePtr(this.ptr, 0);
const rc = impl(pDb, iCol, this.ptr);
return rc
? SQLite3Error.toss(rc,arguments[2]+"() failed with code "+rc)
: capi.sqlite3_value_to_js( wasm.peekPtr(this.ptr), true );
}.bind(Object.create(null));
/**
A wrapper around sqlite3_preupdate_new() which fetches the
sqlite3_value at the given index and returns the result of
passing it to sqlite3_value_to_js(). Throws on error.
*/
capi.sqlite3_preupdate_new_js =
(pDb, iCol)=>__preupdateNewOld(pDb, iCol, 'sqlite3_preupdate_new');
/**
A wrapper around sqlite3_preupdate_old() which fetches the
sqlite3_value at the given index and returns the result of
passing it to sqlite3_value_to_js(). Throws on error.
*/
capi.sqlite3_preupdate_old_js =
(pDb, iCol)=>__preupdateNewOld(pDb, iCol, 'sqlite3_preupdate_old');
/* The remainder of the API will be set up in later steps. */ /* The remainder of the API will be set up in later steps. */
const sqlite3 = { const sqlite3 = {
WasmAllocError: WasmAllocError, WasmAllocError: WasmAllocError,

View File

@ -2690,7 +2690,7 @@ self.sqlite3InitModule = sqlite3InitModule;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
T.g('Hook APIs') T.g('Hook APIs')
.t({ .t({
name: "Commit/rollback/update hooks", name: "sqlite3_commit/rollback/update_hook()",
predicate: ()=>wasm.bigIntEnabled || "Update hook requires int64", predicate: ()=>wasm.bigIntEnabled || "Update hook requires int64",
test: function(sqlite3){ test: function(sqlite3){
let countCommit = 0, countRollback = 0;; let countCommit = 0, countRollback = 0;;
@ -2746,7 +2746,7 @@ self.sqlite3InitModule = sqlite3InitModule;
case capi.SQLITE_DELETE: case capi.SQLITE_DELETE:
countUpdate[op] = (countUpdate[op]||0) + 1; countUpdate[op] = (countUpdate[op]||0) + 1;
break; break;
default: return; default: toss("Unexpected hook operator:",op);
} }
}, 3); }, 3);
db.transaction((d)=>{ db.transaction((d)=>{
@ -2770,7 +2770,51 @@ self.sqlite3InitModule = sqlite3InitModule;
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false; //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
db.close(); db.close();
} }
}); })/* commit/rollback/update hooks */
.t({
name: "sqlite3_preupdate_hook()",
predicate: ()=>wasm.bigIntEnabled || "Pre-update hook requires int64",
test: function(sqlite3){
const db = new sqlite3.oo1.DB(':memory:', 1 ? 'c' : 'ct');
const countHook = Object.create(null);
let rc = capi.sqlite3_preupdate_hook(
db, function(p, pDb, op, zDb, zTbl, iKey1, iKey2){
T.assert(9 === p)
.assert(db.pointer === pDb)
.assert(1 === capi.sqlite3_preupdate_count(pDb))
.assert( 0 > capi.sqlite3_preupdate_blobwrite(pDb) );
countHook[op] = (countHook[op]||0) + 1;
switch(op){
case capi.SQLITE_INSERT:
case capi.SQLITE_UPDATE:
T.assert('number' === typeof capi.sqlite3_preupdate_new_js(pDb, 0));
break;
case capi.SQLITE_DELETE:
T.assert('number' === typeof capi.sqlite3_preupdate_old_js(pDb, 0));
break;
default: toss("Unexpected hook operator:",op);
}
},
9
);
db.transaction((d)=>{
d.exec([
"create table t(a);",
"insert into t(a) values(1);",
"update t set a=2;",
"update t set a=3;",
"delete from t where a=3"
]);
});
T.assert(1 === countHook[capi.SQLITE_INSERT])
.assert(2 === countHook[capi.SQLITE_UPDATE])
.assert(1 === countHook[capi.SQLITE_DELETE]);
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
db.close();
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
}
})/*pre-update hooks*/
;/*end hook API tests*/
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
T.g('Auto-extension API') T.g('Auto-extension API')

View File

@ -1,5 +1,5 @@
C Fix\sa\smissing\s0\sat\sthe\send\sof\san\sinteger\sliteral\sin\scheck-in\s[8da0f0c38a458c57] C Expose\ssqlite3_preupdate_hook()\sand\sfriends\sto\sthe\sJS\sAPI.
D 2022-12-27T14:03:04.522 D 2022-12-27T14:34:32.202
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -494,7 +494,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
F ext/wasm/GNUmakefile ffe0e9818a3b6b36c85a1d10dab76b220a8f5cd83439c62e50223a7970b3d68a F ext/wasm/GNUmakefile ffe0e9818a3b6b36c85a1d10dab76b220a8f5cd83439c62e50223a7970b3d68a
F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20 F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9 F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 445ae63749f47c50c251de53388ca2d1247f06b62f71289d3d2b9c3cee014575 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54 F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d
@ -503,9 +503,9 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f 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-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
F ext/wasm/api/sqlite3-api-glue.js 7d619834cc0d378e9f46afc1eab0587f8f097944936aff5723da7243f36bc787 F ext/wasm/api/sqlite3-api-glue.js a5f68e5cd6fe91528a10fe925c75c980440e4dcd02ef1db13a5eaa9c840a301b
F ext/wasm/api/sqlite3-api-oo1.js e9fba119e9b1716b3f731838ed1ab18741401bcf4c51d2a4a6e9d1d23cf9d771 F ext/wasm/api/sqlite3-api-oo1.js e9fba119e9b1716b3f731838ed1ab18741401bcf4c51d2a4a6e9d1d23cf9d771
F ext/wasm/api/sqlite3-api-prologue.js e862e5b79d565bd79c8ff59ebb6618a07ecb1a0262a1560dc6a10aa0f4d6f531 F ext/wasm/api/sqlite3-api-prologue.js c53a482a38113d965914890cb8ab6f4c901558cc44c2073577e8f7fa2b28f269
F ext/wasm/api/sqlite3-api-worker1.js c9ef8865f072e61251260b218aa4ed614a21a25e9e3cc6f22acf81794d32fc0b F ext/wasm/api/sqlite3-api-worker1.js c9ef8865f072e61251260b218aa4ed614a21a25e9e3cc6f22acf81794d32fc0b
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3 F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9 F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406 F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
F ext/wasm/tester1.c-pp.js e5c0d9d9b4e2ce32764dd4c77a13babc3fd6fcb14b6e068deb072da0a3e43ed8 F ext/wasm/tester1.c-pp.js 7786fa3bdf074be8935e3a77b1ca135fd36ef6f87823c0695deaca585b133d06
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70 F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 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.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P ff5a9b054f4d5ad3d33787aee93b4181822c6dfc513626236d9867bb431f64da P e3776796f55574f357eb429e20399389092a68e9ca00aa104ed33eb559ae0de5
R f92681d8d01e129072904a73edd86d3a R d834976b54fd785cca19e8460af50575
U drh U stephan
Z 8530f7f2ef51d599626e5ba8501c27e4 Z ac4d1df745aa91809b44c04961ee6a48
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
e3776796f55574f357eb429e20399389092a68e9ca00aa104ed33eb559ae0de5 cc02783a1210a083683320fae1ec1519e45b8e3003a9e32809d808513a2ce06b