diff options
author | stephan <stephan@noemail.net> | 2024-03-11 09:32:38 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2024-03-11 09:32:38 +0000 |
commit | bf030d53b14bc38fbdc745636ef8dffdd57a1fa0 (patch) | |
tree | 9881aa87e22e2778904827c513fffbcd4dd69c9a /ext | |
parent | 5007833f5f82d33c95f44c65fc46221de1c5950f (diff) | |
download | sqlite-bf030d53b14bc38fbdc745636ef8dffdd57a1fa0.tar.gz sqlite-bf030d53b14bc38fbdc745636ef8dffdd57a1fa0.zip |
Add delete-before-open=1 URI flag to the 'opfs' VFS to tell it to xDelete the db file before opening it, primarily to enable users to work around a corrupt db without having to reach into OPFS-specific APIs to remove the db file.
FossilOrigin-Name: e83f9788636f7f9bcca7d2a09620c13ab4eb83436d5b2946a827e48addf0267d
Diffstat (limited to 'ext')
-rw-r--r-- | ext/wasm/api/sqlite3-opfs-async-proxy.js | 11 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-vfs-opfs.c-pp.js | 18 | ||||
-rw-r--r-- | ext/wasm/tester1.c-pp.js | 36 |
3 files changed, 47 insertions, 18 deletions
diff --git a/ext/wasm/api/sqlite3-opfs-async-proxy.js b/ext/wasm/api/sqlite3-opfs-async-proxy.js index cafd296c6..58b8bcb23 100644 --- a/ext/wasm/api/sqlite3-opfs-async-proxy.js +++ b/ext/wasm/api/sqlite3-opfs-async-proxy.js @@ -562,6 +562,17 @@ const installAsyncProxy = function(self){ wTimeEnd(); return; } + if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){ + //log("async proxy opfsFlags =",opfsFlags); + try{ + await hDir.removeEntry(filenamePart); + //log("Unlinked",filename,hDir,filenamePart); + } + catch(e){ + /* ignoring */ + //warn("Ignoring failed Unlink of",filename,":",e); + } + } const hFile = await hDir.getFileHandle(filenamePart, {create}); wTimeEnd(); const fh = Object.assign(Object.create(null),{ diff --git a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js index f7fd951a4..65e39e5b5 100644 --- a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js +++ b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js @@ -423,11 +423,19 @@ const installOpfsVfs = function callee(options){ }); state.opfsFlags = Object.assign(Object.create(null),{ /** - Flag for use with xOpen(). "opfs-unlock-asap=1" enables - this. See defaultUnlockAsap, below. + Flag for use with xOpen(). URI flag "opfs-unlock-asap=1" + enables this. See defaultUnlockAsap, below. */ OPFS_UNLOCK_ASAP: 0x01, /** + Flag for use with xOpen(). URI flag "delete-before-open=1" + tells the VFS to delete the db file before attempting to open + it. This can be used, e.g., to replace a db which has been + corrupted (without forcing us to expose a delete/unlink() + function in the public API). + */ + OPFS_UNLINK_BEFORE_OPEN: 0x02, + /** If true, any async routine which implicitly acquires a sync access handle (i.e. an OPFS lock) will release that locks at the end of the call which acquires it. If false, such @@ -875,13 +883,17 @@ const installOpfsVfs = function callee(options){ let opfsFlags = 0; if(0===zName){ zName = randomFilename(); - }else if('number'===typeof zName){ + }else if(wasm.isPtr(zName)){ if(capi.sqlite3_uri_boolean(zName, "opfs-unlock-asap", 0)){ /* -----------------------^^^^^ MUST pass the untranslated C-string here. */ opfsFlags |= state.opfsFlags.OPFS_UNLOCK_ASAP; } + if(capi.sqlite3_uri_boolean(zName, "delete-before-open", 0)){ + opfsFlags |= state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN; + } zName = wasm.cstrToJs(zName); + //warn("xOpen zName =",zName, "opfsFlags =",opfsFlags); } const fh = Object.create(null); fh.fid = pFile; diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index f8a022523..fdde98635 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -2888,18 +2888,17 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .t({ name: 'OPFS db sanity checks', test: async function(sqlite3){ + T.assert(capi.sqlite3_vfs_find('opfs')); + const opfs = sqlite3.opfs; const filename = this.opfsDbFile = '/dir/sqlite3-tester1.db'; - const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs'); - T.assert(pVfs); - const unlink = this.opfsUnlink = - (fn=filename)=>{sqlite3.util.sqlite3__wasm_vfs_unlink(pVfs,fn)}; - unlink(); - let db = new sqlite3.oo1.OpfsDb(filename); + const fileUri = 'file://'+filename+'?delete-before-open=1'; + const initSql = [ + 'create table p(a);', + 'insert into p(a) values(1),(2),(3)' + ]; + let db = new sqlite3.oo1.OpfsDb(fileUri); try { - db.exec([ - 'create table p(a);', - 'insert into p(a) values(1),(2),(3)' - ]); + db.exec(initSql); T.assert(3 === db.selectValue('select count(*) from p')); db.close(); db = new sqlite3.oo1.OpfsDb(filename); @@ -2911,7 +2910,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule; && 0===this.opfsDbExport.byteLength % 512); }finally{ db.close(); - unlink(); + } + T.assert(await opfs.entryExists(filename)); + try { + db = new sqlite3.oo1.OpfsDb(fileUri); + db.exec(initSql) /* will throw if delete-before-open did not work */; + T.assert(3 === db.selectValue('select count(*) from p')); + }finally{ + if(db) db.close(); } } }/*OPFS db sanity checks*/) @@ -2919,15 +2925,17 @@ globalThis.sqlite3InitModule = sqlite3InitModule; name: 'OPFS import', test: async function(sqlite3){ let db; + const filename = this.opfsDbFile; try { const exp = this.opfsDbExport; - const filename = this.opfsDbFile; delete this.opfsDbExport; this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(filename, exp); db = new sqlite3.oo1.OpfsDb(this.opfsDbFile); T.assert(6 === db.selectValue('select count(*) from p')). assert( this.opfsImportSize == exp.byteLength ); db.close(); + const unlink = this.opfsUnlink = + (fn=filename)=>sqlite3.util.sqlite3__wasm_vfs_unlink("opfs",fn); this.opfsUnlink(filename); T.assert(!(await sqlite3.opfs.entryExists(filename))); // Try again with a function as an input source: @@ -2954,11 +2962,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule; name: '(Internal-use) OPFS utility APIs', test: async function(sqlite3){ const filename = this.opfsDbFile; - const pVfs = this.opfsVfs; const unlink = this.opfsUnlink; - T.assert(filename && pVfs && !!unlink); + T.assert(filename && !!unlink); delete this.opfsDbFile; - delete this.opfsVfs; delete this.opfsUnlink; /************************************************************** ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended |