1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

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

@ -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);