diff --git a/Makefile.linux-gcc b/Makefile.linux-gcc index ad5d4dd093..fe7349ad46 100644 --- a/Makefile.linux-gcc +++ b/Makefile.linux-gcc @@ -22,12 +22,6 @@ TOP = ../sqlite BCC = gcc -g -O0 #BCC = /opt/ancic/bin/c89 -0 -#### If the target operating system supports the "usleep()" system -# call, then define the HAVE_USLEEP macro for all C modules. -# -#USLEEP = -USLEEP = -DHAVE_USLEEP=1 - #### If you want the SQLite library to be safe for use within a # multi-threaded program, then define the following macro # appropriately: diff --git a/ext/fts5/fts5.h b/ext/fts5/fts5.h index 081e534f3f..2309460f02 100644 --- a/ext/fts5/fts5.h +++ b/ext/fts5/fts5.h @@ -263,7 +263,7 @@ struct Fts5PhraseIter { ** See xPhraseFirstColumn above. */ struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 3 */ + int iVersion; /* Currently always set to 2 */ void *(*xUserData)(Fts5Context*); @@ -541,7 +541,7 @@ struct fts5_api { int (*xCreateTokenizer)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_tokenizer *pTokenizer, void (*xDestroy)(void*) ); @@ -550,7 +550,7 @@ struct fts5_api { int (*xFindTokenizer)( fts5_api *pApi, const char *zName, - void **ppContext, + void **ppUserData, fts5_tokenizer *pTokenizer ); @@ -558,7 +558,7 @@ struct fts5_api { int (*xCreateFunction)( fts5_api *pApi, const char *zName, - void *pContext, + void *pUserData, fts5_extension_function xFunction, void (*xDestroy)(void*) ); diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index e46840c2e8..9d80e79e56 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4752,7 +4752,7 @@ static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){ nEntry += pLvl->aSeg[iSeg].nEntry; nTomb += pLvl->aSeg[iSeg].nEntryTombstone; } - assert( nEntry>0 || pLvl->nSeg==0 ); + assert_nc( nEntry>0 || pLvl->nSeg==0 ); if( nEntry>0 ){ int nPercent = (nTomb * 100) / nEntry; if( nPercent>=pConfig->nDeleteMerge && nPercent>nBest ){ @@ -8092,15 +8092,16 @@ static int fts5structCloseMethod(sqlite3_vtab_cursor *cur){ */ static int fts5structNextMethod(sqlite3_vtab_cursor *cur){ Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur; + Fts5Structure *p = pCsr->pStruct; assert( pCsr->pStruct ); pCsr->iSeg++; pCsr->iRowid++; - while( pCsr->iSeg>=pCsr->pStruct->aLevel[pCsr->iLevel].nSeg ){ + while( pCsr->iLevelnLevel && pCsr->iSeg>=p->aLevel[pCsr->iLevel].nSeg ){ pCsr->iLevel++; pCsr->iSeg = 0; } - if( pCsr->iLevel>=pCsr->pStruct->nLevel ){ + if( pCsr->iLevel>=p->nLevel ){ fts5StructureRelease(pCsr->pStruct); pCsr->pStruct = 0; } diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index d1c79d3604..c34a5a332b 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -1689,7 +1689,7 @@ static int fts5UpdateMethod( ** VIRTUAL TABLE statement contained "contentless_delete=1". */ if( eType0==SQLITE_INTEGER && pConfig->eContent==FTS5_CONTENT_NONE - && (nArg>1 || pConfig->bContentlessDelete==0) + && pConfig->bContentlessDelete==0 ){ pTab->p.base.zErrMsg = sqlite3_mprintf( "cannot %s contentless fts5 table: %s", @@ -2544,6 +2544,12 @@ static int fts5ColumnMethod( sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); } pConfig->pzErrmsg = 0; + }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){ + char *zErr = sqlite3_mprintf("cannot UPDATE a subset of " + "columns on fts5 contentless-delete table: %s", pConfig->zName + ); + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); } return rc; } diff --git a/ext/fts5/test/fts5contentless.test b/ext/fts5/test/fts5contentless.test index 41a78e9c8f..f75ccb44c2 100644 --- a/ext/fts5/test/fts5contentless.test +++ b/ext/fts5/test/fts5contentless.test @@ -188,11 +188,11 @@ do_execsql_test 5.2 { do_catchsql_test 5.3 { UPDATE ft SET x='four six' WHERE rowid=3 -} {1 {cannot UPDATE contentless fts5 table: ft}} +} {0 {}} do_execsql_test 5.4 { SELECT rowid FROM ft('one'); -} {1 3 4 5} +} {1 4 5} do_execsql_test 5.5 { REPLACE INTO ft(rowid, x) VALUES(3, 'four six'); diff --git a/ext/fts5/test/fts5contentless5.test b/ext/fts5/test/fts5contentless5.test new file mode 100644 index 0000000000..1541b0c68d --- /dev/null +++ b/ext/fts5/test/fts5contentless5.test @@ -0,0 +1,59 @@ +# 2023 August 7 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file contains tests for the content= and content_rowid= options. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5contentless5 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, content='', contentless_delete=1); + INSERT INTO t1 VALUES('A', 'B', 'C'); + INSERT INTO t1 VALUES('D', 'E', 'F'); + INSERT INTO t1 VALUES('G', 'H', 'I'); +} + +do_execsql_test 1.01 { + CREATE TABLE t2(x, y); + INSERT INTO t2 VALUES('x', 'y'); +} + +# explain_i "UPDATE t1 SET a='a' WHERE t1.rowid=1" +breakpoint +explain_i "UPDATE t1 SET a='a' FROM t2 WHERE t1.rowid=1 AND b IS NULL" + +#breakpoint +#explain_i "UPDATE t1 SET a='a' WHERE b IS NULL AND rowid=?" + +foreach {tn up err} { + 1 "UPDATE t1 SET a='a', b='b', c='c' WHERE rowid=1" 0 + 2 "UPDATE t1 SET a='a', b='b' WHERE rowid=1" 1 + 3 "UPDATE t1 SET b='b', c='c' WHERE rowid=1" 1 + 4 "UPDATE t1 SET a='a', c='c' WHERE rowid=1" 1 + 5 "UPDATE t1 SET a='a', c='c' WHERE t1.rowid=1 AND b IS NULL" 1 + 6 "UPDATE t1 SET a='a' FROM t2 WHERE t1.rowid=1" 1 + 7 "UPDATE t1 SET a='a', b='b', c='c' FROM t2 WHERE t1.rowid=1" 0 +} { + + set res(0) {0 {}} + set res(1) {1 {cannot UPDATE a subset of columns on fts5 contentless-delete table: t1}} + do_catchsql_test 1.$tn $up $res($err) +} + +finish_test + diff --git a/ext/wasm/api/extern-post-js.c-pp.js b/ext/wasm/api/extern-post-js.c-pp.js index 00cb3fab90..63e55051c6 100644 --- a/ext/wasm/api/extern-post-js.c-pp.js +++ b/ext/wasm/api/extern-post-js.c-pp.js @@ -62,6 +62,7 @@ const toExportForESM = globalThis.sqlite3InitModule = function ff(...args){ //console.warn("Using replaced sqlite3InitModule()",globalThis.location); return originalInit(...args).then((EmscriptenModule)=>{ +//#if wasmfs if('undefined'!==typeof WorkerGlobalScope && EmscriptenModule['ENVIRONMENT_IS_PTHREAD']){ /** Workaround for wasmfs-generated worker, which calls this @@ -72,6 +73,7 @@ const toExportForESM = //console.warn("sqlite3InitModule() returning E-module.",EmscriptenModule); return EmscriptenModule; } +//#endif //console.warn("sqlite3InitModule() returning sqlite3 object."); const s = EmscriptenModule.sqlite3; s.scriptInfo = initModuleState; diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index 0179091c02..3b29041c37 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -1645,7 +1645,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( do not. */ tgt.push(capi.sqlite3_value_to_js( - wasm.peekPtr(pArgv + (wasm.ptrSizeof * i)) + wasm.peekPtr(pArgv + (wasm.ptrSizeof * i)), + throwIfCannotConvert )); } return tgt; diff --git a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js index ee8d1a5d68..709d3414c3 100644 --- a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js +++ b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js @@ -854,17 +854,24 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return true; } + //! Documented elsewhere in this file. exportFile(name){ const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name); const n = sah.getSize() - HEADER_OFFSET_DATA; - const b = new Uint8Array(n>=0 ? n : 0); - if(n>0) sah.read(b, {at: HEADER_OFFSET_DATA}); + const b = new Uint8Array(n>0 ? n : 0); + if(n>0){ + const nRead = sah.read(b, {at: HEADER_OFFSET_DATA}); + if(nRead != n){ + toss("Expected to read "+n+" bytes but read "+nRead+"."); + } + } return b; } //! Documented elsewhere in this file. importDb(name, bytes){ + if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); const n = bytes.byteLength; if(n<512 || n%512!=0){ toss("Byte array size is invalid for an SQLite db."); @@ -878,8 +885,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const sah = this.#mapFilenameToSAH.get(name) || this.nextAvailableSAH() || toss("No available handles to import to."); - sah.write(bytes, {at: HEADER_OFFSET_DATA}); - this.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); + const nWrote = sah.write(bytes, {at: HEADER_OFFSET_DATA}); + if(nWrote != n){ + this.setAssociatedPath(sah, '', 0); + toss("Expected to write "+n+" bytes but wrote "+nWrote+"."); + }else{ + this.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); + } } }/*class OpfsSAHPool*/; @@ -1074,16 +1086,20 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ Returns an array of the names of the files currently allocated to slots. This list is the same length as getFileCount(). - - void importDb(name, byteArray) + - void importDb(name, bytes) Imports the contents of an SQLite database, provided as a byte - array, under the given name, overwriting any existing - content. Throws if the pool has no available file slots, on I/O - error, or if the input does not appear to be a database. In the - latter case, only a cursory examination is made. Note that this - routine is _only_ for importing database files, not arbitrary files, - the reason being that this VFS will automatically clean up any - non-database files so importing them is pointless. + array or ArrayBuffer, under the given name, overwriting any + existing content. Throws if the pool has no available file slots, + on I/O error, or if the input does not appear to be a + database. In the latter case, only a cursory examination is made. + Note that this routine is _only_ for importing database files, + not arbitrary files, the reason being that this VFS will + automatically clean up any non-database files so importing them + is pointless. + + On a write error, the handle is removed from the pool and made + available for re-use. - [async] number reduceCapacity(n) diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js index ee7ea20c34..0437ef35d8 100644 --- a/ext/wasm/common/whwasmutil.js +++ b/ext/wasm/common/whwasmutil.js @@ -613,8 +613,6 @@ globalThis.WhWasmUtilInstaller = function(target){ target.installFunction = (func, sig)=>__installFunction(func, sig, false); /** - EXPERIMENTAL! DO NOT USE IN CLIENT CODE! - Works exactly like installFunction() but requires that a scopedAllocPush() is active and uninstalls the given function when that alloc scope is popped via scopedAllocPop(). @@ -1180,7 +1178,7 @@ globalThis.WhWasmUtilInstaller = function(target){ cache.scopedAlloc.splice(n,1); for(let p; (p = state.pop()); ){ if(target.functionEntry(p)){ - //console.warn("scopedAllocPop() uninstalling transient function",p); + //console.warn("scopedAllocPop() uninstalling function",p); target.uninstallFunction(p); } else target.dealloc(p); @@ -1637,6 +1635,7 @@ globalThis.WhWasmUtilInstaller = function(target){ 'and is not intended to be invoked from', 'client-level code. Invoked with:',opt); } + this.name = opt.name || "unnamed"; this.signature = opt.signature; if(opt.contextKey instanceof Function){ this.contextKey = opt.contextKey; @@ -1698,14 +1697,16 @@ globalThis.WhWasmUtilInstaller = function(target){ exactly the 2nd and 3rd arguments are. */ convertArg(v,argv,argIndex){ - //FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.signature,this.transient,v); + //FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.name,this.signature,this.transient,v); let pair = this.singleton; if(!pair && this.isContext){ pair = this.contextMap(this.contextKey(argv,argIndex)); + //FuncPtrAdapter.debugOut(this.name, this.signature, "contextKey() =",this.contextKey(argv,argIndex), pair); } if(pair && pair[0]===v) return pair[1]; if(v instanceof Function){ /* Install a WASM binding and return its pointer. */ + //FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.name,this.signature,this.transient,v,pair); if(this.callProxy) v = this.callProxy(v); const fp = __installFunction(v, this.signature, this.isTransient); if(FuncPtrAdapter.debugFuncInstall){ @@ -1719,7 +1720,18 @@ globalThis.WhWasmUtilInstaller = function(target){ FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this, this.contextKey(argv,argIndex), '@'+pair[1], v); } - try{target.uninstallFunction(pair[1])} + try{ + /* Because the pending native call might rely on the + pointer we're replacing, e.g. as is normally the case + with sqlite3's xDestroy() methods, we don't + immediately uninstall but instead add its pointer to + the scopedAlloc stack, which will be cleared when the + xWrap() mechanism is done calling the native + function. We're relying very much here on xWrap() + having pushed an alloc scope. + */ + cache.scopedAlloc[cache.scopedAlloc.length-1].push(pair[1]); + } catch(e){/*ignored*/} } pair[0] = v; @@ -1727,13 +1739,14 @@ globalThis.WhWasmUtilInstaller = function(target){ } return fp; }else if(target.isPtr(v) || null===v || undefined===v){ + //FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.name,this.signature,this.transient,v,pair); if(pair && pair[1] && pair[1]!==v){ /* uninstall stashed mapping and replace stashed mapping with v. */ if(FuncPtrAdapter.debugFuncInstall){ FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this, this.contextKey(argv,argIndex), '@'+pair[1], v); } - try{target.uninstallFunction(pair[1])} + try{ cache.scopedAlloc[cache.scopedAlloc.length-1].push(pair[1]) } catch(e){/*ignored*/} pair[0] = pair[1] = (v | 0); } diff --git a/ext/wasm/fiddle.make b/ext/wasm/fiddle.make index cbe6ab3518..57141d7e2b 100644 --- a/ext/wasm/fiddle.make +++ b/ext/wasm/fiddle.make @@ -18,7 +18,7 @@ endif ifeq (,$(SHELL_SRC)) $(error Could not parse SHELL_SRC from $(dir.top)/Makefile.) endif -$(dir.top)/shell.c: $(SHELL_SRC) $(dir.top)/tool/mkshellc.tcl +$(dir.top)/shell.c: $(SHELL_SRC) $(dir.top)/tool/mkshellc.tcl $(sqlite3.c) $(MAKE) -C $(dir.top) shell.c # /shell.c ######################################################################## @@ -61,9 +61,9 @@ $(fiddle.SOAP.js): $(SOAP.js) $(eval $(call call-make-pre-post,fiddle-module,vanilla)) $(fiddle-module.js): $(MAKEFILE) $(MAKEFILE.fiddle) \ $(EXPORTED_FUNCTIONS.fiddle) \ - $(fiddle.cses) $(pre-post-fiddle-module.deps.vanilla) $(fiddle.SOAP.js) + $(fiddle.cses) $(pre-post-fiddle-module-vanilla.deps) $(fiddle.SOAP.js) $(emcc.bin) -o $@ $(fiddle.emcc-flags) \ - $(pre-post-fiddle-module.flags.vanilla) \ + $(pre-post-fiddle-module-vanilla.flags) \ $(fiddle.cses) $(maybe-wasm-strip) $(fiddle-module.wasm) gzip < $@ > $@.gz diff --git a/ext/wasm/fiddle/fiddle-worker.js b/ext/wasm/fiddle/fiddle-worker.js index e239cbf51e..67f61008fb 100644 --- a/ext/wasm/fiddle/fiddle-worker.js +++ b/ext/wasm/fiddle/fiddle-worker.js @@ -221,7 +221,7 @@ f._(); } }; - + self.onmessage = function f(ev){ ev = ev.data; if(!f.cache){ @@ -371,12 +371,14 @@ sqlite3InitModule(fiddleModule).then((_sqlite3)=>{ sqlite3 = _sqlite3; console.warn("Installing sqlite3 module globally (in Worker)", - "for use in the dev console."); - self.sqlite3 = sqlite3; + "for use in the dev console.", sqlite3); + globalThis.sqlite3 = sqlite3; const dbVfs = sqlite3.wasm.xWrap('fiddle_db_vfs', "*", ['string']); fiddleModule.fsUnlink = (fn)=>{ return sqlite3.wasm.sqlite3_wasm_vfs_unlink(dbVfs(0), fn); }; wMsg('fiddle-ready'); - })/*then()*/; + }).catch(e=>{ + console.error("Fiddle worker init failed:",e); + }); })(); diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index db4b50f4b6..c1b16d5e81 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -353,7 +353,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; const sahPoolConfig = { name: 'opfs-sahpool-tester1', clearOnInit: true, - initialCapacity: 3 + initialCapacity: 6 }; //////////////////////////////////////////////////////////////////////// // End of infrastructure setup. Now define the tests... @@ -3076,7 +3076,24 @@ globalThis.sqlite3InitModule = sqlite3InitModule; T.assert(1 === fileNames.length) .assert(dbName === fileNames[0]) .assert(1 === u1.getFileCount()) - .assert(true === u1.unlink(dbName)) + + if(1){ // test exportFile() and importDb() + const dbytes = u1.exportFile(dbName); + T.assert(dbytes.length >= 4096); + const dbName2 = '/exported.db'; + u1.importDb(dbName2, dbytes); + T.assert( 2 == u1.getFileCount() ); + let db2 = new u1.OpfsSAHPoolDb(dbName2); + T.assert(db2 instanceof sqlite3.oo1.DB) + .assert(3 === db2.selectValue('select count(*) from t')); + db2.close(); + T.assert(true === u1.unlink(dbName2)) + .assert(false === u1.unlink(dbName2)) + .assert(1 === u1.getFileCount()) + .assert(1 === u1.getFileNames().length); + } + + T.assert(true === u1.unlink(dbName)) .assert(false === u1.unlink(dbName)) .assert(0 === u1.getFileCount()) .assert(0 === u1.getFileNames().length); @@ -3089,6 +3106,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; log("Installed second SAH instance as",conf2.name); T.assert(0 === POther.getFileCount()) .assert(true === await POther.removeVfs()); + if(0){ /* Enable this block to inspect vfs's contents via the dev console or OPFS Explorer browser extension. The diff --git a/manifest b/manifest index b37cc822ec..bcbb0a69ea 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\swal-shm-exceptions\sbranch. -D 2023-07-28T19:07:25.753 +C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. +D 2023-08-10T17:07:34.643 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0f4cb3955aaff8a40ec3857ba1784bd98b69802e51eff979f874b65713b627b2 -F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 +F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6 F Makefile.msc daad4a19e0b3c3c3b79b64d4ddbf75e3f506405e8d3f3f604d6f48b26043c51f F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224 F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa @@ -85,15 +85,15 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7 F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 -F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca2a +F ext/fts5/fts5.h 9bebc9fb8b75b0777e741c758540e07c3c80ce75204198979028fe6cc4c59486 F ext/fts5/fts5Int.h 78a63cc0795186cde5384816a9403a68c65774b35d952e05b81a1b4b158e07c8 F ext/fts5/fts5_aux.c 572d5ec92ba7301df2fea3258576332f2f4d2dfd66d8263afd157d9deceac480 F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5 F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d934c7b081 F ext/fts5/fts5_expr.c 2473c13542f463cae4b938c498d6193c90d38ea1a2a4f9849c0479736e50d24d F ext/fts5/fts5_hash.c 65e7707bc8774706574346d18c20218facf87de3599b995963c3e6d6809f203d -F ext/fts5/fts5_index.c a4e35cd126c19df66887801db15ccae7290b51129add3d4cdd31e2d9ea240398 -F ext/fts5/fts5_main.c 2f87ee44fdb21539c264541149f07f70e065d58f37420063e5ddef80ba0f5ede +F ext/fts5/fts5_index.c 93b4cd116b76b6adf224cd3d213f1e06cfe10ae0eb21d6372b1c53b8f0c382a3 +F ext/fts5/fts5_main.c 7070031993ba5b5d89b13206ec4ef624895f2f7c0ec72725913d301e4d382445 F ext/fts5/fts5_storage.c 3c9b41fce41b6410f2e8f82eb035c6a29b2560483f773e6dc98cf3cb2e4ddbb5 F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee @@ -132,10 +132,11 @@ F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825 F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4 F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283 -F ext/fts5/test/fts5contentless.test 9a42a86822670792ba632f5c57459addeb774d93b29d5e6ddae08faa64c2b6d9 +F ext/fts5/test/fts5contentless.test eb31159d62811b3a32fb1cfb36be20f9d9db75637c7fe6aa7f5c533db2d00576 F ext/fts5/test/fts5contentless2.test 12c778d134a121b8bad000fbf3ae900d53226fee840ce36fe941b92737f1fda7 F ext/fts5/test/fts5contentless3.test 487dce16b6677f68b44d7cbd158b9b7275d25e2c14d713f9188d9645bb699286 F ext/fts5/test/fts5contentless4.test 0f43ededc2874f65d7da99b641a82239854d98d3fa43db729f284b723f23b69f +F ext/fts5/test/fts5contentless5.test 216962d51376b62e4ff45e8db00aa3e1ab548cb36b7fd450633e73b2d678f88e F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78 @@ -494,7 +495,7 @@ F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 F ext/wasm/api/README.md 5eb44fa02e9c693a1884a3692428647894b0380b24bca120866b7a24c8786134 -F ext/wasm/api/extern-post-js.c-pp.js e7257ea56d4077d0773d7537fcb8eade59aad0c118dab92497c27939edca41cb +F ext/wasm/api/extern-post-js.c-pp.js c4154a7f90c2d7e51fd6738273908152036c3457fdc0b6523f1be3ef51105aac F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41 F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62 @@ -502,12 +503,12 @@ F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057af F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e F ext/wasm/api/sqlite3-api-glue.js cc6b0bb093bdb6279d4af259200b7b9e150e3796a8a3a4cd09a4928c43d25e56 F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8 -F ext/wasm/api/sqlite3-api-prologue.js cbd7d6ba185f3a844a8b0020e954b49bbc2ca78b305d117bec2ceca21431795a +F ext/wasm/api/sqlite3-api-prologue.js 76258e160bf6a89cc75a7d3c05646a054c8cab7219cd1e10bc20cacaad022131 F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379 F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25 -F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 44740935f6eeab3a0c6dc9f0ca93aebb6339f8d8365f03ea6d7808c134dbfe46 +F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js abb69b5e008961026bf5ff433d7116cb046359af92a5daf73208af2e7ac80ae7 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e7a690e0e78ff4d563f2eca468f91db69f001ff4b79c6d2304cbb6f62dca437d F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f @@ -518,7 +519,7 @@ F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25 F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51 F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15 F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f -F ext/wasm/common/whwasmutil.js db6368ee57af90ee6691b6fb3ca97ee8064d12482e06a29113127c67b08f956e +F ext/wasm/common/whwasmutil.js 4c64594eecc7af4ae64259e95a71ba2a7edf118881aaff0bba86d0c7164e78e4 F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508 F ext/wasm/demo-123.js 38aa8faec4d0ace1c973bc8a7a1533584463ebeecd4c420daa7d9687beeb9cb5 @@ -530,9 +531,9 @@ F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2 F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef F ext/wasm/dist.make 3a851858aad72e246a5d9c5aaf6b6a144305f1bf898ac1846760ea7bab95c9a3 F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f -F ext/wasm/fiddle.make dbe36b90b8907ae28ecb9c0e9fd8389dbdaecf117ea4fb2ea33864bdfa498a94 +F ext/wasm/fiddle.make fa2ba6e90457ba2a71cb745f200d409caf773076df75ae5b177cc225d7627a11 F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f -F ext/wasm/fiddle/fiddle-worker.js 163d6139a93fab4bcb72064923df050d4e7c0ff0d8aa061ce8776a6e75da8a10 +F ext/wasm/fiddle/fiddle-worker.js e0153f9af6500805c6f09c0b3cfdb7d857e9d6863dbee9d50d1628fccf5f4b4d F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715 F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2 F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74eb8069d412e @@ -554,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555 F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2 -F ext/wasm/tester1.c-pp.js b9a493a764f2113f6a8205d4e5573a25731d6f965338005460920389ac0693e0 +F ext/wasm/tester1.c-pp.js b88dcad5424a652e8204c44a71bbc3deb22a4922c97ba792aedbabb7a6827b91 F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1 F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 @@ -584,7 +585,7 @@ F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645 F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522 F src/btree.c 7a37bdf09f338561880860681cb03499a60c3bb0869e539c58bc1d2cdd705ff2 F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240 -F src/btreeInt.h 3b4eff7155c0cea6971dc51f62e3529934a15a6640ec607dd42a767e379cb3a9 +F src/btreeInt.h 91a9e0c41a0e71fa91a742ec285c63dd8dcb38b73d14fae0ed7209174ff0fdc1 F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4 F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e @@ -592,8 +593,8 @@ F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94 F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387 F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef -F src/delete.c cd5f5cd06ed0b6a882ec1a8c2a0d73b3cecb28479ad19e9931c4706c5e2182be -F src/expr.c ef4a81822da6f767696bd7f4b9983328af061158958138540142285a5b1181b7 +F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 +F src/expr.c 1affe0cc049683ef0ef3545d9b6901508556b0ef7e2892a344c3df6d7288d79d F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36 F src/func.c cc1da67fd643a43cfe691784158ec656d8ec6d13bb17e67018b01b38b3e4f5ab @@ -603,10 +604,10 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276 -F src/json.c 60b6b0815ddaf546396e3c7328065a114b581721dc1fa20697a52610fb2259aa +F src/json.c 9c231a853268ce6aee2e300e26d4445ba42117374a2275f8e9537b2f912909d6 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465 -F src/main.c 512b1d45bc556edf4471a845afb7ba79e64bd5b832ab222dc195c469534cd002 +F src/main.c fde8f13c876a658b4e8b74b77d875ca887915c174ea6a2f3122d80966f93d865 F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2 @@ -627,7 +628,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06 F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107 -F src/os_unix.c 95b407307deb902a3bd9a5d5666c7838709cccb337baeee6ef0a53f512d3673e +F src/os_unix.c 2e8b12107f75d1bd16412f312b4c5d5103191807a37836d3b81beb26436ad81b F src/os_win.c 7038223a1cda0a47e2ab4db47f63bf1833fe53ba0542f0f283a062ea13894103 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 993445a19b611d473ca007542ab3149840661a4c7e9f2d9e1ec008b7cc2abe78 @@ -643,17 +644,17 @@ F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 3328b8c758016b400a4fea053ab1f5927929083a49d0c3921802ce99eea73cde +F src/select.c 5f545a2c8702d4d3430bbb188cfec47d6c122d899061ef00cbe56af14591c574 F src/shell.c.in 694aaf751f00610381533d4a31c83d142cfc83ef91ef65e2aa6912ace7c39b40 -F src/sqlite.h.in 8f4d771444935386e32411f46c101a33f1c275a1757cd993aaedd6a47af8bbac +F src/sqlite.h.in 73a366c1c45d5ac9888cfe81c458826a44498531d106cfb4f328193ab5f6f17d F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4 -F src/sqliteInt.h 6140eb4058d995f3004ee2732fa098b884f26eb497a7fbb3a51c781ec824d14b +F src/sqliteInt.h 025ed58a41968ef80d64cdc194caa8dd207b0256b147253d762fdac7a62408f9 F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd -F src/test1.c dfd07574689ee7c57af219c5f627ff32dae65dba478c124ba0359a1bde9983be +F src/test1.c ebba2473874a23add4a10881b90bd445cfa7f59f90749434938aec14239c6486 F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664 @@ -708,18 +709,18 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 0fb405f9adf3f757c26bfc1ae6d58ac5dccbb918917ba9e5ef0e6673a06563d3 F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0 -F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731 +F src/update.c 0bb9171afaa4d0b100ad946873bccda7aef90ffe083ef5c63668fce08c4df9da F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c 987e31e45aa9a7f206b8b86b0d09dd440263b869b627931a8dace5f39638e698 +F src/util.c a40062117e705eb3339201842717a022092816b92479eead6397cde28af32ff9 F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104 -F src/vdbe.c cd0396758da6a95e6c4e3bec7c3d6e767c3b39930c295c2425f83bb086cdc6ba +F src/vdbe.c 346d848a0bf8128e3e3722c5406f4bde6c32d7093b93402c6f8e0718d19305c3 F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0 -F src/vdbeInt.h cd829ff67fc18aff2476fe3209262ba8671cb43d51cb6913de4a670e37d2fbe3 -F src/vdbeapi.c 0cba9fe6e860e46bfb5e45a76a8c2c6ccd5ebc8f954319e4288e7793c2eca88c +F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c +F src/vdbeapi.c f37822f215740ede2a8fcae99bc13f2cc3a72dd0e1d22b81b9298c5ca67dbc38 F src/vdbeaux.c e3aa5c46827cd95e0fc4d0f302fa3e901ab5f07258fdbb42709eeef40f63018d F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce -F src/vdbemem.c adb5877dc54330865e45e0fba50f6455c1d9d8b83434c59f0e3d2d2a0b9f0e58 +F src/vdbemem.c 317b9f48708139db6239ade40c7980b4bc8233168383690d588dad6d8437f722 F src/vdbesort.c 0d40dca073c94e158ead752ef4225f4fee22dee84145e8c00ca2309afb489015 F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823 F src/vdbevtab.c 57fa8f56478e5b5cb558cb425e7878515e0a105c54f96f1d1bbf4b9433529254 @@ -728,7 +729,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 02e10f033a6972bc7d50122b400318003199c504cda48f61ad404564505f4e89 F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 -F src/where.c 477fcc5e561ef169e6002499602af6b805156c2aae6b2f5c2c93ef8c1cd64768 +F src/where.c b8917792f1e0dbfa28fb29e6cd3d560060d69667be0ba4c491cbc772363264f5 F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1 F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00 @@ -909,7 +910,7 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 F test/corruptI.test 9d8cbf6214e492abe9e822e759b9751ae336cec0a6fe3ff3b37bfbd8ff9c22ca F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af -F test/corruptL.test b42978028afc5eefc8b51d8d7cd6a9344ba7362d7ed4511ee2070f56e06d5a1c +F test/corruptL.test 504d90502d9993440226edc355d2275524b89064ea3df5ee5c27f7028ec59d07 F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067 F test/corruptN.test 7c099d153a554001b4fb829c799b01f2ea6276cbc32479131e0db0da4efd9cc4 F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576 @@ -1138,7 +1139,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db b8725a5f5cf7a3b7241a9038e57ca7e7cc8c3f4d86b44bd770617bda245ab2b0 F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2 -F test/fuzzdata8.db f6c2f2af4deaaae0ddb3310d509c2659990794aa653dc501b80a0534c3493f80 +F test/fuzzdata8.db 40c85daae47da64387c3dab7bbd99c21e425c0bfdb4b149cb685b1ab474a2cb4 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc @@ -1233,7 +1234,7 @@ F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd286 F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307 F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x F test/json101.test 94126d4291d4a00e45f6988ce885c410de69243490e46e70e9946cb6e6f9ea02 -F test/json102.test 13dc9e7b7f359ecb861e02f9bd7019f7342a63d1c354273b0a8f3904050560a8 +F test/json102.test 24f6f204f9cde45b971016691d0b92a9b4c58040d699e36d6b12cb165f9083ff F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1 F test/json105.test 11670a4387f4308ae0318cadcbd6a918ea7edcd19fbafde020720a073952675d @@ -1770,7 +1771,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2 F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2 -F test/update.test 90772ede84cfc779fc3d31884a84ec4c74deb501eeb09a1c6c91c03d8e94c0d8 +F test/update.test 85d3f46d0863033370bd881b1097f5694369a8730e53c5f85d96f32b7b310b47 F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3 F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041 F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1 @@ -1872,7 +1873,7 @@ F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67 F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b -F test/where7.test 1c1bf436bf31b913d4764a2b62ac6e98b9681e5c7ae2b562605592a56b7e946b +F test/where7.test 15041c7a5838f3bac98f3fb933709674a0b59367664e88fafaf105ff7416eb07 F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f F test/where9.test 2db942671a002621eff4f713e347bb25243295f79d8990297cd160bebcfde3f7 F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20 @@ -1946,7 +1947,7 @@ F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e04534bbf F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 F tool/build-all-msvc.bat c817b716e0edeecaf265a6775b63e5f45c34a6544f1d4114a222701ed5ac79ab x -F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 +F tool/build-shell.sh f193b5e3eb4afcb4abbf96bf1475be6cfb74763ee2e50c82bc7ca105e8a136c5 F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/custom.txt 6cdf298f43e1db4bb91406d14777669b8fb1df790837823fa6754c4308decc27 @@ -1984,7 +1985,7 @@ F tool/mkshellc.tcl b7adf08b82de60811d2cb6af05ff59fc17e5cd6f3e98743c14eaaa3f8971 F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f -F tool/mksqlite3c.tcl 44bc3bdb675a9e3a507f4d82575332bccd7e6f830a47c9aa29460ea2240593a9 +F tool/mksqlite3c.tcl 49e39b1e616abc92fd8c24445f2b0a38881825f764541e0026f72371f0d84b65 F tool/mksqlite3h.tcl d391cff7cad0a372ee1406faee9ccc7dad9cb80a0c95cae0f73d10dd26e06762 F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5 @@ -2027,7 +2028,7 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003 F tool/vdbe-compress.tcl 1dcb7632e57cf57105248029e6e162fddaf6c0fccb3bb9e6215603752c5a2d4a F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 -F tool/warnings.sh ab651bb82586c43ff8b560beceac959735bf917b44c5e0f67ba3426e474f29f8 +F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85 F vsixtest/App.xaml.cpp 41158ee43269820136fa3bba00c0bd91b26cc38b650ee392aec2a8d823e54318 @@ -2050,8 +2051,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 8e20354242d5f34a90b6c00d9034535ef6f6086ee4971230c7fd69985e2777d2 0443c0ef85f8f6f3efdee68bf59126c9459f08a58458756f8cbeeaf043d43a86 -R 23d78abe8cd936ba319106e904e535fb -U drh -Z b7ed01e121576b0b22bf35ed273ca0ab +P c44fb4d06591ef4872f015aa9e81ce8b93a38bd9143cf20db38cbe5c77a0d71f aa6de539c09faa320b68c63659e602107145c4263fa680d5b40fe4d7d7ac4534 +R 306d4b3f8aa93e07edcdfd262b597d0d +U dan +Z d6eddbca55d948f45c2bde6455133439 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 9f22921b56..90cc22ad97 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c44fb4d06591ef4872f015aa9e81ce8b93a38bd9143cf20db38cbe5c77a0d71f \ No newline at end of file +3ed89c344fcb3b7ee8b764d95144643e42e053e1116150d6eda8355fbd6669df \ No newline at end of file diff --git a/src/btreeInt.h b/src/btreeInt.h index 3e69206193..26a0bc6869 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -180,7 +180,7 @@ ** 0x81 0x00 becomes 0x00000080 ** 0x82 0x00 becomes 0x00000100 ** 0x80 0x7f becomes 0x0000007f -** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 0x91 0xd1 0xac 0x78 becomes 0x12345678 ** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 ** ** Variable length integers are used for rowids and to hold the number of diff --git a/src/delete.c b/src/delete.c index 641d1ae589..2baff5b3d4 100644 --- a/src/delete.c +++ b/src/delete.c @@ -525,7 +525,8 @@ void sqlite3DeleteFrom( if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); - assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); + assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF + || OptimizationDisabled(db, SQLITE_OnePass) ); if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); if( sqlite3WhereUsesDeferredSeek(pWInfo) ){ sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur); diff --git a/src/expr.c b/src/expr.c index 0c41f6684a..d96f362856 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3972,10 +3972,13 @@ int sqlite3ExprCodeGetColumn( u8 p5 /* P5 value for OP_Column + FLAGS */ ){ assert( pParse->pVdbe!=0 ); + assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 ); + assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 ); sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); if( p5 ){ VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); if( pOp->opcode==OP_Column ) pOp->p5 = p5; + if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG); } return iReg; } diff --git a/src/json.c b/src/json.c index cc39264c05..fcaa9d84b9 100644 --- a/src/json.c +++ b/src/json.c @@ -30,25 +30,51 @@ ** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). */ static const char jsonIsSpace[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #define fast_isspace(x) (jsonIsSpace[(unsigned char)x]) +/* +** Characters that are special to JSON. Control charaters, +** '"' and '\\'. +*/ +static const char jsonIsOk[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + + #if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) # define VVA(X) #else @@ -357,11 +383,16 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ p->zBuf[p->nUsed++] = '"'; for(i=0; izBuf[p->nUsed++] = c; + }else if( c=='"' || c=='\\' ){ json_simple_escape: if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; p->zBuf[p->nUsed++] = '\\'; - }else if( c<=0x1f ){ + p->zBuf[p->nUsed++] = c; + }else if( c=='\'' ){ + p->zBuf[p->nUsed++] = c; + }else{ static const char aSpecial[] = { 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -372,6 +403,7 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ assert( aSpecial['\n']=='n' ); assert( aSpecial['\r']=='r' ); assert( aSpecial['\t']=='t' ); + assert( c>=0 && czBuf[p->nUsed++] = 'u'; p->zBuf[p->nUsed++] = '0'; p->zBuf[p->nUsed++] = '0'; - p->zBuf[p->nUsed++] = '0' + (c>>4); - c = "0123456789abcdef"[c&0xf]; + p->zBuf[p->nUsed++] = "0123456789abcdef"[c>>4]; + p->zBuf[p->nUsed++] = "0123456789abcdef"[c&0xf]; } - p->zBuf[p->nUsed++] = c; } p->zBuf[p->nUsed++] = '"'; assert( p->nUsednAlloc ); @@ -1070,7 +1101,9 @@ static int jsonParseAddNode( if( pParse->nNode>=pParse->nAlloc ){ return jsonParseAddNodeExpand(pParse, eType, n, zContent); } + assert( pParse->aNode!=0 ); p = &pParse->aNode[pParse->nNode]; + assert( p!=0 ); p->eType = (u8)(eType & 0xff); p->jnFlags = (u8)(eType >> 8); VVA( p->eU = zContent ? 1 : 0 ); @@ -1090,6 +1123,8 @@ static void jsonParseAddNodeArray( JsonNode *aNode, /* Array of nodes to add */ u32 nNode /* Number of elements in aNew */ ){ + assert( aNode!=0 ); + assert( nNode>=1 ); if( pParse->nNode + nNode > pParse->nAlloc ){ u32 nNew = pParse->nNode + nNode; JsonNode *aNew = sqlite3_realloc64(pParse->aNode, nNew*sizeof(JsonNode)); @@ -1465,26 +1500,7 @@ json_parse_restart: parse_string: cDelim = z[i]; for(j=i+1; 1; j++){ - static const char aOk[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - }; - if( aOk[(unsigned char)z[j]] ) continue; + if( jsonIsOk[(unsigned char)z[j]] ) continue; c = z[j]; if( c==cDelim ){ break; @@ -2006,20 +2022,25 @@ static JsonNode *jsonLookupStep( JsonNode *pRoot; if( pParse->oom ) return 0; pRoot = &pParse->aNode[iRoot]; - while( (pRoot->jnFlags & JNODE_REPLACE)!=0 && pParse->useMod ){ - u32 idx = (u32)(pRoot - pParse->aNode); - i = pParse->iSubst; - while( 1 /*exit-by-break*/ ){ - assert( inNode ); - assert( pParse->aNode[i].eType==JSON_SUBST ); - assert( pParse->aNode[i].eU==4 ); - assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ - pRoot = &pParse->aNode[i+1]; - iRoot = i+1; - break; + if( pRoot->jnFlags & (JNODE_REPLACE|JNODE_REMOVE) && pParse->useMod ){ + while( (pRoot->jnFlags & JNODE_REPLACE)!=0 ){ + u32 idx = (u32)(pRoot - pParse->aNode); + i = pParse->iSubst; + while( 1 /*exit-by-break*/ ){ + assert( inNode ); + assert( pParse->aNode[i].eType==JSON_SUBST ); + assert( pParse->aNode[i].eU==4 ); + assert( pParse->aNode[i].u.iPrevaNode[i].n==idx ){ + pRoot = &pParse->aNode[i+1]; + iRoot = i+1; + break; + } + i = pParse->aNode[i].u.iPrev; } - i = pParse->aNode[i].u.iPrev; + } + if( pRoot->jnFlags & JNODE_REMOVE ){ + return 0; } } if( zPath[0]==0 ) return pRoot; @@ -2672,10 +2693,11 @@ static void jsonPatchFunc( UNUSED_PARAMETER(argc); pX = jsonParseCached(ctx, argv[0], ctx, 1); if( pX==0 ) return; + assert( pX->hasMod==0 ); + pX->hasMod = 1; pY = jsonParseCached(ctx, argv[1], ctx, 1); if( pY==0 ) return; pX->useMod = 1; - pX->hasMod = 1; pY->useMod = 1; pResult = jsonMergePatch(pX, 0, pY->aNode); assert( pResult!=0 || pX->oom ); diff --git a/src/main.c b/src/main.c index 8f21af13ee..cd02008909 100644 --- a/src/main.c +++ b/src/main.c @@ -1665,9 +1665,9 @@ static int sqliteDefaultBusyCallback( void *ptr, /* Database connection */ int count /* Number of times table has been busy */ ){ -#if SQLITE_OS_WIN || HAVE_USLEEP +#if SQLITE_OS_WIN || !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP /* This case is for systems that have support for sleeping for fractions of - ** a second. Examples: All windows systems, unix systems with usleep() */ + ** a second. Examples: All windows systems, unix systems with nanosleep() */ static const u8 delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; static const u8 totals[] = @@ -4160,10 +4160,12 @@ int sqlite3_test_control(int op, ...){ sqlite3ShowSrcList(0); sqlite3ShowWith(0); sqlite3ShowUpsert(0); +#ifndef SQLITE_OMIT_TRIGGER sqlite3ShowTriggerStep(0); sqlite3ShowTriggerStepList(0); sqlite3ShowTrigger(0); sqlite3ShowTriggerList(0); +#endif #ifndef SQLITE_OMIT_WINDOWFUNC sqlite3ShowWindow(0); sqlite3ShowWinFunc(0); @@ -4470,6 +4472,7 @@ int sqlite3_test_control(int op, ...){ break; } +#if !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_USELONGDOUBLE, int X); ** ** X<0 Make no changes to the bUseLongDouble. Just report value. @@ -4484,6 +4487,7 @@ int sqlite3_test_control(int op, ...){ rc = sqlite3Config.bUseLongDouble!=0; break; } +#endif #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) diff --git a/src/os_unix.c b/src/os_unix.c index aed4ac213f..59f67d142a 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -6715,12 +6715,17 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** than the argument. */ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ -#if OS_VXWORKS || _POSIX_C_SOURCE >= 199309L +#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0 struct timespec sp; - sp.tv_sec = microseconds / 1000000; sp.tv_nsec = (microseconds % 1000000) * 1000; + + /* Almost all modern unix systems support nanosleep(). But if you are + ** compiling for one of the rare exceptions, you can use + ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if + ** usleep() is available) in order to bypass the use of nanosleep() */ nanosleep(&sp, NULL); + UNUSED_PARAMETER(NotUsed); return microseconds; #elif defined(HAVE_USLEEP) && HAVE_USLEEP diff --git a/src/select.c b/src/select.c index 098b745849..321badd07f 100644 --- a/src/select.c +++ b/src/select.c @@ -1298,6 +1298,16 @@ static void selectInnerLoop( testcase( eDest==SRT_Fifo ); testcase( eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); +#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) + /* A destination of SRT_Table and a non-zero iSDParm2 parameter means + ** that this is an "UPDATE ... FROM" on a virtual table or view. In this + ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. + ** This does not affect operation in any way - it just allows MakeRecord + ** to process OPFLAG_NOCHANGE values without an assert() failing. */ + if( eDest==SRT_Table && pDest->iSDParm2 ){ + sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); + } +#endif #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open @@ -4292,7 +4302,8 @@ static int compoundHasDifferentAffinities(Select *p){ ** (27b) the subquery is a compound query and the RIGHT JOIN occurs ** in any arm of the compound query. (See also (17g).) ** -** (28) The subquery is not a MATERIALIZED CTE. +** (28) The subquery is not a MATERIALIZED CTE. (This is handled +** in the caller before ever reaching this routine.) ** ** ** In this routine, the "p" parameter is a pointer to the outer query. @@ -4402,9 +4413,9 @@ static int flattenSubquery( if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* Restriction (27a) */ } - if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){ - return 0; /* (28) */ - } + + /* Condition (28) is blocked by the caller */ + assert( !pSubitem->fg.isCte || pSubitem->u2.pCteUse->eM10d!=M10d_Yes ); /* Restriction (17): If the sub-query is a compound SELECT, then it must ** use only the UNION ALL operator. And none of the simple select queries @@ -7285,6 +7296,14 @@ int sqlite3Select( goto select_end; } + /* Do not attempt the usual optimizations (flattening and ORDER BY + ** elimination) on a MATERIALIZED common table expression because + ** a MATERIALIZED common table expression is an optimization fence. + */ + if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){ + continue; + } + /* Do not try to flatten an aggregate subquery. ** ** Flattening an aggregate subquery is only possible if the outer query @@ -7314,6 +7333,8 @@ int sqlite3Select( ** (a) The outer query has a different ORDER BY clause ** (b) The subquery is part of a join ** See forum post 062d576715d277c8 + ** + ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled. */ if( pSub->pOrderBy!=0 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index aa2cd73436..48009b1454 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -4427,10 +4427,10 @@ int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); ** METHOD: sqlite3_stmt ** ** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN -** setting for prepared statement S. If E is zero, then S becomes +** setting for [prepared statement] S. If E is zero, then S becomes ** a normal prepared statement. If E is 1, then S behaves as if -** its SQL text began with "EXPLAIN". If E is 2, then S behaves as if -** its SQL text began with "EXPLAIN QUERY PLAN". +** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if +** its SQL text began with "[EXPLAIN QUERY PLAN]". ** ** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared. ** SQLite tries to avoid a reprepare, but a reprepare might be necessary @@ -4438,8 +4438,8 @@ int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); ** ** Because of the potential need to reprepare, a call to ** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be -** reprepared because it was created using sqlite3_prepare() instead of -** the newer sqlite_prepare_v2() or sqlite3_prepare_v3() interfaces and +** reprepared because it was created using [sqlite3_prepare()] instead of +** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and ** hence has no saved SQL text with which to reprepare. ** ** Changing the explain setting for a prepared statement does not change diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 78ae7ad69e..c2a9f855a7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -894,7 +894,7 @@ typedef INT16_TYPE LogEst; /* ** P is one byte past the end of a large buffer. Return true if a span of bytes ** between S..E crosses the end of that buffer. In other words, return true -** if the sub-buffer S..E-1 overflows the buffer show last byte is P-1. +** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. ** ** S is the start of the span. E is one byte past the end of end of span. ** @@ -1257,7 +1257,6 @@ typedef struct Cte Cte; typedef struct CteUse CteUse; typedef struct Db Db; typedef struct DbFixer DbFixer; -typedef struct DblDbl DblDbl; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; @@ -1874,6 +1873,7 @@ struct sqlite3 { #define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ #define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ #define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */ +#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* @@ -3777,6 +3777,9 @@ struct Parse { int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ +#endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ @@ -3790,12 +3793,9 @@ struct Parse { int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ Returning *pReturning; /* The RETURNING clause */ } u1; - u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ -#endif + LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ u8 bReturning; /* Coding a RETURNING trigger */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ diff --git a/src/test1.c b/src/test1.c index 520508d1ca..4dcf7bc11f 100644 --- a/src/test1.c +++ b/src/test1.c @@ -8009,6 +8009,7 @@ static int SQLITE_TCLAPI optimization_control( { "push-down", SQLITE_PushDown }, { "balanced-merge", SQLITE_BalancedMerge }, { "propagate-const", SQLITE_PropagateConst }, + { "one-pass", SQLITE_OnePass }, }; if( objc!=4 ){ diff --git a/src/update.c b/src/update.c index a792862247..3b3c2f838b 100644 --- a/src/update.c +++ b/src/update.c @@ -741,7 +741,7 @@ void sqlite3Update( && !hasFK && !chngKey && !bReplace - && (sNC.ncFlags & NC_Subquery)==0 + && (pWhere==0 || !ExprHasProperty(pWhere, EP_Subquery)) ){ flags |= WHERE_ONEPASS_MULTIROW; } @@ -1259,7 +1259,9 @@ static void updateVirtualTable( sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) ); }else{ - pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); + Expr *pRow = exprRowColumn(pParse, i); + if( pRow ) pRow->op2 = OPFLAG_NOCHNG; + pList = sqlite3ExprListAppend(pParse, pList, pRow); } } diff --git a/src/util.c b/src/util.c index edb02f9b7c..e417034754 100644 --- a/src/util.c +++ b/src/util.c @@ -608,7 +608,12 @@ do_atof_calc: while( e<=-10 ){ e+=10; r *= 1.0e-10L; } while( e<=-1 ){ e+=1; r *= 1.0e-01L; } } - *pResult = r; + assert( r>=0.0 ); + if( r>+1.7976931348623157081452742373e+308L ){ + *pResult = +INFINITY; + }else{ + *pResult = (double)r; + } }else{ double rr[2]; u64 s2; diff --git a/src/vdbe.c b/src/vdbe.c index b8ee05e415..5899fa518e 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -708,6 +708,8 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow( int iCol, /* The column to read */ int t, /* The serial-type code for the column value */ i64 iOffset, /* Offset to the start of the content value */ + u32 cacheStatus, /* Current Vdbe.cacheCtr value */ + u32 colCacheCtr, /* Current value of the column cache counter */ Mem *pDest /* Store the value into this register. */ ){ int rc; @@ -716,12 +718,16 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow( int len = sqlite3VdbeSerialTypeLen(t); assert( pC->eCurType==CURTYPE_BTREE ); if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) return SQLITE_TOOBIG; - if( len > 4000 ){ + if( len > 4000 && pC->pKeyInfo==0 ){ /* Cache large column values that are on overflow pages using ** an RCStr (reference counted string) so that if they are reloaded, ** that do not have to be copied a second time. The overhead of ** creating and managing the cache is such that this is only ** profitable for larger TEXT and BLOB values. + ** + ** Only do this on table-btrees so that writes to index-btrees do not + ** need to clear the cache. This buys performance in the common case + ** in exchange for generality. */ VdbeTxtBlbCache *pCache; char *pBuf; @@ -733,6 +739,8 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow( pCache = pC->pCache; if( pCache->pCValue==0 || pCache->iCol!=iCol + || pCache->cacheStatus!=cacheStatus + || pCache->colCacheCtr!=colCacheCtr || pCache->iOffset!=sqlite3BtreeOffset(pC->uc.pCursor) ){ if( pCache->pCValue ) sqlite3RCStrUnref(pCache->pCValue); @@ -744,6 +752,8 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow( pBuf[len+1] = 0; pBuf[len+2] = 0; pCache->iCol = iCol; + pCache->cacheStatus = cacheStatus; + pCache->colCacheCtr = colCacheCtr; pCache->iOffset = sqlite3BtreeOffset(pC->uc.pCursor); }else{ pBuf = pCache->pCValue; @@ -814,6 +824,7 @@ int sqlite3VdbeExec( Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ + u32 colCacheCtr = 0; /* Column cache counter */ #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) u64 *pnCycle = 0; int bStmtScanStatus = IS_STMT_SCANSTATUS(db)!=0; @@ -2349,10 +2360,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** opcodes are allowed to occur between this instruction and the previous ** OP_Lt or OP_Gt. ** -** If result of an OP_Eq comparison on the same two operands as the -** prior OP_Lt or OP_Gt would have been true, then jump to P2. -** If the result of an OP_Eq comparison on the two previous -** operands would have been false or NULL, then fall through. +** If the result of an OP_Eq comparison on the same two operands as +** the prior OP_Lt or OP_Gt would have been true, then jump to P2. If +** the result of an OP_Eq comparison on the two previous operands +** would have been false or NULL, then fall through. */ case OP_ElseEq: { /* same as TK_ESCAPE, jump */ @@ -2782,7 +2793,7 @@ case OP_IsType: { /* jump */ /* Opcode: ZeroOrNull P1 P2 P3 * * ** Synopsis: r[P2] = 0 OR NULL ** -** If all both registers P1 and P3 are NOT NULL, then store a zero in +** If both registers P1 and P3 are NOT NULL, then store a zero in ** register P2. If either registers P1 or P3 are NULL then put ** a NULL in register P2. */ @@ -3145,7 +3156,7 @@ op_column_restart: || (t>=12 && ((t&1)==0 || p5==OPFLAG_BYTELENARG)) ) ) - || (len = sqlite3VdbeSerialTypeLen(t))==0 + || sqlite3VdbeSerialTypeLen(t)==0 ){ /* Content is irrelevant for ** 1. the typeof() function, @@ -3162,7 +3173,8 @@ op_column_restart: */ sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); }else{ - rc = vdbeColumnFromOverflow(pC, p2, t, aOffset[p2], pDest); + rc = vdbeColumnFromOverflow(pC, p2, t, aOffset[p2], + p->cacheCtr, colCacheCtr, pDest); if( rc ){ if( rc==SQLITE_NOMEM ) goto no_mem; if( rc==SQLITE_TOOBIG ) goto too_big; @@ -5182,13 +5194,13 @@ case OP_IfNotOpen: { /* jump */ ** operands to OP_NotFound and OP_IdxGT. ** ** This opcode is an optimization attempt only. If this opcode always -** falls through, the correct answer is still obtained, but extra works +** falls through, the correct answer is still obtained, but extra work ** is performed. ** ** A value of N in the seekHit flag of cursor P1 means that there exists ** a key P3:N that will match some record in the index. We want to know ** if it is possible for a record P3:P4 to match some record in the -** index. If it is not possible, we can skips some work. So if seekHit +** index. If it is not possible, we can skip some work. So if seekHit ** is less than P4, attempt to find out if a match is possible by running ** OP_NotFound. ** @@ -5700,6 +5712,7 @@ case OP_Insert: { ); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + colCacheCtr++; /* Invoke the update-hook if required. */ if( rc ) goto abort_due_to_error; @@ -5753,10 +5766,10 @@ case OP_RowCell: { ** left in an undefined state. ** ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this -** delete one of several associated with deleting a table row and all its -** associated index entries. Exactly one of those deletes is the "primary" -** delete. The others are all on OPFLAG_FORDELETE cursors or else are -** marked with the AUXDELETE flag. +** delete is one of several associated with deleting a table row and +** all its associated index entries. Exactly one of those deletes is +** the "primary" delete. The others are all on OPFLAG_FORDELETE +** cursors or else are marked with the AUXDELETE flag. ** ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row ** change count is incremented (otherwise not). @@ -5860,6 +5873,7 @@ case OP_Delete: { rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; + colCacheCtr++; pC->seekResult = 0; if( rc ) goto abort_due_to_error; @@ -5927,7 +5941,7 @@ case OP_SorterCompare: { ** Write into register P2 the current sorter data for sorter cursor P1. ** Then clear the column header cache on cursor P3. ** -** This opcode is normally use to move a record out of the sorter and into +** This opcode is normally used to move a record out of the sorter and into ** a register that is the source for a pseudo-table cursor created using ** OpenPseudo. That pseudo-table cursor is the one that is identified by ** parameter P3. Clearing the P3 column cache as part of this opcode saves @@ -6736,7 +6750,7 @@ case OP_IdxGE: { /* jump, ncycle */ ** file is given by P1. ** ** The table being destroyed is in the main database file if P3==0. If -** P3==1 then the table to be clear is in the auxiliary database file +** P3==1 then the table to be destroyed is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** If AUTOVACUUM is enabled then it is possible that another root page @@ -6796,8 +6810,8 @@ case OP_Destroy: { /* out2 */ ** in the database file is given by P1. But, unlike Destroy, do not ** remove the table or index from the database file. ** -** The table being clear is in the main database file if P2==0. If -** P2==1 then the table to be clear is in the auxiliary database file +** The table being cleared is in the main database file if P2==0. If +** P2==1 then the table to be cleared is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** ** If the P3 value is non-zero, then the row change count is incremented diff --git a/src/vdbeInt.h b/src/vdbeInt.h index f424559929..2a23c3f285 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -159,6 +159,8 @@ struct VdbeTxtBlbCache { char *pCValue; /* A RCStr buffer to hold the value */ i64 iOffset; /* File offset of the row being cached */ int iCol; /* Column for which the cache is valid */ + u32 cacheStatus; /* Vdbe.cacheCtr value */ + u32 colCacheCtr; /* Column cache counter */ }; /* diff --git a/src/vdbeapi.c b/src/vdbeapi.c index cb631413c4..cc58e7a877 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1863,19 +1863,23 @@ int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){ Vdbe *v = (Vdbe*)pStmt; int rc; - if( v->eVdbeState!=VDBE_READY_STATE ) return SQLITE_BUSY; - if( v->explain==eMode ) return SQLITE_OK; - if( v->zSql==0 || eMode<0 || eMode>2 ) return SQLITE_ERROR; sqlite3_mutex_enter(v->db->mutex); - if( v->nMem>=10 && (eMode!=2 || v->haveEqpOps) ){ + if( v->explain==eMode ){ + rc = SQLITE_OK; + }else if( eMode<0 || eMode>2 ){ + rc = SQLITE_ERROR; + }else if( (v->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ + rc = SQLITE_ERROR; + }else if( v->eVdbeState!=VDBE_READY_STATE ){ + rc = SQLITE_BUSY; + }else if( v->nMem>=10 && (eMode!=2 || v->haveEqpOps) ){ /* No reprepare necessary */ v->explain = eMode; rc = SQLITE_OK; }else{ - int haveEqpOps = v->explain==2 || v->haveEqpOps; v->explain = eMode; rc = sqlite3Reprepare(v); - v->haveEqpOps = haveEqpOps!=0; + v->haveEqpOps = eMode==2; } if( v->explain ){ v->nResColumn = 12 - 4*v->explain; diff --git a/src/vdbemem.c b/src/vdbemem.c index 07fb8feee8..e25efc9771 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -322,7 +322,10 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ ** this routine is a no-op. */ void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ - if( (pMem->flags & (MEM_Str|MEM_Term))!=MEM_Str ) return; + if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ + /* pMem must be a string, and it cannot be an ephemeral or static string */ + return; + } if( pMem->enc!=SQLITE_UTF8 ) return; if( NEVER(pMem->z==0) ) return; if( pMem->flags & MEM_Dyn ){ @@ -338,7 +341,7 @@ void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ pMem->flags |= MEM_Term; return; } - }else if( pMem->szMalloc>0 && pMem->szMalloc >= pMem->n+1 ){ + }else if( pMem->szMalloc >= pMem->n+1 ){ pMem->z[pMem->n] = 0; pMem->flags |= MEM_Term; return; diff --git a/src/where.c b/src/where.c index 35b9056ffe..213df42230 100644 --- a/src/where.c +++ b/src/where.c @@ -2535,7 +2535,7 @@ static WhereLoop **whereLoopFindLesser( /* If pTemplate is always better than p, then cause p to be overwritten ** with pTemplate. pTemplate is better than p if: - ** (1) pTemplate has no more dependences than p, and + ** (1) pTemplate has no more dependencies than p, and ** (2) pTemplate has an equal or lower cost than p. */ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ @@ -5003,7 +5003,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** For joins of 3 or more tables, track the 10 best paths */ mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10); assert( nLoop<=pWInfo->pTabList->nSrc ); - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); + WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n", + nRowEst, pParse->nQueryLoop)); /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this ** case the purpose of this call is to estimate the number of rows returned @@ -5757,6 +5758,28 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( } } +/* +** Set the reverse-scan order mask to one for all tables in the query +** with the exception of MATERIALIZED common table expressions that have +** their own internal ORDER BY clauses. +** +** This implements the PRAGMA reverse_unordered_selects=ON setting. +** (Also SQLITE_DBCONFIG_REVERSE_SCANORDER). +*/ +static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){ + int ii; + for(ii=0; iipTabList->nSrc; ii++){ + SrcItem *pItem = &pWInfo->pTabList->a[ii]; + if( !pItem->fg.isCte + || pItem->u2.pCteUse->eM10d!=M10d_Yes + || NEVER(pItem->pSelect==0) + || pItem->pSelect->pOrderBy==0 + ){ + pWInfo->revMask |= MASKBIT(ii); + } + } +} + /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains @@ -6121,8 +6144,9 @@ WhereInfo *sqlite3WhereBegin( if( db->mallocFailed ) goto whereBeginError; } } + assert( pWInfo->pTabList!=0 ); if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - pWInfo->revMask = ALLBITS; + whereReverseScanOrder(pWInfo); } if( pParse->nErr ){ goto whereBeginError; @@ -6222,6 +6246,7 @@ WhereInfo *sqlite3WhereBegin( 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) && !IsVirtual(pTabList->a[0].pTab) && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) + && OptimizationEnabled(db, SQLITE_OnePass) )){ pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ diff --git a/test/corruptL.test b/test/corruptL.test index 65d9821b35..cf38764415 100644 --- a/test/corruptL.test +++ b/test/corruptL.test @@ -1269,6 +1269,7 @@ do_test 15.0 { }]} {} extra_schema_checks 0 +optimization_control db one-pass off do_catchsql_test 15.1 { PRAGMA cell_size_check = 0; UPDATE c1 SET c= NOT EXISTS(SELECT 1 FROM c1 ORDER BY (SELECT 1 FROM c1 ORDER BY a)) +10 WHERE d BETWEEN 4 AND 7; diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index a4969047aa..6b434f6bbf 100644 Binary files a/test/fuzzdata8.db and b/test/fuzzdata8.db differ diff --git a/test/json102.test b/test/json102.test index bfd5e7ed07..276c1816a7 100644 --- a/test/json102.test +++ b/test/json102.test @@ -397,4 +397,22 @@ do_execsql_test json102-1610 { 6 {} null {} null {} null ] +reset_db +do_execsql_test json102-1700 { + CREATE TABLE t1(a1 DATE, a2 INTEGER PRIMARY KEY, a3 INTEGER, memo TEXT); + CREATE INDEX t1x1 ON t1(a3, a1, memo->>'y'); + INSERT INTO t1(a2,a1,a3,memo) VALUES (876, '2023-08-03', 5, '{"x":77,"y":4}'); +} +do_execsql_test json102-1710 { + UPDATE t1 SET memo = JSON_REMOVE(memo, '$.y'); + PRAGMA integrity_check; + SELECT * FROM t1; +} {ok 2023-08-03 876 5 {{"x":77}}} +do_execsql_test json102-1720 { + UPDATE t1 SET memo = JSON_SET(memo, '$.y', 6) + WHERE a2 IN (876) AND JSON_TYPE(memo, '$.y') IS NULL; + PRAGMA integrity_check; + SELECT * FROM t1; +} {ok 2023-08-03 876 5 {{"x":77,"y":6}}} + finish_test diff --git a/test/update.test b/test/update.test index 47b6029bee..bf7666662a 100644 --- a/test/update.test +++ b/test/update.test @@ -764,5 +764,27 @@ do_execsql_test update-21.4 { SELECT * FROM t1 ORDER BY vkey, c5; ROLLBACK; } {6 -54 100 NULL} +# Follow-up on 2023-07-31 (forum post https://sqlite.org/forum/forumpost/8ab195fd44e75ed0): +# Only disable one-pass if the subquery is in the WHERE clause. The SET expressions +# do not count. +do_execsql_test update-21.11 { + DROP TABLE t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT); + CREATE TABLE t2(d INT); +} +do_eqp_test update-21.12 { + WITH t3(x,y) AS (SELECT d, row_number()OVER() FROM t2) + UPDATE t1 SET b=(SELECT y FROM t3 WHERE t1.a=t3.x); +} { + QUERY PLAN + |--SCAN t1 + `--CORRELATED SCALAR SUBQUERY xxxxxx + |--CO-ROUTINE t3 + | |--CO-ROUTINE (subquery-xxxxxx) + | | `--SCAN t2 + | `--SCAN (subquery-xxxxxx) + |--BLOOM FILTER ON t3 (x=?) + `--SEARCH t3 USING AUTOMATIC COVERING INDEX (x=?) +} finish_test diff --git a/test/where7.test b/test/where7.test index f76e8aba8b..681684b809 100644 --- a/test/where7.test +++ b/test/where7.test @@ -47,18 +47,33 @@ do_test where7-1.1 { SELECT * FROM t1; } } {1 2 3 4 2 3 4 5 3 4 6 8 4 5 10 15 5 10 100 1000} -do_execsql_test where7-1.1.1 { - CREATE TABLE t(a); - CREATE INDEX ta ON t(a); - INSERT INTO t(a) VALUES(1),(2); - SELECT * FROM t ORDER BY a; - SELECT * FROM t WHERE a<2 OR a<3 ORDER BY a; - PRAGMA count_changes=ON; - DELETE FROM t WHERE a<2 OR a<3; - SELECT * FROM t; - PRAGMA count_changes=OFF; - DROP TABLE t; -} {1 2 1 2 2} +if {[permutation] != "no_optimization"} { + do_execsql_test where7-1.1.1 { + CREATE TABLE t(a); + CREATE INDEX ta ON t(a); + INSERT INTO t(a) VALUES(1),(2); + SELECT * FROM t ORDER BY a; + SELECT * FROM t WHERE a<2 OR a<3 ORDER BY a; + PRAGMA count_changes=ON; + DELETE FROM t WHERE a<2 OR a<3; + SELECT * FROM t; + PRAGMA count_changes=OFF; + DROP TABLE t; + } {1 2 1 2 2} +} else { + do_execsql_test where7-1.1.1-noopt { + CREATE TABLE t(a); + CREATE INDEX ta ON t(a); + INSERT INTO t(a) VALUES(1),(2); + SELECT * FROM t ORDER BY a; + SELECT * FROM t WHERE a<2 OR a<3 ORDER BY a; + PRAGMA count_changes=ON; + DELETE FROM t WHERE a<2 OR a<3; + SELECT * FROM t; + PRAGMA count_changes=OFF; + DROP TABLE t; + } {1 2 1 2 3} +} do_test where7-1.2 { count_steps { SELECT a FROM t1 WHERE b=3 OR c=6 ORDER BY a diff --git a/tool/build-shell.sh b/tool/build-shell.sh index 6a48299d73..a57f753039 100644 --- a/tool/build-shell.sh +++ b/tool/build-shell.sh @@ -16,7 +16,6 @@ gcc -o sqlite3 -g -Os -I. \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_RTREE \ -DHAVE_READLINE \ - -DHAVE_USLEEP=1 \ ../sqlite/src/shell.c \ ../sqlite/src/test_vfstrace.c \ sqlite3.c -ldl -lreadline -lncurses diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 2b8f08deb5..6def8fa447 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -87,7 +87,7 @@ set out [open $fname w] # Force the output to use unix line endings, even on Windows. fconfigure $out -translation lf set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] -puts $out \ +puts $out [subst \ {/****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version $VERSION. By combining all the individual C code files into this @@ -106,7 +106,7 @@ puts $out \ ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. -**} +**}] set srcroot [file dirname [file dirname [info script]]] if {$tcl_platform(platform)=="windows"} { set vsrcprog src-verify.exe diff --git a/tool/warnings.sh b/tool/warnings.sh index 60d2b42100..2b962d15ed 100644 --- a/tool/warnings.sh +++ b/tool/warnings.sh @@ -32,7 +32,6 @@ if test x`uname` = 'xLinux'; then echo '********** Android configuration ******************************' echo '********** ' Options: $WARNING_ANDROID_OPTS gcc -c \ - -DHAVE_USLEEP=1 \ -DSQLITE_HAVE_ISNAN \ -DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \ -DSQLITE_THREADSAFE=2 \