1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Correct duplicate copies of sqlite3-api.js being embedded in the wasmfs-based builds.

FossilOrigin-Name: bbfcfba260f39a9c91e82d87e06b1c2cb297c03498b4530aa3e7e01ef9916012
This commit is contained in:
stephan
2022-09-28 13:01:49 +00:00
parent d98011852d
commit 5ad3631915
6 changed files with 389 additions and 216 deletions

View File

@@ -293,7 +293,7 @@ dir.sql := sql
speedtest1 := ../../speedtest1 speedtest1 := ../../speedtest1
speedtest1.c := ../../test/speedtest1.c speedtest1.c := ../../test/speedtest1.c
speedtest1.sql := $(dir.sql)/speedtest1.sql speedtest1.sql := $(dir.sql)/speedtest1.sql
speedtest1.cliflags := --size 50 --big-transactions speedtest1.cliflags := --size 25 --big-transactions
$(speedtest1): $(speedtest1):
$(MAKE) -C ../.. speedtest1 $(MAKE) -C ../.. speedtest1
$(speedtest1.sql): $(speedtest1) $(MAKEFILE) $(speedtest1.sql): $(speedtest1) $(MAKEFILE)

View File

@@ -32,12 +32,16 @@
<p id='warn-list' class='warning'>ACHTUNG: this file requires a generated input list <p id='warn-list' class='warning'>ACHTUNG: this file requires a generated input list
file. Run "make batch" from this directory to generate it. file. Run "make batch" from this directory to generate it.
</p> </p>
<p id='warn-opfs' class='warning'>WARNING: if the WASMFS/OPFS layer crashes, this page may <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 become completely unresponsive and need to be closed and reloaded to recover.
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> </p>
<hr> <hr>
<div> <div id='toolbar'>
<select class='disable-during-eval' id='sql-select'> <select class='disable-during-eval' id='sql-select'>
<option disabled selected>Populated via script code</option> <option disabled selected>Populated via script code</option>
</select> </select>
@@ -47,19 +51,40 @@
<button class='disable-during-eval' id='export-metrics'>Export metrics (WIP)</button> <button class='disable-during-eval' id='export-metrics'>Export metrics (WIP)</button>
<button class='disable-during-eval' id='db-reset'>Reset db</button> <button class='disable-during-eval' id='db-reset'>Reset db</button>
<button id='output-clear'>Clear output</button> <button id='output-clear'>Clear output</button>
<span class='input-wrapper'> <span class='input-wrapper flex-col'>
<input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input> <label for='select-impl'>Storage impl:</label>
<label for='cb-reverse-log-order'>Reverse log order</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> </span>
</div> </div>
<hr> <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> <div id='test-output'></div>
<!-- batch-runner.js "should" work with sqlite3-kvvfs so long as <!-- batch-runner.js "should" work with sqlite3-kvvfs so long as
its data sets don't violate the the storage limits. --> its data sets don't violate the the storage limits. -->
<!--script src="sqlite3-kvvfs.js"></script--> <script src="sqlite3-wasmfs.js"></script>
<script src="sqlite3.js"></script>
<script src="common/SqliteTestUtil.js"></script> <script src="common/SqliteTestUtil.js"></script>
<script src="batch-runner.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> </body>
</html> </html>

View File

