mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Replace JS-side use of SQLITE_TRANSIENT with the new SQLITE_WASM_DEALLOC, reducing the amount allocation/copying required by sqlite3_bind_blob/text() and sqlite3_result_blob/text(). Remove the 'experimental' log message from the virtual table tests.
FossilOrigin-Name: ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1
This commit is contained in:
@ -24,6 +24,33 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
self.WhWasmUtilInstaller(wasm);
|
||||
delete self.WhWasmUtilInstaller;
|
||||
|
||||
{
|
||||
/**
|
||||
Find a mapping for SQLITE_WASM_DEALLOC, which the API
|
||||
guarantees is a WASM pointer to the same underlying function as
|
||||
wasm.dealloc() (noting that wasm.dealloc() is permitted to be a
|
||||
JS wrapper around the WASM function). There is unfortunately no
|
||||
O(1) algorithm for finding this pointer: we have to walk the
|
||||
WASM indirect function table to find it. However, experience
|
||||
indicates that that particular function is always very close to
|
||||
the front of the table (it's been entry #3 in all relevant
|
||||
tests).
|
||||
*/
|
||||
const dealloc = wasm.exports[sqlite3.config.deallocExportName];
|
||||
const nFunc = wasm.functionTable().length;
|
||||
let i;
|
||||
for(i = 0; i < nFunc; ++i){
|
||||
const e = wasm.functionEntry(i);
|
||||
if(dealloc === e){
|
||||
capi.SQLITE_WASM_DEALLOC = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dealloc !== wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
|
||||
toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Signatures for the WASM-exported C-side functions. Each entry
|
||||
is an array with 2+ elements:
|
||||
@ -874,7 +901,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
text = pMem.join('');
|
||||
}
|
||||
let p, n;
|
||||
try {
|
||||
try{
|
||||
if(util.isSQLableTypedArray(text)){
|
||||
p = wasm.allocFromTypedArray(text);
|
||||
n = text.byteLength;
|
||||
@ -886,9 +913,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"Invalid 3rd argument type for sqlite3_bind_text()."
|
||||
);
|
||||
}
|
||||
return __bindText(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
|
||||
}finally{
|
||||
return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
|
||||
}catch(e){
|
||||
wasm.dealloc(p);
|
||||
return util.sqlite3_wasm_db_error(
|
||||
capi.sqlite3_db_handle(pStmt), e
|
||||
);
|
||||
}
|
||||
}/*sqlite3_bind_text()*/;
|
||||
|
||||
@ -917,9 +947,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
"Invalid 3rd argument type for sqlite3_bind_blob()."
|
||||
);
|
||||
}
|
||||
return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
|
||||
}finally{
|
||||
return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
|
||||
}catch(e){
|
||||
wasm.dealloc(p);
|
||||
return util.sqlite3_wasm_db_error(
|
||||
capi.sqlite3_db_handle(pStmt), e
|
||||
);
|
||||
}
|
||||
}/*sqlite3_bind_blob()*/;
|
||||
|
||||
|
@ -1285,7 +1285,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
success.
|
||||
*/
|
||||
const bindOne = function f(stmt,ndx,bindType,val){
|
||||
affirmUnlocked(stmt, 'bind()');
|
||||
affirmUnlocked(affirmStmtOpen(stmt), 'bind()');
|
||||
if(!f._){
|
||||
f._tooBigInt = (v)=>toss3(
|
||||
"BigInt value is too big to store without precision loss:", v
|
||||
@ -1295,14 +1295,9 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
so we have no range checking. */
|
||||
f._ = {
|
||||
string: function(stmt, ndx, val, asBlob){
|
||||
const stack = wasm.scopedAllocPush();
|
||||
try{
|
||||
const [pStr, n] = wasm.scopedAllocCString(val, true);
|
||||
const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
|
||||
return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_TRANSIENT);
|
||||
}finally{
|
||||
wasm.scopedAllocPop(stack);
|
||||
}
|
||||
const [pStr, n] = wasm.allocCString(val, true);
|
||||
const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
|
||||
return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_WASM_DEALLOC);
|
||||
}
|
||||
};
|
||||
}/* static init */
|
||||
@ -1354,15 +1349,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
toss3("Binding a value as a blob requires",
|
||||
"that it be a string, Uint8Array, Int8Array, or ArrayBuffer.");
|
||||
}
|
||||
const stack = wasm.scopedAllocPush();
|
||||
try{
|
||||
const pBlob = wasm.scopedAlloc(val.byteLength || 1);
|
||||
wasm.heap8().set(val.byteLength ? val : [0], pBlob)
|
||||
rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
|
||||
capi.SQLITE_TRANSIENT);
|
||||
}finally{
|
||||
wasm.scopedAllocPop(stack);
|
||||
}
|
||||
const pBlob = wasm.alloc(val.byteLength || 1);
|
||||
wasm.heap8().set(val.byteLength ? val : [0], pBlob)
|
||||
rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
|
||||
capi.SQLITE_WASM_DEALLOC);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -321,14 +321,17 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
};
|
||||
|
||||
/**
|
||||
Returns true if v appears to be one of our bind()-able TypedArray
|
||||
types: Uint8Array or Int8Array. Support for TypedArrays with
|
||||
element sizes >1 is a potential TODO just waiting on a use case
|
||||
to justify them.
|
||||
Returns v if v appears to be one of our bind()-able TypedArray
|
||||
types: Uint8Array or Int8Array or ArrayBuffer. Support for
|
||||
TypedArrays with element sizes >1 is a potential TODO just
|
||||
waiting on a use case to justify them. Until then, their `buffer`
|
||||
property can be used to pass them as an ArrayBuffer. If it's not
|
||||
a bindable array type, a falsy value is returned.
|
||||
*/
|
||||
const isBindableTypedArray = (v)=>{
|
||||
return v && (v instanceof Uint8Array || v instanceof Int8Array);
|
||||
//v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
|
||||
return v && (v instanceof Uint8Array
|
||||
|| v instanceof Int8Array
|
||||
|| v instanceof ArrayBuffer);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -341,8 +344,9 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
isSQLableTypedArray() list.
|
||||
*/
|
||||
const isSQLableTypedArray = (v)=>{
|
||||
return v && (v instanceof Uint8Array || v instanceof Int8Array);
|
||||
//v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
|
||||
return v && (v instanceof Uint8Array
|
||||
|| v instanceof Int8Array
|
||||
|| v instanceof ArrayBuffer);
|
||||
};
|
||||
|
||||
/** Returns true if isBindableTypedArray(v) does, else throws with a message
|
||||
@ -439,8 +443,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
- If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
|
||||
treated as that type.
|
||||
|
||||
In all of those cases, the final argument (text destructor) is
|
||||
ignored and capi.SQLITE_TRANSIENT is assumed.
|
||||
In all of those cases, the final argument (destructor) is
|
||||
ignored and capi.SQLITE_WASM_DEALLOC is assumed.
|
||||
|
||||
A 3rd argument of `null` is treated as if it were a WASM pointer
|
||||
of 0.
|
||||
@ -477,7 +481,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
treated as that type.
|
||||
|
||||
In each of those cases, the final argument (text destructor) is
|
||||
ignored and capi.SQLITE_TRANSIENT is assumed.
|
||||
ignored and capi.SQLITE_WASM_DEALLOC is assumed.
|
||||
|
||||
A 3rd argument of `null` is treated as if it were a WASM pointer
|
||||
of 0.
|
||||
@ -1661,7 +1665,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
- `bigint`: similar to `number` but will trigger an error if the
|
||||
value is too big to store in an int64.
|
||||
- `string`: `sqlite3_result_text()`
|
||||
- Uint8Array or Int8Array: `sqlite3_result_blob()`
|
||||
- Uint8Array or Int8Array or ArrayBuffer: `sqlite3_result_blob()`
|
||||
- `undefined`: is a no-op provided to simplify certain use cases.
|
||||
|
||||
Anything else triggers `sqlite3_result_error()` with a
|
||||
@ -1712,9 +1716,11 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
f(pCtx, val);
|
||||
break;
|
||||
}
|
||||
case 'string':
|
||||
capi.sqlite3_result_text(pCtx, val, -1, capi.SQLITE_TRANSIENT);
|
||||
case 'string': {
|
||||
const [p, n] = wasm.allocCString(val,true);
|
||||
capi.sqlite3_result_text(pCtx, p, n, capi.SQLITE_WASM_DEALLOC);
|
||||
break;
|
||||
}
|
||||
case 'object':
|
||||
if(null===val/*yes, typeof null === 'object'*/) {
|
||||
capi.sqlite3_result_null(pCtx);
|
||||
@ -1723,7 +1729,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
const pBlob = wasm.allocFromTypedArray(val);
|
||||
capi.sqlite3_result_blob(
|
||||
pCtx, pBlob, val.byteLength,
|
||||
wasm.exports[sqlite3.config.deallocExportName]
|
||||
capi.SQLITE_WASM_DEALLOC
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -1621,6 +1621,11 @@ int sqlite3_wasm_test_intptr(int * p){
|
||||
return *p = *p * 2;
|
||||
}
|
||||
|
||||
SQLITE_WASM_KEEP
|
||||
void * sqlite3_wasm_test_voidptr(void * p){
|
||||
return p;
|
||||
}
|
||||
|
||||
SQLITE_WASM_KEEP
|
||||
int64_t sqlite3_wasm_test_int64_max(void){
|
||||
return (int64_t)0x7fffffffffffffff;
|
||||
|
@ -1987,7 +1987,6 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
name: 'virtual table #1: eponymous w/ manual exception handling',
|
||||
predicate: ()=>!!capi.sqlite3_index_info,
|
||||
test: function(sqlite3){
|
||||
warn("The vtab/module JS bindings are experimental and subject to change.");
|
||||
const VT = sqlite3.vtab;
|
||||
const tmplCols = Object.assign(Object.create(null),{
|
||||
A: 0, B: 1
|
||||
@ -2185,7 +2184,6 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
name: 'virtual table #2: non-eponymous w/ automated exception wrapping',
|
||||
predicate: ()=>!!capi.sqlite3_index_info,
|
||||
test: function(sqlite3){
|
||||
warn("The vtab/module JS bindings are experimental and subject to change.");
|
||||
const VT = sqlite3.vtab;
|
||||
const tmplCols = Object.assign(Object.create(null),{
|
||||
A: 0, B: 1
|
||||
|
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Extend\soo1.Stmt.bind()\sto\saccept\sArrayBuffer\sinstances\sto\sbind\sas\sblobs.
|
||||
D 2022-12-24T14:16:02.217
|
||||
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.
|
||||
D 2022-12-24T15:28:45.647
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -503,16 +503,16 @@ 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 f0651048a2601bf79f7f39c2c855f6417e65548417f5019ac9ac2ffb2463f2b9
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 1312eaf2776c957e41a6fd63c31e7487502bf71745805c41f72429e0925802a5
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 683956ea6ab5e0132db48bb693a6bb9dd92f36c8c0902af36572e9b29006ac6d
|
||||
F ext/wasm/api/sqlite3-api-glue.js ba532798e577497da9221bf9ac7d286619eec4d16736c927f1d10f3c8d21ada3
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b
|
||||
F ext/wasm/api/sqlite3-api-prologue.js b0302c61abf21966c8cf9788453fea29c790633f7a14a92e05e6db994b590d11
|
||||
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
||||
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-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115
|
||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||
F ext/wasm/api/sqlite3-wasm.c b114bb85cdf8be7b2939ddcc2bbc2f30c190c44b993c34a77b017c978345efb1
|
||||
F ext/wasm/api/sqlite3-wasm.c 313489816e1733a10ece74a92cbea65d3ee241eb07d98088e96258cc211c9719
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
|
||||
F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
@ -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 145c493221727eb40194280bb2852da49f857e850d8394c31b7bd4caeb5d7bed
|
||||
F ext/wasm/tester1.c-pp.js dec750b65ec33ff267b35370ab746899859beb0a7c695cb9b087663d5b144512
|
||||
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 6a37874db04f3b4842994ad17fc74cb6222f8ea0fa1315a23aff1ffa69bcd12a
|
||||
R b07f6a4d9e30a3f649f5decc82bdf7ef
|
||||
P f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d
|
||||
R 244f04d134cc6151e3968d82d6c44161
|
||||
U stephan
|
||||
Z 934cef85bd1b053ac09da3261d128afb
|
||||
Z 5d490510463cd36c1f126d30ea32761d
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d
|
||||
ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1
|
Reference in New Issue
Block a user