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

Got JS non-eponymous vtable working thanks to a hint from Dan.

FossilOrigin-Name: 750719b4981df62fa2ff3665e6f559ec760609ad2493495628295ad9ae6024fc
This commit is contained in:
stephan
2022-12-08 09:06:20 +00:00
parent ab8b22a03d
commit d061f14466
5 changed files with 54 additions and 63 deletions

View File

@ -520,10 +520,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
db is closed but before auxiliary state like this.filename is
cleared.
Both onclose handlers are passed this object. If this db is not
opened, neither of the handlers are called. Any exceptions the
handlers throw are ignored because "destructors must not
throw."
Both onclose handlers are passed this object, with the onclose
object as their "this," noting that the db will have been
closed when onclose.after is called. If this db is not opened
when close() is called, neither of the handlers are called. Any
exceptions the handlers throw are ignored because "destructors
must not throw."
Note that garbage collection of a db handle, if it happens at
all, will never trigger close(), so onclose handlers are not a

View File

@ -339,8 +339,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
(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...
from sqlite3_module methods which take a (sqlite3_vtab*)
pointer _except_ for xDestroy() (if there is a distinct
xCreate()) or xDisconnect() (if xCreate() is 0 or is the same
as xConnect()), in which case use...
- wrapVtab(pVtab,true) as for the previous form, but removes the
pointer-to-object mapping before returning. The caller must

View File

@ -999,13 +999,19 @@ self.sqlite3InitModule = sqlite3InitModule;
const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
db.onclose = {
disposeThese: [],
before: (db)=>{
console.debug("db.onclose.before dropping modules");
sqlite3.capi.sqlite3_drop_modules(db, 0);
},
after: function(){
while(this.disposeThese.length){
const v = this.disposeThese.shift();
console.debug("db.onclose cleaning up:",v);
console.debug("db.onclose.after cleaning up:",v);
if(wasm.isPtr(v)) wasm.dealloc(v);
else if(v instanceof sqlite3.StructBinder.StructType){
v.dispose();
}else if(v instanceof Function){
try{v()} catch(e){/*ignored*/}
}
}
}
@ -1867,7 +1873,7 @@ self.sqlite3InitModule = sqlite3InitModule;
////////////////////////////////////////////////////////////////////////
.t({
name: 'virtual table #2 (w/ automated exception wrapping)',
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.");
@ -1879,7 +1885,7 @@ self.sqlite3InitModule = sqlite3InitModule;
The vtab demonstrated here is a JS-ification of
ext/misc/templatevtab.c.
*/
let throwOnConnect = 1 ? 0 : capi.SQLITE_CANTOPEN
let throwOnCreate = 1 ? 0 : capi.SQLITE_CANTOPEN
/* ^^^ just for testing exception wrapping. Note that sqlite
always translates errors from a vtable to a generic
SQLITE_ERROR unless it's from xConnect()/xCreate() and that
@ -1889,10 +1895,18 @@ self.sqlite3InitModule = sqlite3InitModule;
catchExceptions: true,
name: "vtab2test",
methods:{
xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){
console.debug("xConnect(",...arguments,")");
const t = vth.xVtab();
wasm.setPtrValue(ppVtab, t.pointer);
T.assert(t === vth.xVtab(wasm.getPtrValue(ppVtab)));
console.debug("xConnect(",...arguments,") ppVtab =",t.pointer);
},
xCreate: function(pDb, pAux, argc, argv, ppVtab, pzErr){
if(throwOnConnect){
console.debug("xCreate(",...arguments,")");
if(throwOnCreate){
sqlite3.SQLite3Error.toss(
throwOnConnect,
throwOnCreate,
"Throwing a test exception."
);
}
@ -1906,11 +1920,20 @@ self.sqlite3InitModule = sqlite3InitModule;
const t = vth.xVtab();
wasm.setPtrValue(ppVtab, t.pointer);
T.assert(t === vth.xVtab(wasm.getPtrValue(ppVtab)));
console.debug("xCreate(",...arguments,") ppVtab =",t.pointer);
}
return rc;
},
xDisconnect: function(pVtab){
console.debug("sqlite3_module::xDisconnect(",pVtab,")");
const t = vth.xVtab(pVtab, true);
T.assert(t);
t.dispose();
},
xDestroy: function(pVtab){
console.debug("sqlite3_module::xDestroy(",pVtab,")");
const t = vth.xVtab(pVtab, true);
T.assert(t);
t.dispose();
},
xOpen: function(pVtab, ppCursor){
@ -1945,12 +1968,10 @@ self.sqlite3InitModule = sqlite3InitModule;
xRowid: function(pCursor, ppRowid64){
const c = vth.xCursor(pCursor);
vth.xRowid(ppRowid64, c._rowId);
c.dispose();
},
xEof: function(pCursor){
const c = vth.xCursor(pCursor),
rc = c._rowId>=10;
c.dispose();
return rc;
},
xFilter: function(pCursor, idxNum, idxCStr,
@ -1959,7 +1980,6 @@ self.sqlite3InitModule = sqlite3InitModule;
c._rowId = 0;
const list = vth.sqlite3ValuesToJs(argc, argv);
T.assert(argc === list.length);
c.dispose();
},
xBestIndex: function(pVtab, pIdxInfo){
//const t = vth.xVtab(pVtab);
@ -1970,54 +1990,21 @@ self.sqlite3InitModule = sqlite3InitModule;
}
}/*methods*/
};
const doEponymousOnly =
/* Bug (somewhere): non-eponymous is behaving as is
the call to sqlite3_create_module() is missing
or failed:
SQL TRACE #63 create virtual table testvtab2 using vtab2test(arg1, arg2)
=> sqlite3 result code 1: no such module: vtab2test
*/ true;
modConfig.methods.xConnect =
modConfig.methods.xCreate;
if(doEponymousOnly){
warn("Reminder: non-eponymous mode is still not working here.",
"Details are in the code comments.");
modConfig.methods.xCreate = 0;
}else{
/*(...args)=>{
try{return modConfig.methods.xConnect(...args)}
catch(e){return vth.xError('xConnect',e)}
};*/
}
const tmplMod = vth.setupModule(modConfig);
T.assert(tmplMod instanceof capi.sqlite3_module)
.assert(1===tmplMod.$iVersion);
if(doEponymousOnly){
if(modConfig.methods.xCreate !== 0){
T.assert(modConfig.methods.xCreate === modConfig.methods.xConnect)
.assert(tmplMod.$xCreate === tmplMod.$xConnect);
}else{
T.assert(0 === tmplMod.$xCreate);
}
}else{
//T.assert(tmplMod.$xCreate !== tmplMod.$xConnect);
}
this.db.onclose.disposeThese.push(tmplMod);
this.db.checkRc(capi.sqlite3_create_module(
this.db.pointer, modConfig.name, tmplMod.pointer, 0
));
if(!doEponymousOnly){
this.db.exec([
"create virtual table testvtab2 using ",
modConfig.name,
"(arg1, arg2)"
]);
}
this.db.exec([
"create virtual table testvtab2 using ",
modConfig.name,
"(arg1, arg2)"
]);
const list = this.db.selectArrays(
["SELECT a,b FROM ",
(doEponymousOnly ? modConfig.name : "testvtab2"),
["SELECT a,b FROM",
" testvtab2",
" 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(). */