@@ -19,30 +19,110 @@
const warn = console.warn.bind(console); const warn = console.warn.bind(console);
let sqlite3; 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 = { const App = {
e: { e: {
output: document.querySelector('#test-output'), output: E('#test-output'),
selSql: document.querySelector('#sql-select'), selSql: E('#sql-select'),
btnRun: document.querySelector('#sql-run'), btnRun: E('#sql-run'),
btnRunNext: document.querySelector('#sql-run-next'), btnRunNext: E('#sql-run-next'),
btnRunRemaining: document.querySelector('#sql-run-remaining'), btnRunRemaining: E('#sql-run-remaining'),
btnExportMetrics: document.querySelector('#export-metrics'), btnExportMetrics: E('#export-metrics'),
btnClear: document.querySelector('#output-clear'), btnClear: E('#output-clear'),
btnReset: document.querySelector('#db-reset'), btnReset: E('#db-reset'),
cbReverseLog: document.querySelector('#cb-reverse-log-order') cbReverseLog: E('#cb-reverse-log-order'),
selImpl: E('#select-impl')
}, },
db: Object.create(null), db: Object.create(null),
dbs: Object.create(null),
cache:{}, 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), log: console.log.bind(console),
warn: console.warn.bind(console), warn: console.warn.bind(console),
cls: function(){this.e.output.innerHTML = ''}, cls: function(){this.e.output.innerHTML = ''},
@@ -62,47 +142,159 @@
if(1) this.logHtml2('error', ...args); if(1) this.logHtml2('error', ...args);
}, },
openDb: function(fn, unlinkFirst=true){ execSql: async function(name,sql){
if(this.db.ptr){ const db = this.getSelectedDb();
toss("Already have an opened db."); const banner = "========================================";
} this.logHtml(banner,
"Running",name,'('+sql.length,'bytes) using',db.id);
const capi = this.sqlite3.capi, wasm = capi.wasm; const capi = this.sqlite3.capi, wasm = capi.wasm;
let pStmt = 0, pSqlBegin;
const stack = wasm.scopedAllocPush(); const stack = wasm.scopedAllocPush();
let pDb = 0; const metrics = db.metrics = Object.create(null);
try{ metrics.prepTotal = metrics.stepTotal = 0;
if(unlinkFirst && fn){ metrics.stmtCount = 0;
if(':'!==fn[0]) capi.wasm.sqlite3_wasm_vfs_unlink(fn); metrics.malloc = 0;
this.clearStorage(); metrics.strcpy = 0;
} this.blockControls(true);
const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE; if(this.gotErr){
const ppDb = wasm.scopedAllocPtr(); this.logErr("Cannot run SQL: error cleanup is pending.");
const rc = capi.sqlite3_open_v2(fn, ppDb, oFlags, null); return;
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);
} }
this.db.filename = fn; // Run this async so that the UI can be updated for the above header...
this.db.ptr = pDb; const dumpMetrics = ()=>{
this.logHtml("Opened db:",fn); metrics.evalSqlEnd = performance.now();
return this.db.ptr; 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){ let runner;
if(this.db.ptr){ if('websql'===db.id){
this.sqlite3.capi.sqlite3_close_v2(this.db.ptr); runner = function(resolve, reject){
this.logHtml("Closed db",this.db.filename); /* WebSQL cannot execute multiple statements, nor can it execute SQL without
if(unlink){ an explicit transaction. Thus we have to do some fragile surgery on the
capi.wasm.sqlite3_wasm_vfs_unlink(this.db.filename); input SQL. Since we're only expecting carefully curated inputs, the hope is
this.clearStorage(); that this will suffice. */
} metrics.evalSqlStart = performance.now();
this.db.ptr = this.db.filename = undefined; 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 Loads batch-runner.list and populates the selection list from
it. Returns a promise which resolves to nothing in particular it. Returns a promise which resolves to nothing in particular
@@ -123,7 +315,7 @@
} }
if(!r.ok) toss("Loading",infile,"failed:",r.statusText); if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
txt = await r.text(); txt = await r.text();
const warning = document.querySelector('#warn-list'); const warning = E('#warn-list');
if(warning) warning.remove(); if(warning) warning.remove();
}catch(e){ }catch(e){
this.logErr(e.message); this.logErr(e.message);
@@ -169,13 +361,6 @@
return sql; return sql;
}/*fetchFile()*/, }/*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. */ /** Disable or enable certain UI controls. */
blockControls: function(disable){ blockControls: function(disable){
document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable); document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable);
@@ -191,11 +376,11 @@
const rc = []; const rc = [];
Object.keys(this.metrics).sort().forEach((k)=>{ Object.keys(this.metrics).sort().forEach((k)=>{
const m = this.metrics[k]; const m = this.metrics[k];
delete m.evalFileStart; delete m.evalSqlStart;
delete m.evalFileEnd; delete m.evalSqlEnd;
const mk = Object.keys(m).sort(); const mk = Object.keys(m).sort();
if(!rc.length){ if(!rc.length){
rc.push(['file', ...mk]); rc.push(['db', ...mk]);
} }
const row = [k.split('/').pop()/*remove dir prefix from filename*/]; const row = [k.split('/').pop()/*remove dir prefix from filename*/];
rc.push(row); rc.push(row);
@@ -205,6 +390,10 @@
}, },
metricsToBlob: function(colSeparator='\t'){ metricsToBlob: function(colSeparator='\t'){
if(1){
this.logErr("TODO: re-do metrics dump");
return;
}
const ar = [], ma = this.metricsToArrays(); const ar = [], ma = this.metricsToArrays();
if(!ma.length){ if(!ma.length){
this.logErr("Metrics are empty. Run something."); this.logErr("Metrics are empty. Run something.");
@@ -239,114 +428,84 @@
*/ */
evalFile: async function(fn){ evalFile: async function(fn){
const sql = await this.fetchFile(fn); const sql = await this.fetchFile(fn);
const banner = "========================================"; return this.execSql(fn,sql);
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;
}
// 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.");
}
}
}catch(e){
if(pStmt) capi.sqlite3_finalize(pStmt);
this.gotErr = e;
//throw e;
reject(e);
return;
}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()*/, }/*evalFile()*/,
clearStorage: function(){ /**
const sz = sqlite3.capi.sqlite3_web_kvvfs_size(); Clears all DB tables in all _opened_ databases. Because of
const n = sqlite3.capi.sqlite3_web_kvvfs_clear(this.db.filename || ''); disparities between backends, we cannot simply "unlink" the
this.logHtml("Cleared kvvfs local/sessionStorage:", databases to clean them up.
n,"entries totaling approximately",sz,"bytes."); */
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();
}
}
}, },
resetDb: function(){ /**
if(this.db.ptr){ Fetches the handle of the db associated with
const fn = this.db.filename; this.e.selImpl.value, opening it if needed.
this.closeDb(true); */
this.openDb(fn,false); 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(pDb) capi.sqlite3_close_v2(pDb);
}finally{
wasm.scopedAllocPop(stack);
}
d.handle = pDb;
d.clear = ()=>clearDbSqlite(d);
} }
d.clear();
this.logHtml("Opened db:",dbId);
console.log("db =",d);
return d;
}, },
run: function(sqlite3){ run: function(sqlite3){
@@ -356,38 +515,24 @@
this.logHtml("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid()); this.logHtml("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
this.logHtml("WASM heap size =",wasm.heap8().length); this.logHtml("WASM heap size =",wasm.heap8().length);
this.loadSqlList(); this.loadSqlList();
let pDir, dbFile; if(capi.sqlite3_wasmfs_opfs_dir()){
if(sqlite3.capi.sqlite3_vfs_find('kvvfs')){ E('#warn-opfs').classList.remove('hidden');
dbFile = 1 ? 'local' : 'session';
this.logHtml("Using KVVFS storage:",dbFile);
}else{ }else{
pDir = capi.sqlite3_wasmfs_opfs_dir(); E('#warn-opfs').remove();
if(pDir){ E('option[value=wasmfs-opfs]').disabled = true;
dbFile = pDir+"/speedtest.db";
this.logHtml("Using persistent storage:",dbFile);
}else{
dbFile = ':memory:';
this.logHtml("Using",dbFile,"storage.");
}
} }
if(!pDir){ if('function' === typeof self.openDatabase){
document.querySelector('#warn-opfs').remove(); 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 who = this;
const eReverseLogNotice = document.querySelector('#reverse-log-notice');
if(this.e.cbReverseLog.checked){ if(this.e.cbReverseLog.checked){
eReverseLogNotice.classList.remove('hidden');
this.e.output.classList.add('reverse'); this.e.output.classList.add('reverse');
} }
this.e.cbReverseLog.addEventListener('change', function(){ this.e.cbReverseLog.addEventListener('change', function(){
if(this.checked){ who.e.output.classList[this.checked ? 'add' : 'remove']('reverse');
who.e.output.classList.add('reverse');
eReverseLogNotice.classList.remove('hidden');
}else{
who.e.output.classList.remove('reverse');
eReverseLogNotice.classList.add('hidden');
}
}, false); }, false);
this.e.btnClear.addEventListener('click', ()=>this.cls(), false); this.e.btnClear.addEventListener('click', ()=>this.cls(), false);
this.e.btnRun.addEventListener('click', function(){ this.e.btnRun.addEventListener('click', function(){
@@ -400,7 +545,7 @@
who.evalFile(who.e.selSql.value); who.evalFile(who.e.selSql.value);
}, false); }, false);
this.e.btnReset.addEventListener('click', function(){ this.e.btnReset.addEventListener('click', function(){
who.resetDb(); who.clearStorage(true);
}, false); }, false);
this.e.btnExportMetrics.addEventListener('click', function(){ this.e.btnExportMetrics.addEventListener('click', function(){
who.logHtml2('warning',"Triggering download of metrics CSV. Check your downloads folder."); who.logHtml2('warning',"Triggering download of metrics CSV. Check your downloads folder.");
@@ -408,6 +553,9 @@
//const m = who.metricsToArrays(); //const m = who.metricsToArrays();
//console.log("Metrics:",who.metrics, m); //console.log("Metrics:",who.metrics, m);
}); });
this.e.selImpl.addEventListener('change', function(){
who.getSelectedDb();
});
this.e.btnRunRemaining.addEventListener('click', async function(){ this.e.btnRunRemaining.addEventListener('click', async function(){
let v = who.e.selSql.value; let v = who.e.selSql.value;
const timeStart = performance.now(); const timeStart = performance.now();
@@ -430,6 +578,7 @@
self.sqlite3TestModule.initSqlite3().then(function(theEmccModule){ self.sqlite3TestModule.initSqlite3().then(function(theEmccModule){
self._MODULE = theEmccModule /* this is only to facilitate testing from the console */; self._MODULE = theEmccModule /* this is only to facilitate testing from the console */;
sqlite3 = theEmccModule.sqlite3; sqlite3 = theEmccModule.sqlite3;
console.log("App",App);
App.run(theEmccModule.sqlite3); App.run(theEmccModule.sqlite3);
}); });
})(); })();

View File

@@ -83,7 +83,7 @@ $(sqlite3-wasmfs.js): $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasm.c) $(sqlite3-wasmf
$(post-js.js) $(post-js.js)
@echo "Building $@ ..." @echo "Building $@ ..."
$(emcc.bin) -o $@ $(emcc_opt) $(emcc.flags) \ $(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) chmod -x $(sqlite3-wasmfs.wasm)
$(maybe-wasm-strip) $(sqlite3-wasmfs.wasm) $(maybe-wasm-strip) $(sqlite3-wasmfs.wasm)
@ls -la $@ $(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.wasm := $(subst .js,.wasm,$(speedtest1-wasmfs.js))
speedtest1-wasmfs.eflags := $(sqlite3-wasmfs.fsflags) speedtest1-wasmfs.eflags := $(sqlite3-wasmfs.fsflags)
speedtest1-wasmfs.eflags += $(SQLITE_OPT) -DSQLITE_WASM_WASMFS 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): $(MAKEFILE) $(MAKEFILE.wasmfs)
#$(speedtest1-wasmfs.js): $(sqlite3-wasmfs.js) #$(speedtest1-wasmfs.js): $(sqlite3-wasmfs.js)
$(speedtest1-wasmfs.js): $(speedtest1.cs) $(sqlite3-wasmfs.js) \ $(speedtest1-wasmfs.js): $(speedtest1.cs) $(sqlite3-wasmfs.js) \

View File

@@ -1,5 +1,5 @@
C Work\saround\sbroken\s-Os\swasm\sbuilds\sby\sadding\sthe\s-g3\sflag.\sUnrelated\sdocumentation\stweaks. C Correct\sduplicate\scopies\sof\ssqlite3-api.js\sbeing\sembedded\sin\sthe\swasmfs-based\sbuilds.
D 2022-09-28T07:53:47.790 D 2022-09-28T13:01:49.194
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -474,7 +474,7 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0 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/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77a5ee8bd209b5e75dd0e822bc3f6e7319dc9b36431463d4175c775170f92126 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77a5ee8bd209b5e75dd0e822bc3f6e7319dc9b36431463d4175c775170f92126
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 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-api-worker1.js d5d5b7fac4c4731c38c7e03f4f404b2a95c388a2a1d8bcf361caada572f107e0
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c b756b9c1fee9d0598f715e6df6bf089b750da24aa91bb7ef9277a037d81e7612 F ext/wasm/api/sqlite3-wasm.c b756b9c1fee9d0598f715e6df6bf089b750da24aa91bb7ef9277a037d81e7612
F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04 F ext/wasm/batch-runner.html 168fda0f66369edec6427991683af3ed3919f3713158b70571d296f9a269a281
F ext/wasm/batch-runner.js b1f443bc63a779aac97ba6d54fc731a707ece2783b94e3b019abbfa79108e9a1 F ext/wasm/batch-runner.js c8d13f673a68e2094264a0284f8775dbda4a12e609d20c501316fe641a05c760
F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962 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/testing1.js 20b37766d29815180e2e932bfc6132b649403ece1f1bf612a4712db131287970
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3 F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
F ext/wasm/testing2.js 34737da985c4cbd4812b2e7f200942662cae991c5a58ffa5d0350be089d0d410 F ext/wasm/testing2.js 34737da985c4cbd4812b2e7f200942662cae991c5a58ffa5d0350be089d0d410
F ext/wasm/wasmfs.make 52f24bc9c10e404d26bd0b0ee28d450269808a78e359d6ddedc45d31e7b9c29c F ext/wasm/wasmfs.make fb4d0b4a6596ec2ed7815508a43b77bd7d14d3910ac387eb795643e33f5a3652
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
@@ -2026,8 +2026,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 093f6e4b36db294e8e47df2fc75a4bc4fc101e2b6ff0201c912ccd1dcf394479 P f5d6bf8616341037fa3e229edf820d19acef3e0a6207a652b2b143de0a493214
R f13bcaf00e26043effcfda9235e61887 R 2d5aa67e77362d00ccd0491d8ca53ec4
U stephan U stephan
Z ec2d0b4aa25d1549f3750ebec3c29f7f Z c9260f6deeb302437c703eb12e2e08ac
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
f5d6bf8616341037fa3e229edf820d19acef3e0a6207a652b2b143de0a493214 bbfcfba260f39a9c91e82d87e06b1c2cb297c03498b4530aa3e7e01ef9916012