]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
More work on the JS vtable tests. wasm-vtab
authorstephan <stephan@noemail.net>
Thu, 8 Dec 2022 10:06:07 +0000 (10:06 +0000)
committerstephan <stephan@noemail.net>
Thu, 8 Dec 2022 10:06:07 +0000 (10:06 +0000)
FossilOrigin-Name: 51e3c3b569dce2097063d39dc484f44b2f98cad0a902ef66765ca4cdc3e06f47

ext/wasm/api/sqlite3-wasm.c
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid

index 96234bca3a471cc1184ef7b37590dd02d132f235..0262375ace92166e6bdb6f2708d75a3edf17d40c 100644 (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);
index 65ef5f6098640a0d6484a882a9de4ed2e5383919..61531cf87f59b333bd1728857467de5ff1768239 100644 (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,")");
+            xDestroy: function(pVtab){
+              vtabTrace("sqlite3_xDestroy",pVtab);
               const t = vth.xVtab(pVtab, true);
               T.assert(t);
               t.dispose();
             },
-            xDestroy: function(pVtab){
-              console.debug("sqlite3_module::xDestroy(",pVtab,")");
+            /*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);
     })
index 5a4e5ff7ad1058e949a12435c2c583a962f39b52..05d04898120370d0663b7e39e613f541d78c5804 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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.
index 49f8a8535052400e847582b556105f6e87409c59..e9d0fed4dca888764140173811858b477a09b22c 100644 (file)
@@ -1 +1 @@
-750719b4981df62fa2ff3665e6f559ec760609ad2493495628295ad9ae6024fc
\ No newline at end of file
+51e3c3b569dce2097063d39dc484f44b2f98cad0a902ef66765ca4cdc3e06f47
\ No newline at end of file