Fix the OR-to-IN optimization so that it works in cases where there are

conflicting collation sequences on the equality constraints within the OR.
[bugs:/info/2026-06-17T05:04:48Z|Bug 2026-06-17T05:04:48Z].

FossilOrigin-Name: 984c9b181801c1de06782335eb049f32d1dc1d5739a7fb9c94630c22159a4f8c
This commit is contained in:
drh
2026-06-17 13:31:01 +00:00
parent 8227408b6f
commit aa1579de80
4 changed files with 97 additions and 16 deletions
+7 -7
View File
@@ -1,5 +1,5 @@
C Typo\sfix\sin\sa\scomment\sused\sto\sgenerate\sdocumentation.\s\sNo\schanges\sto\scode.\n[forum:/info/2026-06-16T23:18:50Z|Forum\s2026-06-16T23:18:50Z].
D 2026-06-16T23:59:58.512
C Fix\sthe\sOR-to-IN\soptimization\sso\sthat\sit\sworks\sin\scases\swhere\sthere\sare\nconflicting\scollation\ssequences\son\sthe\sequality\sconstraints\swithin\sthe\sOR.\n[bugs:/info/2026-06-17T05:04:48Z|Bug\s2026-06-17T05:04:48Z].
D 2026-06-17T13:31:01.199
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -822,7 +822,7 @@ F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 33e4a6558ee69f33d6a4e7069e3a40a55959d14e5653a9a83926e70305d471f3
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
F src/wherecode.c bc39ccbe3648f01157038b16cc55bdbff128590972b7185521b5526dc2815765
F src/whereexpr.c a1e22cf9f6cb59770d9652c757dcf1924078ad2d48a9da89e254be9327677465
F src/whereexpr.c 906d30c21470bbafc31bbc2cd07a0753bdd57169caed6ba75b8b4fc0ecb24134
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
@@ -2036,7 +2036,7 @@ F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9
F test/walthread.test d562f51a61191ccfab64940df7aa1cef87c902fa5ab742590ef7f859dfe6a44b
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
F test/where.test 5087c72d26fd075a1644c8512be9fe18de9bf2d2b0754f7fd9b74a1c6540c4fc
F test/where2.test b73f8ee8f94b850764c429efe2d48171090628737dcc3df64a9f2214da02089f
F test/where2.test 5d93a8aec78386539aa01cf72926eb39d90de4ce1bfb6d517f56ae9bf704ba8a
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
@@ -2208,8 +2208,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P 3f3fb9b638f59ad982beafb7c117f24ddd3da612e62c862510805fa672ffae06
R 2749023ec3b3a42db0202431b16ac364
P 7386faef618acb006086d688fcea854a7c555ac1bcfcaa294ea86e964e4ce75f
R 836fd25a1bda58cdd1d612594b2acd20
U drh
Z a9125302b24a90e1badf9939a73e768f
Z 09733955458454de050382ab21f95241
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
7386faef618acb006086d688fcea854a7c555ac1bcfcaa294ea86e964e4ce75f
984c9b181801c1de06782335eb049f32d1dc1d5739a7fb9c94630c22159a4f8c
+35 -8
View File
@@ -907,29 +907,56 @@ static void exprAnalyzeOrTerm(
}
}
/* At this point, okToChngToIN is true if original pTerm satisfies
** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
/* At this point, okToChngToIN is true if original pTerm is a
** candidate to satisfy case 1, though we are not yet certain that
** the collating sequences are all compatible. Try to construct a
** new virtual term that is pTerm converted from an OR operator
** into an IN operator.
**
** During construction, verify that the collating sequences on all
** subterms of the OR are compatible. Omit the construction of the
** new IN operator if there are any collating sequence mismatches.
*/
if( okToChngToIN ){
Expr *pDup; /* A transient duplicate expression */
ExprList *pList = 0; /* The RHS of the IN operator */
Expr *pLeft = 0; /* The LHS of the IN operator */
CollSeq *pCollSeq = 0; /* Collating sequence to use */
Expr *pNew; /* The complete IN operator */
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
Expr *pThis;
if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pThis = pOrTerm->pExpr;
pDup = sqlite3ExprDup(db, pThis->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
if( pLeft==0 ){
pLeft = pThis->pLeft;
pCollSeq = sqlite3ExprCompareCollSeq(pParse, pThis);
}else{
assert( 0==sqlite3ExprCompare(pParse, pThis->pLeft, pLeft, -1) );
if( pCollSeq!=sqlite3ExprCompareCollSeq(pParse, pThis) ){
pLeft = 0; /* Collating sequence mismatch */
break;
}
}
}
if( pLeft==0 ){
pNew = 0; /* Collating sequence mismatch */
}else{
pDup = sqlite3ExprDup(db, pLeft, 0);
if( sqlite3ExprCollSeq(pParse, pDup)!=pCollSeq
&& ALWAYS(pCollSeq!=0)
){
assert( pCollSeq->zName!=0 );
pDup = sqlite3ExprAddCollateString(pParse, pDup, pCollSeq->zName);
}
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(db, pLeft, 0);
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
+54
View File
@@ -456,6 +456,60 @@ ifcapable explain&&subquery {
} {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
}
# Bug 2026-06-17T05:04:48Z
#
do_execsql_test where2-6.14.1 {
CREATE TABLE t614a(a TEXT COLLATE NOCASE, b TEXT COLLATE NOCASE);
INSERT INTO t614a VALUES('AAA','BBB');
CREATE TABLE t614b(x,y,c TEXT);
INSERT INTO t614b(c) VALUES('aaa'),('bbb');
CREATE INDEX t614b_c ON t614b(c);
SELECT c FROM t614a, t614b WHERE a=c OR b=c;
} {aaa bbb}
do_execsql_test where2-6.14.2 {
SELECT c FROM t614a, t614b WHERE c=a OR c=b;
} {}
do_execsql_test where2-6.14.3 {
SELECT c FROM t614a, t614b WHERE c=a OR b=c;
} {bbb}
do_execsql_test where2-6.14.4 {
SELECT c FROM t614a, t614b WHERE a=c OR c=b;
} {aaa}
do_execsql_test where2-6.15.1 {
CREATE TABLE t615a(a TEXT, b TEXT);
INSERT INTO t615a VALUES('AAA','BBB');
CREATE TABLE t615b(x,y,c TEXT COLLATE NOCASE);
INSERT INTO t615b(c) VALUES('aaa'),('bbb');
CREATE INDEX t615b_c ON t615b(c);
SELECT c FROM t615a, t615b WHERE c=a OR c=b;
} {aaa bbb}
do_execsql_test where2-6.15.2 {
SELECT c FROM t615a, t615b WHERE a=c OR b=c;
} {}
do_execsql_test where2-6.15.3 {
SELECT c FROM t615a, t615b WHERE c=a OR b=c;
} {aaa}
do_execsql_test where2-6.15.4 {
SELECT c FROM t615a, t615b WHERE a=c OR c=b;
} {bbb}
do_execsql_test where2-6.16.1 {
CREATE TABLE t616a(a TEXT COLLATE NOCASE, b TEXT COLLATE NOCASE);
INSERT INTO t616a VALUES('AAA','BBB');
CREATE TABLE t616b(x,y,c TEXT COLLATE NOCASE);
INSERT INTO t616b(c) VALUES('aaa'),('bbb');
CREATE INDEX t616b_c ON t616b(c);
SELECT c FROM t616a, t616b WHERE c=a OR c=b;
} {aaa bbb}
do_execsql_test where2-6.16.2 {
SELECT c FROM t616a, t616b WHERE a=c OR b=c;
} {aaa bbb}
do_execsql_test where2-6.16.3 {
SELECT c FROM t616a, t616b WHERE c=a OR b=c;
} {aaa bbb}
do_execsql_test where2-6.16.4 {
SELECT c FROM t616a, t616b WHERE a=c OR c=b;
} {aaa bbb}
# Variations on the order of terms in a WHERE clause in order
# to make sure the OR optimizer can recognize them all.
do_test where2-6.20 {