mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Fiddle: replace db export routine with a C-side one which works for both Emscripten FS-hosted and OPFS-hosted db files. Minor code-adjacent cleanups.
FossilOrigin-Name: 3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94
This commit is contained in:
@ -6,4 +6,5 @@ _fiddle_interrupt
|
|||||||
_fiddle_main
|
_fiddle_main
|
||||||
_fiddle_reset_db
|
_fiddle_reset_db
|
||||||
_fiddle_db_handle
|
_fiddle_db_handle
|
||||||
_fiddle_db_is_opfs
|
_fiddle_db_vfs
|
||||||
|
_fiddle_export_db
|
||||||
|
@ -1025,51 +1025,6 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
this.exec("ROLLBACK to SAVEPOINT oo1; RELEASE SAVEPOINT oo1");
|
this.exec("ROLLBACK to SAVEPOINT oo1; RELEASE SAVEPOINT oo1");
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function currently does nothing and always throws. It
|
|
||||||
WILL BE REMOVED pending other refactoring, to eliminate a hard
|
|
||||||
dependency on Emscripten. This feature will be moved into a
|
|
||||||
higher-level API or a runtime-configurable feature.
|
|
||||||
|
|
||||||
That said, what its replacement should eventually do is...
|
|
||||||
|
|
||||||
Exports a copy of this db's file as a Uint8Array and
|
|
||||||
returns it. It is technically not legal to call this while
|
|
||||||
any prepared statement are currently active because,
|
|
||||||
depending on the platform, it might not be legal to read
|
|
||||||
the db while a statement is locking it. Throws if this db
|
|
||||||
is not open or has any opened statements.
|
|
||||||
|
|
||||||
The resulting buffer can be passed to this class's
|
|
||||||
constructor to restore the DB.
|
|
||||||
|
|
||||||
Maintenance reminder: the corresponding sql.js impl of this
|
|
||||||
feature closes the current db, finalizing any active
|
|
||||||
statements and (seemingly unnecessarily) destroys any UDFs,
|
|
||||||
copies the file, and then re-opens it (without restoring
|
|
||||||
the UDFs). Those gymnastics are not necessary on the tested
|
|
||||||
platform but might be necessary on others. Because of that
|
|
||||||
eventuality, this interface currently enforces that no
|
|
||||||
statements are active when this is run. It will throw if
|
|
||||||
any are.
|
|
||||||
*/
|
|
||||||
exportBinaryImage: function(){
|
|
||||||
toss3("exportBinaryImage() is slated for removal for portability reasons.");
|
|
||||||
/***********************
|
|
||||||
The following is currently kept only for reference when
|
|
||||||
porting to some other layer, noting that we may well not be
|
|
||||||
able to implement this, at this level, when using the OPFS
|
|
||||||
VFS because of its exclusive locking policy.
|
|
||||||
|
|
||||||
affirmDbOpen(this);
|
|
||||||
if(this.openStatementCount()>0){
|
|
||||||
toss3("Cannot export with prepared statements active!",
|
|
||||||
"finalize() all statements and try again.");
|
|
||||||
}
|
|
||||||
return MODCFG.FS.readFile(this.filename, {encoding:"binary"});
|
|
||||||
***********************/
|
|
||||||
}
|
}
|
||||||
}/*DB.prototype*/;
|
}/*DB.prototype*/;
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
|
|||||||
const rc = opRun('xFileSize', pFile);
|
const rc = opRun('xFileSize', pFile);
|
||||||
if(0==rc){
|
if(0==rc){
|
||||||
const sz = state.s11n.deserialize()[0];
|
const sz = state.s11n.deserialize()[0];
|
||||||
wasm.setMemValue(pSz64, BigInt(sz), 'i64');
|
wasm.setMemValue(pSz64, sz, 'i64');
|
||||||
}
|
}
|
||||||
mTimeEnd();
|
mTimeEnd();
|
||||||
return rc;
|
return rc;
|
||||||
@ -820,10 +820,12 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Install the vfs/io_methods into their C-level shared instances... */
|
/* Install the vfs/io_methods into their C-level shared instances... */
|
||||||
let inst = installMethod(opfsIoMethods);
|
for(let k of Object.keys(ioSyncWrappers)){
|
||||||
for(let k of Object.keys(ioSyncWrappers)) inst(k, ioSyncWrappers[k]);
|
installMethod(opfsIoMethods, k, ioSyncWrappers[k]);
|
||||||
inst = installMethod(opfsVfs);
|
}
|
||||||
for(let k of Object.keys(vfsSyncWrappers)) inst(k, vfsSyncWrappers[k]);
|
for(let k of Object.keys(vfsSyncWrappers)){
|
||||||
|
installMethod(opfsVfs, k, vfsSyncWrappers[k]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Syncronously deletes the given OPFS filesystem entry, ignoring
|
Syncronously deletes the given OPFS filesystem entry, ignoring
|
||||||
@ -831,7 +833,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
|
|||||||
directory", the given name must be an absolute path. If the 2nd
|
directory", the given name must be an absolute path. If the 2nd
|
||||||
argument is truthy, deletion is recursive (use with caution!).
|
argument is truthy, deletion is recursive (use with caution!).
|
||||||
|
|
||||||
Returns true if the deletion succeeded and fails if it fails,
|
Returns true if the deletion succeeded and false if it fails,
|
||||||
but cannot report the nature of the failure.
|
but cannot report the nature of the failure.
|
||||||
*/
|
*/
|
||||||
opfsUtil.deleteEntry = function(fsEntryName,recursive=false){
|
opfsUtil.deleteEntry = function(fsEntryName,recursive=false){
|
||||||
|
@ -784,13 +784,16 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Given an `sqlite3*` and an sqlite3_vfs name, returns a truthy
|
Given an `sqlite3*`, an sqlite3_vfs name, and an optional db
|
||||||
value (see below) if that db handle uses that VFS, else returns
|
name, returns a truthy value (see below) if that db handle uses
|
||||||
false. If pDb is falsy then this function returns a truthy value
|
that VFS, else returns false. If pDb is falsy then the 3rd
|
||||||
if the default VFS is that VFS. Results are undefined if pDb is
|
argument is ignored and this function returns a truthy value if
|
||||||
truthy but refers to an invalid pointer.
|
the default VFS name matches that of the 2nd argument. Results
|
||||||
|
are undefined if pDb is truthy but refers to an invalid
|
||||||
|
pointer. The 3rd argument specifies the database name of the
|
||||||
|
given database connection to check, defaulting to the main db.
|
||||||
|
|
||||||
The 2nd argument may either be a JS string or a C-string
|
The 2nd and 3rd arguments may either be a JS string or a C-string
|
||||||
allocated from the wasm environment.
|
allocated from the wasm environment.
|
||||||
|
|
||||||
The truthy value it returns is a pointer to the `sqlite3_vfs`
|
The truthy value it returns is a pointer to the `sqlite3_vfs`
|
||||||
@ -801,11 +804,9 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
bad arguments cause a conversion error when passing into
|
bad arguments cause a conversion error when passing into
|
||||||
wasm-space, false is returned.
|
wasm-space, false is returned.
|
||||||
*/
|
*/
|
||||||
capi.sqlite3_web_db_uses_vfs = function(pDb,vfsName){
|
capi.sqlite3_web_db_uses_vfs = function(pDb,vfsName,dbName="main"){
|
||||||
try{
|
try{
|
||||||
const pK = ('number'===vfsName)
|
const pK = capi.sqlite3_vfs_find(vfsName);
|
||||||
? capi.wasm.exports.sqlite3_vfs_find(vfsName)
|
|
||||||
: capi.sqlite3_vfs_find(vfsName);
|
|
||||||
if(!pK) return false;
|
if(!pK) return false;
|
||||||
else if(!pDb){
|
else if(!pDb){
|
||||||
return capi.sqlite3_vfs_find(0)===pK ? pK : false;
|
return capi.sqlite3_vfs_find(0)===pK ? pK : false;
|
||||||
@ -814,7 +815,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
try{
|
try{
|
||||||
return (
|
return (
|
||||||
(0===capi.sqlite3_file_control(
|
(0===capi.sqlite3_file_control(
|
||||||
pDb, "main", capi.SQLITE_FCNTL_VFS_POINTER, ppVfs
|
pDb, dbName, capi.SQLITE_FCNTL_VFS_POINTER, ppVfs
|
||||||
)) && (capi.wasm.getPtrValue(ppVfs) === pK)
|
)) && (capi.wasm.getPtrValue(ppVfs) === pK)
|
||||||
) ? pK : false;
|
) ? pK : false;
|
||||||
}finally{
|
}finally{
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
- WASM-exported "indirect function table" access and
|
- WASM-exported "indirect function table" access and
|
||||||
manipulation. e.g. creating new WASM-side functions using JS
|
manipulation. e.g. creating new WASM-side functions using JS
|
||||||
functions, analog to Emscripten's addFunction() and
|
functions, analog to Emscripten's addFunction() and
|
||||||
removeFunction() but slightly different.
|
uninstallFunction() but slightly different.
|
||||||
|
|
||||||
- Get/set specific heap memory values, analog to Emscripten's
|
- Get/set specific heap memory values, analog to Emscripten's
|
||||||
getValue() and setValue().
|
getValue() and setValue().
|
||||||
@ -483,9 +483,12 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
available slot of this.functionTable(), and returns the
|
available slot of this.functionTable(), and returns the
|
||||||
function's index in that table (which acts as a pointer to that
|
function's index in that table (which acts as a pointer to that
|
||||||
function). The returned pointer can be passed to
|
function). The returned pointer can be passed to
|
||||||
removeFunction() to uninstall it and free up the table slot for
|
uninstallFunction() to uninstall it and free up the table slot for
|
||||||
reuse.
|
reuse.
|
||||||
|
|
||||||
|
If passed (string,function) arguments then it treats the first
|
||||||
|
argument as the signature and second as the function.
|
||||||
|
|
||||||
As a special case, if the passed-in function is a WASM-exported
|
As a special case, if the passed-in function is a WASM-exported
|
||||||
function then the signature argument is ignored and func is
|
function then the signature argument is ignored and func is
|
||||||
installed as-is, without requiring re-compilation/re-wrapping.
|
installed as-is, without requiring re-compilation/re-wrapping.
|
||||||
@ -499,12 +502,20 @@ self.WhWasmUtilInstaller = function(target){
|
|||||||
Sidebar: this function differs from Emscripten's addFunction()
|
Sidebar: this function differs from Emscripten's addFunction()
|
||||||
_primarily_ in that it does not share that function's
|
_primarily_ in that it does not share that function's
|
||||||
undocumented behavior of reusing a function if it's passed to
|
undocumented behavior of reusing a function if it's passed to
|
||||||
addFunction() more than once, which leads to removeFunction()
|
addFunction() more than once, which leads to uninstallFunction()
|
||||||
breaking clients which do not take care to avoid that case:
|
breaking clients which do not take care to avoid that case:
|
||||||
|
|
||||||
https://github.com/emscripten-core/emscripten/issues/17323
|
https://github.com/emscripten-core/emscripten/issues/17323
|
||||||
*/
|
*/
|
||||||
target.installFunction = function f(func, sig){
|
target.installFunction = function f(func, sig){
|
||||||
|
if(2!==arguments.length){
|
||||||
|
toss("installFunction() requires exactly 2 arguments");
|
||||||
|
}
|
||||||
|
if('string'===typeof func && sig instanceof Function){
|
||||||
|
const x = sig;
|
||||||
|
sig = func;
|
||||||
|
func = x;
|
||||||
|
}
|
||||||
const ft = target.functionTable();
|
const ft = target.functionTable();
|
||||||
const oldLen = ft.length;
|
const oldLen = ft.length;
|
||||||
let ptr;
|
let ptr;
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
throw new Error(args.join(' '));
|
throw new Error(args.join(' '));
|
||||||
};
|
};
|
||||||
const fixmeOPFS = "(FIXME: won't work with vanilla OPFS.)";
|
const fixmeOPFS = "(FIXME: won't work with vanilla OPFS.)";
|
||||||
|
let sqlite3 /* gets assigned when the wasm module is loaded */;
|
||||||
|
|
||||||
self.onerror = function(/*message, source, lineno, colno, error*/) {
|
self.onerror = function(/*message, source, lineno, colno, error*/) {
|
||||||
const err = arguments[4];
|
const err = arguments[4];
|
||||||
@ -121,9 +122,18 @@
|
|||||||
const Sqlite3Shell = {
|
const Sqlite3Shell = {
|
||||||
/** Returns the name of the currently-opened db. */
|
/** Returns the name of the currently-opened db. */
|
||||||
dbFilename: function f(){
|
dbFilename: function f(){
|
||||||
if(!f._) f._ = fiddleModule.cwrap('fiddle_db_filename', "string", ['string']);
|
if(!f._) f._ = sqlite3.capi.wasm.xWrap('fiddle_db_filename', "string", ['string']);
|
||||||
|
return f._(0);
|
||||||
|
},
|
||||||
|
dbHandle: function f(){
|
||||||
|
if(!f._) f._ = sqlite3.capi.wasm.xWrap("fiddle_db_handle", "sqlite3*");
|
||||||
return f._();
|
return f._();
|
||||||
},
|
},
|
||||||
|
dbIsOpfs: function f(){
|
||||||
|
return sqlite3.opfs && sqlite3.capi.sqlite3_web_db_uses_vfs(
|
||||||
|
this.dbHandle(), "opfs"
|
||||||
|
);
|
||||||
|
},
|
||||||
runMain: function f(){
|
runMain: function f(){
|
||||||
if(f.argv) return 0===f.argv.rc;
|
if(f.argv) return 0===f.argv.rc;
|
||||||
const dbName = "/fiddle.sqlite3";
|
const dbName = "/fiddle.sqlite3";
|
||||||
@ -141,7 +151,8 @@
|
|||||||
after sqlite3_initialize() has been called. This means,
|
after sqlite3_initialize() has been called. This means,
|
||||||
however, that any initialization done by the JS code may need
|
however, that any initialization done by the JS code may need
|
||||||
to be re-done (e.g. re-registration of dynamically-loaded
|
to be re-done (e.g. re-registration of dynamically-loaded
|
||||||
VFSes). */
|
VFSes). We need a more generic approach to running such
|
||||||
|
init-level code. */
|
||||||
S.capi.sqlite3_shutdown();
|
S.capi.sqlite3_shutdown();
|
||||||
f.argv.pArgv = S.capi.wasm.allocMainArgv(f.argv);
|
f.argv.pArgv = S.capi.wasm.allocMainArgv(f.argv);
|
||||||
f.argv.rc = S.capi.wasm.exports.fiddle_main(
|
f.argv.rc = S.capi.wasm.exports.fiddle_main(
|
||||||
@ -196,6 +207,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resetDb: function f(){
|
resetDb: function f(){
|
||||||
|
if(Sqlite3Shell.dbIsOpfs()){
|
||||||
|
/* The problem is that fiddle_reset_db() uses the POSIX APIs
|
||||||
|
for file removal, which cannot see OPFS-hosted files. */
|
||||||
|
stderr("TODO: cannot currently reset an OPFS-hosted db.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(!f._) f._ = fiddleModule.cwrap('fiddle_reset_db', null);
|
if(!f._) f._ = fiddleModule.cwrap('fiddle_reset_db', null);
|
||||||
stdout("Resetting database.",fixmeOPFS);
|
stdout("Resetting database.",fixmeOPFS);
|
||||||
f._();
|
f._();
|
||||||
@ -216,29 +233,30 @@
|
|||||||
(and, hypothetically, kvvfs). Throws on error. On success returns
|
(and, hypothetically, kvvfs). Throws on error. On success returns
|
||||||
a Blob containing the whole db contents.
|
a Blob containing the whole db contents.
|
||||||
|
|
||||||
Bug: xFileSize() is returning garbage for the default VFS but
|
Bug/to investigate: xFileSize() is returning garbage for the
|
||||||
works in OPFS. Thus for exporting that impl we'll use the
|
default VFS but works in OPFS. Thus for exporting that impl we'll
|
||||||
fiddleModule.FS API for the time being.
|
use the fiddleModule.FS API for the time being. The equivalent
|
||||||
|
native impl, fiddle_export_db(), works okay with both VFSes, so
|
||||||
|
the bug is apparently in (or via) this code.
|
||||||
*/
|
*/
|
||||||
const exportDbFileToBlob = function(){
|
const brokenExportDbFileToBlob = function(){
|
||||||
const S = fiddleModule.sqlite3, capi = S.capi, wasm = capi.wasm;
|
const S = fiddleModule.sqlite3, capi = S.capi, wasm = capi.wasm;
|
||||||
const pDb = wasm.xCall("fiddle_db_handle");
|
const pDb = Sqlite3Shell.dbHandle();
|
||||||
if(!pDb) toss("No db is opened.");
|
if(!pDb) toss("No db is opened.");
|
||||||
const scope = wasm.scopedAllocPush();
|
const scope = wasm.scopedAllocPush();
|
||||||
try{
|
try{
|
||||||
const ppFile = wasm.scopedAlloc(12/*sizeof(i32 + i64)*/);
|
const ppFile = wasm.scopedAlloc(12/*sizeof(i32 + i64)*/);
|
||||||
const pFileSize = ppFile + 4;
|
const pFileSize = ppFile + 4;
|
||||||
wasm.setMemValue(ppFile, 0, 'i32');
|
wasm.setMemValue(ppFile, 0, '*');
|
||||||
let rc = capi.sqlite3_file_control(
|
let rc = capi.sqlite3_file_control(
|
||||||
pDb, "main", capi.SQLITE_FCNTL_FILE_POINTER, ppFile
|
pDb, "main", capi.SQLITE_FCNTL_FILE_POINTER, ppFile
|
||||||
);
|
);
|
||||||
if(rc) toss("Cannot get sqlite3_file handle.");
|
if(rc) toss("Cannot get sqlite3_file handle.");
|
||||||
const jFile = new capi.sqlite3_file(wasm.getPtrValue(ppFile));
|
const jFile = new capi.sqlite3_file(wasm.getPtrValue(ppFile));
|
||||||
const jIom = new capi.sqlite3_io_methods(jFile.$pMethods);
|
const jIom = new capi.sqlite3_io_methods(jFile.$pMethods);
|
||||||
console.warn("jIom =",jIom);
|
|
||||||
const xFileSize = wasm.functionEntry(jIom.$xFileSize);
|
const xFileSize = wasm.functionEntry(jIom.$xFileSize);
|
||||||
const xRead = wasm.functionEntry(jIom.$xRead);
|
const xRead = wasm.functionEntry(jIom.$xRead);
|
||||||
wasm.setMemValue(pFileSize, 0n, 'i64');
|
wasm.setMemValue(pFileSize, 0, 'i64');
|
||||||
//stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
|
//stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
|
||||||
rc = xFileSize( jFile.pointer, pFileSize );
|
rc = xFileSize( jFile.pointer, pFileSize );
|
||||||
if(rc) toss("Cannot get db file size.");
|
if(rc) toss("Cannot get db file size.");
|
||||||
@ -273,6 +291,30 @@
|
|||||||
}
|
}
|
||||||
}/*exportDbFileToBlob()*/;
|
}/*exportDbFileToBlob()*/;
|
||||||
|
|
||||||
|
const exportDbFileToBlob = function f(){
|
||||||
|
if(!f._){
|
||||||
|
f._ = sqlite3.capi.wasm.xWrap('fiddle_export_db', 'int', '*');
|
||||||
|
}
|
||||||
|
const capi = sqlite3.capi;
|
||||||
|
const wasm = capi.wasm;
|
||||||
|
const blobList = [];
|
||||||
|
const heap = wasm.heap8u();
|
||||||
|
const callback = wasm.installFunction('ipi', function(buf, n){
|
||||||
|
blobList.push(heap.slice(buf, buf+n));
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const rc = wasm.exports.fiddle_export_db( callback );
|
||||||
|
if(rc) toss("DB export failed with code", capi.sqlite3_wasm_rc_str(rc));
|
||||||
|
return new Blob(blobList);
|
||||||
|
}catch(e){
|
||||||
|
console.error("exportDbFileToBlob():",e.message);
|
||||||
|
throw(e);
|
||||||
|
}finally{
|
||||||
|
wasm.uninstallFunction(callback);
|
||||||
|
}
|
||||||
|
}/*exportDbFileToBlob()*/;
|
||||||
|
|
||||||
self.onmessage = function f(ev){
|
self.onmessage = function f(ev){
|
||||||
ev = ev.data;
|
ev = ev.data;
|
||||||
if(!f.cache){
|
if(!f.cache){
|
||||||
@ -302,18 +344,9 @@
|
|||||||
const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
|
const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
|
||||||
try{
|
try{
|
||||||
if(!fn2) throw new Error("DB appears to be closed.");
|
if(!fn2) throw new Error("DB appears to be closed.");
|
||||||
if(fiddleModule.sqlite3.capi.wasm.xCall(
|
|
||||||
'fiddle_db_is_opfs'
|
|
||||||
)){
|
|
||||||
exportDbFileToBlob().arrayBuffer().then((buffer)=>{
|
exportDbFileToBlob().arrayBuffer().then((buffer)=>{
|
||||||
wMsg('db-export',{filename: fn2, buffer}, [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){
|
}catch(e){
|
||||||
/* Post a failure message so that UI elements disabled
|
/* Post a failure message so that UI elements disabled
|
||||||
during the export can be re-enabled. */
|
during the export can be re-enabled. */
|
||||||
@ -427,15 +460,15 @@
|
|||||||
emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule
|
emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule
|
||||||
*/
|
*/
|
||||||
initFiddleModule(fiddleModule).then(function(thisModule){
|
initFiddleModule(fiddleModule).then(function(thisModule){
|
||||||
const S = thisModule.sqlite3;
|
sqlite3 = thisModule.sqlite3;
|
||||||
const atEnd = ()=>{
|
const atEnd = ()=>{
|
||||||
thisModule.fsUnlink = (fn)=>{
|
thisModule.fsUnlink = (fn)=>{
|
||||||
stderr("unlink:",fixmeOPFS);
|
stderr("unlink:",fixmeOPFS);
|
||||||
return S.capi.wasm.sqlite3_wasm_vfs_unlink(fn);
|
return sqlite3.capi.wasm.sqlite3_wasm_vfs_unlink(fn);
|
||||||
};
|
};
|
||||||
wMsg('fiddle-ready');
|
wMsg('fiddle-ready');
|
||||||
};
|
};
|
||||||
if(S.installOpfsVfs) S.installOpfsVfs().finally(atEnd);
|
if(sqlite3.installOpfsVfs) sqlite3.installOpfsVfs().finally(atEnd);
|
||||||
else atEnd();
|
else atEnd();
|
||||||
})/*then()*/;
|
})/*then()*/;
|
||||||
})();
|
})();
|
||||||
|
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
|||||||
C Get\sfiddle\sdb\sexport\sworking\sfor\sOPFS\sVFS.\sAdd\sroot\sdir\shandle\sto\sthe\smain\sOPFS\sVFS\sworker\sto\senable\screation\sof\scertain\sutility\sfunctions\swithout\sdelegating\sto\sthe\sasync\sworker.\sAdd\ssqlite3.capi.sqlite3_wasm_rc_str()\sto\smap\sinteger\sresult\scodes\sback\sto\stheir\sSQLITE_xxx\scounterparts.\sMinor\sdoc\stouchups.
|
C Fiddle:\sreplace\sdb\sexport\sroutine\swith\sa\sC-side\sone\swhich\sworks\sfor\sboth\sEmscripten\sFS-hosted\sand\sOPFS-hosted\sdb\sfiles.\sMinor\scode-adjacent\scleanups.
|
||||||
D 2022-09-26T11:38:58.930
|
D 2022-09-26T13:55:10.137
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -472,7 +472,7 @@ F ext/session/test_session.c f433f68a8a8c64b0f5bc74dc725078f12483301ad4ae8375205
|
|||||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 48af0d812e2e1099798ae0e27f1d4836d572d0d068c83b3e2088ef4d97c45c2f
|
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||||
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0
|
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0
|
||||||
F ext/wasm/GNUmakefile 34a84e30e6b25e24959a8264e9dec020dffa82d96879dc55ad65d3c31c95d3b1
|
F ext/wasm/GNUmakefile 34a84e30e6b25e24959a8264e9dec020dffa82d96879dc55ad65d3c31c95d3b1
|
||||||
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
|
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
|
||||||
@ -483,9 +483,9 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814
|
|||||||
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
|
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
|
||||||
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
|
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
|
||||||
F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e
|
F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js f974e79d9af8f26bf33928c5730b0988cc706d14f59a5fe36394739b92249841
|
F ext/wasm/api/sqlite3-api-oo1.js 455fcb28dd77b9781e087aac77392fb78f8ee8e5b125a99c1488604de27a5bb1
|
||||||
F ext/wasm/api/sqlite3-api-opfs.js 151f8bab445915dd4fa8fe3329accc5250351e7bf0af1518cb5cc49886c123d2
|
F ext/wasm/api/sqlite3-api-opfs.js e0dfae09aedc6fe414d8d350e7228a6a88de030a0cb19a748ac8269aef9b11db
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js 76db12cce58ec6724ec01a977dfbedabfd4916e915a6e7679ffc24dd52eef64e
|
F ext/wasm/api/sqlite3-api-prologue.js d39bda7d83aaeb8e15574afe8308221ed11c6f24865ccff06cf0424b665e681e
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b
|
F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b
|
||||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||||
F ext/wasm/api/sqlite3-wasm.c 7010405f1981cd5929568403a618f80398f7acbf76b3eb11c4f23789206eb164
|
F ext/wasm/api/sqlite3-wasm.c 7010405f1981cd5929568403a618f80398f7acbf76b3eb11c4f23789206eb164
|
||||||
@ -494,7 +494,7 @@ F ext/wasm/batch-runner.js 6f5b86e0b5519a9a941d9f17ee9c5ecdc63f452f157602fe7fdf8
|
|||||||
F ext/wasm/common/SqliteTestUtil.js 529161a624265ba84271a52db58da022649832fa1c71309fb1e02cc037327a2b
|
F ext/wasm/common/SqliteTestUtil.js 529161a624265ba84271a52db58da022649832fa1c71309fb1e02cc037327a2b
|
||||||
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||||
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
|
F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962
|
||||||
F ext/wasm/common/whwasmutil.js 2a8cd8b0c936da5812971aa39c8d989306c2ad8fc841dcd037c3be62737dc652
|
F ext/wasm/common/whwasmutil.js 20291bbf4955358d0b5ead58db4c575be269b4976e39c43a93331547e3b86363
|
||||||
F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f
|
F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f
|
||||||
F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4
|
F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4
|
||||||
F ext/wasm/demo-123.js 234655683e35a4543a23de7b10800d76b0369947b33e089e5613171fa7795afb
|
F ext/wasm/demo-123.js 234655683e35a4543a23de7b10800d76b0369947b33e089e5613171fa7795afb
|
||||||
@ -502,7 +502,7 @@ F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424
|
|||||||
F ext/wasm/demo-kvvfs1.js e884ea35022d772c0d1dd884b40011413696438394f605c6cd4808cfb1642a4a
|
F ext/wasm/demo-kvvfs1.js e884ea35022d772c0d1dd884b40011413696438394f605c6cd4808cfb1642a4a
|
||||||
F ext/wasm/fiddle.make fd56fa21bada6ecbf860686a9a789ebda7cc3d9b60835927000fcb00246ea50f
|
F ext/wasm/fiddle.make fd56fa21bada6ecbf860686a9a789ebda7cc3d9b60835927000fcb00246ea50f
|
||||||
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||||
F ext/wasm/fiddle/fiddle-worker.js 42c31065660e57844afa796bcf120666348c060fc4c656c335151b62da7fc60d
|
F ext/wasm/fiddle/fiddle-worker.js 1fe173ba963314df99df9eb8f0f45f1c3a72c056f16510e47787eb1790cb5531
|
||||||
F ext/wasm/fiddle/fiddle.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
|
F ext/wasm/fiddle/fiddle.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
|
||||||
F ext/wasm/fiddle/fiddle.js aa44051be6e48c53fd23c829177d43f557dcc6f0998ccfcbae7c473ff405f0c6
|
F ext/wasm/fiddle/fiddle.js aa44051be6e48c53fd23c829177d43f557dcc6f0998ccfcbae7c473ff405f0c6
|
||||||
F ext/wasm/index.html a39d14f6de6bd1294d39522fcf40eca3c9f0b6da44bb8df6948378e9f30468f5
|
F ext/wasm/index.html a39d14f6de6bd1294d39522fcf40eca3c9f0b6da44bb8df6948378e9f30468f5
|
||||||
@ -615,7 +615,7 @@ F src/random.c 546d6feb15ec69c1aafe9bb351a277cbb498fd5410e646add673acb805714960
|
|||||||
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
|
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
|
||||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||||
F src/select.c d69dfb5b082f9a25e6700e152ddb3d942359b847b1df504eb09f9b4531844f8d
|
F src/select.c d69dfb5b082f9a25e6700e152ddb3d942359b847b1df504eb09f9b4531844f8d
|
||||||
F src/shell.c.in 00a72221c8b2df823f3a9d712457ae8bebe627b5989fefa1ccfe099eafab5139
|
F src/shell.c.in 2980312ab57fc5ccf298d1f0682588ec3832f52a878bea8abe34647d2cf31d05
|
||||||
F src/sqlite.h.in b9b7fd73239d94db20332bb6e504688001e5564b655e1318a4427a1caef4b99e
|
F src/sqlite.h.in b9b7fd73239d94db20332bb6e504688001e5564b655e1318a4427a1caef4b99e
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d
|
F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d
|
||||||
@ -2026,8 +2026,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 85f2e877e53899860af4dc6630044b471a9c7c82faba1f4e1e60ae991460b943
|
P 9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41
|
||||||
R 021d11845b25e048635a4d675c2c9f1f
|
R ee45c68d4b4cfbf2a729d26cea95ac0e
|
||||||
U stephan
|
U stephan
|
||||||
Z 684fe82520a24a3caf4c9fdd7b640f27
|
Z a7778a8aaef90b52f5b829e56bd6cae3
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41
|
3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94
|
@ -12639,6 +12639,20 @@ sqlite3 * fiddle_db_handle(){
|
|||||||
return globalDb;
|
return globalDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Returns a pointer to the given DB name's VFS. If zDbName is 0 then
|
||||||
|
** "main" is assumed. Returns 0 if no db with the given name is
|
||||||
|
** open.
|
||||||
|
*/
|
||||||
|
sqlite3_vfs * fiddle_db_vfs(const char *zDbName){
|
||||||
|
sqlite3_vfs * pVfs = 0;
|
||||||
|
if(globalDb){
|
||||||
|
sqlite3_file_control(globalDb, zDbName ? zDbName : "main",
|
||||||
|
SQLITE_FCNTL_VFS_POINTER, &pVfs);
|
||||||
|
}
|
||||||
|
return pVfs;
|
||||||
|
}
|
||||||
|
|
||||||
/* Only for emcc experimentation purposes. */
|
/* Only for emcc experimentation purposes. */
|
||||||
sqlite3 * fiddle_db_arg(sqlite3 *arg){
|
sqlite3 * fiddle_db_arg(sqlite3 *arg){
|
||||||
printf("fiddle_db_arg(%p)\n", (const void*)arg);
|
printf("fiddle_db_arg(%p)\n", (const void*)arg);
|
||||||
@ -12689,53 +12703,46 @@ void fiddle_reset_db(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This is a bit of a workaround: returns true if the current db uses
|
** Uses the current database's VFS xRead to stream the db file's
|
||||||
** the "opfs" VFS, else false.
|
** contents out to the given callback. The callback gets a single
|
||||||
|
** chunk of size n (its 2nd argument) on each call and must return 0
|
||||||
|
** on success, non-0 on error. This function returns 0 on success,
|
||||||
|
** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
|
||||||
|
** code from the callback. Note that this is not thread-friendly: it
|
||||||
|
** expects that it will be the only thread reading the db file and
|
||||||
|
** takes no measures to ensure that is the case.
|
||||||
*/
|
*/
|
||||||
int fiddle_db_is_opfs(void){
|
int fiddle_export_db( int (*xCallback)(unsigned const char *zOut, int n) ){
|
||||||
sqlite3_vfs * pVfs = 0;
|
|
||||||
if( 0!=shellState.db ){
|
|
||||||
sqlite3_file_control( shellState.db, "main",
|
|
||||||
SQLITE_FCNTL_VFS_POINTER, &pVfs );
|
|
||||||
}
|
|
||||||
return pVfs ? 0==strcmp("opfs", pVfs->zName) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* TODO: test whether this impl works properly wrt xSize() in the
|
|
||||||
** unix-none VFS. The JS impl works fine for OPFS but not unix-none
|
|
||||||
** because xSize() is returning a garbage size.
|
|
||||||
*/
|
|
||||||
int fiddle_export_db( int (*callback)(unsigned const char *zOut, int n) ){
|
|
||||||
sqlite3_int64 nSize = 0;
|
sqlite3_int64 nSize = 0;
|
||||||
sqlite3_int64 nPos = 0;
|
sqlite3_int64 nPos = 0;
|
||||||
sqlite3_vfs * pVfs = 0;
|
|
||||||
sqlite3_file * pFile = 0;
|
sqlite3_file * pFile = 0;
|
||||||
unsigned char buf[1024 * 4];
|
unsigned char buf[1024 * 8];
|
||||||
const int nBuf = (int)sizeof(buf);
|
int nBuf = (int)sizeof(buf);
|
||||||
int rc = shellState.db
|
int rc = shellState.db
|
||||||
? sqlite3_file_control(shellState.db, "main",
|
? sqlite3_file_control(shellState.db, "main",
|
||||||
SQLITE_FCNTL_VFS_POINTER, &pVfs)
|
SQLITE_FCNTL_FILE_POINTER, &pFile)
|
||||||
: 0;
|
: SQLITE_NOTFOUND;
|
||||||
if( rc ) return rc;
|
|
||||||
else if( 0==pVfs ) return SQLITE_NOTFOUND;
|
|
||||||
rc = sqlite3_file_control(shellState.db, "main",
|
|
||||||
SQLITE_FCNTL_FILE_POINTER, &pFile);
|
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
rc = pFile->pMethods->xFileSize(pFile, &nSize);
|
rc = pFile->pMethods->xFileSize(pFile, &nSize);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
|
if(nSize % nBuf){
|
||||||
|
/* DB size is not an even multiple of the buffer size. Reduce
|
||||||
|
** buffer size so that we do not unduly inflate the db size when
|
||||||
|
** exporting. */
|
||||||
|
if(0 == nSize % 4096) nBuf = 4096;
|
||||||
|
else if(0 == nSize % 2048) nBuf = 2048;
|
||||||
|
else if(0 == nSize % 1024) nBuf = 1024;
|
||||||
|
else nBuf = 512;
|
||||||
|
}
|
||||||
for( ; 0==rc && nPos<nSize; nPos += nBuf ){
|
for( ; 0==rc && nPos<nSize; nPos += nBuf ){
|
||||||
rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
|
rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
|
||||||
if(SQLITE_IOERR_SHORT_READ == rc){
|
if(SQLITE_IOERR_SHORT_READ == rc){
|
||||||
rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
|
rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
|
||||||
}
|
}
|
||||||
if(rc) return rc;
|
if( 0==rc ) rc = xCallback(buf, nBuf);
|
||||||
nPos += nBuf;
|
|
||||||
rc = callback(buf, nBuf);
|
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Trivial exportable function for emscripten. It processes zSql as if
|
** Trivial exportable function for emscripten. It processes zSql as if
|
||||||
|
Reference in New Issue
Block a user