JS vtables: add infrastructure related to accessing and modifying sqlite3_index_info.
FossilOrigin-Name: 0d77c348039926c24e0fb50a7dc7e4b62895cd201c021f8e29832917e4b8b09f
This commit is contained in:
parent
d254db53e5
commit
241cde98b8
@ -22,6 +22,53 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
sqlite3.VfsHelper = vh;
|
||||
sqlite3.VtabHelper = vt;
|
||||
|
||||
const sii = capi.sqlite3_index_info;
|
||||
/**
|
||||
If n is >=0 and less than this.$nConstraint, this function
|
||||
returns either a WASM pointer to the 0-based nth entry of
|
||||
this.$aConstraint (if passed a truthy 2nd argument) or an
|
||||
sqlite3_index_info.sqlite3_index_constraint object wrapping that
|
||||
address (if passed a falsy value or no 2nd argument). Returns a
|
||||
falsy value if n is out of range.
|
||||
*/
|
||||
sii.prototype.nthConstraint = function(n, asPtr=false){
|
||||
if(n<0 || n>=this.$nConstraint) return false;
|
||||
const ptr = this.$aConstraint + (
|
||||
sii.sqlite3_index_constraint.structInfo.sizeof * n
|
||||
);
|
||||
return asPtr ? ptr : new sii.sqlite3_index_constraint(ptr);
|
||||
};
|
||||
|
||||
/**
|
||||
Works identically to nthConstraint() but returns state from
|
||||
this.$aConstraintUsage, so returns an
|
||||
sqlite3_index_info.sqlite3_index_constraint_usage instance
|
||||
if passed no 2nd argument or a falsy 2nd argument.
|
||||
*/
|
||||
sii.prototype.nthConstraintUsage = function(n, asPtr=false){
|
||||
if(n<0 || n>=this.$nConstraint) return false;
|
||||
const ptr = this.$aConstraintUsage + (
|
||||
sii.sqlite3_index_constraint_usage.structInfo.sizeof * n
|
||||
);
|
||||
return asPtr ? ptr : new sii.sqlite3_index_constraint_usage(ptr);
|
||||
};
|
||||
|
||||
/**
|
||||
If n is >=0 and less than this.$nOrderBy, this function
|
||||
returns either a WASM pointer to the 0-based nth entry of
|
||||
this.$aOrderBy (if passed a truthy 2nd argument) or an
|
||||
sqlite3_index_info.sqlite3_index_orderby object wrapping that
|
||||
address (if passed a falsy value or no 2nd argument). Returns a
|
||||
falsy value if n is out of range.
|
||||
*/
|
||||
sii.prototype.nthOrderBy = function(n, asPtr=false){
|
||||
if(n<0 || n>=this.$nOrderBy) return false;
|
||||
const ptr = this.$aOrderBy + (
|
||||
sii.sqlite3_index_orderby.structInfo.sizeof * n
|
||||
);
|
||||
return asPtr ? ptr : new sii.sqlite3_index_orderby(ptr);
|
||||
};
|
||||
|
||||
/**
|
||||
Installs a StructBinder-bound function pointer member of the
|
||||
given name and function in the given StructType target object.
|
||||
@ -109,6 +156,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
const pFunc = wasm.installFunction(fProxy, tgt.memberSignature(name, true));
|
||||
tgt[memKey] = pFunc;
|
||||
if(!tgt.ondispose) tgt.ondispose = [];
|
||||
else if(!Array.isArray(tgt.ondispose)) tgt.ondispose = [tgt.ondispose];
|
||||
if(!tgt.ondispose.__removeFuncList){
|
||||
tgt.ondispose.push('ondispose.__removeFuncList handler',
|
||||
callee.removeFuncList);
|
||||
@ -244,9 +292,9 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
vt.sqlite3ValuesToJs = capi.sqlite3_create_function_v2.udfConvertArgs;
|
||||
|
||||
/**
|
||||
Factory function for xyz2js() impls.
|
||||
Factory function for wrapXyz() impls.
|
||||
*/
|
||||
const __v2jsFactory = function(structType){
|
||||
const __xWrapFactory = function(structType){
|
||||
return function(ptr,remove=false){
|
||||
if(0===arguments.length) ptr = new structType;
|
||||
if(ptr instanceof structType){
|
||||
@ -254,7 +302,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
this.set(ptr.pointer, ptr);
|
||||
return ptr;
|
||||
}else if(!wasm.isPtr(ptr)){
|
||||
sqlite3.SQLite3Error.toss("Invalid argument to v2jsFactory");
|
||||
sqlite3.SQLite3Error.toss("Invalid argument to xWrapFactory");
|
||||
}
|
||||
let rc = this.get(ptr);
|
||||
if(remove) this.delete(ptr);
|
||||
@ -270,45 +318,45 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
Has 3 distinct uses:
|
||||
|
||||
- vtab2js() instantiates a new capi.sqlite3_vtab instance, maps
|
||||
- wrapVtab() instantiates a new capi.sqlite3_vtab instance, maps
|
||||
its pointer for later by-pointer lookup, and returns that
|
||||
object. This is intended to be called from
|
||||
sqlite3_module::xConnect() or xCreate() implementations.
|
||||
|
||||
- vtab2js(pVtab) accepts a WASM pointer to a C-level
|
||||
- wrapVtab(pVtab) accepts a WASM pointer to a C-level
|
||||
(sqlite3_vtab*) instance and returns the capi.sqlite3_vtab
|
||||
object created by the first form of this function, or undefined
|
||||
if that form has not been used. This is intended to be called
|
||||
from sqlite3_module methods which take a (sqlite3_vtab*) pointer
|
||||
_except_ for xDisconnect(), in which case use...
|
||||
|
||||
- vtab2js(pVtab,true) as for the previous form, but removes the
|
||||
- wrapVtab(pVtab,true) as for the previous form, but removes the
|
||||
pointer-to-object mapping before returning. The caller must
|
||||
call dispose() on the returned object. This is intended to be
|
||||
called from sqlite3_module::xDisconnect() implementations or
|
||||
in error handling of a failed xCreate() or xConnect().
|
||||
*/
|
||||
vt.vtab2js = __v2jsFactory(capi.sqlite3_vtab);
|
||||
vt.xWrapVtab = __xWrapFactory(capi.sqlite3_vtab);
|
||||
|
||||
/**
|
||||
EXPERIMENTAL. DO NOT USE IN CLIENT CODE.
|
||||
|
||||
Works identically to vtab2js() except that it deals with
|
||||
Works identically to wrapVtab() except that it deals with
|
||||
sqlite3_cursor objects and pointers instead of sqlite3_vtab.
|
||||
|
||||
- vcur2js() is intended to be called from sqlite3_module::xOpen()
|
||||
- wrapCursor() is intended to be called from sqlite3_module::xOpen()
|
||||
|
||||
- vcur2js(pCursor) is intended to be called from all sqlite3_module
|
||||
- wrapCursor(pCursor) is intended to be called from all sqlite3_module
|
||||
methods which take a (sqlite3_vtab_cursor*) _except_ for
|
||||
xClose(), in which case use...
|
||||
|
||||
- vcur2js(pCursor, true) will remove the m apping of pCursor to a
|
||||
- wrapCursor(pCursor, true) will remove the m apping of pCursor to a
|
||||
capi.sqlite3_vtab_cursor object and return that object. The
|
||||
caller must call dispose() on the returned object. This is
|
||||
intended to be called form xClose() or in error handling of a
|
||||
failed xOpen().
|
||||
*/
|
||||
vt.vcur2js = __v2jsFactory(capi.sqlite3_vtab_cursor);
|
||||
vt.xWrapCursor = __xWrapFactory(capi.sqlite3_vtab_cursor);
|
||||
|
||||
/**
|
||||
Given an error object, this function returns
|
||||
|
@ -1553,9 +1553,9 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
pDb, "CREATE TABLE ignored(a,b)"
|
||||
);
|
||||
if(0===rc){
|
||||
const t = vth.vtab2js();
|
||||
const t = vth.xWrapVtab();
|
||||
wasm.setPtrValue(ppVtab, t.pointer);
|
||||
T.assert(t === vth.vtab2js(wasm.getPtrValue(ppVtab)));
|
||||
T.assert(t === vth.xWrapVtab(wasm.getPtrValue(ppVtab)));
|
||||
}
|
||||
return rc;
|
||||
}catch(e){
|
||||
@ -1567,7 +1567,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xDisconnect: function(pVtab){
|
||||
try {
|
||||
const t = vth.vtab2js(pVtab, true);
|
||||
const t = vth.xWrapVtab(pVtab, true);
|
||||
t.dispose();
|
||||
return 0;
|
||||
}catch(e){
|
||||
@ -1576,7 +1576,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xOpen: function(pVtab, ppCursor){
|
||||
try{
|
||||
const t = vth.vtab2js(pVtab), c = vth.vcur2js();
|
||||
const t = vth.xWrapVtab(pVtab), c = vth.xWrapCursor();
|
||||
T.assert(t instanceof capi.sqlite3_vtab);
|
||||
T.assert(c instanceof capi.sqlite3_vtab_cursor);
|
||||
wasm.setPtrValue(ppCursor, c.pointer);
|
||||
@ -1588,9 +1588,9 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xClose: function(pCursor){
|
||||
try{
|
||||
const c = vth.vcur2js(pCursor,true);
|
||||
const c = vth.xWrapCursor(pCursor,true);
|
||||
T.assert(c instanceof capi.sqlite3_vtab_cursor)
|
||||
.assert(!vth.vcur2js(pCursor));
|
||||
.assert(!vth.xWrapCursor(pCursor));
|
||||
c.dispose();
|
||||
return 0;
|
||||
}catch(e){
|
||||
@ -1599,7 +1599,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xNext: function(pCursor){
|
||||
try{
|
||||
const c = vth.vcur2js(pCursor);
|
||||
const c = vth.xWrapCursor(pCursor);
|
||||
++c._rowId;
|
||||
return 0;
|
||||
}catch(e){
|
||||
@ -1609,7 +1609,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xColumn: function(pCursor, pCtx, iCol){
|
||||
try{
|
||||
const c = vth.vcur2js(pCursor);
|
||||
const c = vth.xWrapCursor(pCursor);
|
||||
switch(iCol){
|
||||
case tmplCols.A:
|
||||
capi.sqlite3_result_int(pCtx, 1000 + c._rowId);
|
||||
@ -1626,7 +1626,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xRowid: function(pCursor, ppRowid64){
|
||||
try{
|
||||
const c = vth.vcur2js(pCursor);
|
||||
const c = vth.xWrapCursor(pCursor);
|
||||
vth.setRowId(ppRowid64, c._rowId);
|
||||
return 0;
|
||||
}catch(e){
|
||||
@ -1634,14 +1634,17 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
},
|
||||
xEof: function(pCursor){
|
||||
const c = vth.vcur2js(pCursor);
|
||||
const c = vth.xWrapCursor(pCursor);
|
||||
return c._rowId>=10;
|
||||
},
|
||||
xFilter: function(pCursor, idxNum, idxCStr,
|
||||
argc, argv/* [sqlite3_value* ...] */){
|
||||
try{
|
||||
const c = vth.vcur2js(pCursor);
|
||||
const c = vth.xWrapCursor(pCursor);
|
||||
c._rowId = 0;
|
||||
const list = vth.sqlite3ValuesToJs(argc, argv);
|
||||
T.assert(argc === list.length);
|
||||
//log(argc,"xFilter value(s):",list);
|
||||
return 0;
|
||||
}catch(e){
|
||||
return vth.xMethodError('xFilter',e);
|
||||
@ -1649,10 +1652,44 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
},
|
||||
xBestIndex: function(pVtab, pIdxInfo){
|
||||
try{
|
||||
const t = vth.vtab2js(pVtab);
|
||||
const pii = new capi.sqlite3_index_info(pIdxInfo);
|
||||
//const t = vth.xWrapVtab(pVtab);
|
||||
const sii = capi.sqlite3_index_info;
|
||||
const pii = new sii(pIdxInfo);
|
||||
pii.$estimatedRows = 10;
|
||||
pii.$estimatedCost = 10.0;
|
||||
//log("xBestIndex $nConstraint =",pii.$nConstraint);
|
||||
if(pii.$nConstraint>0){
|
||||
// Validate nthConstraint() and nthConstraintUsage()
|
||||
const max = pii.$nConstraint;
|
||||
for(let i=0; i < max; ++i ){
|
||||
let v = pii.nthConstraint(i,true);
|
||||
T.assert(wasm.isPtr(v));
|
||||
v = pii.nthConstraint(i);
|
||||
T.assert(v instanceof sii.sqlite3_index_constraint)
|
||||
.assert(v.pointer >= pii.$aConstraint);
|
||||
v.dispose();
|
||||
v = pii.nthConstraintUsage(i,true);
|
||||
T.assert(wasm.isPtr(v));
|
||||
v = pii.nthConstraintUsage(i);
|
||||
T.assert(v instanceof sii.sqlite3_index_constraint_usage)
|
||||
.assert(v.pointer >= pii.$aConstraintUsage);
|
||||
v.$argvIndex = i;//just to get some values into xFilter
|
||||
v.dispose();
|
||||
}
|
||||
}
|
||||
//log("xBestIndex $nOrderBy =",pii.$nOrderBy);
|
||||
if(pii.$nOrderBy>0){
|
||||
// Validate nthOrderBy()
|
||||
const max = pii.$nOrderBy;
|
||||
for(let i=0; i < max; ++i ){
|
||||
let v = pii.nthOrderBy(i,true);
|
||||
T.assert(wasm.isPtr(v));
|
||||
v = pii.nthOrderBy(i);
|
||||
T.assert(v instanceof sii.sqlite3_index_orderby)
|
||||
.assert(v.pointer >= pii.$aOrderBy);
|
||||
v.dispose();
|
||||
}
|
||||
}
|
||||
pii.dispose();
|
||||
return 0;
|
||||
}catch(e){
|
||||
@ -1692,7 +1729,9 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
this.db.checkRc(rc);
|
||||
|
||||
const list = this.db.selectArrays(
|
||||
"SELECT a,b FROM testvtab order by a"
|
||||
"SELECT a,b FROM testvtab where a<9999 and b>1 order by a, b"
|
||||
/* Query is shaped so that it will ensure that some constraints
|
||||
end up in xBestIndex(). */
|
||||
);
|
||||
T.assert(10===list.length)
|
||||
.assert(1000===list[0][0])
|
||||
|
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Remove\sdeprecated\ssymbol\ssqlite3.opfs.OpfsDb,\swhich\swas\srenamed\sto\ssqlite3.oo1.OpfsDb\son\s2022-11-29.
|
||||
D 2022-12-06T09:49:04.292
|
||||
C JS\svtables:\sadd\sinfrastructure\srelated\sto\saccessing\sand\smodifying\ssqlite3_index_info.
|
||||
D 2022-12-06T11:21:46.303
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -509,7 +509,7 @@ F ext/wasm/api/sqlite3-api-prologue.js a7596c30392d9ca8f5b7c14feb4e6788107d1159f
|
||||
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 f79dd8d98ef3e0b55c10bb2bee7a3840fa967318e1f577c156aafc34664271d1
|
||||
F ext/wasm/api/sqlite3-v-helper.js 4451763a0cd85734f0afe18b48918cb3c88ca99cef399b7c5f12119281e7b6a8
|
||||
F ext/wasm/api/sqlite3-v-helper.js 6b408ee4e926cb0f7fe41a63a1205049283af301fe3f5de3c038845ccf9106df
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 8ec510fee735c646fb18a3b99f0ca5ca461f9e066c43cdc404d7144f12ae6ed6
|
||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||
F ext/wasm/api/sqlite3-wasm.c 723522a6c2a2463884a83fa1cc7ae5770deaaf0856a1058cc1023b2bfa1c898b
|
||||
@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
|
||||
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
|
||||
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
|
||||
F ext/wasm/tester1.c-pp.js 81c40395be4a7e97a3ca0ff62a4e02204239b1db6f24fe15b3c96a17fb41f29b
|
||||
F ext/wasm/tester1.c-pp.js c5679da7895377df03e6075fc0e9dff8b5f570bd4edb63f714154d3030279fce
|
||||
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 cbf483ea0ba3e6dc08ad7ed654380f818544b4c3cedfdb8aa848a83298268ceb
|
||||
R 16a04cd1971a4487c1631d3a37d3ce6e
|
||||
P 0ce51bed65d5e430364f74bf959fb76c42ac5eec0769490231d8c8110a1f388c
|
||||
R a1b37a98bcb406acaf386e5a65bbf6e3
|
||||
U stephan
|
||||
Z 455bc03c9fd6d42a81f698c07992ea6a
|
||||
Z 3e0a3245949f854c4eed760afd40e3ce
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
0ce51bed65d5e430364f74bf959fb76c42ac5eec0769490231d8c8110a1f388c
|
||||
0d77c348039926c24e0fb50a7dc7e4b62895cd201c021f8e29832917e4b8b09f
|
Loading…
x
Reference in New Issue
Block a user