aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/api/sqlite3-api-oo1.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/wasm/api/sqlite3-api-oo1.js')
-rw-r--r--ext/wasm/api/sqlite3-api-oo1.js88
1 files changed, 63 insertions, 25 deletions
diff --git a/ext/wasm/api/sqlite3-api-oo1.js b/ext/wasm/api/sqlite3-api-oo1.js
index e6685d35a..37c292840 100644
--- a/ext/wasm/api/sqlite3-api-oo1.js
+++ b/ext/wasm/api/sqlite3-api-oo1.js
@@ -62,6 +62,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
for the argument docs. This is split into a separate function
@@ -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,25 +149,49 @@ 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,
dbVfsName). It returns a new object containing:
@@ -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);