Export sqlite3_trace_v2() to wasm and use it to ensure that the new per-VFS post-open SQL support in the DB ctor works. Default opfs vfs to journal_mode=truncate, as it's faster in that mode. Add 't' DB open-mode flag to enable SQL tracing to console.log().

FossilOrigin-Name: 508f7f6d63e52f61fae5abe817579a4e130fa7fbd18733d741d521a5bdabb7ce
This commit is contained in:
stephan 2022-10-03 13:03:41 +00:00
parent a4c357f94c
commit 4f5bbedb3a
10 changed files with 122 additions and 44 deletions

View File

@ -74,6 +74,7 @@ _sqlite3_strglob
_sqlite3_strlike
_sqlite3_total_changes
_sqlite3_total_changes64
_sqlite3_trace_v2
_sqlite3_uri_boolean
_sqlite3_uri_int64
_sqlite3_uri_key

View File

@ -621,7 +621,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
for(const t of ['access', 'blobFinalizers', 'dataTypes',
'encodings', 'fcntl', 'flock', 'ioCap',
'openFlags', 'prepareFlags', 'resultCodes',
'serialize', 'syncFlags', 'udfFlags',
'serialize', 'syncFlags', 'trace', 'udfFlags',
'version'
]){
for(const e of Object.entries(wasm.ctype[t])){

View File

@ -61,6 +61,25 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
};
/**
sqlite3_trace_v2() callback which gets installed by the DB ctor
if its open-flags contain "t".
*/
const __dbTraceToConsole =
wasm.installFunction('i(ippp)', function(t,c,p,x){
if(capi.SQLITE_TRACE_STMT===t){
// x == SQL, p == sqlite3_stmt*
console.log("SQL TRACE #"+(++this.counter),
wasm.cstringToJs(x));
}
}.bind({counter: 0}));
/**
A map of sqlite3_vfs pointers to SQL code to run when the DB
constructor opens a database with the given VFS.
*/
const __vfsPostOpenSql = Object.create(null);
/**
A proxy for DB class constructors. It must be called with the
being-construct DB object as its "this". See the DB constructor
@ -101,12 +120,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
? (n)=>toss3("The VFS for",n,"is only available in the main window thread.")
: false;
ctor._name2vfs[':localStorage:'] = {
vfs: 'kvvfs',
filename: isWorkerThread || (()=>'local')
vfs: 'kvvfs', filename: isWorkerThread || (()=>'local')
};
ctor._name2vfs[':sessionStorage:'] = {
vfs: 'kvvfs',
filename: isWorkerThread || (()=>'session')
vfs: 'kvvfs', filename: isWorkerThread || (()=>'session')
};
}
const opt = ctor.normalizeArgs(...args);
@ -123,7 +140,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
vfsName = vfsCheck.vfs;
fn = fnJs = vfsCheck.filename(fnJs);
}
let ptr, oflags = 0;
let pDb, oflags = 0;
if( flagsStr.indexOf('c')>=0 ){
oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
}
@ -132,24 +149,48 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
oflags |= capi.SQLITE_OPEN_EXRESCODE;
const scope = wasm.scopedAllocPush();
try {
const ppDb = wasm.allocPtr() /* output (sqlite3**) arg */;
const pPtr = wasm.allocPtr() /* output (sqlite3**) arg */;
const pVfsName = vfsName ? (
('number'===typeof vfsName ? vfsName : wasm.scopedAllocCString(vfsName))
): 0;
const rc = capi.sqlite3_open_v2(fn, ppDb, oflags, pVfsName);
ptr = wasm.getPtrValue(ppDb);
checkSqlite3Rc(ptr, rc);
let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, pVfsName);
pDb = wasm.getPtrValue(pPtr);
checkSqlite3Rc(pDb, rc);
if(flagsStr.indexOf('t')>=0){
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
__dbTraceToConsole, 0);
}
// Check for per-VFS post-open SQL...
wasm.setPtrValue(pPtr, 0);
if(0===capi.sqlite3_file_control(
pDb, "main", capi.SQLITE_FCNTL_VFS_POINTER, pPtr
)){
const postInitSql = __vfsPostOpenSql[wasm.getPtrValue(pPtr)];
if(postInitSql){
rc = capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0);
checkSqlite3Rc(pDb, rc);
}
}
}catch( e ){
if( ptr ) capi.sqlite3_close_v2(ptr);
if( pDb ) capi.sqlite3_close_v2(pDb);
throw e;
}finally{
wasm.scopedAllocPop(scope);
}
this.filename = fnJs;
__ptrMap.set(this, ptr);
__ptrMap.set(this, pDb);
__stmtMap.set(this, Object.create(null));
};
/**
Sets SQL which should be exec()'d on a DB instance after it is
opened with the given VFS pointer. This is intended only for use
by DB subclasses or sqlite3_vfs implementations.
*/
dbCtorHelper.setVfsPostOpenSql = function(pVfs, sql){
__vfsPostOpenSql[pVfs] = sql;
};
/**
A helper for DB constructors. It accepts either a single
config-style object or up to 3 arguments (filename, dbOpenFlags,
@ -175,7 +216,6 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}
return arg;
};
/**
The DB class provides a high-level OO wrapper around an sqlite3
db handle.
@ -193,14 +233,18 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
database. It must be string containing a sequence of letters (in
any order, but case sensitive) specifying the mode:
- "c" => create if it does not exist, else fail if it does not
- "c": create if it does not exist, else fail if it does not
exist. Implies the "w" flag.
- "w" => write. Implies "r": a db cannot be write-only.
- "w": write. Implies "r": a db cannot be write-only.
- "r" => read-only if neither "w" nor "c" are provided, else it
- "r": read-only if neither "w" nor "c" are provided, else it
is ignored.
- "t": enable tracing of SQL executed on this database handle,
sending it to `console.log()`. Once enabled, it cannot
currently be easily switched off (TODO).
If "w" is not provided, the db is implicitly read-only, noting that
"rc" is meaningless
@ -229,16 +273,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
`sqlite3*` pointer value. That property can also be used to check
whether this DB instance is still open.
EXPERIMENTAL: in the main window thread, the filenames
":localStorage:" and ":sessionStorage:" are special: they cause
the db to use either localStorage or sessionStorage for storing
the database. In this mode, only a single database is permitted
in each storage object. This feature is experimental and subject
to any number of changes (including outright removal). This
support requires the kvvfs sqlite3 VFS, the existence of which
can be determined at runtime by checking for a non-0 return value
from sqlite3.capi.sqlite3_vfs_find("kvvfs").
In the main window thread, the filenames ":localStorage:" and
":sessionStorage:" are special: they cause the db to use either
localStorage or sessionStorage for storing the database using
the kvvfs.
*/
const DB = function(...args){
dbCtorHelper.apply(this, args);

View File

@ -898,8 +898,14 @@ const installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri){
sqlite3.oo1.dbCtorHelper.call(this, opt);
};
opfsUtil.OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype);
sqlite3.oo1.dbCtorHelper.setVfsPostOpenSql(
opfsVfs.pointer,
/* Truncate journal mode is faster than delete or wal for
OPFS, per speedtest1. */
"pragma journal_mode=truncate"
);
}
/**
Potential TODOs:
@ -907,7 +913,6 @@ const installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri){
publish an interface for proxying the higher-level OPFS
features like getting a directory listing.
*/
const sanityCheck = function(){
const scope = wasm.scopedAllocPush();
const sq3File = new sqlite3_file();

View File

@ -815,6 +815,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
["sqlite3_step", "int", "sqlite3_stmt*"],
["sqlite3_strglob", "int", "string","string"],
["sqlite3_strlike", "int", "string","string","int"],
["sqlite3_trace_v2", "int", "sqlite3*", "int", "*", "*"],
["sqlite3_total_changes", "int", "sqlite3*"],
["sqlite3_uri_boolean", "int", "string", "string", "int"],
["sqlite3_uri_key", "string", "string", "int"],

View File

@ -527,6 +527,13 @@ const char * sqlite3_wasm_enum_json(void){
DefInt(SQLITE_SYNC_DATAONLY);
} _DefGroup;
DefGroup(trace) {
DefInt(SQLITE_TRACE_STMT);
DefInt(SQLITE_TRACE_PROFILE);
DefInt(SQLITE_TRACE_ROW);
DefInt(SQLITE_TRACE_CLOSE);
} _DefGroup;
DefGroup(udfFlags) {
DefInt(SQLITE_DETERMINISTIC);
DefInt(SQLITE_DIRECTONLY);
@ -680,6 +687,28 @@ int sqlite3_wasm_vfs_unlink(const char * zName){
return rc;
}
/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.
**
** This function resets the given db pointer's database as described at
**
** https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigresetdatabase
**
** Returns 0 on success, an SQLITE_xxx code on error. Returns
** SQLITE_MISUSE if pDb is NULL.
*/
WASM_KEEP
int sqlite3_wasm_db_reset(sqlite3*pDb){
int rc = SQLITE_MISUSE;
if( pDb ){
rc = sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
if( 0==rc ) rc = sqlite3_exec(pDb, "VACUUM", 0, 0, 0);
sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
}
return rc;
}
/*
** Uses the current database's VFS xRead to stream the db file's
** contents out to the given callback. The callback gets a single

View File

@ -609,7 +609,11 @@ const waitLoop = async function f(){
now - relinquishTime >= fh.syncHandleTime
)){
//warn("Relinquishing for timeout:",fh.filenameAbs);
closeSyncHandle(fh)/*async!*/;
await closeSyncHandle(fh)
/* Testing shows that we have to wait on this async
op to finish, else we might try to re-open it
before the close has run. The FS layer does not
retain the order those operations, apparently. */;
}
}
}

