aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/fiddle/fiddle-worker.js
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2022-09-26 11:38:58 +0000
committerstephan <stephan@noemail.net>2022-09-26 11:38:58 +0000
commit1f095d482d1803deb9fcb60449e9ca1223018d73 (patch)
treeee83c502c48008460a89a0aaab2adcc728c7c69b /ext/wasm/fiddle/fiddle-worker.js
parent6a643e4bcdc81f835be75377d1c6306f5e23f541 (diff)
downloadsqlite-1f095d482d1803deb9fcb60449e9ca1223018d73.tar.gz
sqlite-1f095d482d1803deb9fcb60449e9ca1223018d73.zip
Get fiddle db export working for OPFS VFS. Add root dir handle to the main OPFS VFS worker to enable creation of certain utility functions without delegating to the async worker. Add sqlite3.capi.sqlite3_wasm_rc_str() to map integer result codes back to their SQLITE_xxx counterparts. Minor doc touchups.
FossilOrigin-Name: 9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41
Diffstat (limited to 'ext/wasm/fiddle/fiddle-worker.js')
-rw-r--r--ext/wasm/fiddle/fiddle-worker.js89
1 files changed, 81 insertions, 8 deletions
diff --git a/ext/wasm/fiddle/fiddle-worker.js b/ext/wasm/fiddle/fiddle-worker.js
index 827d2cfa9..5da09257d 100644
--- a/ext/wasm/fiddle/fiddle-worker.js
+++ b/ext/wasm/fiddle/fiddle-worker.js
@@ -99,7 +99,9 @@
};
const stdout = (...args)=>wMsg('stdout', args);
const stderr = (...args)=>wMsg('stderr', args);
-
+ const toss = (...args)=>{
+ throw new Error(args.join(' '));
+ };
const fixmeOPFS = "(FIXME: won't work with vanilla OPFS.)";
self.onerror = function(/*message, source, lineno, colno, error*/) {
@@ -136,7 +138,7 @@
const S = fiddleModule.sqlite3;
/* We need to call sqlite3_shutdown() in order to avoid numerous
legitimate warnings from the shell about it being initialized
- after sqlite3_initialize() has been called. This mean ,
+ after sqlite3_initialize() has been called. This means,
however, that any initialization done by the JS code may need
to be re-done (e.g. re-registration of dynamically-loaded
VFSes). */
@@ -156,7 +158,7 @@
if(S.opfs){
stdout("\nOPFS is available. To open a persistent db, use:\n\n",
" .open file:name?vfs=opfs\n\nbut note that some",
- "features (e.g. export) do not yet work with OPFS.");
+ "features (e.g. upload) do not yet work with OPFS.");
S.opfs.reregisterVfs();
}
stdout('\nEnter ".help" for usage hints.');
@@ -207,6 +209,69 @@
f._();
}
};
+
+ /**
+ Exports the shell's current db file in such a way that it can
+ export DBs hosted in the Emscripten-supplied FS or in native OPFS
+ (and, hypothetically, kvvfs). Throws on error. On success returns
+ a Blob containing the whole db contents.
+
+ Bug: xFileSize() is returning garbage for the default VFS but
+ works in OPFS. Thus for exporting that impl we'll use the
+ fiddleModule.FS API for the time being.
+ */
+ const exportDbFileToBlob = function(){
+ const S = fiddleModule.sqlite3, capi = S.capi, wasm = capi.wasm;
+ const pDb = wasm.xCall("fiddle_db_handle");
+ if(!pDb) toss("No db is opened.");
+ const scope = wasm.scopedAllocPush();
+ try{
+ const ppFile = wasm.scopedAlloc(12/*sizeof(i32 + i64)*/);
+ const pFileSize = ppFile + 4;
+ wasm.setMemValue(ppFile, 0, 'i32');
+ let rc = capi.sqlite3_file_control(
+ pDb, "main", capi.SQLITE_FCNTL_FILE_POINTER, ppFile
+ );
+ if(rc) toss("Cannot get sqlite3_file handle.");
+ const jFile = new capi.sqlite3_file(wasm.getPtrValue(ppFile));
+ const jIom = new capi.sqlite3_io_methods(jFile.$pMethods);
+ console.warn("jIom =",jIom);
+ const xFileSize = wasm.functionEntry(jIom.$xFileSize);
+ const xRead = wasm.functionEntry(jIom.$xRead);
+ wasm.setMemValue(pFileSize, 0n, 'i64');
+ //stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
+ rc = xFileSize( jFile.pointer, pFileSize );
+ if(rc) toss("Cannot get db file size.");
+ //stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
+ const nFileSize = Number( wasm.getMemValue(pFileSize,'i64') );
+ if(nFileSize <= 0n || nFileSize>=Number.MAX_SAFE_INTEGER){
+ toss("Unexpected DB size:",nFileSize);
+ }
+ //stderr("nFileSize =",nFileSize,"pFileSize =",pFileSize);
+ const nIobuf = 1024 * 4;
+ const iobuf = wasm.scopedAlloc(nIobuf);
+ let nPos = 0;
+ const blobList = [];
+ const heap = wasm.heap8u();
+ for( ; nPos < nFileSize; nPos += nIobuf ){
+ rc = xRead(jFile.pointer, iobuf, nIobuf, BigInt(nPos));
+ if(rc){
+ if(capi.SQLITE_IOERR_SHORT_READ === rc){
+ //stderr('rc =',rc,'nPos =',nPos,'nIobuf =',nIobuf,'nFileSize =',nFileSize);
+ rc = ((nPos + nIobuf) < nFileSize) ? rc : 0/*assume EOF*/;
+ }
+ if(rc) toss("xRead() SQLITE_xxx error #"+rc,capi.sqlite3_wasm_rc_str(rc));
+ }
+ blobList.push(heap.slice(iobuf, iobuf+nIobuf));
+ }
+ return new Blob(blobList);
+ }catch(e){
+ console.error('exportDbFileToBlob()',e);
+ stderr("exportDbFileToBlob():",e.message);
+ }finally{
+ wasm.scopedAllocPop(scope);
+ }
+ }/*exportDbFileToBlob()*/;
self.onmessage = function f(ev){
ev = ev.data;
@@ -233,14 +298,22 @@
*/
case 'db-export': {
const fn = Sqlite3Shell.dbFilename();
- stdout("Exporting",fn+".",fixmeOPFS);
+ stdout("Exporting",fn+".");
const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
try{
if(!fn2) throw new Error("DB appears to be closed.");
- const buffer = fiddleModule.FS.readFile(
- fn, {encoding:"binary"}
- ).buffer;
- wMsg('db-export',{filename: fn2, buffer}, [buffer]);
+ if(fiddleModule.sqlite3.capi.wasm.xCall(
+ 'fiddle_db_is_opfs'
+ )){
+ exportDbFileToBlob().arrayBuffer().then((buffer)=>{
+ wMsg('db-export',{filename: fn2, buffer}, [buffer]);
+ });
+ }else{
+ const buffer = fiddleModule.FS.readFile(
+ fn, {encoding:"binary"}
+ ).buffer;
+ wMsg('db-export',{filename: fn2, buffer}, [buffer]);
+ }
}catch(e){
/* Post a failure message so that UI elements disabled
during the export can be re-enabled. */