Fix a problem with automatic indexes introduced by

check-in [664b461bb5063d980] and reported by
[forum:/forumpost/0d3200f4f3bcd3a3|forum post 0d3200f4f3bcd3a3].

FossilOrigin-Name: 7ca3456c00998a429418ff29cf251b381586b330b88344c94a40c5df0b71da85
This commit is contained in:
drh 2022-04-25 19:40:33 +00:00
parent 95fe38f2fc
commit a9cdb90421
7 changed files with 78 additions and 27 deletions

View File

@ -1,5 +1,5 @@
C Add\sa\snew\soptimizer\sdisabling\sbit\sto\sdisable\sjust\sthe\sUNION\sALL\sbranch\sof\sthe\nquery\sflattener. C Fix\sa\sproblem\swith\sautomatic\sindexes\sintroduced\sby\ncheck-in\s[664b461bb5063d980]\sand\sreported\sby\n[forum:/forumpost/0d3200f4f3bcd3a3|forum\spost\s0d3200f4f3bcd3a3].
D 2022-04-25T14:59:59.150 D 2022-04-25T19:40:33.982
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -504,7 +504,7 @@ F src/date.c 15082566229d4b1e5f24fdb490bf9bcc68824b911d70e3573ef075a1b9e2d26f
F src/dbpage.c 90661a87e1db8bfbc8d2ebbdcd3749651ddb287c555c07a28fb17c7c591ffb68 F src/dbpage.c 90661a87e1db8bfbc8d2ebbdcd3749651ddb287c555c07a28fb17c7c591ffb68
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c a8e844af211a48b13b5b358be77a12c860c6a557c21990ad51a548e2536500ce F src/delete.c a8e844af211a48b13b5b358be77a12c860c6a557c21990ad51a548e2536500ce
F src/expr.c 06dfbfb7f469c00eba3c8a7e282765969fe7c772f235a365f51bfffcaa69fe7f F src/expr.c 5d4178f8462ca55a38cefcfcdf9635030607e3532649c96de471afafeca732c4
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c d965ede15d8360c09ed59348940649ee647b192e784466837d7aefa836d1d91e F src/fkey.c d965ede15d8360c09ed59348940649ee647b192e784466837d7aefa836d1d91e
F src/func.c a3407a6fbb0d4088d8d502e46f0ace63e0aeae7467ae23a9ca9815bbf9239761 F src/func.c a3407a6fbb0d4088d8d502e46f0ace63e0aeae7467ae23a9ca9815bbf9239761
@ -553,12 +553,12 @@ F src/printf.c 512574910a45341c8ad244bd3d4939968ebdfde215645b676fff01cc46e90757
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c f72bb13359dd5a74d440df25f320dc2c1baff5cde4fc9f0d1bc3feba90b8932a F src/resolve.c f72bb13359dd5a74d440df25f320dc2c1baff5cde4fc9f0d1bc3feba90b8932a
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c ea203cd4f5d07443d7d25ae30fc0fb11b04ab9bd46a047ff5ebcb0abef63b4e9 F src/select.c e5772fb9c1b56a3e9ca688ea27303fc115d1cf336d68561ceee4145dfa2f36d9
F src/shell.c.in ae0a6fae983caac6f8c824733f0599dfdf7b3a7e8efdef3cb5e3ab2e457ffc35 F src/shell.c.in ae0a6fae983caac6f8c824733f0599dfdf7b3a7e8efdef3cb5e3ab2e457ffc35
F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17 F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e
F src/sqliteInt.h 2ed6fde4c3cd0438816f2b4597634067b11e430028b0e27b4be27736930d1739 F src/sqliteInt.h 11cd60560cd14bb6eecd04d244faf4c1895417b97d89e2f50833f83c4611588d
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4a3da6d77eeb3531cb0dbdf7047772a2a1b99f98c69e90ce009c75fe6328b2c0 F src/status.c 4a3da6d77eeb3531cb0dbdf7047772a2a1b99f98c69e90ce009c75fe6328b2c0
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@ -640,7 +640,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c bd4895fbb6ac9cc5b772d191b93dd5a240a505e3113be9aee0dc8c957568dd41 F src/where.c 43085b3a4ce2e56315fabb0b240a56e76667d9e03c79f287695bcae7b76152d5
F src/whereInt.h 4db5a877a9d1f38b5c928c1c84297c07f30b9a3bc1f5f66214cf1a8ef90a0556 F src/whereInt.h 4db5a877a9d1f38b5c928c1c84297c07f30b9a3bc1f5f66214cf1a8ef90a0556
F src/wherecode.c 55a33d9db1759970c30220904bcc628ba66a1ccb63b5437ef4642f7ea6267b03 F src/wherecode.c 55a33d9db1759970c30220904bcc628ba66a1ccb63b5437ef4642f7ea6267b03
F src/whereexpr.c 174d4ad5be165c610c907abb779ef4a97974d22b84e1ce7898d2d9f6947249e5 F src/whereexpr.c 174d4ad5be165c610c907abb779ef4a97974d22b84e1ce7898d2d9f6947249e5
@ -705,7 +705,7 @@ F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39 F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
F test/autoindex1.test 523b26034dc5e0c5ff0865055b4593f75863b82f17748dec9ca64bb8b267c502 F test/autoindex1.test cdc336e80cfd586c0e09426d58bec412db7527ca22dfabe88eab690e3acbb406
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5 F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
F test/autoindex4.test 5df39313526b6f22a26bd119bbd97ca69f28386ab3c671fc10568d921c41eb08 F test/autoindex4.test 5df39313526b6f22a26bd119bbd97ca69f28386ab3c671fc10568d921c41eb08
@ -1951,8 +1951,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 59789fe1e745bb6f81898176e7e9c6064ac9f4bbefb4dc3c8f3e4c1379568f69 P c0f9ebab5455d8541a562122d3270b95ce571c3fd870b0048dda2b036c2b66c0
R 5dab58ddb6f58a52bd1b258cb5165dfd R cb2c389ae944c4d6eaa6314dd1b0dc57
U drh U drh
Z 6423624c0497dbe7560341f194996237 Z 42d259eeea1f414b7f57e1057b3c3aee
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
c0f9ebab5455d8541a562122d3270b95ce571c3fd870b0048dda2b036c2b66c0 7ca3456c00998a429418ff29cf251b381586b330b88344c94a40c5df0b71da85

