mirror of
https://github.com/sqlite/sqlite.git
synced 2025-10-21 11:13:54 +03:00
Overhaul the wasm build to (A) support more coexisting variants, e.g. 32/64-bit of both vanilla and esm, and (B) build each variant to its own subdir so that they can build in parallel. It can, with make -j4, now build all new variants in half the time it previously took for just the 32-bit builds. The new build logging output, though unconventional, serves two purposes: (A) improve my build-time situational awareness and (B) it help demystify some of the build steps and output files.
FossilOrigin-Name: 2f4be98614b49def2c2951887796c736269ef3bb7ba5b045cae5f748ae165a83
This commit is contained in:
1469
ext/wasm/GNUmakefile
1469
ext/wasm/GNUmakefile
File diff suppressed because it is too large
Load Diff
@@ -69,6 +69,7 @@ const toExportForESM =
|
||||
EmscriptenModule /* see post-js-header/footer.js */,
|
||||
!!ff.__isUnderTest
|
||||
);
|
||||
sIMS.debugModule("sqlite3InitModule() sqlite3 =",s);
|
||||
//const rv = s.asyncPostInit();
|
||||
//delete s.asyncPostInit;
|
||||
//#if wasmfs
|
||||
|
@@ -36,7 +36,6 @@ if( 'undefined' === typeof EmscriptenModule/*from post-js-header.js*/ ){
|
||||
throw new Error("sqlite3-api-cleanup.js expects to be running in the "+
|
||||
"context of its Emscripten module loader.");
|
||||
}
|
||||
|
||||
try{
|
||||
/* Config options for sqlite3ApiBootstrap(). */
|
||||
const bootstrapConfig = Object.assign(
|
||||
@@ -60,6 +59,8 @@ try{
|
||||
bootstrapConfig.wasmPtrIR =
|
||||
'number'===(typeof bootstrapConfig.exports.sqlite3_libversion())
|
||||
? 'i32' :'i64';
|
||||
const sIMS = sqlite3InitScriptInfo;
|
||||
sIMS.debugModule("Bootstrapping lib config", sIMS);
|
||||
|
||||
/**
|
||||
For purposes of the Emscripten build, call sqlite3ApiBootstrap().
|
||||
|
@@ -252,10 +252,12 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
|
||||
|
||||
globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
worker: function(){
|
||||
//#if target=es6-module
|
||||
//#if target=es6-bundler-friendly
|
||||
return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{
|
||||
type: 'module'
|
||||
});
|
||||
//#elif target=es6-module
|
||||
return new Worker(new URL("sqlite3-worker1.js", import.meta.url));
|
||||
//#else
|
||||
let theJs = "sqlite3-worker1.js";
|
||||
if(this.currentScript){
|
||||
|
@@ -34,6 +34,8 @@
|
||||
*/
|
||||
//#if target=es6-bundler-friendly
|
||||
import {default as sqlite3InitModule} from './sqlite3-bundler-friendly.mjs';
|
||||
//#elif target=es6-module
|
||||
return new Worker(new URL("sqlite3.js", import.meta.url));
|
||||
//#else
|
||||
"use strict";
|
||||
{
|
||||
|
@@ -1,86 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<link rel="stylesheet" href="common/testing.css"/>
|
||||
<title>sqlite3-api batch SQL runner for the SAHPool VFS</title>
|
||||
</head>
|
||||
<body>
|
||||
<header id='titlebar'><span>sqlite3-api batch SQL runner for the SAHPool VFS</span></header>
|
||||
<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' id='lbl-reverse-log-order'>Reverse log order</label>
|
||||
</span>
|
||||
</div>
|
||||
<div id='test-output' class='reverse'></div>
|
||||
<script>
|
||||
(function(){
|
||||
const E = (sel)=>document.querySelector(sel);
|
||||
|
||||
const eOut = E('#test-output');
|
||||
const log2 = function(cssClass,...args){
|
||||
let ln;
|
||||
if(1 || cssClass){
|
||||
ln = document.createElement('div');
|
||||
if(cssClass) ln.classList.add(cssClass);
|
||||
ln.append(document.createTextNode(args.join(' ')));
|
||||
}else{
|
||||
// This doesn't work with the "reverse order" option!
|
||||
ln = document.createTextNode(args.join(' ')+'\n');
|
||||
}
|
||||
eOut.append(ln);
|
||||
};
|
||||
const log = (...args)=>{
|
||||
//console.log(...args);
|
||||
log2('', ...args);
|
||||
};
|
||||
const logErr = function(...args){
|
||||
console.error(...args);
|
||||
log2('error', ...args);
|
||||
};
|
||||
const logWarn = function(...args){
|
||||
console.warn(...args);
|
||||
log2('warning', ...args);
|
||||
};
|
||||
|
||||
const cbReverseLog = E('#cb-reverse-log-order');
|
||||
const lblReverseLog = E('#lbl-reverse-log-order');
|
||||
if(cbReverseLog.checked){
|
||||
lblReverseLog.classList.add('warning');
|
||||
eOut.classList.add('reverse');
|
||||
}
|
||||
cbReverseLog.addEventListener('change', function(){
|
||||
if(this.checked){
|
||||
eOut.classList.add('reverse');
|
||||
lblReverseLog.classList.add('warning');
|
||||
}else{
|
||||
eOut.classList.remove('reverse');
|
||||
lblReverseLog.classList.remove('warning');
|
||||
}
|
||||
}, false);
|
||||
|
||||
const w = new Worker('batch-runner-sahpool.js?sqlite3.dir=jswasm');
|
||||
w.onmessage = function(msg){
|
||||
msg = msg.data;
|
||||
switch(msg.type){
|
||||
case 'stdout': log(...msg.data); break;
|
||||
case 'warn': logWarn(...msg.data); break;
|
||||
case 'error': logErr(...msg.data); break;
|
||||
default:
|
||||
logErr("Unhandled worker message type:",msg);
|
||||
break;
|
||||
}
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
#test-output {
|
||||
white-space: break-spaces;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
2023-11-30
|
||||
|
||||
The author disclaims copyright to this source code. In place of a
|
||||
legal notice, here is a blessing:
|
||||
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
|
||||
***********************************************************************
|
||||
|
||||
A basic batch SQL runner for the SAHPool VFS. This file must be run in
|
||||
a worker thread. This is not a full-featured app, just a way to get some
|
||||
measurements for batch execution of SQL for the OPFS SAH Pool VFS.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const wMsg = function(msgType,...args){
|
||||
postMessage({
|
||||
type: msgType,
|
||||
data: args
|
||||
});
|
||||
};
|
||||
const toss = function(...args){throw new Error(args.join(' '))};
|
||||
const warn = (...args)=>{ wMsg('warn',...args); };
|
||||
const error = (...args)=>{ wMsg('error',...args); };
|
||||
const log = (...args)=>{ wMsg('stdout',...args); }
|
||||
let sqlite3;
|
||||
const urlParams = new URL(globalThis.location.href).searchParams;
|
||||
const cacheSize = (()=>{
|
||||
if(urlParams.has('cachesize')) return +urlParams.get('cachesize');
|
||||
return 200;
|
||||
})();
|
||||
|
||||
|
||||
/** 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 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...
|
||||
const rc = sqlite3.wasm.exports.sqlite3_wasm_db_reset(db.handle);
|
||||
log("reset db rc =",rc,db.id, db.filename);
|
||||
};
|
||||
|
||||
const App = {
|
||||
db: undefined,
|
||||
cache:Object.create(null),
|
||||
log: log,
|
||||
warn: warn,
|
||||
error: error,
|
||||
metrics: {
|
||||
fileCount: 0,
|
||||
runTimeMs: 0,
|
||||
prepareTimeMs: 0,
|
||||
stepTimeMs: 0,
|
||||
stmtCount: 0,
|
||||
strcpyMs: 0,
|
||||
sqlBytes: 0
|
||||
},
|
||||
fileList: undefined,
|
||||
execSql: async function(name,sql){
|
||||
const db = this.db;
|
||||
const banner = "========================================";
|
||||
this.log(banner,
|
||||
"Running",name,'('+sql.length,'bytes)');
|
||||
const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
|
||||
let pStmt = 0, pSqlBegin;
|
||||
const metrics = db.metrics = Object.create(null);
|
||||
metrics.prepTotal = metrics.stepTotal = 0;
|
||||
metrics.stmtCount = 0;
|
||||
metrics.malloc = 0;
|
||||
metrics.strcpy = 0;
|
||||
if(this.gotErr){
|
||||
this.error("Cannot run SQL: error cleanup is pending.");
|
||||
return;
|
||||
}
|
||||
// Run this async so that the UI can be updated for the above header...
|
||||
const endRun = ()=>{
|
||||
metrics.evalSqlEnd = performance.now();
|
||||
metrics.evalTimeTotal = (metrics.evalSqlEnd - metrics.evalSqlStart);
|
||||
this.log("metrics:",JSON.stringify(metrics, undefined, ' '));
|
||||
this.log("prepare() count:",metrics.stmtCount);
|
||||
this.log("Time in prepare_v2():",metrics.prepTotal,"ms",
|
||||
"("+(metrics.prepTotal / metrics.stmtCount),"ms per prepare())");
|
||||
this.log("Time in step():",metrics.stepTotal,"ms",
|
||||
"("+(metrics.stepTotal / metrics.stmtCount),"ms per step())");
|
||||
this.log("Total runtime:",metrics.evalTimeTotal,"ms");
|
||||
this.log("Overhead (time - prep - step):",
|
||||
(metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
|
||||
this.log(banner,"End of",name);
|
||||
this.metrics.prepareTimeMs += metrics.prepTotal;
|
||||
this.metrics.stepTimeMs += metrics.stepTotal;
|
||||
this.metrics.stmtCount += metrics.stmtCount;
|
||||
this.metrics.strcpyMs += metrics.strcpy;
|
||||
this.metrics.sqlBytes += sql.length;
|
||||
};
|
||||
|
||||
const runner = function(resolve, reject){
|
||||
++this.metrics.fileCount;
|
||||
metrics.evalSqlStart = performance.now();
|
||||
const stack = wasm.scopedAllocPush();
|
||||
try {
|
||||
let t, rc;
|
||||
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.poke(pSql + sqlByteLen, 0);
|
||||
//log("SQL:",wasm.cstrToJs(pSql));
|
||||
metrics.strcpy = performance.now() - t;
|
||||
let breaker = 0;
|
||||
while(pSql && wasm.peek8(pSql)){
|
||||
wasm.pokePtr(ppStmt, 0);
|
||||
wasm.pokePtr(pzTail, 0);
|
||||
t = performance.now();
|
||||
rc = capi.sqlite3_prepare_v2(
|
||||
db.handle, pSql, sqlByteLen, ppStmt, pzTail
|
||||
);
|
||||
metrics.prepTotal += performance.now() - t;
|
||||
checkSqliteRc(db.handle, rc);
|
||||
pStmt = wasm.peekPtr(ppStmt);
|
||||
pSql = wasm.peekPtr(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);
|
||||
}finally{
|
||||
capi.sqlite3_exec(db.handle,"rollback;",0,0,0);
|
||||
wasm.scopedAllocPop(stack);
|
||||
}
|
||||
}.bind(this);
|
||||
const p = new Promise(runner);
|
||||
return p.catch(
|
||||
(e)=>this.error("Error via execSql("+name+",...):",e.message)
|
||||
).finally(()=>{
|
||||
endRun();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Loads batch-runner.list and populates the selection list from
|
||||
it. Returns a promise which resolves to nothing in particular
|
||||
when it completes. Only intended to be run once at the start
|
||||
of the app.
|
||||
*/
|
||||
loadSqlList: async function(){
|
||||
const infile = 'batch-runner.list';
|
||||
this.log("Loading list of SQL files:", infile);
|
||||
let txt;
|
||||
try{
|
||||
const r = await fetch(infile);
|
||||
if(404 === r.status){
|
||||
toss("Missing file '"+infile+"'.");
|
||||
}
|
||||
if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
|
||||
txt = await r.text();
|
||||
}catch(e){
|
||||
this.error(e.message);
|
||||
throw e;
|
||||
}
|
||||
App.fileList = txt.split(/\n+/).filter(x=>!!x);
|
||||
this.log("Loaded",infile);
|
||||
},
|
||||
|
||||
/** Fetch ./fn and return its contents as a Uint8Array. */
|
||||
fetchFile: async function(fn, cacheIt=false){
|
||||
if(cacheIt && this.cache[fn]) return this.cache[fn];
|
||||
this.log("Fetching",fn,"...");
|
||||
let sql;
|
||||
try {
|
||||
const r = await fetch(fn);
|
||||
if(!r.ok) toss("Fetch failed:",r.statusText);
|
||||
sql = new Uint8Array(await r.arrayBuffer());
|
||||
}catch(e){
|
||||
this.error(e.message);
|
||||
throw e;
|
||||
}
|
||||
this.log("Fetched",sql.length,"bytes from",fn);
|
||||
if(cacheIt) this.cache[fn] = sql;
|
||||
return sql;
|
||||
}/*fetchFile()*/,
|
||||
|
||||
/**
|
||||
Converts this.metrics() to a form which is suitable for easy conversion to
|
||||
CSV. It returns an array of arrays. The first sub-array is the column names.
|
||||
The 2nd and subsequent are the values, one per test file (only the most recent
|
||||
metrics are kept for any given file).
|
||||
*/
|
||||
metricsToArrays: function(){
|
||||
const rc = [];
|
||||
Object.keys(this.dbs).sort().forEach((k)=>{
|
||||
const d = this.dbs[k];
|
||||
const m = d.metrics;
|
||||
delete m.evalSqlStart;
|
||||
delete m.evalSqlEnd;
|
||||
const mk = Object.keys(m).sort();
|
||||
if(!rc.length){
|
||||
rc.push(['db', ...mk]);
|
||||
}
|
||||
const row = [k.split('/').pop()/*remove dir prefix from filename*/];
|
||||
rc.push(row);
|
||||
row.push(...mk.map((kk)=>m[kk]));
|
||||
});
|
||||
return rc;
|
||||
},
|
||||
|
||||
metricsToBlob: function(colSeparator='\t'){
|
||||
const ar = [], ma = this.metricsToArrays();
|
||||
if(!ma.length){
|
||||
this.error("Metrics are empty. Run something.");
|
||||
return;
|
||||
}
|
||||
ma.forEach(function(row){
|
||||
ar.push(row.join(colSeparator),'\n');
|
||||
});
|
||||
return new Blob(ar);
|
||||
},
|
||||
|
||||
/**
|
||||
Fetch file fn and eval it as an SQL blob. This is an async
|
||||
operation and returns a Promise which resolves to this
|
||||
object on success.
|
||||
*/
|
||||
evalFile: async function(fn){
|
||||
const sql = await this.fetchFile(fn);
|
||||
return this.execSql(fn,sql);
|
||||
}/*evalFile()*/,
|
||||
|
||||
/**
|
||||
Fetches the handle of the db associated with
|
||||
this.e.selImpl.value, opening it if needed.
|
||||
*/
|
||||
initDb: function(){
|
||||
const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
|
||||
const stack = wasm.scopedAllocPush();
|
||||
let pDb = 0;
|
||||
const d = Object.create(null);
|
||||
d.filename = "/batch.db";
|
||||
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, this.PoolUtil.vfsName);
|
||||
pDb = wasm.peekPtr(ppDb)
|
||||
if(rc) toss("sqlite3_open_v2() failed with code",rc);
|
||||
capi.sqlite3_exec(pDb, "PRAGMA cache_size="+cacheSize, 0, 0, 0);
|
||||
this.log("cache_size =",cacheSize);
|
||||
}catch(e){
|
||||
if(pDb) capi.sqlite3_close_v2(pDb);
|
||||
throw e;
|
||||
}finally{
|
||||
wasm.scopedAllocPop(stack);
|
||||
}
|
||||
d.handle = pDb;
|
||||
this.log("Opened db:",d.filename,'@',d.handle);
|
||||
return d;
|
||||
},
|
||||
|
||||
closeDb: function(){
|
||||
if(this.db.handle){
|
||||
this.sqlite3.capi.sqlite3_close_v2(this.db.handle);
|
||||
this.db.handle = undefined;
|
||||
}
|
||||
},
|
||||
|
||||
run: async function(sqlite3){
|
||||
delete this.run;
|
||||
this.sqlite3 = sqlite3;
|
||||
const capi = sqlite3.capi, wasm = sqlite3.wasm;
|
||||
this.log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
|
||||
this.log("WASM heap size =",wasm.heap8().length);
|
||||
let timeStart;
|
||||
sqlite3.installOpfsSAHPoolVfs({
|
||||
clearOnInit: true, initialCapacity: 4,
|
||||
name: 'batch-sahpool',
|
||||
verbosity: 2
|
||||
}).then(PoolUtil=>{
|
||||
App.PoolUtil = PoolUtil;
|
||||
App.db = App.initDb();
|
||||
})
|
||||
.then(async ()=>this.loadSqlList())
|
||||
.then(async ()=>{
|
||||
timeStart = performance.now();
|
||||
for(let i = 0; i < App.fileList.length; ++i){
|
||||
const fn = App.fileList[i];
|
||||
await App.evalFile(fn);
|
||||
if(App.gotErr) throw App.gotErr;
|
||||
}
|
||||
})
|
||||
.then(()=>{
|
||||
App.metrics.runTimeMs = performance.now() - timeStart;
|
||||
App.log("total metrics:",JSON.stringify(App.metrics, undefined, ' '));
|
||||
App.log("Reload the page to run this again.");
|
||||
App.closeDb();
|
||||
App.PoolUtil.removeVfs();
|
||||
})
|
||||
.catch(e=>this.error("ERROR:",e));
|
||||
}/*run()*/
|
||||
}/*App*/;
|
||||
|
||||
let sqlite3Js = 'sqlite3.js';
|
||||
if(urlParams.has('sqlite3.dir')){
|
||||
sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
|
||||
}
|
||||
importScripts(sqlite3Js);
|
||||
globalThis.sqlite3InitModule().then(async function(sqlite3_){
|
||||
log("Done initializing. Running batch runner...");
|
||||
sqlite3 = sqlite3_;
|
||||
App.run(sqlite3_);
|
||||
});
|
@@ -1,90 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<link rel="stylesheet" href="common/emscripten.css"/>
|
||||
<link rel="stylesheet" href="common/testing.css"/>
|
||||
<title>sqlite3-api batch SQL runner</title>
|
||||
</head>
|
||||
<body>
|
||||
<header id='titlebar'><span>sqlite3-api batch SQL runner</span></header>
|
||||
<!-- emscripten bits -->
|
||||
<figure id="module-spinner">
|
||||
<div class="spinner"></div>
|
||||
<div class='center'><strong>Initializing app...</strong></div>
|
||||
<div class='center'>
|
||||
On a slow internet connection this may take a moment. If this
|
||||
message displays for "a long time", intialization may have
|
||||
failed and the JavaScript console may contain clues as to why.
|
||||
</div>
|
||||
</figure>
|
||||
<div class="emscripten" id="module-status">Downloading...</div>
|
||||
<div class="emscripten">
|
||||
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
|
||||
</div><!-- /emscripten bits -->
|
||||
<p>
|
||||
This page is for batch-running extracts from the output
|
||||
of <tt>speedtest1 --script</tt>, as well as other standalone SQL
|
||||
scripts.
|
||||
</p>
|
||||
<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 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>
|
||||
<fieldset id='toolbar'>
|
||||
<div>
|
||||
<select class='disable-during-eval' id='sql-select'>
|
||||
<option disabled selected>Populated via script code</option>
|
||||
</select>
|
||||
<button class='disable-during-eval' id='sql-run'>Run selected SQL</button>
|
||||
<button class='disable-during-eval' id='sql-run-next'>Run next...</button>
|
||||
<button class='disable-during-eval' id='sql-run-remaining'>Run all remaining...</button>
|
||||
<button class='disable-during-eval' id='export-metrics' disabled>Export metrics (WIP)<br>(broken by refactoring)</button>
|
||||
<button class='disable-during-eval' id='db-reset'>Reset db</button>
|
||||
<button id='output-clear'>Clear output</button>
|
||||
<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>
|
||||
</fieldset>
|
||||
</div>
|
||||
<hr>
|
||||
<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>
|
||||
<script src="jswasm/sqlite3.js"></script>
|
||||
<script src="common/SqliteTestUtil.js"></script>
|
||||
<script src="batch-runner.js"></script>
|
||||
<style>
|
||||
.flex-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#toolbar > div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#toolbar > div > * {
|
||||
margin: 0.25em;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
2022-08-29
|
||||
|
||||
The author disclaims copyright to this source code. In place of a
|
||||
legal notice, here is a blessing:
|
||||
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
|
||||
***********************************************************************
|
||||
|
||||
A basic batch SQL runner for sqlite3-api.js. This file must be run in
|
||||
main JS thread and sqlite3.js must have been loaded before it.
|
||||
*/
|
||||
'use strict';
|
||||
(function(){
|
||||
const toss = function(...args){throw new Error(args.join(' '))};
|
||||
const warn = console.warn.bind(console);
|
||||
let sqlite3;
|
||||
const urlParams = new URL(self.location.href).searchParams;
|
||||
const cacheSize = (()=>{
|
||||
if(urlParams.has('cachesize')) return +urlParams.get('cachesize');
|
||||
return 200;
|
||||
})();
|
||||
|
||||
/** 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 'index': case 'table':
|
||||
case 'trigger': case 'view': {
|
||||
const sql2 = 'DROP '+type+' '+name;
|
||||
tx.executeSql(sql2, [], ()=>{}, onErr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warn("Unhandled db entry type:",type,'name =',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...
|
||||
const rc = sqlite3.wasm.exports.sqlite3_wasm_db_reset(db.handle);
|
||||
App.logHtml("reset db rc =",rc,db.id, db.filename);
|
||||
};
|
||||
|
||||
const E = (s)=>document.querySelector(s);
|
||||
const App = {
|
||||
e: {
|
||||
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'),
|
||||
fsToolbar: E('#toolbar')
|
||||
},
|
||||
db: Object.create(null),
|
||||
dbs: Object.create(null),
|
||||
cache:{},
|
||||
metrics: {
|
||||
fileCount: 0,
|
||||
runTimeMs: 0,
|
||||
prepareTimeMs: 0,
|
||||
stepTimeMs: 0,
|
||||
stmtCount: 0,
|
||||
strcpyMs: 0,
|
||||
sqlBytes: 0
|
||||
},
|
||||
log: console.log.bind(console),
|
||||
warn: console.warn.bind(console),
|
||||
cls: function(){this.e.output.innerHTML = ''},
|
||||
logHtml2: function(cssClass,...args){
|
||||
const ln = document.createElement('div');
|
||||
if(cssClass) ln.classList.add(cssClass);
|
||||
ln.append(document.createTextNode(args.join(' ')));
|
||||
this.e.output.append(ln);
|
||||
//this.e.output.lastElementChild.scrollIntoViewIfNeeded();
|
||||
},
|
||||
logHtml: function(...args){
|
||||
console.log(...args);
|
||||
if(1) this.logHtml2('', ...args);
|
||||
},
|
||||
logErr: function(...args){
|
||||
console.error(...args);
|
||||
if(1) this.logHtml2('error', ...args);
|
||||
},
|
||||
|
||||
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 = this.sqlite3.wasm;
|
||||
let pStmt = 0, pSqlBegin;
|
||||
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;
|
||||
}
|
||||
// Run this async so that the UI can be updated for the above header...
|
||||
const endRun = ()=>{
|
||||
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);
|
||||
this.metrics.prepareTimeMs += metrics.prepTotal;
|
||||
this.metrics.stepTimeMs += metrics.stepTotal;
|
||||
this.metrics.stmtCount += metrics.stmtCount;
|
||||
this.metrics.strcpyMs += metrics.strcpy;
|
||||
this.metrics.sqlBytes += sql.length;
|
||||
};
|
||||
|
||||
let runner;
|
||||
if('websql'===db.id){
|
||||
const who = this;
|
||||
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. PS: it also can't run most SQL functions, e.g. even
|
||||
instr() results in "not authorized". */
|
||||
if('string'!==typeof sql){ // assume TypedArray
|
||||
sql = new TextDecoder().decode(sql);
|
||||
}
|
||||
sql = sql.replace(/-- [^\n]+\n/g,''); // comment lines interfere with our split()
|
||||
const sqls = sql.split(/;+\n/);
|
||||
const rxBegin = /^BEGIN/i, rxCommit = /^COMMIT/i;
|
||||
try {
|
||||
const nextSql = ()=>{
|
||||
let x = sqls.shift();
|
||||
while(sqls.length && !x) x = sqls.shift();
|
||||
return x && x.trim();
|
||||
};
|
||||
const who = this;
|
||||
const transaction = function(tx){
|
||||
try {
|
||||
let s;
|
||||
/* Try to approximate the spirit of the input scripts
|
||||
by running batches bound by BEGIN/COMMIT statements. */
|
||||
for(s = nextSql(); !!s; s = nextSql()){
|
||||
if(rxBegin.test(s)) continue;
|
||||
else if(rxCommit.test(s)) break;
|
||||
//console.log("websql sql again",sqls.length, s);
|
||||
++metrics.stmtCount;
|
||||
const t = performance.now();
|
||||
tx.executeSql(s,[], ()=>{}, (t,e)=>{
|
||||
console.error("WebSQL error",e,"SQL =",s);
|
||||
who.logErr(e.message);
|
||||
//throw e;
|
||||
return false;
|
||||
});
|
||||
metrics.stepTotal += performance.now() - t;
|
||||
}
|
||||
}catch(e){
|
||||
who.logErr("transaction():",e.message);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
const n = sqls.length;
|
||||
const nextBatch = function(){
|
||||
if(sqls.length){
|
||||
console.log("websql sqls.length",sqls.length,'of',n);
|
||||
db.handle.transaction(transaction, (e)=>{
|
||||
who.logErr("Ignoring and contiuing:",e.message)
|
||||
//reject(e);
|
||||
return false;
|
||||
}, nextBatch);
|
||||
}else{
|
||||
resolve(who);
|
||||
}
|
||||
};
|
||||
metrics.evalSqlStart = performance.now();
|
||||
nextBatch();
|
||||
}catch(e){
|
||||
//this.gotErr = e;
|
||||
console.error("websql error:",e);
|
||||
who.logErr(e.message);
|
||||
//reject(e);
|
||||
}
|
||||
}.bind(this);
|
||||
}else{/*sqlite3 db...*/
|
||||
runner = function(resolve, reject){
|
||||
++this.metrics.fileCount;
|
||||
metrics.evalSqlStart = performance.now();
|
||||
const stack = wasm.scopedAllocPush();
|
||||
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.poke(pSql + sqlByteLen, 0);
|
||||
metrics.strcpy = performance.now() - t;
|
||||
let breaker = 0;
|
||||
while(pSql && wasm.peek(pSql,'i8')){
|
||||
wasm.pokePtr(ppStmt, 0);
|
||||
wasm.pokePtr(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.peekPtr(ppStmt);
|
||||
pSql = wasm.peekPtr(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);
|
||||
}finally{
|
||||
capi.sqlite3_exec(db.handle,"rollback;",0,0,0);
|
||||
wasm.scopedAllocPop(stack);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
let p;
|
||||
if(1){
|
||||
p = new Promise(function(res,rej){
|
||||
setTimeout(()=>runner(res, rej), 0)/*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(()=>{
|
||||
endRun();
|
||||
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 = this.sqlite3.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
|
||||
when it completes. Only intended to be run once at the start
|
||||
of the app.
|
||||
*/
|
||||
loadSqlList: async function(){
|
||||
const sel = this.e.selSql;
|
||||
sel.innerHTML = '';
|
||||
this.blockControls(true);
|
||||
const infile = 'batch-runner.list';
|
||||
this.logHtml("Loading list of SQL files:", infile);
|
||||
let txt;
|
||||
try{
|
||||
const r = await fetch(infile);
|
||||
if(404 === r.status){
|
||||
toss("Missing file '"+infile+"'.");
|
||||
}
|
||||
if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
|
||||
txt = await r.text();
|
||||
const warning = E('#warn-list');
|
||||
if(warning) warning.remove();
|
||||
}catch(e){
|
||||
this.logErr(e.message);
|
||||
throw e;
|
||||
}finally{
|
||||
this.blockControls(false);
|
||||
}
|
||||
const list = txt.split(/\n+/);
|
||||
let opt;
|
||||
if(0){
|
||||
opt = document.createElement('option');
|
||||
opt.innerText = "Select file to evaluate...";
|
||||
opt.value = '';
|
||||
opt.disabled = true;
|
||||
opt.selected = true;
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
list.forEach(function(fn){
|
||||
if(!fn) return;
|
||||
opt = document.createElement('option');
|
||||
opt.value = fn;
|
||||
opt.innerText = fn.split('/').pop();
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
this.logHtml("Loaded",infile);
|
||||
},
|
||||
|
||||
/** Fetch ./fn and return its contents as a Uint8Array. */
|
||||
fetchFile: async function(fn, cacheIt=false){
|
||||
if(cacheIt && this.cache[fn]) return this.cache[fn];
|
||||
this.logHtml("Fetching",fn,"...");
|
||||
let sql;
|
||||
try {
|
||||
const r = await fetch(fn);
|
||||
if(!r.ok) toss("Fetch failed:",r.statusText);
|
||||
sql = new Uint8Array(await r.arrayBuffer());
|
||||
}catch(e){
|
||||
this.logErr(e.message);
|
||||
throw e;
|
||||
}
|
||||
this.logHtml("Fetched",sql.length,"bytes from",fn);
|
||||
if(cacheIt) this.cache[fn] = sql;
|
||||
return sql;
|
||||
}/*fetchFile()*/,
|
||||
|
||||
/** Disable or enable certain UI controls. */
|
||||
blockControls: function(disable){
|
||||
//document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable);
|
||||
this.e.fsToolbar.disabled = disable;
|
||||
},
|
||||
|
||||
/**
|
||||
Converts this.metrics() to a form which is suitable for easy conversion to
|
||||
CSV. It returns an array of arrays. The first sub-array is the column names.
|
||||
The 2nd and subsequent are the values, one per test file (only the most recent
|
||||
metrics are kept for any given file).
|
||||
*/
|
||||
metricsToArrays: function(){
|
||||
const rc = [];
|
||||
Object.keys(this.dbs).sort().forEach((k)=>{
|
||||
const d = this.dbs[k];
|
||||
const m = d.metrics;
|
||||
delete m.evalSqlStart;
|
||||
delete m.evalSqlEnd;
|
||||
const mk = Object.keys(m).sort();
|
||||
if(!rc.length){
|
||||
rc.push(['db', ...mk]);
|
||||
}
|
||||
const row = [k.split('/').pop()/*remove dir prefix from filename*/];
|
||||
rc.push(row);
|
||||
row.push(...mk.map((kk)=>m[kk]));
|
||||
});
|
||||
return rc;
|
||||
},
|
||||
|
||||
metricsToBlob: function(colSeparator='\t'){
|
||||
const ar = [], ma = this.metricsToArrays();
|
||||
if(!ma.length){
|
||||
this.logErr("Metrics are empty. Run something.");
|
||||
return;
|
||||
}
|
||||
ma.forEach(function(row){
|
||||
ar.push(row.join(colSeparator),'\n');
|
||||
});
|
||||
return new Blob(ar);
|
||||
},
|
||||
|
||||
downloadMetrics: function(){
|
||||
const b = this.metricsToBlob();
|
||||
if(!b) return;
|
||||
const url = URL.createObjectURL(b);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'batch-runner-js-'+((new Date().getTime()/1000) | 0)+'.csv';
|
||||
this.logHtml("Triggering download of",a.download);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(()=>{
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}, 500);
|
||||
},
|
||||
|
||||
/**
|
||||
Fetch file fn and eval it as an SQL blob. This is an async
|
||||
operation and returns a Promise which resolves to this
|
||||
object on success.
|
||||
*/
|
||||
evalFile: async function(fn){
|
||||
const sql = await this.fetchFile(fn);
|
||||
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 = onlySelectedDb
|
||||
? [('boolean'===typeof onlySelectedDb)
|
||||
? this.dbs[this.e.selImpl.value]
|
||||
: onlySelectedDb]
|
||||
: Object.values(this.dbs);
|
||||
for(let db of list){
|
||||
if(db && db.handle){
|
||||
this.logHtml("Clearing db",db.id);
|
||||
db.clear();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
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.sqlite3b';
|
||||
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);
|
||||
d.handle.transaction(function(tx){
|
||||
tx.executeSql("PRAGMA cache_size="+cacheSize);
|
||||
App.logHtml(dbId,"cache_size =",cacheSize);
|
||||
});
|
||||
}else{
|
||||
const capi = this.sqlite3.capi, wasm = this.sqlite3.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.peekPtr(ppDb)
|
||||
if(rc) toss("sqlite3_open_v2() failed with code",rc);
|
||||
capi.sqlite3_exec(pDb, "PRAGMA cache_size="+cacheSize, 0, 0, 0);
|
||||
this.logHtml(dbId,"cache_size =",cacheSize);
|
||||
}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,d.filename);
|
||||
console.log("db =",d);
|
||||
return d;
|
||||
},
|
||||
|
||||
run: function(sqlite3){
|
||||
delete this.run;
|
||||
this.sqlite3 = sqlite3;
|
||||
const capi = sqlite3.capi, wasm = sqlite3.wasm;
|
||||
this.logHtml("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
|
||||
this.logHtml("WASM heap size =",wasm.heap8().length);
|
||||
this.loadSqlList();
|
||||
if(capi.sqlite3_wasmfs_opfs_dir()){
|
||||
E('#warn-opfs').classList.remove('hidden');
|
||||
}else{
|
||||
E('#warn-opfs').remove();
|
||||
E('option[value=wasmfs-opfs]').disabled = true;
|
||||
}
|
||||
if('function' === typeof self.openDatabase){
|
||||
E('#warn-websql').classList.remove('hidden');
|
||||
}else{
|
||||
E('option[value=websql]').disabled = true;
|
||||
E('#warn-websql').remove();
|
||||
}
|
||||
const who = this;
|
||||
if(this.e.cbReverseLog.checked){
|
||||
this.e.output.classList.add('reverse');
|
||||
}
|
||||
this.e.cbReverseLog.addEventListener('change', function(){
|
||||
who.e.output.classList[this.checked ? 'add' : 'remove']('reverse');
|
||||
}, false);
|
||||
this.e.btnClear.addEventListener('click', ()=>this.cls(), false);
|
||||
this.e.btnRun.addEventListener('click', function(){
|
||||
if(!who.e.selSql.value) return;
|
||||
who.evalFile(who.e.selSql.value);
|
||||
}, false);
|
||||
this.e.btnRunNext.addEventListener('click', function(){
|
||||
++who.e.selSql.selectedIndex;
|
||||
if(!who.e.selSql.value) return;
|
||||
who.evalFile(who.e.selSql.value);
|
||||
}, false);
|
||||
this.e.btnReset.addEventListener('click', function(){
|
||||
who.clearStorage(true);
|
||||
}, false);
|
||||
this.e.btnExportMetrics.addEventListener('click', function(){
|
||||
who.logHtml2('warning',"Triggering download of metrics CSV. Check your downloads folder.");
|
||||
who.downloadMetrics();
|
||||
//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();
|
||||
while(v){
|
||||
await who.evalFile(v);
|
||||
if(who.gotError){
|
||||
who.logErr("Error handling script",v,":",who.gotError.message);
|
||||
break;
|
||||
}
|
||||
++who.e.selSql.selectedIndex;
|
||||
v = who.e.selSql.value;
|
||||
}
|
||||
const timeTotal = performance.now() - timeStart;
|
||||
who.logHtml("Run-remaining time:",timeTotal,"ms ("+(timeTotal/1000/60)+" minute(s))");
|
||||
who.clearStorage();
|
||||
App.metrics.runTimeMs = timeTotal;
|
||||
who.logHtml("Total metrics:",JSON.stringify(App.metrics,undefined,' '));
|
||||
}, false);
|
||||
}/*run()*/
|
||||
}/*App*/;
|
||||
|
||||
self.sqlite3TestModule.initSqlite3().then(function(sqlite3_){
|
||||
sqlite3 = sqlite3_;
|
||||
self.App = App /* only to facilitate dev console access */;
|
||||
App.run(sqlite3);
|
||||
});
|
||||
})();
|
@@ -278,6 +278,8 @@ void fatalv(char const *zFmt, va_list va){
|
||||
vfprintf(stderr, zFmt, va);
|
||||
}
|
||||
fputc('\n', stderr);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1417,15 +1419,16 @@ void cmpp_process_keyword(CmppTokenizer * const t){
|
||||
void cmpp_process_file(const char * zName){
|
||||
FileWrapper fw = FileWrapper_empty;
|
||||
CmppTokenizer ct = CmppTokenizer_empty;
|
||||
|
||||
FileWrapper_open(&fw, zName, "r");
|
||||
FileWrapper_slurp(&fw);
|
||||
g_debug(1,("Read %u byte(s) from [%s]\n", fw.nContent, fw.zName));
|
||||
ct.zName = zName;
|
||||
ct.zBegin = fw.zContent;
|
||||
ct.zEnd = fw.zContent + fw.nContent;
|
||||
while(cmpp_next_keyword_line(&ct)){
|
||||
cmpp_process_keyword(&ct);
|
||||
if( fw.zContent ){
|
||||
ct.zName = zName;
|
||||
ct.zBegin = fw.zContent;
|
||||
ct.zEnd = fw.zContent + fw.nContent;
|
||||
while(cmpp_next_keyword_line(&ct)){
|
||||
cmpp_process_keyword(&ct);
|
||||
}
|
||||
}
|
||||
FileWrapper_close(&fw);
|
||||
if(0!=ct.level.ndx){
|
||||
@@ -1438,13 +1441,13 @@ void cmpp_process_file(const char * zName){
|
||||
static void usage(int isErr){
|
||||
FILE * const fOut = isErr ? stderr : stdout;
|
||||
fprintf(fOut,
|
||||
"Usage: %s [flags] [infile]\n"
|
||||
"Usage: %s [flags] [infile...]\n"
|
||||
"Flags:\n",
|
||||
g.zArgv0);
|
||||
#define arg(F,D) fprintf(fOut," %s\n %s\n",F, D)
|
||||
arg("-f|--file FILE","Read input from FILE (default=- (stdin)).\n"
|
||||
" Alternately, the first non-flag argument is assumed to "
|
||||
"be the input file.");
|
||||
" Alternately, non-flag arguments are assumed to "
|
||||
"be the input files.");
|
||||
arg("-o|--outfile FILE","Send output to FILE (default=- (stdout))");
|
||||
arg("-DXYZ","Define XYZ to true");
|
||||
arg("-UXYZ","Undefine XYZ (equivalent to false)");
|
||||
@@ -1459,13 +1462,16 @@ int main(int argc, char const * const * argv){
|
||||
int rc = 0;
|
||||
int i;
|
||||
int inclCount = 0;
|
||||
const char * zInfile = 0;
|
||||
int nFile = 0;
|
||||
char const *zFileList[128] = {0};
|
||||
#define M(X) (0==strcmp(X,zArg))
|
||||
#define ISFLAG(X) else if(M(X))
|
||||
#define ISFLAG2(X,Y) else if(M(X) || M(Y))
|
||||
#define ARGVAL \
|
||||
if(i+1>=argc) fatal("Missing value for flag '%s'", zArg); \
|
||||
zArg = argv[++i]
|
||||
|
||||
memset(zFileList, 0, sizeof(zFileList));
|
||||
g.zArgv0 = argv[0];
|
||||
atexit(cmpp_atexit);
|
||||
cmpp_initdb();
|
||||
@@ -1497,8 +1503,11 @@ int main(int argc, char const * const * argv){
|
||||
ISFLAG2("f","file"){
|
||||
ARGVAL;
|
||||
do_infile:
|
||||
if(zInfile) fatal("Cannot use -i more than once.");
|
||||
zInfile = zArg;
|
||||
if( nFile>=sizeof(zFileList)/sizeof(zFileList[0]) ){
|
||||
fatal("Too many file arguments. Max is %d.",
|
||||
(int)(sizeof(zFileList)/sizeof(zFileList[0])));
|
||||
}
|
||||
zFileList[nFile++] = zArg;
|
||||
}
|
||||
ISFLAG2("d","delimiter"){
|
||||
ARGVAL;
|
||||
@@ -1508,17 +1517,21 @@ int main(int argc, char const * const * argv){
|
||||
}
|
||||
ISFLAG("debug"){
|
||||
++g.doDebug;
|
||||
}else if(!zInfile && '-'!=argv[i][0]){
|
||||
}else if('-'!=*zArg){
|
||||
goto do_infile;
|
||||
}else{
|
||||
fatal("Unhandled flag: %s", argv[i]);
|
||||
}
|
||||
}
|
||||
if(!zInfile) zInfile = "-";
|
||||
if(!nFile){
|
||||
zFileList[nFile++] = "-";
|
||||
}
|
||||
if(!g.out.zName) g.out.zName = "-";
|
||||
if(!inclCount) db_include_dir_add(".");
|
||||
FileWrapper_open(&g.out, g.out.zName, "w");
|
||||
cmpp_process_file(zInfile);
|
||||
for(i = 0; i < nFile; ++i){
|
||||
cmpp_process_file(zFileList[i]);
|
||||
}
|
||||
FileWrapper_close(&g.out);
|
||||
end:
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
|
@@ -1,186 +0,0 @@
|
||||
#!/do/not/make
|
||||
#^^^ help emacs select edit mode
|
||||
#
|
||||
# Intended to include'd by ./GNUmakefile.
|
||||
#######################################################################
|
||||
|
||||
########################################################################
|
||||
# shell.c and its build flags...
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
make-np-0 = make -C $(dir.top) -n -p
|
||||
make-np-1 = sed -e 's/(TOP)/(dir.top)/g'
|
||||
# Extract SHELL_OPT and SHELL_DEP from the top-most makefile and import
|
||||
# them as vars here...
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
|
||||
$(eval $(shell $(make-np-0) | grep -e '^SHELL_DEP ' | $(make-np-1)))
|
||||
# ^^^ can't do that in 1 invocation b/c newlines get stripped
|
||||
ifeq (,$(SHELL_OPT))
|
||||
$(error Could not parse SHELL_OPT from $(dir.top)/Makefile.)
|
||||
endif
|
||||
ifeq (,$(SHELL_DEP))
|
||||
$(error Could not parse SHELL_DEP from $(dir.top)/Makefile.)
|
||||
endif
|
||||
$(dir.top)/shell.c: $(SHELL_DEP) $(dir.tool)/mkshellc.tcl $(sqlite3.c)
|
||||
$(MAKE) -C $(dir.top) shell.c
|
||||
endif
|
||||
# /shell.c
|
||||
########################################################################
|
||||
|
||||
EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
fiddle.emcc-flags = \
|
||||
$(emcc.cflags) $(emcc_opt_full) \
|
||||
--minify 0 \
|
||||
-sALLOW_TABLE_GROWTH \
|
||||
-sMEMORY64=$(emcc.MEMORY64) \
|
||||
-sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.8) \
|
||||
-sABORTING_MALLOC \
|
||||
-sSTRICT_JS=0 \
|
||||
-sENVIRONMENT=web,worker \
|
||||
-sMODULARIZE \
|
||||
-sDYNAMIC_EXECUTION=0 \
|
||||
-sWASM_BIGINT=$(emcc.WASM_BIGINT) \
|
||||
-sEXPORT_NAME=$(sqlite3.js.init-func) \
|
||||
-Wno-limited-postlink-optimizations \
|
||||
$(emcc.exportedRuntimeMethods),FS \
|
||||
-sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
|
||||
$(SQLITE_OPT.full-featured) \
|
||||
$(SQLITE_OPT.common) \
|
||||
$(SHELL_OPT) \
|
||||
-UHAVE_READLINE -UHAVE_EDITLINE -UHAVE_LINENOISE \
|
||||
-USQLITE_HAVE_ZLIB \
|
||||
-USQLITE_WASM_BARE_BONES \
|
||||
-DSQLITE_SHELL_FIDDLE
|
||||
|
||||
# Flags specifically for debug builds of fiddle. Performance suffers
|
||||
# greatly in debug builds.
|
||||
fiddle.emcc-flags.debug = $(fiddle.emcc-flags) \
|
||||
-DSQLITE_DEBUG \
|
||||
-DSQLITE_ENABLE_SELECTTRACE \
|
||||
-DSQLITE_ENABLE_WHERETRACE
|
||||
|
||||
fiddle.EXPORTED_FUNCTIONS.in = \
|
||||
EXPORTED_FUNCTIONS.fiddle.in \
|
||||
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core \
|
||||
$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
|
||||
|
||||
$(EXPORTED_FUNCTIONS.fiddle): $(MKDIR.bld) $(fiddle.EXPORTED_FUNCTIONS.in) \
|
||||
$(MAKEFILE.fiddle)
|
||||
sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@
|
||||
|
||||
fiddle.cses = $(dir.top)/shell.c $(sqlite3-wasm.c)
|
||||
|
||||
clean: clean-fiddle
|
||||
clean-fiddle:
|
||||
rm -f $(dir.fiddle)/fiddle-module.js \
|
||||
$(dir.fiddle)/*.wasm \
|
||||
$(dir.fiddle)/sqlite3-opfs-*.js \
|
||||
$(dir.fiddle)/*.gz \
|
||||
EXPORTED_FUNCTIONS.fiddle
|
||||
rm -fr $(dir.fiddle-debug)
|
||||
.PHONY: fiddle fiddle.debug
|
||||
all: fiddle
|
||||
|
||||
########################################################################
|
||||
# fiddle_remote is the remote destination for the fiddle app. It must
|
||||
# be a [user@]HOST:/path for rsync. The target "should probably"
|
||||
# contain a symlink of index.html -> fiddle.html.
|
||||
fiddle_remote ?=
|
||||
ifeq (,$(fiddle_remote))
|
||||
ifneq (,$(wildcard /home/stephan))
|
||||
fiddle_remote = wh:www/wasm-testing/fiddle/.
|
||||
else ifneq (,$(wildcard /home/drh))
|
||||
#fiddle_remote = if appropriate, add that user@host:/path here
|
||||
endif
|
||||
endif
|
||||
push-fiddle: fiddle
|
||||
@if [ x = "x$(fiddle_remote)" ]; then \
|
||||
echo "fiddle_remote must be a [user@]HOST:/path for rsync"; \
|
||||
exit 1; \
|
||||
fi
|
||||
rsync -va fiddle/ $(fiddle_remote)
|
||||
# end fiddle remote push
|
||||
########################################################################
|
||||
|
||||
|
||||
########################################################################
|
||||
# Explanation of the emcc build flags follows. Full docs for these can
|
||||
# be found at:
|
||||
#
|
||||
# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
|
||||
#
|
||||
# -sENVIRONMENT=web: elides bootstrap code related to non-web JS
|
||||
# environments like node.js. Removing this makes the output a tiny
|
||||
# tick larger but hypothetically makes it more portable to
|
||||
# non-browser JS environments.
|
||||
#
|
||||
# -sMODULARIZE: changes how the generated code is structured to avoid
|
||||
# declaring a global Module object and instead installing a function
|
||||
# which loads and initializes the module. The function is named...
|
||||
#
|
||||
# -sEXPORT_NAME=jsFunctionName (see -sMODULARIZE)
|
||||
#
|
||||
# -sEXPORTED_RUNTIME_METHODS=@/absolute/path/to/file: a file
|
||||
# containing a list of emscripten-supplied APIs, one per line, which
|
||||
# must be exported into the generated JS. Must be an absolute path!
|
||||
#
|
||||
# -sEXPORTED_FUNCTIONS=@/absolute/path/to/file: a file containing a
|
||||
# list of C functions, one per line, which must be exported via wasm
|
||||
# so they're visible to JS. C symbols names in that file must all
|
||||
# start with an underscore for reasons known only to the emcc
|
||||
# developers. e.g., _sqlite3_open_v2 and _sqlite3_finalize. Must be
|
||||
# an absolute path!
|
||||
#
|
||||
# -sSTRICT_JS ensures that the emitted JS code includes the 'use
|
||||
# strict' option. Note that -sSTRICT is more broadly-scoped and
|
||||
# results in build errors.
|
||||
#
|
||||
# -sALLOW_TABLE_GROWTH is required for (at a minimum) the UDF-binding
|
||||
# feature. Without it, JS functions cannot be made to proxy C-side
|
||||
# callbacks.
|
||||
#
|
||||
# -sABORTING_MALLOC causes the JS-bound _malloc() to abort rather than
|
||||
# return 0 on OOM. If set to 0 then all code which uses _malloc()
|
||||
# must, just like in C, check the result before using it, else
|
||||
# they're likely to corrupt the JS/WASM heap by writing to its
|
||||
# address of 0. It is, as of this writing, enabled in Emscripten by
|
||||
# default but we enable it explicitly in case that default changes.
|
||||
#
|
||||
# -sDYNAMIC_EXECUTION=0 disables eval() and the Function constructor.
|
||||
# If the build runs without these, it's preferable to use this flag
|
||||
# because certain execution environments disallow those constructs.
|
||||
# This flag is not strictly necessary, however.
|
||||
#
|
||||
# --no-entry: for compiling library code with no main(). If this is
|
||||
# not supplied and the code has a main(), it is called as part of the
|
||||
# module init process. Note that main() is #if'd out of shell.c
|
||||
# (renamed) when building in wasm mode.
|
||||
#
|
||||
# --pre-js/--post-js=FILE relative or absolute paths to JS files to
|
||||
# prepend/append to the emcc-generated bootstrapping JS. It's
|
||||
# easier/faster to develop with separate JS files (reduces rebuilding
|
||||
# requirements) but certain configurations, namely -sMODULARIZE, may
|
||||
# require using at least a --pre-js file. They can be used
|
||||
# individually and need not be paired.
|
||||
#
|
||||
# -O0..-O3 and -Oz: optimization levels affect not only C-style
|
||||
# optimization but whether or not the resulting generated JS code
|
||||
# gets minified. -O0 compiles _much_ more quickly than -O3 or -Oz,
|
||||
# and doesn't minimize any JS code, so is recommended for
|
||||
# development. -O3 or -Oz are recommended for deployment, but
|
||||
# primarily because -Oz will shrink the wasm file notably. JS-side
|
||||
# minification makes little difference in terms of overall
|
||||
# distributable size.
|
||||
#
|
||||
# --minify 0: supposedly disables minification of the generated JS
|
||||
# code, regardless of optimization level, but that's not quite true:
|
||||
# search the main makefile for wasm-strip for details. Minification
|
||||
# of the JS has minimal overall effect in the larger scheme of things
|
||||
# and results in JS files which can neither be edited nor viewed as
|
||||
# text files in Fossil (which flags them as binary because of their
|
||||
# extreme line lengths). Interestingly, whether or not the comments
|
||||
# in the generated JS file get stripped is unaffected by this setting
|
||||
# and depends entirely on the optimization level. Higher optimization
|
||||
# levels reduce the size of the JS considerably even without
|
||||
# minification.
|
||||
#
|
||||
########################################################################
|
@@ -49,20 +49,23 @@
|
||||
<ul id='test-list'>
|
||||
<li>Core-most tests
|
||||
<ul>
|
||||
<li><a href='tester1.html'>tester1</a>: Core unit and
|
||||
<li>tester1 (<a href='tester1.html'>32-bit</a>
|
||||
<a href='tester1-64bit.html'>64-bit</a>): Core unit and
|
||||
regression tests for the various APIs and surrounding
|
||||
utility code.</li>
|
||||
<li><a href='tester1-worker.html'>tester1-worker</a>: same thing
|
||||
but running in a Worker.</li>
|
||||
<li><a href='tester1-esm.html'>tester1-esm</a>: same as
|
||||
<li>tester1-esm (<a href='tester1-esm.html'>32-bit</a>
|
||||
<a href='tester1-esm-64bit.html'>64-bit</a>): same as
|
||||
<code>tester1</code> but loads sqlite3 in the main thread via
|
||||
an ES6 module.
|
||||
</li>
|
||||
<li><a href='tester1-worker.html?esm'>tester1-worker?esm</a>:
|
||||
same as <code>tester1-esm</code> but loads a Worker Module which
|
||||
then loads the sqlite3 API via an ES6 module. Note that
|
||||
not all browsers permit loading modules in Worker
|
||||
threads.
|
||||
<li>tester1-worker (<a href='tester1-worker.html'>32-bit</a>
|
||||
<a href='tester1-worker-64bit.html'>64-bit</a>): same thing
|
||||
but running in a Worker.</li>
|
||||
<li>tester1-worker ESM (<a href='tester1-worker.html?esm'>32-bit</a>
|
||||
<a href='tester1-worker-64bit.html?esm'>64-bit</a>): same as
|
||||
tester1-worker but loads a Worker Module which then
|
||||
loads the sqlite3 API via an ES6 module. Not all
|
||||
browsers permit loading modules in Worker threads.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -123,6 +126,13 @@
|
||||
demonstrates usage of the OPFS SAHPool VFS's "pause" feature to coordinate
|
||||
access to a database.
|
||||
</li>
|
||||
<li><a href='SQLTester/index.html'>SQLTester</a> is
|
||||
another testing tool for the library but making use of
|
||||
it requires tests from an external, proprietary
|
||||
project. Despite not being useful to the general public,
|
||||
a link to it is in this list so that its developer has
|
||||
easy access to it.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>WASMFS</strong>-specific tests which require that
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -170,9 +170,10 @@
|
||||
|
||||
const urlParams = new URL(self.location.href).searchParams;
|
||||
const W = new Worker(
|
||||
"speedtest1-worker.js?sqlite3.dir=jswasm"+
|
||||
(urlParams.has('opfs-verbose') ? '&opfs-verbose' : '')+
|
||||
(urlParams.has('opfs-disable') ? '&opfs-disable' : '')
|
||||
"speedtest1-worker.js?sqlite3.dir=jswasm"+
|
||||
'&sqlite3.debugModule'+
|
||||
(urlParams.has('opfs-verbose') ? '&opfs-verbose' : '')+
|
||||
(urlParams.has('opfs-disable') ? '&opfs-disable' : '')
|
||||
);
|
||||
const mPost = function(msgType,payload){
|
||||
W.postMessage({type: msgType, data: payload});
|
||||
|
@@ -4,13 +4,25 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<link rel="stylesheet" href="../common/emscripten.css"/>
|
||||
<link rel="stylesheet" href="../common/testing.css"/>
|
||||
<title>sqlite3 tester #1: Worker thread</title>
|
||||
<link rel="stylesheet" href="common/emscripten.css"/>
|
||||
<link rel="stylesheet" href="common/testing.css"/>
|
||||
<title>sqlite3 tester #1: Worker thread
|
||||
//#if 64bit
|
||||
(64-bit WASM)
|
||||
//#else
|
||||
(32-bit WASM)
|
||||
//#endif
|
||||
</title>
|
||||
<style></style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id='color-target'>sqlite3 tester #1: Worker thread</h1>
|
||||
<h1 id='color-target'>sqlite3 tester #1: Worker thread
|
||||
//#if 64bit
|
||||
(64-bit WASM)
|
||||
//#else
|
||||
(32-bit WASM)
|
||||
//#endif
|
||||
</h1>
|
||||
<div>Variants:
|
||||
<a href='tester1.html' target='tester1.html'>conventional UI thread</a>,
|
||||
<a href='tester1-worker.html' target='tester1-worker.html'>conventional worker</a>,
|
||||
@@ -35,23 +47,42 @@
|
||||
logTarget.append(ln);
|
||||
};
|
||||
const cbReverse = document.querySelector('#cb-log-reverse');
|
||||
const cbReverseKey = 'tester1:cb-log-reverse';
|
||||
const cbReverseIt = ()=>{
|
||||
logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
|
||||
localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
|
||||
};
|
||||
cbReverse.addEventListener('change',cbReverseIt,true);
|
||||
if(localStorage.getItem(cbReverseKey)){
|
||||
cbReverse.checked = !!(+localStorage.getItem(cbReverseKey));
|
||||
}
|
||||
cbReverseIt();
|
||||
const urlParams = new URL(self.location.href).searchParams;
|
||||
const workerArgs = [];
|
||||
if(urlParams.has('esm')){
|
||||
logHtml('warning',"Attempting to run an ES6 Worker Module, "+
|
||||
"which is not supported by all browsers! "+
|
||||
"e.g. Firefox (as of 2023-05) cannot do this.");
|
||||
workerArgs.push("tester1.mjs",{type:"module"});
|
||||
const baseName =
|
||||
//#if 64bit
|
||||
'tester1-64bit'
|
||||
//#else
|
||||
'tester1'
|
||||
//#endif
|
||||
;
|
||||
if(urlParams.has('esm')){
|
||||
logHtml('warning',"Attempting to run an ES6 Worker Module, "+
|
||||
"which is not supported by all browsers!.");
|
||||
workerArgs.push(baseName+'.mjs', {type:"module"});
|
||||
const bitness =
|
||||
//#if 64bit
|
||||
64
|
||||
//#else
|
||||
32
|
||||
//#endif
|
||||
;
|
||||
document.querySelectorAll('title,#color-target').forEach((e)=>{
|
||||
e.innerText = "sqlite3 tester #1: ES6 Worker Module";
|
||||
e.innerText =
|
||||
"sqlite3 tester #1: ES6 Worker Module ("+bitness+"-bit WASM)";
|
||||
});
|
||||
}else{
|
||||
workerArgs.push("tester1.js?sqlite3.dir=jswasm");
|
||||
workerArgs.push(baseName+'.js?sqlite3.dir=jswasm');
|
||||
}
|
||||
const w = new Worker(...workerArgs);
|
||||
w.onmessage = function({data}){
|
@@ -8,9 +8,13 @@
|
||||
<link rel="stylesheet" href="common/testing.css"/>
|
||||
<title>sqlite3 tester #1:
|
||||
//#if target=es6-module
|
||||
ES6 Module in UI thread
|
||||
ES6 Module in
|
||||
//#endif
|
||||
UI thread
|
||||
//#if 64bit
|
||||
(64-bit WASM)
|
||||
//#else
|
||||
UI thread
|
||||
(32-bit WASM)
|
||||
//#endif
|
||||
</title>
|
||||
<style></style>
|
||||
@@ -32,10 +36,19 @@ UI thread
|
||||
document.querySelector('title').innerHTML;
|
||||
})();</script>
|
||||
//#if target=es6-module
|
||||
//#if 64bit
|
||||
<script src="tester1-64bit.mjs" type="module"></script>
|
||||
//#else
|
||||
<script src="tester1.mjs" type="module"></script>
|
||||
//#endif
|
||||
//#else
|
||||
//#if 64bit
|
||||
<script src="jswasm/sqlite3-64bit.js"></script>
|
||||
<script src="tester1-64bit.js"></script>
|
||||
//#else
|
||||
<script src="jswasm/sqlite3.js"></script>
|
||||
<script src="tester1.js"></script>
|
||||
//#endif
|
||||
//#endif target=es6-module
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -44,7 +44,13 @@
|
||||
./c-pp -f tester1.c-pp.js -o tester1-esm.mjs -Dtarget=es6-module
|
||||
*/
|
||||
//#if target=es6-module
|
||||
import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
|
||||
import {default as sqlite3InitModule} from
|
||||
//#if 64bit
|
||||
'./jswasm/sqlite3-64bit.mjs'
|
||||
//#else
|
||||
'./jswasm/sqlite3.mjs'
|
||||
//#endif
|
||||
;
|
||||
globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
//#else
|
||||
'use strict';
|
||||
@@ -108,16 +114,15 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
logTarget.append(ln);
|
||||
};
|
||||
const cbReverse = document.querySelector('#cb-log-reverse');
|
||||
//cbReverse.setAttribute('checked','checked');
|
||||
const cbReverseKey = 'tester1:cb-log-reverse';
|
||||
const cbReverseIt = ()=>{
|
||||
logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
|
||||
//localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
|
||||
localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
|
||||
};
|
||||
cbReverse.addEventListener('change', cbReverseIt, true);
|
||||
/*if(localStorage.getItem(cbReverseKey)){
|
||||
if(localStorage.getItem(cbReverseKey)){
|
||||
cbReverse.checked = !!(+localStorage.getItem(cbReverseKey));
|
||||
}*/
|
||||
}
|
||||
cbReverseIt();
|
||||
}else{ /* Worker thread */
|
||||
console.log("Running in a Worker thread.");
|
||||
@@ -138,6 +143,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}else{
|
||||
postMessage({type:'test-result', payload:{pass}});
|
||||
}
|
||||
TestUtil.checkHeapSize(true);
|
||||
};
|
||||
const log = (...args)=>{
|
||||
//console.log(...args);
|
||||
@@ -298,6 +304,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
logClass(['faded','one-test-summary'],
|
||||
TestUtil.counter - tc, 'assertion(s) in',
|
||||
roundMs(then-now),'ms');
|
||||
TestUtil.checkHeapSize();
|
||||
}
|
||||
logClass(['green','group-end'],
|
||||
"#"+this.number+":",
|
||||
@@ -348,6 +355,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
reportFinalTestStatus(false);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
checkHeapSize: function(force=false){
|
||||
const heapSize = SQLite3.wasm.heap8().byteLength;
|
||||
if( force || heapSize !== TestUtil.lastHeapSize ){
|
||||
TestUtil.lastHeapSize = heapSize;
|
||||
log('WASM heap size:', heapSize,'bytes');
|
||||
}
|
||||
}
|
||||
}/*TestUtil*/;
|
||||
const T = TestUtil;
|
||||
@@ -3807,7 +3822,11 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
are simply lost, and such scripts see the globalThis.location of
|
||||
_this_ script.
|
||||
*/
|
||||
//#if 64bit
|
||||
let sqlite3Js = 'sqlite3-64bit.js';
|
||||
//#else
|
||||
let sqlite3Js = 'sqlite3.js';
|
||||
//#endif
|
||||
const urlParams = new URL(globalThis.location.href).searchParams;
|
||||
if(urlParams.has('sqlite3.dir')){
|
||||
sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
|
||||
@@ -3840,7 +3859,6 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}else{
|
||||
logClass('warning',"BigInt/int64 support is disabled.");
|
||||
}
|
||||
log("WASM pointer size:",wasm.ptr.size,"bytes");
|
||||
if(haveWasmCTests()){
|
||||
log("sqlite3__wasm_test_...() APIs are available.");
|
||||
}else{
|
||||
@@ -3848,6 +3866,8 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
log("registered vfs list =",capi.sqlite3_js_vfs_list().join(', '));
|
||||
SQLite3 = sqlite3;
|
||||
log("WASM pointer size:",wasm.ptr.size,"bytes.");
|
||||
TestUtil.checkHeapSize();
|
||||
TestUtil.runTests(sqlite3);
|
||||
});
|
||||
})(self);
|
||||
|
@@ -97,7 +97,7 @@ $(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \
|
||||
$(emcc.flags.sqlite3-wasmfs) \
|
||||
$(emcc.flags.speedtest1-wasmfs) \
|
||||
-o $@ $(speedtest1.cfiles) -lm
|
||||
@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,1)
|
||||
@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,1,$(logtag.wasmfs))
|
||||
$(maybe-wasm-strip) $(speedtest1-wasmfs.wasm)
|
||||
chmod -x $(speedtest1-wasmfs.wasm)
|
||||
ls -la $@ $(speedtest1-wasmfs.wasm)
|
||||
|
46
manifest
46
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\sthe\stranslation\sof\s"\v"\sin\sJSON5.\n[forum:/forumpost/28e21085f9c6a4e7|Forum\spost\s28e21085f9].
|
||||
D 2025-09-25T15:06:57.956
|
||||
C Overhaul\sthe\swasm\sbuild\sto\s(A)\ssupport\smore\scoexisting\svariants,\se.g.\s32/64-bit\sof\sboth\svanilla\sand\sesm,\sand\s(B)\sbuild\seach\svariant\sto\sits\sown\ssubdir\sso\sthat\sthey\scan\sbuild\sin\sparallel.\sIt\scan,\swith\smake\s-j4,\snow\sbuild\sall\snew\svariants\sin\shalf\sthe\stime\sit\spreviously\stook\sfor\sjust\sthe\s32-bit\sbuilds.\sThe\snew\sbuild\slogging\soutput,\sthough\sunconventional,\sserves\stwo\spurposes:\s(A)\simprove\smy\sbuild-time\ssituational\sawareness\sand\s(B)\sit\shelp\sdemystify\ssome\sof\sthe\sbuild\ssteps\sand\soutput\sfiles.
|
||||
D 2025-09-25T15:17:58.460
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -578,7 +578,7 @@ F ext/session/sqlite3session.c b3de195ce668cace9b324599bf6255a70290cbfb5451e826e
|
||||
F ext/session/sqlite3session.h 7404723606074fcb2afdc6b72c206072cdb2b7d8ba097ca1559174a80bc26f7a
|
||||
F ext/session/test_session.c 8766b5973a6323934cb51248f621c3dc87ad2a98f023c3cc280d79e7d78d36fb
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/GNUmakefile 39beef47c945a140f93435998f07df70e7f0157e4c198f6197dc3b8236fec7ca
|
||||
F ext/wasm/GNUmakefile 473695f6c5d9fcfa4099ee1d447b3a965d387e44f213d34ed18f7abce84a7852
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md 66ace67ae98a45e4116f2ca5425b716887bcee4d64febee804ff6398e1ae9ec7
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -591,12 +591,12 @@ F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras cb4fa8842c875b6ee99381523792975
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||
F ext/wasm/api/README.md f4c0d67caaee21a77b8938c30b5f79667bfc9d0c95d01b51df77ea35ee773884
|
||||
F ext/wasm/api/extern-post-js.c-pp.js d3748c6bbdcef15d8e494e0558aad370b9c24242eb020042b3a73b4950562f5b
|
||||
F ext/wasm/api/extern-post-js.c-pp.js 6bf4407c028fac7d387821420cd25f6d68ad80f7d526e86539b6a3012230917f
|
||||
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
|
||||
F ext/wasm/api/post-js-footer.js e617e5f81a907362de152576323155f02d24642e625fc05fb801b86b6a269444
|
||||
F ext/wasm/api/post-js-header.js 79d078aec33d93b640a19c574b504d88bb2446432f38e2fbb3bb8e36da436e70
|
||||
F ext/wasm/api/pre-js.c-pp.js 664551f490d296e0f4590d3a029787ab0782b9a1fa5954d73bde4fb2c6bfc709
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js f91a2afdef19c350bce99784fff20310d4d060520001059822aa36c4ce80dc56
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js e643a96c5323e051e29046bfd6412750917ca2c955e31c9192fb924ecc8ed004
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js 12f5b36775fab1e7bf5385689fded2b2a9f77360562515e9849acb5e66602e2d
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js db4c8ebb03bac60db32ce03f8c615b00f4e4ad53e7d5de5e63d2780cba052caa
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 259c72c6a33ba1be2297c568cbc2ad53437d1d4b2613d7772c56a3aa00bf435d
|
||||
@@ -608,13 +608,9 @@ F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js e2c0bd6917b697137035d775ed3300e6
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js f8e762aeb568e0fd050ab991c5f3420dca9c14630386e4e18d42c0624b8ff7cd
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 9097074724172e31e56ce20ccd7482259cf72a76124213cbc9469d757676da86
|
||||
F ext/wasm/api/sqlite3-wasm.c ff2dc011e17b06186b8b35e408626d7ace69a362b92c197a34d78bef25c7105a
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 4ad256b4ff7f839ad18931ed35d46cced544207bd2209665ec552e193f7f4544
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
F ext/wasm/batch-runner.js 05ec254f5dbfe605146d9640b3db17d6ef8c3fbef6aa8396051ca72bb5884e3f
|
||||
F ext/wasm/c-pp.c 75e23ad9ca3a3771e70d401ba79c0bacdf7b2169d1c17f9e2639d81067e5ab95
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 8fb6adfbae6270344f43f2652e63780df3f86521755bde8f92cf6b809ba7891d
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 69483df1df2d0988e708390f7b1feda769c16e9e9efd4683557f8e7197099cc0
|
||||
F ext/wasm/c-pp.c 7692739ac435120c37b9de993f152c90e5dbf6a340ca6331de81d7b8b06b5307
|
||||
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
|
||||
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
|
||||
F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
|
||||
@@ -631,21 +627,20 @@ F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2
|
||||
F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535da776950314
|
||||
F ext/wasm/dist.make 57f5da2f0de5a297b5a0bc39ffec736380050578240ab24d864c2ff1b3634a3b
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make 7ed14ba851d331b62ea9ddfcdb62184ff853c5620c3856631310ca0f9633ef93
|
||||
F ext/wasm/fiddle/fiddle-worker.js 7798af02e672e088ff192716f80626c8895e19301a65b8af6d5d12b2d13d2451
|
||||
F ext/wasm/fiddle/fiddle.js 84fd75967e0af8b69d3dd849818342227d0f81d13db92e0dcbc63649b31a4893
|
||||
F ext/wasm/fiddle/index.html a27b8127ef9ecf19612da93b2a6a73bdb3777b5c56b5450bb7200a94bc108ff9
|
||||
F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730
|
||||
F ext/wasm/index.html bcaa00eca521b372a6a62c7e7b17a870b0fcdf3e418a5921df1fd61e5344080d
|
||||
F ext/wasm/index.html 1b329fb63e057c02a17ce178308d6b06aac62d92af7dd6d821fb0e183e0f1557
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js bbac67bc7a79dca34afe6215fd16b27768d84e22273507206f888c117e2ede7d
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 167fc0b624c9bc2c477846e336de9403842d81b1a24fc4d3b24317cb9eba734f
|
||||
F ext/wasm/mkwasmbuilds.c fc6044341e6cdc8825ffc07db505c92f83cb62cb7c8d271f293f4dc8a8887468
|
||||
F ext/wasm/mkwasmbuilds.c 3f27681fd3b32a78560feb3bb54f0f46a68f75024f65d9c5d4247f6bd08a04ad
|
||||
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
|
||||
F ext/wasm/speedtest1-wasmfs.mjs c77c7231338ed5c0e1ce16aa29106df8e5b5cf11a48319c49433490a8d3ded30
|
||||
F ext/wasm/speedtest1-worker.html d24d1e06caf3dcd83430c8c3d87761ff7555fd06eaeaf2fc02ce49cf45f0d032
|
||||
F ext/wasm/speedtest1-worker.html 068d4190f304fa1c34e6501a1b3a4c32fe8d8dac93c2d0f53d667a1cb386eedc
|
||||
F ext/wasm/speedtest1-worker.js 5b7eba7cdb5239768e1ed61edb046df8e0092e6c9d6e0bc76e51536022bdccb9
|
||||
F ext/wasm/speedtest1.html e2a0e0bd12243ca34b11235bf9f3c229f4574ea1125f2ecf2bf0589853d6f9c8
|
||||
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
|
||||
@@ -653,9 +648,9 @@ F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d826
|
||||
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
|
||||
F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||
F ext/wasm/tester1.c-pp.js a2bc1a96dbe55e3b14ace35e8561893e84221d63794a9bc2ab5a5f1b1d6bc5a1
|
||||
F ext/wasm/tester1-worker.c-pp.html b240b59cd313427434190d5795f57986b9add1a08df53921311fc0b8221b672a w ext/wasm/tester1-worker.html
|
||||
F ext/wasm/tester1.c-pp.html 93fbedb6b15eaad9b03df0524c702a81896e358785655ae2c751e30ef8202e54
|
||||
F ext/wasm/tester1.c-pp.js 2b2aea6d9938fcfad0e3fd8ae094bced45212b807812b60a0dbe970f7f143f82
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
|
||||
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
@@ -664,7 +659,7 @@ F ext/wasm/tests/opfs/sahpool/digest.html 206d08a34dc8bd570b2581d3d9ab3ecad3201b
|
||||
F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca01385e2732294b53f4c842328
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
|
||||
F ext/wasm/wasmfs.make 411dd94b40406572caddf88392a1ccc4deed0f88d260516e59ca6e0c887ee861
|
||||
F ext/wasm/wasmfs.make 5de02751b3e9e79b81a52ab4fe0ed6aa6a23311a90db58fea98c1c4e2845e562
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk fd45a3578989f38bbeb2564a63883f6f6c077105c9f1361c3eac411d31f3afbd
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
@@ -1650,7 +1645,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest.md ee958457ae1b729d9715ae33c0320600000bf1d9ddea1a88dcf79f56729d6fad
|
||||
F test/speedtest.tcl 405411356fbc54af15987b7ffeec330a49138f71584220fb8fe1948b2f7ac907 x
|
||||
F test/speedtest1.c a9b002a7bfed99ba3166c2a9b8ae45a95b4c2d37f891e1637c022f9e1d15e3f9
|
||||
F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce85721
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -2175,8 +2170,9 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 4a1bb874f12adda26e91970b64e700cb904c126412989be4debac9a5647d6f69
|
||||
R 16252f4eed24f0ab043779bc0feb3096
|
||||
U drh
|
||||
Z 2a05a8a00bda16fec363a8f421bf356f
|
||||
P 2914e8fc7b10e8b42c9a0fbd0e71f495714cee3cae67b8c238d37b1e7ec22359 75079401753778e3bc2f7fa307de9217e8d1ec395079fc1009060f707be32943
|
||||
R bf2a14e22103418be159da49f21a135f
|
||||
T +closed 75079401753778e3bc2f7fa307de9217e8d1ec395079fc1009060f707be32943 Closed\sby\sintegrate-merge.
|
||||
U stephan
|
||||
Z c8ddfc47b782e73f61a2d31043443056
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@@ -1 +1 @@
|
||||
2914e8fc7b10e8b42c9a0fbd0e71f495714cee3cae67b8c238d37b1e7ec22359
|
||||
2f4be98614b49def2c2951887796c736269ef3bb7ba5b045cae5f748ae165a83
|
||||
|
@@ -572,9 +572,8 @@ char *speedtest1_once(const char *zFormat, ...){
|
||||
}
|
||||
rc = sqlite3_reset(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "%s\nError code %d: %s\n",
|
||||
sqlite3_sql(pStmt), rc, sqlite3_errmsg(g.db));
|
||||
exit(1);
|
||||
fatal_error("%s\nError code %d: %s\n",
|
||||
sqlite3_sql(pStmt), rc, sqlite3_errmsg(g.db));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
@@ -666,9 +665,8 @@ void speedtest1_run(void){
|
||||
sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0);
|
||||
rc = sqlite3_finalize(g.pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "%s\nError code %d: %s\n",
|
||||
sqlite3_sql(pNew), rc, sqlite3_errmsg(g.db));
|
||||
exit(1);
|
||||
fatal_error("%s\nError code %d: %s\n",
|
||||
sqlite3_sql(pNew), rc, sqlite3_errmsg(g.db));
|
||||
}
|
||||
g.pStmt = pNew;
|
||||
}else
|
||||
@@ -676,9 +674,8 @@ void speedtest1_run(void){
|
||||
{
|
||||
rc = sqlite3_reset(g.pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "%s\nError code %d: %s\n",
|
||||
sqlite3_sql(g.pStmt), rc, sqlite3_errmsg(g.db));
|
||||
exit(1);
|
||||
fatal_error("%s\nError code %d: %s\n",
|
||||
sqlite3_sql(g.pStmt), rc, sqlite3_errmsg(g.db));
|
||||
}
|
||||
}
|
||||
speedtest1_shrink_memory();
|
||||
@@ -2152,7 +2149,7 @@ void testset_rtree(int p1, int p2){
|
||||
}
|
||||
speedtest1_end_test();
|
||||
}
|
||||
|
||||
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n);
|
||||
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2");
|
||||
@@ -2181,7 +2178,6 @@ void testset_rtree(int p1, int p2){
|
||||
}
|
||||
speedtest1_end_test();
|
||||
}
|
||||
|
||||
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(125, "%d custom geometry callback queries", n);
|
||||
|
Reference in New Issue
Block a user