]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Correct duplicate copies of sqlite3-api.js being embedded in the wasmfs-based builds.
authorstephan <stephan@noemail.net>
Wed, 28 Sep 2022 13:01:49 +0000 (13:01 +0000)
committerstephan <stephan@noemail.net>
Wed, 28 Sep 2022 13:01:49 +0000 (13:01 +0000)
FossilOrigin-Name: bbfcfba260f39a9c91e82d87e06b1c2cb297c03498b4530aa3e7e01ef9916012

ext/wasm/GNUmakefile
ext/wasm/batch-runner.html
ext/wasm/batch-runner.js
ext/wasm/wasmfs.make
manifest
manifest.uuid

index 4346b6fcd098036b74e1b4eb9d6de2814508b2ec..0cb05580a7f0d5aefed93540e9593deee6e75e52 100644 (file)
@@ -293,7 +293,7 @@ dir.sql := sql
 speedtest1 := ../../speedtest1
 speedtest1.c := ../../test/speedtest1.c
 speedtest1.sql := $(dir.sql)/speedtest1.sql
-speedtest1.cliflags := --size 50 --big-transactions
+speedtest1.cliflags := --size 25 --big-transactions
 $(speedtest1):
        $(MAKE) -C ../.. speedtest1
 $(speedtest1.sql): $(speedtest1) $(MAKEFILE)
index 2a6c1405cfba563a08c6120a259b18ddace65c4d..bac80f345927958f2943d829f0d4b2200e6ea14c 100644 (file)
     <p id='warn-list' class='warning'>ACHTUNG: this file requires a generated input list
       file. Run "make batch" from this directory to generate it.
     </p>
-    <p id='warn-opfs' class='warning'>WARNING: if the WASMFS/OPFS layer crashes, this page may
-      become completely unresponsive and need to be closed and
-      reloaded to recover.
+    <p id='warn-opfs' class='warning hidden'>WARNING: if the WASMFS/OPFS layer crashes, this page may
+      become completely unresponsive and need to be closed and reloaded to recover.
+    </p>
+    <p id='warn-websql' class='warning hidden'>WARNING: WebSQL's limited API requires that
+      this app split up SQL batches into separate statements for execution. That will
+      only work so long as semicolon characters are <em>only</em> used to terminate
+      SQL statements, and not used within string literals or the like.
     </p>
     <hr>
-    <div>
+    <div id='toolbar'>
       <select class='disable-during-eval' id='sql-select'>
         <option disabled selected>Populated via script code</option>
       </select>
       <button class='disable-during-eval' id='export-metrics'>Export metrics (WIP)</button>
       <button class='disable-during-eval' id='db-reset'>Reset db</button>
       <button id='output-clear'>Clear output</button>
-      <span class='input-wrapper'>
-        <input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
-        <label for='cb-reverse-log-order'>Reverse log order</label>
+      <span class='input-wrapper flex-col'>
+        <label for='select-impl'>Storage impl:</label>
+        <select id='select-impl'>
+          <option value='virtualfs'>Virtual filesystem</option>
+          <option value='memdb'>:memory:</option>
+          <option value='wasmfs-opfs'>WASMFS OPFS</option>
+          <option value='websql'>WebSQL</option>
+        </select>
       </span>
     </div>
     <hr>
-    <div id='reverse-log-notice' class='hidden'>(Log output is in reverse order, newest first!)</div>
+      <span class='input-wrapper'>
+        <input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
+        <label for='cb-reverse-log-order'>Reverse log order (newest first)</label>
+      </span>
     <div id='test-output'></div>
     <!-- batch-runner.js "should" work with sqlite3-kvvfs so long as
          its data sets don't violate the the storage limits. -->
-    <!--script src="sqlite3-kvvfs.js"></script-->
-    <script src="sqlite3.js"></script>
+    <script src="sqlite3-wasmfs.js"></script>
     <script src="common/SqliteTestUtil.js"></script>
     <script src="batch-runner.js"></script>
+    <style>
+      .flex-col {
+          display: flex;
+          flex-direction: column;
+      }
+      #toolbar {
+          display: flex;
+          flex-direction: row;
+          flex-wrap: wrap;
+      }
+      #toolbar > * {
+          margin: 0.25em;
+      }
+    </style>
   </body>
 </html>
