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

Simplify the signature for JS functions, as opposed to function pointers, passed to sqlite3_exec(), eliminating the superfluous initial two arguments. Update related tests to demonstrate both function-passing approaches.

FossilOrigin-Name: e7cc70cdda426863f82ebe1305f4c3053824c5a605b1516b0b7f205f1203178b
This commit is contained in:
stephan
2022-12-25 10:22:27 +00:00
parent 4099b3cab3
commit 75c04ba89c
5 changed files with 80 additions and 42 deletions

View File

@ -569,7 +569,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}/*sqlite3_create_collation() and friends*/ }/*sqlite3_create_collation() and friends*/
if(1){/* Special-case handling of sqlite3_exec() */ {/* Special-case handling of sqlite3_exec() */
const __exec = wasm.xWrap("sqlite3_exec", "int", const __exec = wasm.xWrap("sqlite3_exec", "int",
["sqlite3*", "string:flexible", ["sqlite3*", "string:flexible",
new wasm.xWrap.FuncPtrAdapter({ new wasm.xWrap.FuncPtrAdapter({
@ -585,23 +585,23 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
} }
/* Wrap the callback in a WASM-bound function and convert the callback's /* Wrap the callback in a WASM-bound function and convert the callback's
`(char**)` arguments to arrays of strings... */ `(char**)` arguments to arrays of strings... */
let aNames;
const cbwrap = function(pVoid, nCols, pColVals, pColNames){ const cbwrap = function(pVoid, nCols, pColVals, pColNames){
let rc = capi.SQLITE_ERROR; let rc = capi.SQLITE_ERROR;
try { try {
let aVals = [], aNames = [], i = 0, offset = 0; const aVals = wasm.cArgvToJs(nCols, pColVals);
for( ; i < nCols; offset += (wasm.ptrSizeof * ++i) ){ if(!aNames) aNames = wasm.cArgvToJs(nCols, pColNames);
aVals.push( wasm.cstrToJs(wasm.peekPtr(pColVals + offset)) ); rc = callback(aVals, aNames) | 0;
aNames.push( wasm.cstrToJs(wasm.peekPtr(pColNames + offset)) );
}
rc = callback(pVoid, nCols, aVals, aNames) | 0;
/* The first 2 args of the callback are useless for JS but
we want the JS mapping of the C API to be as close to the
C API as possible. */
}catch(e){ }catch(e){
/* If we set the db error state here, the higher-level exec() call /* If we set the db error state here, the higher-level
replaces it with its own, so we have no way of reporting the exec() call replaces it with its own, so we have no way
exception message except the console. We must not propagate of reporting the exception message except the console. We
exceptions through the C API. */ must not propagate exceptions through the C API. Though
we make an effort to report OOM here, sqlite3_exec()
translates that into SQLITE_ABORT as well. */
rc = (e instanceof sqlite3.WasmAllocError)
? capi.SQLITE_NOMEM
: (e.resultCode || capi.SQLITE_ERROR);
} }
return rc; return rc;
}; };
@ -616,7 +616,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}; };
}/*sqlite3_exec() proxy*/; }/*sqlite3_exec() proxy*/;
if(1){/* Special-case handling of sqlite3_create_function_v2() {/* Special-case handling of sqlite3_create_function_v2()
and sqlite3_create_window_function() */ and sqlite3_create_window_function() */
/* Maintenance reminder: FuncPtrAdapter is not expressive enough /* Maintenance reminder: FuncPtrAdapter is not expressive enough
to be able to perform these mappings. */ to be able to perform these mappings. */
@ -1041,20 +1041,21 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
toss("Maintenance required: increase sqlite3_wasm_enum_json()'s", toss("Maintenance required: increase sqlite3_wasm_enum_json()'s",
"static buffer size!"); "static buffer size!");
} }
wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
//console.debug('wasm.ctype length =',wasm.cstrlen(cJson)); //console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
wasm.ctype = JSON.parse(wasm.cstrToJs(cJson));
// Groups of SQLITE_xyz macros...
const defineGroups = ['access', 'authorizer', const defineGroups = ['access', 'authorizer',
'blobFinalizers', 'config', 'dataTypes', 'blobFinalizers', 'config', 'dataTypes',
'dbConfig', 'dbStatus', 'dbConfig', 'dbStatus',
'encodings', 'fcntl', 'flock', 'ioCap', 'encodings', 'fcntl', 'flock', 'ioCap',
'limits', 'openFlags', 'limits', 'openFlags',
'prepareFlags', 'resultCodes', 'prepareFlags', 'resultCodes',
'serialize', 'sqlite3Status', 'sqlite3Status',
'stmtStatus', 'syncFlags', 'stmtStatus', 'syncFlags',
'trace', 'txnState', 'udfFlags', 'trace', 'txnState', 'udfFlags',
'version' ]; 'version' ];
if(wasm.bigIntEnabled){ if(wasm.bigIntEnabled){
defineGroups.push('vtab'); defineGroups.push('serialize', 'vtab');
} }
for(const t of defineGroups){ for(const t of defineGroups){
for(const e of Object.entries(wasm.ctype[t])){ for(const e of Object.entries(wasm.ctype[t])){

View File

@ -1749,8 +1749,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
argument of sqlite3_value_to_js(). If the sqlite3_column_value() argument of sqlite3_value_to_js(). If the sqlite3_column_value()
returns NULL (e.g. because the column index is out of range), returns NULL (e.g. because the column index is out of range),
this function returns `undefined`, regardless of the 3rd this function returns `undefined`, regardless of the 3rd
argument. 3rd argument is falsy and conversion fails, `undefined` argument. If the 3rd argument is falsy and conversion fails,
will be returned. `undefined` will be returned.
Note that sqlite3_column_value() returns an "unprotected" value Note that sqlite3_column_value() returns an "unprotected" value
object, but in a single-threaded environment (like this one) object, but in a single-threaded environment (like this one)

View File

@ -1882,18 +1882,18 @@ self.sqlite3InitModule = sqlite3InitModule;
T.assert(3===resultRows.length) T.assert(3===resultRows.length)
.assert(2===resultRows[1]); .assert(2===resultRows[1]);
T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a')); T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
/** Demonstrate the JS-simplified form of the sqlite3_exec() callback... */
let colCount = 0, rowCount = 0; let colCount = 0, rowCount = 0;
const execCallback = function(pVoid, nCols, aVals, aNames){ let rc = capi.sqlite3_exec(
db, "select a, a*2 from foo.bar", function(aVals, aNames){
//console.warn("execCallback(",arguments,")"); //console.warn("execCallback(",arguments,")");
colCount = nCols; colCount = aVals.length;
++rowCount; ++rowCount;
T.assert(2===aVals.length) T.assert(2===aVals.length)
.assert(2===aNames.length) .assert(2===aNames.length)
.assert(+(aVals[1]) === 2 * +(aVals[0])); .assert(+(aVals[1]) === 2 * +(aVals[0]));
}; }, 0, 0
let rc = capi.sqlite3_exec(
db.pointer, "select a, a*2 from foo.bar", execCallback,
0, 0
); );
T.assert(0===rc).assert(3===rowCount).assert(2===colCount); T.assert(0===rc).assert(3===rowCount).assert(2===colCount);
rc = capi.sqlite3_exec( rc = capi.sqlite3_exec(
@ -1902,8 +1902,45 @@ self.sqlite3InitModule = sqlite3InitModule;
}, 0, 0 }, 0, 0
); );
T.assert(capi.SQLITE_ABORT === rc); T.assert(capi.SQLITE_ABORT === rc);
/* Demonstrate how to get access to the "full" callback
signature, as opposed to the simplified JS-specific one... */
rowCount = colCount = 0;
const pCb = wasm.installFunction('i(pipp)', function(pVoid,nCols,aVals,aCols){
/* Tip: wasm.cArgvToJs() can be used to convert aVals and
aCols to arrays: const vals = wasm.cArgvToJs(nCols,
aVals); */
++rowCount;
colCount = nCols;
T.assert(2 === nCols)
.assert(wasm.isPtr(pVoid))
.assert(wasm.isPtr(aVals))
.assert(wasm.isPtr(aCols))
.assert(+wasm.cstrToJs(wasm.peekPtr(aVals + wasm.ptrSizeof))
=== 2 * +wasm.cstrToJs(wasm.peekPtr(aVals)));
return 0;
});
try {
T.assert(wasm.isPtr(pCb));
rc = capi.sqlite3_exec(db, "select a, a*2 from foo.bar", pCb, 0, 0);
T.assert(0===rc)
.assert(3===rowCount)
.assert(2===colCount);
}finally{
wasm.uninstallFunction(pCb);
}
// Demonstrate that an OOM result does not propagate through sqlite3_exec()...
rc = capi.sqlite3_exec(
db, "select a, a*2 from foo.bar", function(aVals, aNames){
sqlite3.WasmAllocError.toss("just testing");
}, 0, 0
);
T.assert(capi.SQLITE_ABORT === rc);
db.exec("detach foo"); db.exec("detach foo");
T.mustThrow(()=>db.exec("select * from foo.bar")); T.mustThrow(()=>db.exec("select * from foo.bar"),
"Because foo is no longer attached.");
}) })
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
C Replace\sJS-side\suse\sof\sSQLITE_TRANSIENT\swith\sthe\snew\sSQLITE_WASM_DEALLOC,\sreducing\sthe\samount\sallocation/copying\srequired\sby\ssqlite3_bind_blob/text()\sand\ssqlite3_result_blob/text().\sRemove\sthe\s'experimental'\slog\smessage\sfrom\sthe\svirtual\stable\stests. C Simplify\sthe\ssignature\sfor\sJS\sfunctions,\sas\sopposed\sto\sfunction\spointers,\spassed\sto\ssqlite3_exec(),\seliminating\sthe\ssuperfluous\sinitial\stwo\sarguments.\sUpdate\srelated\stests\sto\sdemonstrate\sboth\sfunction-passing\sapproaches.
D 2022-12-24T15:28:45.647 D 2022-12-25T10:22:27.506
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
@ -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 ba532798e577497da9221bf9ac7d286619eec4d16736c927f1d10f3c8d21ada3 F ext/wasm/api/sqlite3-api-glue.js 72f1ed1d60db62e18cf752c5871bc7c21cfef9258d9c81e61c830914c3f7da91
F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b
F ext/wasm/api/sqlite3-api-prologue.js b0302c61abf21966c8cf9788453fea29c790633f7a14a92e05e6db994b590d11 F ext/wasm/api/sqlite3-api-prologue.js a27762fd1ed2576897026f28a748a69edcdcc53ef79f46cead5e4446dc949763
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
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 dec750b65ec33ff267b35370ab746899859beb0a7c695cb9b087663d5b144512 F ext/wasm/tester1.c-pp.js e75daf4e82ce9c9506d165544b6052403802dd1bcf3f4f06fa6084b8520fb549
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 f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d P ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1
R 244f04d134cc6151e3968d82d6c44161 R 57b44198d665feb79b35a3b3cc62df00
U stephan U stephan
Z 5d490510463cd36c1f126d30ea32761d Z fa52e396693ed4ebb322eeecdf80849b
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1 e7cc70cdda426863f82ebe1305f4c3053824c5a605b1516b0b7f205f1203178b