1
0
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:
stephan
2022-09-26 13:55:10 +00:00
parent 1f095d482d
commit 278d3faf1f
9 changed files with 149 additions and 139 deletions

View File

@ -6,4 +6,5 @@ _fiddle_interrupt
_fiddle_main
_fiddle_reset_db
_fiddle_db_handle
_fiddle_db_is_opfs
_fiddle_db_vfs
_fiddle_export_db

View File

@ -1025,51 +1025,6 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
this.exec("ROLLBACK to SAVEPOINT oo1; RELEASE SAVEPOINT oo1");
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*/;

View File

@ -637,7 +637,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
const rc = opRun('xFileSize', pFile);
if(0==rc){
const sz = state.s11n.deserialize()[0];
wasm.setMemValue(pSz64, BigInt(sz), 'i64');
wasm.setMemValue(pSz64, sz, 'i64');
}
mTimeEnd();
return rc;
@ -820,10 +820,12 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
}
/* Install the vfs/io_methods into their C-level shared instances... */
let inst = installMethod(opfsIoMethods);
for(let k of Object.keys(ioSyncWrappers)) inst(k, ioSyncWrappers[k]);
inst = installMethod(opfsVfs);
for(let k of Object.keys(vfsSyncWrappers)) inst(k, vfsSyncWrappers[k]);
for(let k of Object.keys(ioSyncWrappers)){
installMethod(opfsIoMethods, k, ioSyncWrappers[k]);
}
for(let k of Object.keys(vfsSyncWrappers)){
installMethod(opfsVfs, k, vfsSyncWrappers[k]);
}
/**
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
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.
*/
opfsUtil.deleteEntry = function(fsEntryName,recursive=false){

View File

@ -784,13 +784,16 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}
/**
Given an `sqlite3*` and an sqlite3_vfs name, returns a truthy
value (see below) if that db handle uses that VFS, else returns
false. If pDb is falsy then this function returns a truthy value
if the default VFS is that VFS. Results are undefined if pDb is
truthy but refers to an invalid pointer.
Given an `sqlite3*`, an sqlite3_vfs name, and an optional db
name, returns a truthy value (see below) if that db handle uses
that VFS, else returns false. If pDb is falsy then the 3rd
argument is ignored and this function returns a truthy value if
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.
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
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{
const pK = ('number'===vfsName)
? capi.wasm.exports.sqlite3_vfs_find(vfsName)
: capi.sqlite3_vfs_find(vfsName);
const pK = capi.sqlite3_vfs_find(vfsName);
if(!pK) return false;
else if(!pDb){
return capi.sqlite3_vfs_find(0)===pK ? pK : false;
@ -814,7 +815,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
try{
return (
(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)
) ? pK : false;
}finally{

View File

@ -63,7 +63,7 @@
- WASM-exported "indirect function table" access and
manipulation. e.g. creating new WASM-side functions using JS
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
getValue() and setValue().
@ -483,9 +483,12 @@ self.WhWasmUtilInstaller = function(target){
available slot of this.functionTable(), and returns the
function's index in that table (which acts as a pointer to that
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.
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
function then the signature argument is ignored and func is
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()
_primarily_ in that it does not share that function's
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:
https://github.com/emscripten-core/emscripten/issues/17323
*/
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 oldLen = ft.length;
let ptr;

View File

@ -103,6 +103,7 @@
throw new Error(args.join(' '));
};
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*/) {
const err = arguments[4];
@ -121,9 +122,18 @@
const Sqlite3Shell = {
/** Returns the name of the currently-opened db. */
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._();
},
dbIsOpfs: function f(){
return sqlite3.opfs && sqlite3.capi.sqlite3_web_db_uses_vfs(
this.dbHandle(), "opfs"
);
},
runMain: function f(){
if(f.argv) return 0===f.argv.rc;
const dbName = "/fiddle.sqlite3";
@ -141,7 +151,8 @@
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). */
VFSes). We need a more generic approach to running such
init-level code. */
S.capi.sqlite3_shutdown();
f.argv.pArgv = S.capi.wasm.allocMainArgv(f.argv);
f.argv.rc = S.capi.wasm.exports.fiddle_main(
@ -196,6 +207,12 @@
}
},
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);
stdout("Resetting database.",fixmeOPFS);
f._();
@ -216,29 +233,30 @@
(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.
Bug/to investigate: 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. 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 pDb = wasm.xCall("fiddle_db_handle");
const pDb = Sqlite3Shell.dbHandle();
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');
wasm.setMemValue(ppFile, 0, '*');
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');
wasm.setMemValue(pFileSize, 0, 'i64');
//stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
rc = xFileSize( jFile.pointer, pFileSize );
if(rc) toss("Cannot get db file size.");
@ -273,6 +291,30 @@
}
}/*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){
ev = ev.data;
if(!f.cache){
@ -302,18 +344,9 @@
const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
try{
if(!fn2) throw new Error("DB appears to be closed.");
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;
exportDbFileToBlob().arrayBuffer().then((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. */
@ -427,15 +460,15 @@
emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule
*/
initFiddleModule(fiddleModule).then(function(thisModule){
const S = thisModule.sqlite3;
sqlite3 = thisModule.sqlite3;
const atEnd = ()=>{
thisModule.fsUnlink = (fn)=>{
stderr("unlink:",fixmeOPFS);
return S.capi.wasm.sqlite3_wasm_vfs_unlink(fn);
return sqlite3.capi.wasm.sqlite3_wasm_vfs_unlink(fn);
};
wMsg('fiddle-ready');
};
if(S.installOpfsVfs) S.installOpfsVfs().finally(atEnd);
if(sqlite3.installOpfsVfs) sqlite3.installOpfsVfs().finally(atEnd);
else atEnd();
})/*then()*/;
})();