View File

@ -43,7 +43,7 @@ const tryOpfsVfs = async function(sqlite3){
const dbFile = "my-persistent.db";
if(urlArgs.has('delete')) sqlite3.opfs.deleteEntry(dbFile);
const db = new opfs.OpfsDb(dbFile);
const db = new opfs.OpfsDb(dbFile,'ct');
log("db file:",db.filename);
await waitForRelinquish();
try{

View File

@ -1,5 +1,5 @@
C Reimplement\sfiddle_reset_db()\sso\sthat\sit\sworks\swith\sall\sVFSes.
D 2022-10-03T11:42:45.345
C Export\ssqlite3_trace_v2()\sto\swasm\sand\suse\sit\sto\sensure\sthat\sthe\snew\sper-VFS\spost-open\sSQL\ssupport\sin\sthe\sDB\sctor\sworks.\sDefault\sopfs\svfs\sto\sjournal_mode=truncate,\sas\sit's\sfaster\sin\sthat\smode.\sAdd\s't'\sDB\sopen-mode\sflag\sto\senable\sSQL\stracing\sto\sconsole.log().
D 2022-10-03T13:03:41.207
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -476,7 +476,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0
F ext/wasm/GNUmakefile b313a82060c733c990b91afa981e10f5e21a0b33a483f33b739ce932ed6bc725
F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 9b16040f37805ee7c30f922a970a57d3f2a822d0675a8f5d70f15061e300c4ce
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 89983a8d122c35a90c65ec667844b95a78bcd04f3198a99c1e0c8368c1a0b03a
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 1e350b611465566cfa2e5eccf7c9b29a34f48ee38bbf6d5fb086dd06ce32b3ff
F ext/wasm/api/extern-post-js.js dc68cbf552d8ea085181400a6963907c32e0b088b03ffd8969b1869fea246629
@ -485,13 +485,13 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8de2d3f9b0b
F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99
F ext/wasm/api/sqlite3-api-glue.js 5391338550ef9fafb3a7a6d060b8c19a190c47c01fa14e032c6e30dd96742c02
F ext/wasm/api/sqlite3-api-oo1.js 484f9ea5c7140d07745f4b534a1f6dd67120c65ef34abcf7cdb3a388d73f5ef4
F ext/wasm/api/sqlite3-api-opfs.js 1b097808b7b081b0f0700cf97d49ef19760e401706168edff9cd45cf9169f541
F ext/wasm/api/sqlite3-api-prologue.js b827e2353799b54fffaa9577f51ebf08b8dedc58dcabe344c73be977235da227
F ext/wasm/api/sqlite3-api-glue.js b6e7ae7bfe272a8623a8cae4a84830697314c743cadd14e4c167650455f0fff9
F ext/wasm/api/sqlite3-api-oo1.js 1cf37b2b6e1fb35f9c425380aad198b66a36cdcc65e399e68085509096eca5b0
F ext/wasm/api/sqlite3-api-opfs.js 3d17da752181d67847bd2e3d1f4662df31c5023a1bed5424ebcdeb89770046af
F ext/wasm/api/sqlite3-api-prologue.js 915e3119d2c3cd53afb9575d1681646f3cbebbfc62cdae8bc199d08e7fd566f1
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 2a0f9e4bf1b141a787918951360601128d6a0a190a31a8e5cfe237c99fa640c6
F ext/wasm/api/sqlite3-wasm.c 3bb9fe3de3bb536fdae01934760e651c7c20e7066b9415895042555d62ecd7c0
F ext/wasm/batch-runner.html c363032aba7a525920f61f8be112a29459f73f07e46f0ba3b7730081a617826e
F ext/wasm/batch-runner.js ce92650a6681586c89bef26ceae96674a55ca5a9727815202ca62e1a00ff5015
F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05
@ -522,11 +522,11 @@ F ext/wasm/speedtest1.html e4cb5d722b494104fc1249e7c008ca018f820a784833c51004c95
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/sqlite3-opfs-async-proxy.js d571a40230f54b99863f469e050cc4d4317e90239e64026d8d574689956ff76c
F ext/wasm/sqlite3-opfs-async-proxy.js 5c6748361f2eb2ee0f2941890917fd9f2d9271de80ec1b65695fb023435b8375
F ext/wasm/sqlite3-worker1-promiser.js 307d7837420ca6a9d3780dfc81194f1c0715637e6d9540e935514086b96913d8
F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
F ext/wasm/test-opfs-vfs.js 623de926913fa8cb7bac170f105a0c397f1951aba52d9f54792aadce7892a3c2
F ext/wasm/test-opfs-vfs.js 0115d56f3f2a6475040dffe75a6851a353b1690708795944cf0fe1890bc7ff54
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
F ext/wasm/testing-worker1-promiser.js bd788e33c1807e0a6dda9c9a9d784bd3350ca49c9dd8ae2cc8719b506b6e013e
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
@ -2029,8 +2029,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 2703ac9842335962e488e597168d70b1389b95a6ad39edf70a211b95979b4708
R 0bcb919ac67ff690a464f41cfdc2aecd
P 18462052903bfeb037dd9af3a1fe1898d141eff5d6f527721858120553de808d
R 362ba5dc75c0e8e6f26510dab6893d04
U stephan
Z 78ecb20703c7cf55fa5a9c67c82bb309
Z 8b3cb31b700bd695aa51a5be567b8bc8
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
18462052903bfeb037dd9af3a1fe1898d141eff5d6f527721858120553de808d
508f7f6d63e52f61fae5abe817579a4e130fa7fbd18733d741d521a5bdabb7ce