From: stephan Date: Sat, 29 Nov 2025 16:41:27 +0000 (+0000) Subject: Add a kvvfs vtab for inspecting the storage state. This is for testing and my own... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=facbf34cbfefa3ba4be2cf40235695368e960fd9;p=thirdparty%2Fsqlite.git Add a kvvfs vtab for inspecting the storage state. This is for testing and my own edification, not part of the public API. FossilOrigin-Name: eaff2e8b7f63575e85fb9be800a2c59163e402d6a25fc6a955b9df15afe13b92 --- diff --git a/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js index 9a7867a48a..5c6cb9302f 100644 --- a/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js +++ b/ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js @@ -97,7 +97,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ if( !pKvvfs ) return /* nothing to do */; if( 0 ){ - /* This working would be our proverbial holy grail. */ + /* This working would be our proverbial holy grail, in that it + would allow us to eliminate the current default VFS, which + relies on POSIX I/O APIs. Eliminating that dependency would get + us one giant step closer to creating wasi-sdk builds. */ capi.sqlite3_vfs_register(pKvvfs, 1); } @@ -466,6 +469,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const jsKeyForStorage = (store,zClass,zKey)=> wasm.cstrToJs(zKeyForStorage(store, zClass, zKey)); + const storageGetDbSize = (store)=>+store.storage.getItem(store.keyPrefix + "sz"); + /** sqlite3_file pointers => objects, each of which has: @@ -1434,6 +1439,159 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }; }/*sqlite3.oo1.JsStorageDb*/ + if( sqlite3.__isUnderTest && sqlite3.vtab ){ + /** + An eponymous vtab for inspecting the kvvfs state. This is only + intended for use in testing and development, not part of the + public API. + */ + const cols = Object.assign(Object.create(null),{ + rowid: {type: 'INTEGER'}, + name: {type: 'TEXT'}, + nRef: {type: 'INTEGER'}, + nOpen: {type: 'INTEGER'}, + isTransient: {type: 'INTEGER'}, + dbSize: {type: 'INTEGER'} + }); + Object.keys(cols).forEach((v,i)=>cols[v].colId = i); + + const VT = sqlite3.vtab; + const cursorState = function(cursor){ + return ((cursor instanceof capi.sqlite3_vtab_cursor) + ? cursor + : VT.xCursor.get(cursor) + ).vTabState + ??= Object.assign(Object.create(null),{ + rowid: 0, + names: Object.keys(cache.storagePool) + .filter(v=>!cache.rxJournalSuffix.test(v)), + row: function(){ + return cache.storagePool[this.names[this.rowid]]; + } + }); + }; + + const dbg = 1 ? ()=>{} : (...args)=>debug("vtab",...args); + + const theModule = function f(){ + return f.mod ??= new sqlite3.capi.sqlite3_module().setupModule({ + catchExceptions: true, + methods: { + xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){ + dbg("xConnect"); + try{ + const xcol = []; + Object.keys(cols).forEach((k)=>{ + xcol.push(k+" "+cols[k].type); + }); + const rc = capi.sqlite3_declare_vtab( + pDb, "CREATE TABLE ignored("+xcol.join(',')+")" + ); + if(0===rc){ + const t = VT.xVtab.create(ppVtab); + util.assert( + (t === VT.xVtab.get(wasm.peekPtr(ppVtab))), + "output pointer check failed" + ); + } + return rc; + }catch(e){ + return VT.xErrror('xConnect', e, capi.SQLITE_ERROR); + } + }, + xCreate: wasm.ptr.null, // eponymous only + xDisconnect: function(pVtab){ + dbg("xDisconnect",...arguments); + VT.xVtab.dispose(pVtab); + return 0; + }, + xOpen: function(pVtab, ppCursor){ + dbg("xOpen",...arguments); + VT.xCursor.create(ppCursor); + return 0; + }, + xClose: function(pCursor){ + dbg("xClose",...arguments); + const c = VT.xCursor.unget(pCursor); + delete c.vTabState; + c.dispose(); + return 0; + }, + xNext: function(pCursor){ + dbg("xNext",...arguments); + const c = VT.xCursor.get(pCursor); + ++cursorState(c).rowid; + return 0; + }, + xColumn: function(pCursor, pCtx, iCol){ + dbg("xColumn",...arguments); + //const c = VT.xCursor.get(pCursor); + const st = cursorState(pCursor); + const store = st.row(); + util.assert(store, "Unexpected xColumn call"); + switch(iCol){ + case cols.rowid.colId: + capi.sqlite3_result_int(pCtx, st.rowid); + break; + case cols.name.colId: + capi.sqlite3_result_text(pCtx, store.jzClass, -1, capi.SQLITE_TRANSIENT); + break; + case cols.nRef.colId: + capi.sqlite3_result_int(pCtx, store.refc); + break; + case cols.nOpen.colId: + capi.sqlite3_result_int(pCtx, store.files.length); + break; + case cols.isTransient.colId: + capi.sqlite3_result_int(pCtx, !!store.deleteAtRefc0); + break; + case cols.dbSize.colId: + capi.sqlite3_result_int(pCtx, storageGetDbSize(store)); + break; + default: + capi.sqlite3_result_error(pCtx, "Invalid column id: "+iCol); + return capi.SQLITE_RANGE; + } + return 0; + }, + xRowid: function(pCursor, ppRowid64){ + dbg("xRowid",...arguments); + const st = cursorState(pCursor); + VT.xRowid(ppRowid64, st.rowid); + return 0; + }, + xEof: function(pCursor){ + dbg("xEof",...arguments); + const st = cursorState(pCursor); + return !st.row(); + }, + xFilter: function(pCursor, idxNum, idxCStr, + argc, argv/* [sqlite3_value* ...] */){ + dbg("xFilter",...arguments); + const st = cursorState(pCursor); + st.rowid = 0; + return 0; + }, + xBestIndex: function(pVtab, pIdxInfo){ + dbg("xBestIndex",...arguments); + //const t = VT.xVtab.get(pVtab); + const pii = new capi.sqlite3_index_info(pIdxInfo); + pii.$estimatedRows = cache.storagePool.size; + pii.$estimatedCost = 1.0; + pii.dispose(); + return 0; + } + } + })/*setupModule*/; + }/*theModule()*/; + + sqlite3.kvvfs.create_module = function(pDb, name="sqlite_kvvfs"){ + return capi.sqlite3_create_module(pDb, name, theModule(), + wasm.ptr.null); + }; + + }/* virtual table */ + })/*globalThis.sqlite3ApiBootstrap.initializers*/; //#savepoint rollback //#endif not omit-kvvfs diff --git a/ext/wasm/api/sqlite3-vtab-helper.c-pp.js b/ext/wasm/api/sqlite3-vtab-helper.c-pp.js index 4c2338fc5a..80f4bfac23 100644 --- a/ext/wasm/api/sqlite3-vtab-helper.c-pp.js +++ b/ext/wasm/api/sqlite3-vtab-helper.c-pp.js @@ -172,10 +172,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ Works like unget() plus it calls dispose() on the StructType object. */ - dispose: (pCObj)=>{ - const o = __xWrap(pCObj,true); - if(o) o.dispose(); - } + dispose: (pCObj)=>__xWrap(pCObj,true)?.dispose?.() }); }; diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index 4056d54780..b7d4afe152 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -2631,7 +2631,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .assert(wasm.isPtr(tmplMod.$xRowid)) .assert(wasm.isPtr(tmplMod.$xCreate)) .assert(tmplMod.$xCreate === tmplMod.$xConnect, - "setup() must make these equivalent and "+ + "setupModule() must make these equivalent and "+ "installMethods() must avoid re-compiling identical functions"); tmplMod.$xCreate = wasm.ptr.null /* make tmplMod eponymous-only */; let rc = capi.sqlite3_create_module( @@ -3265,12 +3265,30 @@ globalThis.sqlite3InitModule = sqlite3InitModule; db.close(); const after = JSON.stringify(counts); T.assert( before===after, "Expecting no events after unlistening." ); + sqlite3.kvvfs.unlink(filename); }finally{ db?.close?.(); } - } - })/*kvvfs listeners + })/*kvvfs listeners */ + .t({ + name: 'kvvfs vtab', + predicate: (sqlite3)=>!!sqlite3.kvvfs.create_module, + test: function(sqlite3){ + const kvvfs = sqlite3.kvvfs; + const db = new sqlite3.oo1.DB(); + try{ + kvvfs.create_module(db); + /*db.exec([ + "create virtual table vt using kvvfs()" + ]);*/ + let rc = db.selectObjects("select * from sqlite_kvvfs"); + console.log("vtab rc", rc); + }finally{ + db.close(); + } + } + })/* kvvfs vtab */ //#if enable-see .t({ name: 'kvvfs SEE encryption in sessionStorage', diff --git a/manifest b/manifest index b9ba6731a4..b1271a14aa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\sinto\sthe\skvvfs-v2\sbranch. -D 2025-11-28T22:17:02.501 +C Add\sa\skvvfs\svtab\sfor\sinspecting\sthe\sstorage\sstate.\sThis\sis\sfor\stesting\sand\smy\sown\sedification,\snot\spart\sof\sthe\spublic\sAPI. +D 2025-11-29T16:41:27.823 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -600,10 +600,10 @@ F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1041dd645e8e821c082b628cd8d9acf70c667 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966 F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d -F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js e08a013432aeb5e38f043829d8fa3dca06e124c117294d4c0a23db69138ae5b1 +F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 3f65769166670f2bd044374958f8eeb43b9fae8179ef58506acee38cb435de54 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js a2eea6442556867b589e04107796c6e1d04a472219529eeb45b7cd221d7d048b F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 88ce2078267a2d1af57525a32d896295f4a8db7664de0e17e82dc9ff006ed8d3 -F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86 +F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81 F ext/wasm/api/sqlite3-wasm.c 1d6f8f3486f4f9a21db597f84a015fe9bb7c111652ce6beacdaceb0d162617ff F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bda1c75bd674a92a0e27cc2f3d46dbbf21e422413f8046814515a0bd7409328a F ext/wasm/api/sqlite3-worker1.c-pp.js 802d69ead8c38dc1be52c83afbfc77e757da8a91a2e159e7ed3ecda8b8dba2e7 @@ -625,7 +625,7 @@ F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535 F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f F ext/wasm/fiddle/fiddle-worker.js 7798af02e672e088ff192716f80626c8895e19301a65b8af6d5d12b2d13d2451 F ext/wasm/fiddle/fiddle.js 84fd75967e0af8b69d3dd849818342227d0f81d13db92e0dcbc63649b31a4893 -F ext/wasm/fiddle/index.c-pp.html 72c7e5517217960b3809648429ea396a7cbad0ffb2c92f6a2f5703abecb27317 w ext/wasm/fiddle/index.html +F ext/wasm/fiddle/index.c-pp.html 72c7e5517217960b3809648429ea396a7cbad0ffb2c92f6a2f5703abecb27317 F ext/wasm/index-dist.html db23748044e286773f2768eec287669501703b5d5f72755e8db73607dc54d290 F ext/wasm/index.html 54e27db740695ab2cb296e02d42c4c66b3f11b65797340d19fa6590f5b287da1 F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b @@ -647,7 +647,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555 F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c F ext/wasm/tester1-worker.c-pp.html 0e432ec2c0d99cd470484337066e8d27e7aee4641d97115338f7d962bf7b081a F ext/wasm/tester1.c-pp.html 52d88fe2c6f21a046030a36410b4839b632f4424028197a45a3d5669ea724ddb -F ext/wasm/tester1.c-pp.js f7a2aa456af7b713772d2750c0b9e7693fb2ddbfa152faf0d41a4ef9121ac57b +F ext/wasm/tester1.c-pp.js 05bb1099472d410b8b5b822af0f362ec565c617eea924d5f53a3b643fc1466d8 F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 @@ -2180,8 +2180,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5ec20ebe057af297f5e0ccc0d7184ab0ed720f91db0f470a7cf827df0f2aa530 4384c9a108b58a0b8c38c51678aad871f088358b9bff3922299cc7ddb3d247ce -R 6acef3505b89c0d3fbc9ed9322f624c8 +P 0e1a6ca0f1123da680918027b16608bf87593a9d91f7b1f3fc0c3a454185740d +R 2aee549605fa5886143a182c3a989cec U stephan -Z f3d7f6b7a89a18464041eaff89f54170 +Z db62e7bb06a82ac76e6e3341ca1c99a3 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 20074f8777..9f0211379b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0e1a6ca0f1123da680918027b16608bf87593a9d91f7b1f3fc0c3a454185740d +eaff2e8b7f63575e85fb9be800a2c59163e402d6a25fc6a955b9df15afe13b92