View File

@ -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.
D 2022-09-26T11:38:58.930
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-26T13:55:10.137
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -472,7 +472,7 @@ F ext/session/test_session.c f433f68a8a8c64b0f5bc74dc725078f12483301ad4ae8375205
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
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/GNUmakefile 34a84e30e6b25e24959a8264e9dec020dffa82d96879dc55ad65d3c31c95d3b1
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/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e
F ext/wasm/api/sqlite3-api-oo1.js f974e79d9af8f26bf33928c5730b0988cc706d14f59a5fe36394739b92249841
F ext/wasm/api/sqlite3-api-opfs.js 151f8bab445915dd4fa8fe3329accc5250351e7bf0af1518cb5cc49886c123d2
F ext/wasm/api/sqlite3-api-prologue.js 76db12cce58ec6724ec01a977dfbedabfd4916e915a6e7679ffc24dd52eef64e
F ext/wasm/api/sqlite3-api-oo1.js 455fcb28dd77b9781e087aac77392fb78f8ee8e5b125a99c1488604de27a5bb1
F ext/wasm/api/sqlite3-api-opfs.js e0dfae09aedc6fe414d8d350e7228a6a88de030a0cb19a748ac8269aef9b11db
F ext/wasm/api/sqlite3-api-prologue.js d39bda7d83aaeb8e15574afe8308221ed11c6f24865ccff06cf0424b665e681e
F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
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/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
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.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4
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/fiddle.make fd56fa21bada6ecbf860686a9a789ebda7cc3d9b60835927000fcb00246ea50f
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.js aa44051be6e48c53fd23c829177d43f557dcc6f0998ccfcbae7c473ff405f0c6
F ext/wasm/index.html a39d14f6de6bd1294d39522fcf40eca3c9f0b6da44bb8df6948378e9f30468f5
@ -615,7 +615,7 @@ F src/random.c 546d6feb15ec69c1aafe9bb351a277cbb498fd5410e646add673acb805714960
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
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/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d
@ -2026,8 +2026,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 85f2e877e53899860af4dc6630044b471a9c7c82faba1f4e1e60ae991460b943
R 021d11845b25e048635a4d675c2c9f1f
P 9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41
R ee45c68d4b4cfbf2a729d26cea95ac0e
U stephan
Z 684fe82520a24a3caf4c9fdd7b640f27
Z a7778a8aaef90b52f5b829e56bd6cae3
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41
3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94

View File

@ -12629,14 +12629,28 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#ifdef SQLITE_SHELL_FIDDLE
/* Only for emcc experimentation purposes. */
int fiddle_experiment(int a,int b){
return a + b;
return a + b;
}
/*
** Returns a pointer to the current DB handle.
*/
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. */
@ -12652,7 +12666,7 @@ sqlite3 * fiddle_db_arg(sqlite3 *arg){
** portable enough to make real use of.
*/
void fiddle_interrupt(void){
if(globalDb) sqlite3_interrupt(globalDb);
if( globalDb ) sqlite3_interrupt(globalDb);
}
/*
@ -12673,7 +12687,7 @@ const char * fiddle_db_filename(const char * zDbName){
*/
void fiddle_reset_db(void){
char *zFilename = 0;
if(0==globalDb){
if( 0==globalDb ){
shellState.pAuxDb->zDbFilename = shellState.wasm.zDefaultDbName;
}else{
zFilename =
@ -12689,53 +12703,46 @@ void fiddle_reset_db(void){
}
/*
** This is a bit of a workaround: returns true if the current db uses
** the "opfs" VFS, else false.
** Uses the current database's VFS xRead to stream the db file's
** 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){
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) ){
int fiddle_export_db( int (*xCallback)(unsigned const char *zOut, int n) ){
sqlite3_int64 nSize = 0;
sqlite3_int64 nPos = 0;
sqlite3_vfs * pVfs = 0;
sqlite3_file * pFile = 0;
unsigned char buf[1024 * 4];
const int nBuf = (int)sizeof(buf);
unsigned char buf[1024 * 8];
int nBuf = (int)sizeof(buf);
int rc = shellState.db
? sqlite3_file_control(shellState.db, "main",
SQLITE_FCNTL_VFS_POINTER, &pVfs)
: 0;
if( rc ) return rc;
else if( 0==pVfs ) return SQLITE_NOTFOUND;
rc = sqlite3_file_control(shellState.db, "main",
SQLITE_FCNTL_FILE_POINTER, &pFile);
SQLITE_FCNTL_FILE_POINTER, &pFile)
: SQLITE_NOTFOUND;
if( rc ) return rc;
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 ){
rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
if(SQLITE_IOERR_SHORT_READ == rc){
rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
}
if(rc) return rc;
nPos += nBuf;
rc = callback(buf, nBuf);
if( 0==rc ) rc = xCallback(buf, nBuf);
}
return rc;
}
#endif
/*
** Trivial exportable function for emscripten. It processes zSql as if