diff options
author | stephan <stephan@noemail.net> | 2022-09-28 13:01:49 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-09-28 13:01:49 +0000 |
commit | 5ad3631915e7f96f4647a7ca81c9b9e1d7c9375d (patch) | |
tree | 5d4070d3331783799b4d97199b6693fac884c548 | |
parent | d98011852d956758475d158a1ad2e1992ff3a647 (diff) | |
download | sqlite-5ad3631915e7f96f4647a7ca81c9b9e1d7c9375d.tar.gz sqlite-5ad3631915e7f96f4647a7ca81c9b9e1d7c9375d.zip |
Correct duplicate copies of sqlite3-api.js being embedded in the wasmfs-based builds.
FossilOrigin-Name: bbfcfba260f39a9c91e82d87e06b1c2cb297c03498b4530aa3e7e01ef9916012
-rw-r--r-- | ext/wasm/GNUmakefile | 2 | ||||
-rw-r--r-- | ext/wasm/batch-runner.html | 45 | ||||
-rw-r--r-- | ext/wasm/batch-runner.js | 531 | ||||
-rw-r--r-- | ext/wasm/wasmfs.make | 3 | ||||
-rw-r--r-- | manifest | 18 | ||||
-rw-r--r-- | manifest.uuid | 2 |
6 files changed, 387 insertions, 214 deletions
diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index 4346b6fcd..0cb05580a 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -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) diff --git a/ext/wasm/batch-runner.html b/ext/wasm/batch-runner.html index 2a6c1405c..bac80f345 100644 --- a/ext/wasm/batch-runner.html +++ b/ext/wasm/batch-runner.html @@ -32,12 +32,16 @@ <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> @@ -47,19 +51,40 @@ <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> diff --git a/ext/wasm/batch-runner.js b/ext/wasm/batch-runner.js index 24e28f6ea..7b671c9ea 100644 --- a/ext/wasm/batch-runner.js +++ b/ext/wasm/batch-runner.js @@ -19,30 +19,110 @@ 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 = ''}, @@ -62,47 +142,159 @@ 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 @@ -123,7 +315,7 @@ } 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); @@ -169,13 +361,6 @@ 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); @@ -191,11 +376,11 @@ 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); @@ -205,6 +390,10 @@ }, 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."); @@ -239,114 +428,84 @@ */ 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){ @@ -356,38 +515,24 @@ 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(){ @@ -400,7 +545,7 @@ 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."); @@ -408,6 +553,9 @@ //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(); @@ -430,6 +578,7 @@ 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); }); })(); diff --git a/ext/wasm/wasmfs.make b/ext/wasm/wasmfs.make index ccfd9063b..daa074513 100644 --- a/ext/wasm/wasmfs.make +++ b/ext/wasm/wasmfs.make @@ -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) \ @@ -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. diff --git a/manifest.uuid b/manifest.uuid index 3e1ed3faa..85803c958 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f5d6bf8616341037fa3e229edf820d19acef3e0a6207a652b2b143de0a493214
\ No newline at end of file +bbfcfba260f39a9c91e82d87e06b1c2cb297c03498b4530aa3e7e01ef9916012
\ No newline at end of file |