View File

@ -2296,6 +2296,42 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur); return exprIsConst(p, 3, iCur);
} }
/*
** Check pExpr to see if it is an invariant constraint on data source pSrc.
** This is an optimization. False negatives will perhaps cause slower
** queries, but false positives will yield incorrect answers. So when in
** double, return 0.
**
** To be an invariant constraint, the following must be true:
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2) pExpr cannot use subqueries or non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
(4b) and specifically the ON clause associated with the LEFT JOIN.
**
** (5) If pSrc is not the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
*/
int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){
if( pSrc->fg.jointype & JT_LTORJ ){
return 0; /* rule (3) */
}
if( pSrc->fg.jointype & JT_LEFT ){
if( !ExprHasProperty(pExpr, EP_FromJoin) ) return 0; /* rule (4a) */
if( pExpr->w.iJoin!=pSrc->iCursor ) return 0; /* rule (4b) */
}else{
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; /* rule (5) */
}
return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
}
/* /*
** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy(). ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().

View File

@ -4954,8 +4954,7 @@ static int pushDownWhereTerms(
Parse *pParse, /* Parse context (for malloc() and error reporting) */ Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */ Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor, /* Cursor number of the subquery */ SrcItem *pSrc /* The subquery term of the outer FROM clause */
int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */
){ ){
Expr *pNew; Expr *pNew;
int nChng = 0; int nChng = 0;
@ -4990,10 +4989,11 @@ static int pushDownWhereTerms(
return 0; /* restriction (3) */ return 0; /* restriction (3) */
} }
while( pWhere->op==TK_AND ){ while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc);
iCursor, isLeftJoin);
pWhere = pWhere->pLeft; pWhere = pWhere->pLeft;
} }
#if 0 /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */
if( isLeftJoin if( isLeftJoin
&& (ExprHasProperty(pWhere,EP_FromJoin)==0 && (ExprHasProperty(pWhere,EP_FromJoin)==0
|| pWhere->w.iJoin!=iCursor) || pWhere->w.iJoin!=iCursor)
@ -5005,7 +5005,9 @@ static int pushDownWhereTerms(
){ ){
return 0; /* restriction (5) */ return 0; /* restriction (5) */
} }
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ #endif
if( sqlite3ExprIsTableConstant(pWhere, pSrc->iCursor) ){
nChng++; nChng++;
pSubq->selFlags |= SF_PushDown; pSubq->selFlags |= SF_PushDown;
while( pSubq ){ while( pSubq ){
@ -5013,8 +5015,8 @@ static int pushDownWhereTerms(
pNew = sqlite3ExprDup(pParse->db, pWhere, 0); pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
unsetJoinExpr(pNew, -1); unsetJoinExpr(pNew, -1);
x.pParse = pParse; x.pParse = pParse;
x.iTable = iCursor; x.iTable = pSrc->iCursor;
x.iNewTable = iCursor; x.iNewTable = pSrc->iCursor;
x.isOuterJoin = 0; x.isOuterJoin = 0;
x.pEList = pSubq->pEList; x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew); pNew = substExpr(&x, pNew);
@ -6840,9 +6842,7 @@ int sqlite3Select(
if( OptimizationEnabled(db, SQLITE_PushDown) if( OptimizationEnabled(db, SQLITE_PushDown)
&& (pItem->fg.isCte==0 && (pItem->fg.isCte==0
|| (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2)) || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2))
&& (pItem->fg.jointype & JT_RIGHT)==0 && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem)
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
(pItem->fg.jointype & JT_OUTER)!=0)
){ ){
#if TREETRACE_ENABLED #if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100 ){ if( sqlite3TreeTrace & 0x100 ){

View File

@ -4752,6 +4752,7 @@ int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
int sqlite3ExprIsTableConstant(Expr*,int); int sqlite3ExprIsTableConstant(Expr*,int);
int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*);
#ifdef SQLITE_ENABLE_CURSOR_HINTS #ifdef SQLITE_ENABLE_CURSOR_HINTS
int sqlite3ExprContainsSubquery(Expr*); int sqlite3ExprContainsSubquery(Expr*);
#endif #endif

View File

@ -832,9 +832,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
** WHERE clause (or the ON clause of a LEFT join) that constrain which ** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */ ** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0 if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& ((pSrc->fg.jointype&(JT_LEFT|JT_LTORJ))==0 && sqlite3ExprIsTableConstraint(pExpr, pSrc)
|| ExprHasProperty(pExpr,EP_FromJoin))
&& sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor)
){ ){
pPartial = sqlite3ExprAnd(pParse, pPartial, pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0)); sqlite3ExprDup(pParse->db, pExpr, 0));
@ -1073,7 +1071,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){ for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr; Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0 if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsTableConstant(pExpr, iCur) && sqlite3ExprIsTableConstraint(pExpr, pItem)
){ ){
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
} }

View File

@ -542,7 +542,23 @@ do_execsql_test autoindex1-1020 {
SELECT count(*) FROM t11 LEFT JOIN t12 WHERE t12.y IS t11.w; SELECT count(*) FROM t11 LEFT JOIN t12 WHERE t12.y IS t11.w;
} 0 } 0
# 2022-04-25
# https://sqlite.org/forum/forumpost/0d3200f4f3bcd3a3
#
reset_db
do_execsql_test autoindex-1100 {
CREATE TABLE t1(a INT, b INT);
CREATE TABLE t2(c INT, d INT);
CREATE TABLE t3(e TEXT, f TEXT);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t2 VALUES(1, 2);
INSERT INTO t3 VALUES('abc', 'def');
} {}
do_execsql_test autoindex-1110 {
SELECT * FROM t1, t2 LEFT JOIN t3 ON (t2.d=1) WHERE t2.c = +t1.a;
} {1 1 1 2 {} {}}
do_execsql_test autoindex-1120 {
SELECT * FROM t1 LEFT JOIN t2 ON (t2.c=+t1.a) LEFT JOIN t3 ON (t2.d IS NULL);
} {1 1 1 2 {} {}}
finish_test finish_test