From 4dd1a202deb6bb6411eb13a0623f4c9d0f3e0d1a Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 16 Jan 2026 15:53:20 +0000 Subject: [PATCH] The optimization at [8bdda827a3d26800] is incorrect for the case where one of the two expressions has been commuted such that the collating sequence has changed. This check-in fixes the problem. Problem reported by [forum:/forumpost/2026-01-16T11:35:28Z|forum post 2026-01-16T11:35:28Z]. FossilOrigin-Name: 9d8fb7a9e23d5ef76d05824401976247debe51be6f658f132609257a068a73de --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/whereexpr.c | 16 +++++++++++----- test/whereK.test | 13 +++++++++++++ 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 741cd015e3..25cf9c2b46 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\scopyright\son\sthe\stool/dbtotxt.c\ssource\scode\sfile\sto\sthe\nstandard\sSQLite\sblessing. -D 2026-01-16T12:13:42.015 +C The\soptimization\sat\s[8bdda827a3d26800]\sis\sincorrect\sfor\sthe\scase\swhere\sone\nof\sthe\stwo\sexpressions\shas\sbeen\scommuted\ssuch\sthat\sthe\scollating\ssequence\nhas\schanged.\s\sThis\scheck-in\sfixes\sthe\sproblem.\s\sProblem\sreported\sby\n[forum:/forumpost/2026-01-16T11:35:28Z|forum\spost\s2026-01-16T11:35:28Z]. +D 2026-01-16T15:53:20.470 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -823,7 +823,7 @@ F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 F src/where.c 0079b6ba463ae806b99b20cb335729dcce5f3e496b81cccf6441dc11f8c5bf92 F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da F src/wherecode.c 71c5c6804b7f882dec8ec858758accae02fcfca13df3cc720f1f258e663ec7c5 -F src/whereexpr.c 5f412da6616e26b8000dd736a5ce5da0018dff0933cd656bbb25f407db16bf93 +F src/whereexpr.c cadb37fbaa2cb6d1ec1687923c3ac21aed4187d198f4500c00a01abb24c3cb44 F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d @@ -2040,7 +2040,7 @@ F test/whereG.test 875d020ac0a47828b31e36c54f1bf0cf81c9ea43b257bc21286eca1fe9a48 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581 F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf -F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a +F test/whereK.test 4fb96b078f2ecedc467fa53177787378ff659539e415a4256cae7ae4e2a804b2 F test/whereL.test cb115604cc9bd61acbc99a1f1df0eb1ea7a7875a77fef25ba9282f01d10283e1 F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250 F test/whereN.test 63a3584b71acfb6963416de82f26c6b1644abc5ca6080c76546b9246734c8803 @@ -2192,8 +2192,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P a5918835e172fd4eda6511d297b61368952d617eac33950b67368671e3bd40fe -R c602375ef72a479dcec90722a6270c60 +P 766c89e009578aa5c1a92cbb2dcc34b3529cf4dd6157f07c84f08470d81942a9 +R bdcc204a60ddb01f203734624d8fbe88 U drh -Z cd561f5e126a2aa4688b11fcaa2ab0b6 +Z 38e9f9ef4cf328d41d09316ce8aaeefa # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a3bc416c01..e02e56b585 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -766c89e009578aa5c1a92cbb2dcc34b3529cf4dd6157f07c84f08470d81942a9 +9d8fb7a9e23d5ef76d05824401976247debe51be6f658f132609257a068a73de diff --git a/src/whereexpr.c b/src/whereexpr.c index 91386de3f6..9ee4014dc5 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -549,16 +549,22 @@ static void whereCombineDisjuncts( Expr *pNew; /* New virtual expression */ int op; /* Operator for the combined expression */ int idxNew; /* Index in pWC of the next virtual term */ + Expr *pA, *pB; /* Expressions associated with pOne and pTwo */ if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return; if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; - assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); - assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); - if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; - if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return; + pA = pOne->pExpr; + pB = pTwo->pExpr; + assert( pA->pLeft!=0 && pA->pRight!=0 ); + assert( pB->pLeft!=0 && pB->pRight!=0 ); + if( sqlite3ExprCompare(0,pA->pLeft, pB->pLeft, -1) ) return; + if( sqlite3ExprCompare(0,pA->pRight, pB->pRight,-1) ) return; + if( ExprHasProperty(pA,EP_Commuted)!=ExprHasProperty(pB,EP_Commuted) ){ + return; + } /* If we reach this point, it means the two subterms can be combined */ if( (eOp & (eOp-1))!=0 ){ if( eOp & (WO_LT|WO_LE) ){ @@ -569,7 +575,7 @@ static void whereCombineDisjuncts( } } db = pWC->pWInfo->pParse->db; - pNew = sqlite3ExprDup(db, pOne->pExpr, 0); + pNew = sqlite3ExprDup(db, pA, 0); if( pNew==0 ) return; for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op; diff --git a/test/whereK.test b/test/whereK.test index 060d470ff9..995c083712 100644 --- a/test/whereK.test +++ b/test/whereK.test @@ -69,4 +69,17 @@ do_execsql_test 1.5eqp { ORDER BY +a; } {/SEARCH t1 USING INDEX t1bc/} +# https://sqlite.org/forum/forumpost/2026-01-16T11:35:28Z +do_execsql_test 2.1 { + DROP TABLE t1; + CREATE TABLE t0(x COLLATE NOCASE); + CREATE INDEX t0x ON t0(x); + CREATE TABLE t1(y); + INSERT INTO t0 VALUES('a'); + INSERT INTO t1 VALUES('AB'); + SELECT count(*) FROM t0, t1 WHERE (y BETWEEN 1 AND x) OR (x>=y AND x); + SELECT count(*) FROM t0, t1 WHERE (x>=y AND x) OR (y BETWEEN 1 AND x); +} {1 1} + + finish_test -- 2.47.3