index 24e28f6eac23b9728e46363152a82755d4e6f51b..7b671c9ea170e2b0a301cc9104521f4951c2827c 100644 (file)
   const warn = console.warn.bind(console);
   let sqlite3;
 
+  /** Throws if the given sqlite3 result code is not 0. */
+  const checkSqliteRc = (dbh,rc)=>{
+    if(rc) toss("Prepare failed:",sqlite3.capi.sqlite3_errmsg(dbh));
+  };
+
+  const sqlToDrop = [
+    "SELECT type,name FROM sqlite_schema ",
+    "WHERE name NOT LIKE 'sqlite\\_%' escape '\\' ",
+    "AND name NOT LIKE '\\_%' escape '\\'"
+  ].join('');
+  
+  const clearDbWebSQL = function(db){
+    db.handle.transaction(function(tx){
+      const onErr = (e)=>console.error(e);
+      const callback = function(tx, result){
+        const rows = result.rows;
+        let i, n;
+        i = n = rows.length;
+        while(i--){
+          const row = rows.item(i);
+          const name = JSON.stringify(row.name);
+          const type = row.type;
+          switch(type){
+              case 'table': case 'view': case 'trigger':{
+                const sql2 = 'DROP '+type+' '+name;
+                warn(db.id,':',sql2);
+                tx.executeSql(sql2, [], atEnd, onErr);
+                break;
+              }
+              default:
+                warn("Unhandled db entry type:",type,name);
+                break;
+          }
+        }
+      };
+      tx.executeSql(sqlToDrop, [], callback, onErr);
+      db.handle.changeVersion(db.handle.version, "", ()=>{}, onErr, ()=>{});
+    });
+  };
+
+  const clearDbSqlite = function(db){
+    // This would be SO much easier with the oo1 API, but we specifically want to
+    // inject metrics we can't get via that API, and we cannot reliably (OPFS)
+    // open the same DB twice to clear it using that API, so...
+    let pStmt = 0, pSqlBegin;
+    const capi = sqlite3.capi, wasm = capi.wasm;
+    const scope = wasm.scopedAllocPush();
+    try {
+      const toDrop = [];
+      const ppStmt = wasm.scopedAllocPtr();
+      let rc = capi.sqlite3_prepare_v2(db.handle, sqlToDrop, -1, ppStmt, null);
+      checkSqliteRc(db.handle,rc);
+      pStmt = wasm.getPtrValue(ppStmt);
+      while(capi.SQLITE_ROW===capi.sqlite3_step(pStmt)){
+        toDrop.push(capi.sqlite3_column_text(pStmt,0),
+                    capi.sqlite3_column_text(pStmt,1));
+      }
+      capi.sqlite3_finalize(pStmt);
+      pStmt = 0;
+      while(toDrop.length){
+        const name = toDrop.pop();
+        const type = toDrop.pop();
+        let sql2;
+        switch(type){
+            case 'table': case 'view': case 'trigger':
+              sql2 = 'DROP '+type+' '+name;
+              break;
+            default:
+              warn("Unhandled db entry type:",type,name);
+              continue;
+        }
+        wasm.setPtrValue(ppStmt, 0);
+        warn(db.id,':',sql2);
+        rc = capi.sqlite3_prepare_v2(db.handle, sql2, -1, ppStmt, null);
+        checkSqliteRc(db.handle,rc);
+        pStmt = wasm.getPtrValue(ppStmt);
+        capi.sqlite3_step(pStmt);
+        capi.sqlite3_finalize(pStmt);
+        pStmt = 0;
+      }        
+    }finally{
+      if(pStmt) capi.sqlite3_finalize(pStmt);
+      wasm.scopedAllocPop(scope);
+    }
+  };
+
+  
+  const E = (s)=>document.querySelector(s);
   const App = {
     e: {
-      output: document.querySelector('#test-output'),
-      selSql: document.querySelector('#sql-select'),
-      btnRun: document.querySelector('#sql-run'),
-      btnRunNext: document.querySelector('#sql-run-next'),
-      btnRunRemaining: document.querySelector('#sql-run-remaining'),
-      btnExportMetrics: document.querySelector('#export-metrics'),
-      btnClear: document.querySelector('#output-clear'),
-      btnReset: document.querySelector('#db-reset'),
-      cbReverseLog: document.querySelector('#cb-reverse-log-order')
+      output: E('#test-output'),
+      selSql: E('#sql-select'),
+      btnRun: E('#sql-run'),
+      btnRunNext: E('#sql-run-next'),
+      btnRunRemaining: E('#sql-run-remaining'),
+      btnExportMetrics: E('#export-metrics'),
+      btnClear: E('#output-clear'),
+      btnReset: E('#db-reset'),
+      cbReverseLog: E('#cb-reverse-log-order'),
+      selImpl: E('#select-impl')
     },
     db: Object.create(null),
+    dbs: Object.create(null),
     cache:{},
-    metrics:{
-      /**
-         Map of sql-file to timing metrics. We currently only store
-         the most recent run of each file, but we really should store
-         all runs so that we can average out certain values which vary
-         significantly across runs. e.g. a mandelbrot-generating query
-         will have a wide range of runtimes when run 10 times in a
-         row.         
-      */
-    },
     log: console.log.bind(console),
     warn: console.warn.bind(console),
     cls: function(){this.e.output.innerHTML = ''},
       if(1) this.logHtml2('error', ...args);
     },
 
