More work on the JS vtable tests.

FossilOrigin-Name: 51e3c3b569dce2097063d39dc484f44b2f98cad0a902ef66765ca4cdc3e06f47
This commit is contained in:
stephan 2022-12-08 10:06:07 +00:00
parent d061f14466
commit 16bf97b507
4 changed files with 91 additions and 46 deletions

View File

@ -1021,7 +1021,11 @@ sqlite3_vfs * sqlite3_wasm_db_vfs(sqlite3 *pDb, const char *zDbName){
**
** This function resets the given db pointer's database as described at
**
** https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigresetdatabase
** https://sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigresetdatabase
**
** But beware: virtual tables destroyed that way do not have their
** xDestroy() called, so will leak if they require that function for
** proper cleanup.
**
** Returns 0 on success, an SQLITE_xxx code on error. Returns
** SQLITE_MISUSE if pDb is NULL.
@ -1030,6 +1034,7 @@ SQLITE_WASM_KEEP
int sqlite3_wasm_db_reset(sqlite3 *pDb){
int rc = SQLITE_MISUSE;
if( pDb ){
sqlite3_table_column_metadata(pDb, "main", 0, 0, 0, 0, 0, 0, 0);
rc = sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
if( 0==rc ){
rc = sqlite3_exec(pDb, "VACUUM", 0, 0, 0);

View File

@ -998,14 +998,27 @@ self.sqlite3InitModule = sqlite3InitModule;
wasm.sqlite3_wasm_vfs_unlink(0, dbFile);
const db = this.db = new sqlite3.oo1.DB(dbFile, 0 ? 'ct' : 'c');
db.onclose = {
disposeThese: [],
before: (db)=>{
disposeAfter: [],
disposeBefore: [],
before: function(db){
while(this.disposeBefore.length){
const v = this.disposeBefore.shift();
console.debug("db.onclose.before 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(db) } catch(e){
console.warn("beforeDispose() callback threw:",e);
}
}
}
console.debug("db.onclose.before dropping modules");
sqlite3.capi.sqlite3_drop_modules(db, 0);
sqlite3.capi.sqlite3_drop_modules(db.pointer, 0);
},
after: function(){
while(this.disposeThese.length){
const v = this.disposeThese.shift();
while(this.disposeAfter.length){
const v = this.disposeAfter.shift();
console.debug("db.onclose.after cleaning up:",v);
if(wasm.isPtr(v)) wasm.dealloc(v);
else if(v instanceof sqlite3.StructBinder.StructType){
@ -1847,7 +1860,7 @@ self.sqlite3InitModule = sqlite3InitModule;
const tmplMod = new sqlite3.capi.sqlite3_module();
tmplMod.$iVersion = 0;
this.db.onclose.disposeThese.push(tmplMod);
this.db.onclose.disposeAfter.push(tmplMod);
vth.installMethods(tmplMod, tmplMethods, true);
if(tmplMethods.xCreate){
T.assert(tmplMod.$xCreate)
@ -1867,7 +1880,7 @@ self.sqlite3InitModule = sqlite3InitModule;
);
T.assert(10===list.length)
.assert(1000===list[0][0])
.assert(2009===list[list.length-1][1])
.assert(2009===list[list.length-1][1]);
}
})/*custom vtab #1*/
@ -1890,20 +1903,16 @@ self.sqlite3InitModule = sqlite3InitModule;
always translates errors from a vtable to a generic
SQLITE_ERROR unless it's from xConnect()/xCreate() and that
callback sets an error string. */;
const vtabTrace = 1
? ()=>{}
: (methodName,...args)=>console.debug('sqlite3_module::'+methodName+'():',...args);
const modConfig = {
/* catchExceptions changes how the methods are wrapped */
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){
console.debug("xCreate(",...arguments,")");
vtabTrace("xCreate",...arguments);
if(throwOnCreate){
sqlite3.SQLite3Error.toss(
throwOnCreate,
@ -1911,7 +1920,7 @@ self.sqlite3InitModule = sqlite3InitModule;
);
}
const args = wasm.cArgvToJs(argc, argv);
console.debug("xCreate/xConnect args:",args);
vtabTrace("xCreate","argv:",args);
T.assert(args.length>=3);
const rc = capi.sqlite3_declare_vtab(
pDb, "CREATE TABLE ignored(a,b)"
@ -1920,40 +1929,51 @@ 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);
vtabTrace("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,")");
vtabTrace("sqlite3_xDestroy",pVtab);
const t = vth.xVtab(pVtab, true);
T.assert(t);
t.dispose();
},
/*xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){
vtabTrace("xConnect",...arguments);
const t = vth.xVtab();
wasm.setPtrValue(ppVtab, t.pointer);
T.assert(t === vth.xVtab(wasm.getPtrValue(ppVtab)));
vtabTrace("xConnect",...arguments,"ppVtab =",t.pointer);
},
xDisconnect: function(pVtab){
vtabTrace("xDisconnect",pVtab);
const t = vth.xVtab(pVtab, true);
T.assert(t);
t.dispose();
},*/
xOpen: function(pVtab, ppCursor){
const t = vth.xVtab(pVtab), c = vth.xCursor();
T.assert(t instanceof capi.sqlite3_vtab)
.assert(c instanceof capi.sqlite3_vtab_cursor);
wasm.setPtrValue(ppCursor, c.pointer);
vtabTrace("xOpen",...arguments," cursor =",c.pointer);
c._rowId = 0;
},
xClose: function(pCursor){
vtabTrace("xClose",...arguments);
const c = vth.xCursor(pCursor,true);
T.assert(c instanceof capi.sqlite3_vtab_cursor)
.assert(!vth.xCursor(pCursor));
c.dispose();
},
xNext: function(pCursor){
vtabTrace("xNext",...arguments);
const c = vth.xCursor(pCursor);
++c._rowId;
},
xColumn: function(pCursor, pCtx, iCol){
vtabTrace("xColumn",...arguments);
const c = vth.xCursor(pCursor);
switch(iCol){
case tmplCols.A:
@ -1966,22 +1986,24 @@ self.sqlite3InitModule = sqlite3InitModule;
}
},
xRowid: function(pCursor, ppRowid64){
vtabTrace("xRowid",...arguments);
const c = vth.xCursor(pCursor);
vth.xRowid(ppRowid64, c._rowId);
},
xEof: function(pCursor){
const c = vth.xCursor(pCursor),
rc = c._rowId>=10;
return rc;
vtabTrace("xEof",...arguments);
return vth.xCursor(pCursor)._rowId>=10;
},
xFilter: function(pCursor, idxNum, idxCStr,
argc, argv/* [sqlite3_value* ...] */){
vtabTrace("xFilter",...arguments);
const c = vth.xCursor(pCursor);
c._rowId = 0;
const list = vth.sqlite3ValuesToJs(argc, argv);
T.assert(argc === list.length);
},
xBestIndex: function(pVtab, pIdxInfo){
vtabTrace("xBestIndex",...arguments);
//const t = vth.xVtab(pVtab);
const pii = vth.xIndexInfo(pIdxInfo);
pii.$estimatedRows = 10;
@ -1993,32 +2015,50 @@ self.sqlite3InitModule = sqlite3InitModule;
const tmplMod = vth.setupModule(modConfig);
T.assert(tmplMod instanceof capi.sqlite3_module)
.assert(1===tmplMod.$iVersion);
this.db.onclose.disposeThese.push(tmplMod);
this.db.onclose.disposeAfter.push(tmplMod);
this.db.checkRc(capi.sqlite3_create_module(
this.db.pointer, modConfig.name, tmplMod.pointer, 0
));
this.db.exec([
"create virtual table testvtab2 using ",
modConfig.name,
"(arg1, arg2)"
"(arg1 blah, arg2 bloop)"
]);
const list = this.db.selectArrays(
["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(). */
this.db.onclose.disposeBefore.push(function(db){
console.debug("testvtab2 disposeBefore handler...");
db.exec(
/**
DROP TABLE is the only way to get xDestroy() to be called.
If we DROP TABLE at the end of the containing
test function, xDestroy() is called. If we instead
delay it until db.onclose.before(), we're getting
"no such table"?
*/
"DROP TABLE testvtab2"
);
});
let list = this.db.selectArrays(
"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(). */
);
T.assert(10===list.length)
.assert(1000===list[0][0])
.assert(2009===list[list.length-1][1])
.assert(2009===list[list.length-1][1]);
list = this.db.selectArrays(
"SELECT a,b FROM testvtab2 where a<9999 and b>1 order by b, a limit 5"
);
T.assert(5===list.length)
.assert(1000===list[0][0])
.assert(2004===list[list.length-1][1]);
}
})/*custom vtab #2*/
////////////////////////////////////////////////////////////////////////
.t('Close db', function(){
T.assert(this.db).assert(wasm.isPtr(this.db.pointer));
wasm.sqlite3_wasm_db_reset(this.db);
//wasm.sqlite3_wasm_db_reset(this.db); // will leak virtual tables!
this.db.close();
T.assert(!this.db.pointer);
})

View File

@ -1,5 +1,5 @@
C Got\sJS\snon-eponymous\svtable\sworking\sthanks\sto\sa\shint\sfrom\sDan.
D 2022-12-08T09:06:20.756
C More\swork\son\sthe\sJS\svtable\stests.
D 2022-12-08T10:06:07.508
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -512,7 +512,7 @@ F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c
F ext/wasm/api/sqlite3-v-helper.js ec03a222ad3551764626f14f38de1b1081bda509e098849502b498c041993a0f
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
F ext/wasm/api/sqlite3-wasm.c 97034ab4f40ec1fac71ccfaf3afffdca6b1ea2dcd95b7871527bad0f34e152b0
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 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
F ext/wasm/tester1.c-pp.js 7e3cd6cbad34f44800b2ee3e03d12aa064c598156ee779cf5d5c562156ed83f5
F ext/wasm/tester1.c-pp.js ecd0ecd6c9f0c5bce7f39a3ccb28151c7ae7b1042379a0c855e930661579f2e8
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 0ee495452c014680697aa9035c245024df127a52d1820ab0e02580a015d96ecb
R 09bfd5e1d5efadd7221593e29be578f6
P 750719b4981df62fa2ff3665e6f559ec760609ad2493495628295ad9ae6024fc
R a667c38f5946f2c41a0c069302850ad8
U stephan
Z 6e67580aa5c332587f0481ad10406d76
Z d2bb94e965d8f50e0296d40f52f07644
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
750719b4981df62fa2ff3665e6f559ec760609ad2493495628295ad9ae6024fc
51e3c3b569dce2097063d39dc484f44b2f98cad0a902ef66765ca4cdc3e06f47