From: drh <> Date: Mon, 25 Apr 2022 21:21:08 +0000 (+0000) Subject: Fix a problem with automatic indexes introduced by X-Git-Tag: relese~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c2635c376e5ba6d1bd2192619c0fc0b0858a808;p=thirdparty%2Fsqlite.git Fix a problem with automatic indexes introduced by check-in [664b461bb5063d980] and reported by [forum:/forumpost/0d3200f4f3bcd3a3|forum post 0d3200f4f3bcd3a3]. FossilOrigin-Name: 4fbb9ffe72f112d5f3b02760759b90ef935ddff4089013caac3a9e222a98a304 --- diff --git a/manifest b/manifest index 9fc9bbf89c..47e3ebbab5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stwo\sminor\sproblems\sin\sthe\sJSON\sfunctions\sassociated\swith\sJSON\sPaths\nfor\sobject\slabels\sthat\srequire\squoting. -D 2022-04-04T15:26:31.562 +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-25T21:21:08.193 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -503,7 +503,7 @@ F src/date.c 15082566229d4b1e5f24fdb490bf9bcc68824b911d70e3573ef075a1b9e2d26f F src/dbpage.c 30ff075a9a9156bd2cccb5c1ea579f2afbaa64989648e8c9d72cb4a3417f5136 F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c b5f1716b4d723db48254ee0f896e362cd029e865e05414139ea7f539f3884e1d -F src/expr.c b90a029105a93a93a0ed5e5f8c5eaed8f19043a3b62e4c4d235a4611d9ada178 +F src/expr.c 7b9d66f012ba22bda14261c9a4d0600f4b800fad4cf5868f6a32355f037880cc F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 06e4ac33031b02dde7130c12e79cddf4dc5cfa72b23d8e63a3c26878fc9c1d3c F src/func.c a3407a6fbb0d4088d8d502e46f0ace63e0aeae7467ae23a9ca9815bbf9239761 @@ -552,12 +552,12 @@ F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35 +F src/select.c ba0cd3d264fa788c8d65f063d5ec3e1d65b0dac206c822a564a59ba550210cfc F src/shell.c.in ec4b952f7d9c02919e8e8394be16bcbff55c105fd080895602d10fc8fa5328b8 F src/sqlite.h.in b93deee892f1bc4030e5c8712df9e21d786a1bf8e921ab8dc987eaf1e44c676f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 -F src/sqliteInt.h e7b93bb693cb14259f6c3faadc6d7c824ff509aac673622a76c161a96c5872d0 +F src/sqliteInt.h 272c5ca0a16a1963c0c956524c615a27af57be950b97a395d39cb9fd9b31fc4e F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -639,7 +639,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 48d9836b7bdf301783719156fd50d45685a601605334035c559ed2d655df9fb6 +F src/where.c be30bf0151f5cc77b2d75a664f2ab60632974165ad2bab6df9deca2fc3284264 F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03 F src/wherecode.c 84be340684393248b9f3ecbce9b87c8a6f818149b52302702ea0b8d2a9d51faf F src/whereexpr.c 2a71f5491798460c9590317329234d332d9eb1717cba4f3403122189a75c465e @@ -704,7 +704,7 @@ F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39 -F test/autoindex1.test fe27af92eaf884bd9c38f94be3e8afa04ec494e5eefb189902026181a6175f5e +F test/autoindex1.test b2a87aca5c3717264ef431025c1eb855f6012c9694a3c85c678c762aa0dedf58 F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5 F test/autoindex4.test 75cb1191a552b8201351f5a50d160fcb9387a0fbbfb820c77798bfee7da3f8cf @@ -1944,10 +1944,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 336851b191fe79f0282148b5c42976df9d1ce584fc93e523bc1cd2cf0c2912e7 -Q +0fbbe7881cadf0b3c211653c7a0797e0a90c7c24da78ecc8a27140c05f89f2ed -Q +84fe95d2a5b4d232d657e3b8110027a698a9bcd597f205cc535cfa97bc299f21 -R c62f8acb3c31549a4432b90e0f84b6ae +P 4a1553b55f085163278866617deb26df12571c55fc650f8daa9392fd77c1eba9 +Q +134cfb18ff930e4bccc1a7412a02be353bf67c6d5080bc0673afaac81afa889c +R 27959e986f56e987013d5972ba41b5cb U drh -Z 7ff2484065ddf4d8eb92b028f33af26e +Z 26300eb0e00339270edd11685b01bb07 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bf9c69c1df..7f6492eabc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4a1553b55f085163278866617deb26df12571c55fc650f8daa9392fd77c1eba9 \ No newline at end of file +4fbb9ffe72f112d5f3b02760759b90ef935ddff4089013caac3a9e222a98a304 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 271f06bc6a..1ac5733146 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2284,6 +2284,38 @@ int sqlite3ExprIsTableConstant(Expr *p, int 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. +** +** (*) ** Not applicable to this branch ** +** +** (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_LEFT ){ + if( !ExprHasProperty(pExpr, EP_FromJoin) ) return 0; /* rule (4a) */ + if( pExpr->w.iRightJoinTable!=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(). diff --git a/src/select.c b/src/select.c index 6719d47471..d6d6097401 100644 --- a/src/select.c +++ b/src/select.c @@ -4822,8 +4822,7 @@ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ - int iCursor, /* Cursor number of the subquery */ - int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ + SrcItem *pSrc /* The subquery term of the outer FROM clause */ ){ Expr *pNew; int nChng = 0; @@ -4858,10 +4857,11 @@ static int pushDownWhereTerms( return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, - iCursor, isLeftJoin); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc); pWhere = pWhere->pLeft; } + +#if 0 /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */ if( isLeftJoin && (ExprHasProperty(pWhere,EP_FromJoin)==0 || pWhere->w.iRightJoinTable!=iCursor) @@ -4873,7 +4873,9 @@ static int pushDownWhereTerms( ){ return 0; /* restriction (5) */ } - if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ +#endif + + if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ @@ -4881,8 +4883,8 @@ static int pushDownWhereTerms( pNew = sqlite3ExprDup(pParse->db, pWhere, 0); unsetJoinExpr(pNew, -1); x.pParse = pParse; - x.iTable = iCursor; - x.iNewTable = iCursor; + x.iTable = pSrc->iCursor; + x.iNewTable = pSrc->iCursor; x.isLeftJoin = 0; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); @@ -6664,8 +6666,7 @@ int sqlite3Select( if( OptimizationEnabled(db, SQLITE_PushDown) && (pItem->fg.isCte==0 || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2)) - && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor, - (pItem->fg.jointype & JT_OUTER)!=0) + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem) ){ #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3f11f15715..78c16bea13 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4662,6 +4662,7 @@ int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); int sqlite3ExprIsTableConstant(Expr*,int); +int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*); #ifdef SQLITE_ENABLE_CURSOR_HINTS int sqlite3ExprContainsSubquery(Expr*); #endif diff --git a/src/where.c b/src/where.c index 1e5ac5b75d..3bd640cb21 100644 --- a/src/where.c +++ b/src/where.c @@ -808,8 +808,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex( ** WHERE clause (or the ON clause of a LEFT join) that constrain which ** rows of the target table (pSrc) that can be used. */ if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && ((pSrc->fg.jointype&JT_LEFT)==0 || ExprHasProperty(pExpr,EP_FromJoin)) - && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) + && sqlite3ExprIsTableConstraint(pExpr, pSrc) ){ pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); @@ -1048,7 +1047,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( for(pTerm=pWInfo->sWC.a; pTermpExpr; if( (pTerm->wtFlags & TERM_VIRTUAL)==0 - && sqlite3ExprIsTableConstant(pExpr, iCur) + && sqlite3ExprIsTableConstraint(pExpr, pItem) ){ sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); } diff --git a/test/autoindex1.test b/test/autoindex1.test index 6b437f1867..fac40f8d58 100644 --- a/test/autoindex1.test +++ b/test/autoindex1.test @@ -542,7 +542,23 @@ do_execsql_test autoindex1-1020 { SELECT count(*) FROM t11 LEFT JOIN t12 WHERE t12.y IS t11.w; } 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