aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rw-r--r--ext/wasm/fiddle.make3
-rw-r--r--manifest32
-rw-r--r--manifest.uuid2
-rw-r--r--sqlite3.pc.in2
-rw-r--r--src/build.c1
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/tokenize.c2
-rw-r--r--src/vdbeblob.c33
-rw-r--r--src/where.c18
-rw-r--r--src/wherecode.c29
-rw-r--r--test/incrblob4.test91
-rw-r--r--test/rowvalue.test37
13 files changed, 202 insertions, 53 deletions
diff --git a/Makefile.in b/Makefile.in
index 995bbde44..d462d811e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -264,7 +264,9 @@ AS_AUTO_DEF = $(TOP)/auto.def
# invoked with to produce this makefile.
#
AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
-
+.PHONY: reconfigure
+reconfigure:
+ $(AS_AUTORECONFIG)
USE_AMALGAMATION ?= @USE_AMALGAMATION@
LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@
AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
diff --git a/ext/wasm/fiddle.make b/ext/wasm/fiddle.make
index 8110384a6..5b1eb5e77 100644
--- a/ext/wasm/fiddle.make
+++ b/ext/wasm/fiddle.make
@@ -40,9 +40,8 @@ fiddle.emcc-flags = \
-sWASM_BIGINT=$(emcc.WASM_BIGINT) \
-sEXPORT_NAME=$(sqlite3.js.init-func) \
-Wno-limited-postlink-optimizations \
- $(emcc.exportedRuntimeMethods) \
+ $(emcc.exportedRuntimeMethods),FS \
-sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
- -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory \
$(SQLITE_OPT.full-featured) \
$(SQLITE_OPT.common) \
$(SHELL_OPT) \
diff --git a/manifest b/manifest
index 4b0c4022b..974b081ab 100644
--- a/manifest
+++ b/manifest
@@ -1,10 +1,10 @@
-C Improvements\sto\sthe\sEXPLAIN\sQUERY\sPLAN\soutput\sfor\sEXISTS-to-JOIN.
-D 2025-07-06T01:19:09.350
+C Merge\sthe\slatest\strunk\s\senhancements\sand\sfixes\sinto\sthe\sempty-table-optimizations\sbranch.
+D 2025-07-07T18:35:51.568
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
-F Makefile.in d8bc4aee9fb645c9f2ff0e3a30585d17a0df076bb6a33f0f20bab4999abb45a0
+F Makefile.in a6c14b6906f5322920dd5d1ff9a84808337911068f2a6e777ec7088a87cbc3a8
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc ec2011bbdfc917d6a1c7c173dabb29c14ead0dd8e2e0b67278a00ae4ba576a77
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
@@ -674,7 +674,7 @@ F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2
F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535da776950314
F ext/wasm/dist.make 92ef4ffe33022a50f92d602acabad10bd8dd91759f3eb7df27fc6d7d37072b96
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
-F ext/wasm/fiddle.make c6d7a3d6cc03bb5f21acb295c1233820d0dbf5c6a89b28dc2e093edcc001c45a
+F ext/wasm/fiddle.make 2df87f12bcbae2c966c2cef34ce71bb1584c440c69e14ca6d32f443d8d550dc5
F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
F ext/wasm/fiddle/fiddle.js 2a2f27b4be2674f501fff61c4a09e44dcf2295731a26b5c28e439f3a573bd269
F ext/wasm/fiddle/index.html 7fcfb221165183bef0e05d5af9ceb79b527e799b1708ab05de0ec0eaebd5b7bf
@@ -718,7 +718,7 @@ F mptest/mptest.c aa41ace6dbc5050d76b02548d3521e6bbccae4f0
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
-F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
+F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
F src/alter.c fc7bbbeb9e89c7124bf5772ce474b333b7bdc18d6e080763211a40fde69fb1da
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
@@ -729,7 +729,7 @@ F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c cb5b8ceb9baa02a63a2f83dec09c4153e1cfbdf9c2adef5c62c26d2160eeb067
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
-F src/build.c f0a3d935954b1b344b929f5092f94e535ac98cf72bb8bcd3e72fb3dfa982e169
+F src/build.c bef89ea23db1221556a3a405b7c46cac14c03fc0a8e82954ca2359a7dc98ec69
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
@@ -790,7 +790,7 @@ F src/shell.c.in 73c0eeb7c265d59b99219d5aa055f412f07842088d8036b6d259927d85dd1bb
F src/sqlite.h.in 5c54f2461a1ea529bab8499148a2b238e2d4bb571d59e8ea5322d0c190abb693
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
-F src/sqliteInt.h fcb2fd7eb47f6731ca8d4cbfbada95f24665bcc8a5ec44e2d24942220eb32453
+F src/sqliteInt.h 9c99d7565a839ad342cdda504c4b7921bb1a24c07227b8f50b7b131245a20693
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -844,7 +844,7 @@ F src/test_vfs.c b4135c1308516adf0dfd494e6d6c33114e03732be899eace0502919b674586b
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c 3e37ac2b6cbb9b0abe33827b0153c27595269afd7152b48019808974481aca2c
+F src/tokenize.c 8400646d2830afc2f2dc465a75e3a92e4bedeea623f19dbd79c0c12d0dd6dda2
F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc62279
F src/trigger.c 3ffb8ed6b64dbcc0ccae6e82435d01be3bf547e13b814e2d46f7df9bef84748e
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
@@ -857,7 +857,7 @@ F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
F src/vdbeapi.c f9a4881a9674fec3fa13da35044a1484d3c4b95f9ec891cc8ffb02ef2b7a41df
F src/vdbeaux.c fd2c6b19a8892c31a2adc719f156f313560f9cc490cdbd04ff08fdae5d7aedb7
-F src/vdbeblob.c b1b4032cac46b41e44b957c4d00aee9851f862dfd85ecb68116ba49884b03dfd
+F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
F src/vdbemem.c e67d9c6484d868c879d20c70d00bf4a9058082f1d4058607ca15d50eb3aebc21
F src/vdbesort.c cb6f472e83ca12c46aa7de0ac0a9d11458b357986f2617a1c90dfb19a542ecbe
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
@@ -867,9 +867,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 20be6f0a25a80b7897cf2a5369bfd37ef198e6f0b6cdef16d83eee856056b159
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c f8139d355555e305aa5cf40ddf0f94ca606341d5196c6c597a79e6b1f7a173ee
+F src/where.c 6a9266dd1a559d48d8c7ca670a3e80143c7913153f7d1ceb0a4eca1087318951
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
-F src/wherecode.c ff520ce2a1ac8248e7adc1cff7ea2141fb07260ece28d2c6130e87fdfc0d2afa
+F src/wherecode.c 2a2d2993fd98c46f525f71b3bfd330fde73d8613aa0ff3e20402dd1fc63470af
F src/whereexpr.c d007dc41364de5902181739632380afd671e14f0c5cc9978e64a2c6df8f28c6c
F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1318,7 +1318,7 @@ F test/in7.test d9efdee00b074a60c6343993b2eda78bc369ab080dad864513c73f8aca89d566
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test 67621a04b3084113bf38ce03797d70eca012d9d8f948193b8f655df577b0da6f
-F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
+F test/incrblob4.test 10f4537febe1774c02f8d490d393322b4a50898d4027868b67055e9c3adc22db
F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
F test/incrblobfault.test de274b1e329169c2c3438f9528994807ea8201ebf38ae9f157d34bf3ec0cc549
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
@@ -1579,7 +1579,7 @@ F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190c
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
-F test/rowvalue.test 9c873b2f6e7ce72b24ef133f93515c07a6a7dac4846a344ebc2af7b8bfdf5147
+F test/rowvalue.test 8a3f0fea3a3cbbfc7cb9885b76185a774cd8d891e0c133e289567c755d39eb9f
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 103e9a224ca0548dd0d67e439f39c5dd16de4200221a333927372408c025324c
F test/rowvalue4.test bac9326d1e886656650f67c0ec484eb5f452244a8209c6af508e9a862ace08ed
@@ -2211,8 +2211,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P c1d5295724f9cf7f49e0786d28016eff2d268a2b670f934d24c76787626089db
-R e327f2cba9403b63bcd0d2189ed9005a
+P 6b1ecbaa2ee405be040901dceac45d027d35c313622748ba4dbbd404e297a7fa 28db0d152d90fb5e62d03ea5caceabe8901be98522aef3dc2b54564fbc35355d
+R 1ad2faf618cb852b453d45306c55c408
U drh
-Z 99af5d89797b6a2541e58b654e88bc24
+Z 725feec2e2e8168094856eb7acaf31d4
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index 870e5bc36..f4fafa7e7 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-6b1ecbaa2ee405be040901dceac45d027d35c313622748ba4dbbd404e297a7fa
+f15cdf07573c05276a13885d74bae21a93544766344f19ef939b7a69edd1073b
diff --git a/sqlite3.pc.in b/sqlite3.pc.in
index a9f941b1e..723dd5156 100644
--- a/sqlite3.pc.in
+++ b/sqlite3.pc.in
@@ -9,5 +9,5 @@ Name: SQLite
Description: SQL database engine
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lsqlite3
-Libs.private: @LDFLAGS_MATH@ @LDFLAGS_ZLIB@ @LDFLAGS_ICU@
+Libs.private: @LDFLAGS_MATH@ @LDFLAGS_ZLIB@ @LDFLAGS_DLOPEN@ @LDFLAGS_PTHREAD@ @LDFLAGS_ICU@
Cflags: -I${includedir}
diff --git a/src/build.c b/src/build.c
index 526e2ddfe..cd838557f 100644
--- a/src/build.c
+++ b/src/build.c
@@ -4219,7 +4219,6 @@ void sqlite3CreateIndex(
assert( j<=0x7fff );
if( j<0 ){
j = pTab->iPKey;
- pIndex->bIdxRowid = 1;
}else{
if( pTab->aCol[j].notNull==0 ){
pIndex->uniqNotNull = 0;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 6ae456f59..7b914d958 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2810,7 +2810,6 @@ struct Index {
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
- unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
unsigned bHasExpr:1; /* Index contains an expression, either a literal
** expression, or a reference to a VIRTUAL column */
diff --git a/src/tokenize.c b/src/tokenize.c
index e4d9f5371..6f7bab35b 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -199,7 +199,7 @@ static int getToken(const unsigned char **pz){
int t; /* Token type to return */
do {
z += sqlite3GetToken(z, &t);
- }while( t==TK_SPACE );
+ }while( t==TK_SPACE || t==TK_COMMENT );
if( t==TK_ID
|| t==TK_STRING
|| t==TK_JOIN_KW
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index 42edcf7de..a15fec6c4 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -385,7 +385,7 @@ static int blobReadWrite(
int iOffset,
int (*xCall)(BtCursor*, u32, u32, void*)
){
- int rc;
+ int rc = SQLITE_OK;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v;
sqlite3 *db;
@@ -425,17 +425,32 @@ static int blobReadWrite(
** using the incremental-blob API, this works. For the sessions module
** anyhow.
*/
- sqlite3_int64 iKey;
- iKey = sqlite3BtreeIntegerKey(p->pCsr);
- assert( v->apCsr[0]!=0 );
- assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
- sqlite3VdbePreUpdateHook(
- v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
- );
+ if( sqlite3BtreeCursorIsValidNN(p->pCsr)==0 ){
+ /* If the cursor is not currently valid, try to reseek it. This
+ ** always either fails or finds the correct row - the cursor will
+ ** have been marked permanently CURSOR_INVALID if the open row has
+ ** been deleted. */
+ int bDiff = 0;
+ rc = sqlite3BtreeCursorRestore(p->pCsr, &bDiff);
+ assert( bDiff==0 || sqlite3BtreeCursorIsValidNN(p->pCsr)==0 );
+ }
+ if( sqlite3BtreeCursorIsValidNN(p->pCsr) ){
+ sqlite3_int64 iKey;
+ iKey = sqlite3BtreeIntegerKey(p->pCsr);
+ assert( v->apCsr[0]!=0 );
+ assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
+ sqlite3VdbePreUpdateHook(
+ v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
+ );
+ }
}
+ if( rc==SQLITE_OK ){
+ rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
+ }
+#else
+ rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
#endif
- rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
sqlite3BtreeLeaveCursor(p->pCsr);
if( rc==SQLITE_ABORT ){
sqlite3VdbeFinalize(v);
diff --git a/src/where.c b/src/where.c
index 059b0e89e..ab1b419a2 100644
--- a/src/where.c
+++ b/src/where.c
@@ -3239,6 +3239,7 @@ static int whereLoopAddBtreeIndex(
if( ExprUseXSelect(pExpr) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
int i;
+ int bRedundant = 0;
nIn = 46; assert( 46==sqlite3LogEst(25) );
/* The expression may actually be of the form (x, y) IN (SELECT...).
@@ -3247,7 +3248,20 @@ static int whereLoopAddBtreeIndex(
** for each such term. The following loop checks that pTerm is the
** first such term in use, and sets nIn back to 0 if it is not. */
for(i=0; i<pNew->nLTerm-1; i++){
- if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
+ if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ){
+ nIn = 0;
+ if( pNew->aLTerm[i]->u.x.iField == pTerm->u.x.iField ){
+ /* Detect when two or more columns of an index match the same
+ ** column of a vector IN operater, and avoid adding the column
+ ** to the WhereLoop more than once. See tag-20250707-01
+ ** in test/rowvalue.test */
+ bRedundant = 1;
+ }
+ }
+ }
+ if( bRedundant ){
+ pNew->nLTerm--;
+ continue;
}
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
@@ -3479,7 +3493,7 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
&& (pNew->u.btree.nEq<pProbe->nKeyCol ||
- (pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY && !pProbe->bIdxRowid))
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
if( pNew->u.btree.nEq>3 ){
sqlite3ProgressCheck(pParse);
diff --git a/src/wherecode.c b/src/wherecode.c
index 5111880c0..43a669d81 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -600,7 +600,9 @@ static Expr *removeUnindexableInClauseTerms(
int iField;
assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
iField = pLoop->aLTerm[i]->u.x.iField - 1;
- if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
+ if( NEVER(pOrigRhs->a[iField].pExpr==0) ){
+ continue; /* Duplicate PK column */
+ }
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
@@ -697,7 +699,7 @@ static SQLITE_NOINLINE void codeINTerm(
return;
}
}
- for(i=iEq;i<pLoop->nLTerm; i++){
+ for(i=iEq; i<pLoop->nLTerm; i++){
assert( pLoop->aLTerm[i]!=0 );
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
@@ -706,22 +708,13 @@ static SQLITE_NOINLINE void codeINTerm(
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
- Expr *pExpr = pTerm->pExpr;
- if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
- sqlite3 *db = pParse->db;
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
- if( !db->mallocFailed ){
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
- pExpr->iTable = iTab;
- }
- sqlite3ExprDelete(db, pX);
- }else{
- int n = sqlite3ExprVectorSize(pX->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
+ sqlite3 *db = pParse->db;
+ Expr *pXMod = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+ if( !db->mallocFailed ){
+ aiMap = (int*)sqlite3DbMallocZero(db, sizeof(int)*nEq);
+ eType = sqlite3FindInIndex(pParse, pXMod, IN_INDEX_LOOP, 0, aiMap, &iTab);
}
- pX = pExpr;
+ sqlite3ExprDelete(db, pXMod);
}
if( eType==IN_INDEX_INDEX_DESC ){
@@ -751,7 +744,7 @@ static SQLITE_NOINLINE void codeINTerm(
if( pIn ){
int iMap = 0; /* Index in aiMap[] */
pIn += i;
- for(i=iEq;i<pLoop->nLTerm; i++){
+ for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
int iOut = iTarget + i - iEq;
if( eType==IN_INDEX_ROWID ){
diff --git a/test/incrblob4.test b/test/incrblob4.test
index dbff8eb7d..31040e91b 100644
--- a/test/incrblob4.test
+++ b/test/incrblob4.test
@@ -106,4 +106,95 @@ do_test 4.4 {
} {SQLITE_LOCKED}
close $blob
+#-------------------------------------------------------------------------
+
+reset_db
+do_execsql_test 5.1 {
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
+ INSERT INTO t2 VALUES(1000, 'abcdefghijklmnopqrstuvwxyz');
+ INSERT INTO t2 VALUES(2000, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+ INSERT INTO t2 VALUES(3000, 'abcdefghijklmnopqrstuvwxyz');
+}
+
+do_test 5.2.1 {
+ execsql BEGIN
+ set blob [db incrblob t2 b 2000]
+ seek $blob 0
+ puts -nonewline $blob "hello "
+ flush $blob
+ execsql ROLLBACK
+} {}
+
+do_test 5.2.2 {
+ puts -nonewline $blob "world"
+ list [catch { flush $blob } msg] $msg
+} "1 {error flushing \"$blob\": I/O error}"
+catch { close $blob }
+
+set preupdate_count 0
+proc preupdate {args} { incr ::preupdate_count ; return {} }
+db preupdate hook preupdate
+
+set preupdate_count 0
+do_test 5.3.1 {
+ execsql BEGIN
+ set blob [db incrblob t2 b 1000]
+ seek $blob 0
+ puts -nonewline $blob "hello "
+ flush $blob
+ execsql ROLLBACK
+} {}
+
+do_test 5.3.2 {
+ puts -nonewline $blob "world"
+ list [catch { flush $blob } msg] $msg
+} "1 {error flushing \"$blob\": I/O error}"
+catch { close $blob }
+
+do_test 5.3.3 {
+ set ::preupdate_count
+} {1}
+
+set preupdate_count 0
+do_test 5.4.1 {
+ execsql BEGIN
+ set blob [db incrblob t2 b 1000]
+ seek $blob 0
+ puts -nonewline $blob "hello "
+ flush $blob
+ execsql { DELETE FROM t2 WHERE a=3000; }
+} {}
+
+do_test 5.4.2 {
+ puts -nonewline $blob "world"
+ list [catch { flush $blob } msg] $msg
+} "0 {}"
+catch { close $blob }
+catchsql { ROLLBACK }
+
+do_test 5.3.3 {
+ set ::preupdate_count
+} {3}
+
+set preupdate_count 0
+do_test 5.4.3 {
+ execsql BEGIN
+ set blob [db incrblob t2 b 2000]
+ seek $blob 0
+ puts -nonewline $blob "hello "
+ flush $blob
+ execsql { UPDATE t2 SET b='abcdefghijklmnopqrstuvwxyz' WHERE a=2000 }
+} {}
+
+do_test 5.4.4 {
+ puts -nonewline $blob "world"
+ list [catch { flush $blob } msg] $msg
+} "1 {error flushing \"$blob\": I/O error}"
+catch { close $blob }
+catchsql { ROLLBACK }
+
+do_test 5.3.3 {
+ set ::preupdate_count
+} {2}
+
finish_test
diff --git a/test/rowvalue.test b/test/rowvalue.test
index e2688e903..387780c45 100644
--- a/test/rowvalue.test
+++ b/test/rowvalue.test
@@ -788,6 +788,9 @@ do_execsql_test 33.3 {
# INTEGER PRIMARY KEY, and the columns that UNIQUE constraint are
# used in a rowvalue-IN operator constraint.
#
+# 2025-07-07 Discovered that the original fix was incomplete and
+# new tests added. See tag-20250707-01 in the code.
+#
reset_db
do_execsql_test 34.1 {
CREATE TABLE items (
@@ -804,5 +807,39 @@ do_execsql_test 34.1 {
WHERE (Id, Item) IN (SELECT Id, Item FROM items);
SELECT Id, Item, test FROM items ORDER BY id;
} {1 2 ok 2 2 ok 3 3 ok 4 5 ok}
+db null NULL
+do_execsql_test 34.2 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
+ CREATE INDEX idx ON t1(b,a);
+ INSERT INTO t1(a,b) VALUES (1, 22);
+ SELECT * FROM t1 INDEXED BY idx WHERE (b,a) IN (SELECT b,a FROM t1);
+} {1 22 NULL NULL}
+do_execsql_test 34.3 {
+ DROP TABLE t1;
+ CREATE TABLE t1(a, b, c, d);
+ CREATE INDEX idx ON t1(b,a,a);
+ INSERT INTO t1(a,b) VALUES (1, 22);
+ SELECT * FROM t1 INDEXED BY idx WHERE (b,a) IN (SELECT b,a FROM t1);
+} {1 22 NULL NULL}
+do_execsql_test 34.4 {
+ DROP TABLE t1;
+ CREATE TABLE t1(id INTEGER PRIMARY KEY, a INT);
+ CREATE INDEX t1a ON t1(a,id); -- index includes PRIMARY KEY
+ CREATE TABLE t2(id INTEGER PRIMARY KEY);
+ WITH RECURSIVE c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<100)
+ INSERT INTO t1(id,a) SELECT n, 777 FROM c;
+ INSERT INTO t2 SELECT id FROM t1;
+ SELECT *
+ FROM t1 JOIN t2 USING(id)
+ WHERE t1.a=777 AND t2.id>999
+ ORDER BY t1.id;
+} {}
+do_execsql_test 34.5 {
+ EXPLAIN QUERY PLAN
+ SELECT *
+ FROM t1 JOIN t2 USING(id)
+ WHERE t1.a=777 AND t2.id>999
+ ORDER BY t1.id;
+} {/SEARCH t1 USING COVERING INDEX t1a .a=. AND id>../}
finish_test