-    openDb: function(fn, unlinkFirst=true){
-      if(this.db.ptr){
-        toss("Already have an opened db.");
-      }
+    execSql: async function(name,sql){
+      const db = this.getSelectedDb();
+      const banner = "========================================";
+      this.logHtml(banner,
+                   "Running",name,'('+sql.length,'bytes) using',db.id);
       const capi = this.sqlite3.capi, wasm = capi.wasm;
+      let pStmt = 0, pSqlBegin;
       const stack = wasm.scopedAllocPush();
-      let pDb = 0;
-      try{
-        if(unlinkFirst && fn){
-          if(':'!==fn[0]) capi.wasm.sqlite3_wasm_vfs_unlink(fn);
-          this.clearStorage();
-        }
-        const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
-        const ppDb = wasm.scopedAllocPtr();
-        const rc = capi.sqlite3_open_v2(fn, ppDb, oFlags, null);
-        pDb = wasm.getPtrValue(ppDb)
-        if(rc){
-          if(pDb) capi.sqlite3_close_v2(pDb);
-          toss("sqlite3_open_v2() failed with code",rc);
-        }
-      }finally{
-        wasm.scopedAllocPop(stack);
+      const metrics = db.metrics = Object.create(null);
+      metrics.prepTotal = metrics.stepTotal = 0;
+      metrics.stmtCount = 0;
+      metrics.malloc = 0;
+      metrics.strcpy = 0;
+      this.blockControls(true);
+      if(this.gotErr){
+        this.logErr("Cannot run SQL: error cleanup is pending.");
+        return;
       }
-      this.db.filename = fn;
-      this.db.ptr = pDb;
-      this.logHtml("Opened db:",fn);
-      return this.db.ptr;
-    },
+      // Run this async so that the UI can be updated for the above header...
+      const dumpMetrics = ()=>{
+        metrics.evalSqlEnd = performance.now();
+        metrics.evalTimeTotal = (metrics.evalSqlEnd - metrics.evalSqlStart);
+        this.logHtml(db.id,"metrics:");//,JSON.stringify(metrics, undefined, ' '));
+        this.logHtml("prepare() count:",metrics.stmtCount);
+        this.logHtml("Time in prepare_v2():",metrics.prepTotal,"ms",
+                     "("+(metrics.prepTotal / metrics.stmtCount),"ms per prepare())");
+        this.logHtml("Time in step():",metrics.stepTotal,"ms",
+                     "("+(metrics.stepTotal / metrics.stmtCount),"ms per step())");
+        this.logHtml("Total runtime:",metrics.evalTimeTotal,"ms");
+        this.logHtml("Overhead (time - prep - step):",
+                     (metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
+        this.logHtml(banner,"End of",name);
+      };
 
-    closeDb: function(unlink=false){
-      if(this.db.ptr){
-        this.sqlite3.capi.sqlite3_close_v2(this.db.ptr);
-        this.logHtml("Closed db",this.db.filename);
-        if(unlink){
-          capi.wasm.sqlite3_wasm_vfs_unlink(this.db.filename);
-          this.clearStorage();
-        }
-        this.db.ptr = this.db.filename = undefined;
+      let runner;
+      if('websql'===db.id){
+        runner = function(resolve, reject){
+          /* WebSQL cannot execute multiple statements, nor can it execute SQL without
+             an explicit transaction. Thus we have to do some fragile surgery on the
+             input SQL. Since we're only expecting carefully curated inputs, the hope is
+             that this will suffice. */
+          metrics.evalSqlStart = performance.now();
+          const sqls = sql.split(/;+\n/);
+          const rxBegin = /^BEGIN/i, rxCommit = /^COMMIT/i, rxComment = /^\s*--/;
+          try {
+            const nextSql = ()=>{
+              let x = sqls.shift();
+              while(x && rxComment.test(x)) x = sqls.shift();
+              return x && x.trim();
+            };
+            const transaction = function(tx){
+              let s;
+              for(;s = nextSql(); s = s.nextSql()){
+                if(rxBegin.test(s)) continue;
+                else if(rxCommit.test(s)) break;
+                ++metrics.stmtCount;
+                const t = performance.now();
+                tx.executeSql(s);
+                metrics.stepTotal += performance.now() - t;
+              }
+            };
+            while(sqls.length){
+              db.handle.transaction(transaction);
+            }
+            resolve(this);
+          }catch(e){
+            this.gotErr = e;
+            reject(e);
+            return;
+          }
+        }.bind(this);
+      }else{/*sqlite3 db...*/
+        runner = function(resolve, reject){
+          metrics.evalSqlStart = performance.now();
+          try {
+            let t;
+            let sqlByteLen = sql.byteLength;
+            const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
+            t = performance.now();
+            pSqlBegin = wasm.scopedAlloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
+            metrics.malloc = performance.now() - t;
+            metrics.byteLength = sqlByteLen;
+            let pSql = pSqlBegin;
+            const pSqlEnd = pSqlBegin + sqlByteLen;
+            t = performance.now();
+            wasm.heap8().set(sql, pSql);
+            wasm.setMemValue(pSql + sqlByteLen, 0);
+            metrics.strcpy = performance.now() - t;
+            let breaker = 0;
+            while(pSql && wasm.getMemValue(pSql,'i8')){
+              wasm.setPtrValue(ppStmt, 0);
+              wasm.setPtrValue(pzTail, 0);
+              t = performance.now();
+              let rc = capi.sqlite3_prepare_v3(
+                db.handle, pSql, sqlByteLen, 0, ppStmt, pzTail
+              );
+              metrics.prepTotal += performance.now() - t;
+              checkSqliteRc(db.handle, rc);
+              pStmt = wasm.getPtrValue(ppStmt);
+              pSql = wasm.getPtrValue(pzTail);
+              sqlByteLen = pSqlEnd - pSql;
+              if(!pStmt) continue/*empty statement*/;
+              ++metrics.stmtCount;
+              t = performance.now();
+              rc = capi.sqlite3_step(pStmt);
+              capi.sqlite3_finalize(pStmt);
+              pStmt = 0;
+              metrics.stepTotal += performance.now() - t;
+              switch(rc){
+                  case capi.SQLITE_ROW:
+                  case capi.SQLITE_DONE: break;
+                  default: checkSqliteRc(db.handle, rc); toss("Not reached.");
+              }
+            }
+            resolve(this);
+          }catch(e){
+            if(pStmt) capi.sqlite3_finalize(pStmt);
+            this.gotErr = e;
+            reject(e);
+            return;
+          }finally{
+            wasm.scopedAllocPop(stack);
+          }
+        }.bind(this);
+      }
+      let p;
+      if(1){
+        p = new Promise(function(res,rej){
+          setTimeout(()=>runner(res, rej), 50)/*give UI a chance to output the "running" banner*/;
+        });
+      }else{
+        p = new Promise(runner);
+      }
+      return p.catch(
+        (e)=>this.logErr("Error via execSql("+name+",...):",e.message)
+      ).finally(()=>{
+        dumpMetrics();
+        this.blockControls(false);
+      });
+    },
+    
+    clearDb: function(){
+      const db = this.getSelectedDb();
+      if('websql'===db.id){
+        this.logErr("TODO: clear websql db.");
+        return;
       }
+      if(!db.handle) return;
+      const capi = this.sqlite3, wasm = capi.wasm;
+      //const scope = wasm.scopedAllocPush(
+      this.logErr("TODO: clear db");
     },
-
+    
     /**
        Loads batch-runner.list and populates the selection list from
        it. Returns a promise which resolves to nothing in particular
         }
         if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
         txt = await r.text();
-        const warning = document.querySelector('#warn-list');
+        const warning = E('#warn-list');
         if(warning) warning.remove();
       }catch(e){
         this.logErr(e.message);
       return sql;
     }/*fetchFile()*/,
 
-    /** Throws if the given sqlite3 result code is not 0. */
-    checkRc: function(rc){
-      if(this.db.ptr && rc){
-        toss("Prepare failed:",this.sqlite3.capi.sqlite3_errmsg(this.db.ptr));
-      }
-    },
-
     /** Disable or enable certain UI controls. */
     blockControls: function(disable){
       document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable);
       const rc = [];
       Object.keys(this.metrics).sort().forEach((k)=>{
         const m = this.metrics[k];
-        delete m.evalFileStart;
-        delete m.evalFileEnd;
+        delete m.evalSqlStart;
+        delete m.evalSqlEnd;
         const mk = Object.keys(m).sort();
         if(!rc.length){
-          rc.push(['file', ...mk]);
+          rc.push(['db', ...mk]);
         }
         const row = [k.split('/').pop()/*remove dir prefix from filename*/];
         rc.push(row);
     },
 
     metricsToBlob: function(colSeparator='\t'){
+      if(1){
+        this.logErr("TODO: re-do metrics dump");
+        return;
+      }
       const ar = [], ma = this.metricsToArrays();
       if(!ma.length){
         this.logErr("Metrics are empty. Run something.");
     */
     evalFile: async function(fn){
       const sql = await this.fetchFile(fn);
-      const banner = "========================================";
-      this.logHtml(banner,
-                   "Running",fn,'('+sql.length,'bytes)...');
-      const capi = this.sqlite3.capi, wasm = capi.wasm;
-      let pStmt = 0, pSqlBegin;
-      const stack = wasm.scopedAllocPush();
-      const metrics = this.metrics[fn] = Object.create(null);
-      metrics.prepTotal = metrics.stepTotal = 0;
-      metrics.stmtCount = 0;
-      metrics.malloc = 0;
-      metrics.strcpy = 0;
-      this.blockControls(true);
-      if(this.gotErr){
-        this.logErr("Cannot run ["+fn+"]: error cleanup is pending.");
-        return;
+      return this.execSql(fn,sql);
+    }/*evalFile()*/,
+
+    /**
+       Clears all DB tables in all _opened_ databases. Because of
+       disparities between backends, we cannot simply "unlink" the
+       databases to clean them up.
+    */
+    clearStorage: function(onlySelectedDb=false){
+      const list = onlySelectDb
+            ? [('boolean'===typeof onlySelectDb)
+                ? this.dbs[this.e.selImpl.value]
+                : onlySelectDb]
+            : Object.values(this.dbs);
+      for(let db of list){
+        if(db && db.handle){
+          this.logHtml("Clearing db",db.id);
+          d.clear();
+        }
       }
-      // Run this async so that the UI can be updated for the above header...
-      const ff = function(resolve, reject){
-        metrics.evalFileStart = performance.now();
-        try {
-          let t;
-          let sqlByteLen = sql.byteLength;
-          const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
-          t = performance.now();
-          pSqlBegin = wasm.alloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
-          metrics.malloc = performance.now() - t;
-          metrics.byteLength = sqlByteLen;
-          let pSql = pSqlBegin;
-          const pSqlEnd = pSqlBegin + sqlByteLen;
-          t = performance.now();
-          wasm.heap8().set(sql, pSql);
-          wasm.setMemValue(pSql + sqlByteLen, 0);
-          metrics.strcpy = performance.now() - t;
-          let breaker = 0;
-          while(pSql && wasm.getMemValue(pSql,'i8')){
-            wasm.setPtrValue(ppStmt, 0);
-            wasm.setPtrValue(pzTail, 0);
-            t = performance.now();
-            let rc = capi.sqlite3_prepare_v3(
-              this.db.ptr, pSql, sqlByteLen, 0, ppStmt, pzTail
-            );
-            metrics.prepTotal += performance.now() - t;
-            this.checkRc(rc);
-            pStmt = wasm.getPtrValue(ppStmt);
-            pSql = wasm.getPtrValue(pzTail);
-            sqlByteLen = pSqlEnd - pSql;
-            if(!pStmt) continue/*empty statement*/;
-            ++metrics.stmtCount;
-            t = performance.now();
-            rc = capi.sqlite3_step(pStmt);
-            capi.sqlite3_finalize(pStmt);
-            pStmt = 0;
-            metrics.stepTotal += performance.now() - t;
-            switch(rc){
-                case capi.SQLITE_ROW:
-                case capi.SQLITE_DONE: break;
-                default: this.checkRc(rc); toss("Not reached.");
-            }
+    },
+
+    /**
+       Fetches the handle of the db associated with
+       this.e.selImpl.value, opening it if needed.
+    */
+    getSelectedDb: function(){
+      if(!this.dbs.memdb){
+        for(let opt of this.e.selImpl.options){
+          const d = this.dbs[opt.value] = Object.create(null);
+          d.id = opt.value;
+          switch(d.id){
+              case 'virtualfs':
+                d.filename = 'file:/virtualfs.sqlite3?vfs=unix-none';
+                break;
+              case 'memdb':
+                d.filename = ':memory:';
+                break;
+              case 'wasmfs-opfs':
+                d.filename = 'file:'+(this.sqlite3.capi.sqlite3_wasmfs_opfs_dir())+'/wasmfs-opfs.sqlite3';
+                break;
+              case 'websql':
+                d.filename = 'websql.db';
+                break;
+              default:
+                this.logErr("Unhandled db selection option (see details in the console).",opt);
+                toss("Unhandled db init option");
           }
+        }
+      }/*first-time init*/
+      const dbId = this.e.selImpl.value;
+      const d = this.dbs[dbId];
+      if(d.handle) return d;
+      if('websql' === dbId){
+        d.handle = self.openDatabase('batch-runner', '0.1', 'foo', 1024 * 1024 * 50);
+        d.clear = ()=>clearDbWebSQL(d);
+      }else{
+        const capi = this.sqlite3.capi, wasm = capi.wasm;
+        const stack = wasm.scopedAllocPush();
+        let pDb = 0;
+        try{
+          const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
+          const ppDb = wasm.scopedAllocPtr();
+          const rc = capi.sqlite3_open_v2(d.filename, ppDb, oFlags, null);
+          pDb = wasm.getPtrValue(ppDb)
+          if(rc) toss("sqlite3_open_v2() failed with code",rc);
         }catch(e){
-          if(pStmt) capi.sqlite3_finalize(pStmt);
-          this.gotErr = e;
-          //throw e;
-          reject(e);
-          return;
+          if(pDb) capi.sqlite3_close_v2(pDb);
         }finally{
-          wasm.dealloc(pSqlBegin);
           wasm.scopedAllocPop(stack);
-          this.blockControls(false);
         }
-        metrics.evalFileEnd = performance.now();
-        metrics.evalTimeTotal = (metrics.evalFileEnd - metrics.evalFileStart);
-        this.logHtml("Metrics:");//,JSON.stringify(metrics, undefined, ' '));
-        this.logHtml("prepare() count:",metrics.stmtCount);
-        this.logHtml("Time in prepare_v2():",metrics.prepTotal,"ms",
-                     "("+(metrics.prepTotal / metrics.stmtCount),"ms per prepare())");
-        this.logHtml("Time in step():",metrics.stepTotal,"ms",
-                     "("+(metrics.stepTotal / metrics.stmtCount),"ms per step())");
-        this.logHtml("Total runtime:",metrics.evalTimeTotal,"ms");
-        this.logHtml("Overhead (time - prep - step):",
-                     (metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
-        this.logHtml(banner,"End of",fn);
-        resolve(this);
-      }.bind(this);
-      let p;
-      if(1){
-        p = new Promise(function(res,rej){
-          setTimeout(()=>ff(res, rej), 50)/*give UI a chance to output the "running" banner*/;
-        });
-      }else{
-        p = new Promise(ff);
-      }
-      return p.catch((e)=>this.logErr("Error via evalFile("+fn+"):",e.message));
-    }/*evalFile()*/,
-
-    clearStorage: function(){
-      const sz = sqlite3.capi.sqlite3_web_kvvfs_size();
-      const n = sqlite3.capi.sqlite3_web_kvvfs_clear(this.db.filename || '');
-      this.logHtml("Cleared kvvfs local/sessionStorage:",
-                   n,"entries totaling approximately",sz,"bytes.");
-    },
-
-    resetDb: function(){
-      if(this.db.ptr){
-        const fn = this.db.filename;
-        this.closeDb(true);
-        this.openDb(fn,false);
+        d.handle = pDb;
+        d.clear = ()=>clearDbSqlite(d);
       }
+      d.clear();
+      this.logHtml("Opened db:",dbId);
+      console.log("db =",d);
+      return d;
     },
 
     run: function(sqlite3){
       this.logHtml("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
       this.logHtml("WASM heap size =",wasm.heap8().length);
       this.loadSqlList();
-      let pDir, dbFile;
-      if(sqlite3.capi.sqlite3_vfs_find('kvvfs')){
-        dbFile = 1 ? 'local' : 'session';
-        this.logHtml("Using KVVFS storage:",dbFile);
+      if(capi.sqlite3_wasmfs_opfs_dir()){
+        E('#warn-opfs').classList.remove('hidden');
       }else{
-        pDir = capi.sqlite3_wasmfs_opfs_dir();
-        if(pDir){
-          dbFile = pDir+"/speedtest.db";
-          this.logHtml("Using persistent storage:",dbFile);
-        }else{
-          dbFile = ':memory:';
-          this.logHtml("Using",dbFile,"storage.");
-        }
+        E('#warn-opfs').remove();
+        E('option[value=wasmfs-opfs]').disabled = true;
       }
-      if(!pDir){
-        document.querySelector('#warn-opfs').remove();
+      if('function' === typeof self.openDatabase){
+        E('#warn-websql').classList.remove('hidden');
+      }else{
+        E('option[value=websql]').disabled = true;
+        E('#warn-websql').remove();
       }
-      this.openDb(dbFile, true);
       const who = this;
-      const eReverseLogNotice = document.querySelector('#reverse-log-notice');
       if(this.e.cbReverseLog.checked){
-        eReverseLogNotice.classList.remove('hidden');
         this.e.output.classList.add('reverse');
       }
       this.e.cbReverseLog.addEventListener('change', function(){
-        if(this.checked){
-          who.e.output.classList.add('reverse');
-          eReverseLogNotice.classList.remove('hidden');
-        }else{
-          who.e.output.classList.remove('reverse');
-          eReverseLogNotice.classList.add('hidden');
-        }
+        who.e.output.classList[this.checked ? 'add' : 'remove']('reverse');
       }, false);
       this.e.btnClear.addEventListener('click', ()=>this.cls(), false);
       this.e.btnRun.addEventListener('click', function(){
         who.evalFile(who.e.selSql.value);
       }, false);
       this.e.btnReset.addEventListener('click', function(){
-        who.resetDb();
+        who.clearStorage(true);
       }, false);
       this.e.btnExportMetrics.addEventListener('click', function(){
         who.logHtml2('warning',"Triggering download of metrics CSV. Check your downloads folder.");
         //const m = who.metricsToArrays();
         //console.log("Metrics:",who.metrics, m);
       });
+      this.e.selImpl.addEventListener('change', function(){
+        who.getSelectedDb();
+      });
       this.e.btnRunRemaining.addEventListener('click', async function(){
         let v = who.e.selSql.value;
         const timeStart = performance.now();
   self.sqlite3TestModule.initSqlite3().then(function(theEmccModule){
     self._MODULE = theEmccModule /* this is only to facilitate testing from the console */;
     sqlite3 = theEmccModule.sqlite3;
+    console.log("App",App);
     App.run(theEmccModule.sqlite3);
   });
 })();
index ccfd9063b4cc8e9b7581b18696037d8c8754a9be..daa074513d5a94941e005a4a2989a5a7021d00f4 100644 (file)
@@ -83,7 +83,7 @@ $(sqlite3-wasmfs.js): $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasm.c) $(sqlite3-wasmf
     $(post-js.js)
        @echo "Building $@ ..."
        $(emcc.bin) -o $@ $(emcc_opt) $(emcc.flags) \
-      $(sqlite3-wasmfs.cflags) $(speedtest1-common.eflags) $(sqlite3-wasmfs.jsflags) $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasmfs.extra.c)
+      $(sqlite3-wasmfs.cflags) $(sqlite3-wasmfs.jsflags) $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasmfs.extra.c)
        chmod -x $(sqlite3-wasmfs.wasm)
        $(maybe-wasm-strip) $(sqlite3-wasmfs.wasm)
        @ls -la $@ $(sqlite3-wasmfs.wasm)
@@ -99,7 +99,6 @@ speedtest1-wasmfs.js := speedtest1-wasmfs.js
 speedtest1-wasmfs.wasm := $(subst .js,.wasm,$(speedtest1-wasmfs.js))
 speedtest1-wasmfs.eflags := $(sqlite3-wasmfs.fsflags)
 speedtest1-wasmfs.eflags += $(SQLITE_OPT) -DSQLITE_WASM_WASMFS
-speedtest1-wasmfs.eflags += --post-js=$(sqlite3-wasmfs.js)
 $(speedtest1-wasmfs.js): $(MAKEFILE) $(MAKEFILE.wasmfs)
 #$(speedtest1-wasmfs.js): $(sqlite3-wasmfs.js)
 $(speedtest1-wasmfs.js): $(speedtest1.cs) $(sqlite3-wasmfs.js) \
index 5a971e1b74e4c871542f5ecafc4e0af0f0a69605..465c029488825dc0478b6603e27b373b35d4d5f1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Work\saround\sbroken\s-Os\swasm\sbuilds\sby\sadding\sthe\s-g3\sflag.\sUnrelated\sdocumentation\stweaks.
-D 2022-09-28T07:53:47.790
+C Correct\sduplicate\scopies\sof\ssqlite3-api.js\sbeing\sembedded\sin\sthe\swasmfs-based\sbuilds.
+D 2022-09-28T13:01:49.194
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -474,7 +474,7 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
 F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
 F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0
-F ext/wasm/GNUmakefile 984c33a37fa34786d6be2c79ef19421b3c1a054dfdb56ea09313077de4aa19f6
+F ext/wasm/GNUmakefile 86ee7562063275779b108957db5bc7fdb18df4f6c506abbe28132b4fb071988e
 F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77a5ee8bd209b5e75dd0e822bc3f6e7319dc9b36431463d4175c775170f92126
 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
@@ -489,8 +489,8 @@ F ext/wasm/api/sqlite3-api-prologue.js 2a0dedb8127e8983d3199edea55151a45186b4626
 F ext/wasm/api/sqlite3-api-worker1.js d5d5b7fac4c4731c38c7e03f4f404b2a95c388a2a1d8bcf361caada572f107e0
 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
 F ext/wasm/api/sqlite3-wasm.c b756b9c1fee9d0598f715e6df6bf089b750da24aa91bb7ef9277a037d81e7612
-F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04
-F ext/wasm/batch-runner.js b1f443bc63a779aac97ba6d54fc731a707ece2783b94e3b019abbfa79108e9a1
+F ext/wasm/batch-runner.html 168fda0f66369edec6427991683af3ed3919f3713158b70571d296f9a269a281
+F ext/wasm/batch-runner.js c8d13f673a68e2094264a0284f8775dbda4a12e609d20c501316fe641a05c760
 F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c
 F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
 F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
@@ -530,7 +530,7 @@ F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d766
 F ext/wasm/testing1.js 20b37766d29815180e2e932bfc6132b649403ece1f1bf612a4712db131287970
 F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
 F ext/wasm/testing2.js 34737da985c4cbd4812b2e7f200942662cae991c5a58ffa5d0350be089d0d410
-F ext/wasm/wasmfs.make 52f24bc9c10e404d26bd0b0ee28d450269808a78e359d6ddedc45d31e7b9c29c
+F ext/wasm/wasmfs.make fb4d0b4a6596ec2ed7815508a43b77bd7d14d3910ac387eb795643e33f5a3652
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
@@ -2026,8 +2026,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 093f6e4b36db294e8e47df2fc75a4bc4fc101e2b6ff0201c912ccd1dcf394479
-R f13bcaf00e26043effcfda9235e61887
+P f5d6bf8616341037fa3e229edf820d19acef3e0a6207a652b2b143de0a493214
+R 2d5aa67e77362d00ccd0491d8ca53ec4
 U stephan
-Z ec2d0b4aa25d1549f3750ebec3c29f7f
+Z c9260f6deeb302437c703eb12e2e08ac
 # Remove this line to create a well-formed Fossil manifest.
index 3e1ed3faa8ab87a688f6874885ceb361e31315bc..85803c958df704d9700dc66878aa55f31e1882dc 100644 (file)
@@ -1 +1 @@
-f5d6bf8616341037fa3e229edf820d19acef3e0a6207a652b2b143de0a493214
\ No newline at end of file
+bbfcfba260f39a9c91e82d87e06b1c2cb297c03498b4530aa3e7e01ef9916012
\ No newline at end of file