From: drh <> Date: Thu, 3 Nov 2022 21:08:56 +0000 (+0000) Subject: Experimental changes that try to identify indexes as covering when they contain X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Findexed-expr-exp;p=thirdparty%2Fsqlite.git Experimental changes that try to identify indexes as covering when they contain expressions which do cover all data uses. This check-in does not work, because the AggInfo object might still refer to individual columns. The purpose of this check-in is to preserve the idea. I might come back to it later. FossilOrigin-Name: 018914a5a1dbf09307db3f85627f136fa011ab58641796471f5700937bd69bb6 --- diff --git a/manifest b/manifest index 2443057143..e015f63d16 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\sbuild\scleanups\sand\sfix\sa\sharmless\srace\scondition\sin\sthe\sOPFS\spart\sof\stester1.js. -D 2022-11-02T14:08:59.340 +C Experimental\schanges\sthat\stry\sto\sidentify\sindexes\sas\scovering\swhen\sthey\scontain\nexpressions\swhich\sdo\scover\sall\sdata\suses.\s\sThis\scheck-in\sdoes\snot\swork,\sbecause\nthe\sAggInfo\sobject\smight\sstill\srefer\sto\sindividual\scolumns.\s\sThe\spurpose\sof\nthis\scheck-in\sis\sto\spreserve\sthe\sidea.\s\sI\smight\scome\sback\sto\sit\slater. +D 2022-11-03T21:08:56.993 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -723,7 +723,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 1ef5aae7fac877057b9f360f06b26d4275888460d8fb6e92bbb9e70e07afe946 +F src/where.c 5188da8bcc2fd5988d64c37eb69e0a0ae44d4b9798c4c7d31074434961f907a6 F src/whereInt.h df0c79388c0b71b4a91f480d02791679fe0345d40410435c541c8893e95a4d3f F src/wherecode.c 133a94f82858787217d073143617df19e4a6a7d0b771a1519f957608109ad5a5 F src/whereexpr.c 05295b44b54eea76d1ba766f0908928d0e20e990c249344c9521454d3d09c7ae @@ -2054,8 +2054,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f6fa0cffa921ccde8910e7fa4a63c2e4ef8ddb376c8ce99e436b27ac332c4498 -R 49cc6fc37416a3ba7fdfd0b20ce15895 -U stephan -Z b66cc4ccdf23cf485ede2fda7e429a86 +P 70ee6ee014bc4e2c1daa9b4a8909cf76ccecf32de1eb39055f20d3d0b1daa1bd +R 1dc6261e5b309b19594c2d2789301577 +T *branch * indexed-expr-exp +T *sym-indexed-expr-exp * +T -sym-trunk * +U drh +Z 39e597a6456d4496ffa146482c09b77b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f545a72735..64c1e62563 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70ee6ee014bc4e2c1daa9b4a8909cf76ccecf32de1eb39055f20d3d0b1daa1bd \ No newline at end of file +018914a5a1dbf09307db3f85627f136fa011ab58641796471f5700937bd69bb6 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 7ba72d2766..8991b5b914 100644 --- a/src/where.c +++ b/src/where.c @@ -3274,29 +3274,51 @@ static int whereIsCoveringIndexWalkCallback(Walker *pWalk, Expr *pExpr){ const Index *pIdx; /* The index of interest */ const i16 *aiColumn; /* Columns contained in the index */ u16 nColumn; /* Number of columns in the index */ - if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_AGG_COLUMN ) return WRC_Continue; - if( pExpr->iColumn<(BMS-1) ) return WRC_Continue; - if( pExpr->iTable!=pWalk->u.pCovIdxCk->iTabCur ) return WRC_Continue; - pIdx = pWalk->u.pCovIdxCk->pIdx; - aiColumn = pIdx->aiColumn; - nColumn = pIdx->nColumn; - for(i=0; iiColumn ) return WRC_Continue; - } - pWalk->eCode = 1; - return WRC_Abort; + if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ + if( pExpr->iTable!=pWalk->u.pCovIdxCk->iTabCur ){ + return WRC_Prune; + } + pIdx = pWalk->u.pCovIdxCk->pIdx; + aiColumn = pIdx->aiColumn; + nColumn = pIdx->nColumn; + for(i=0; iiColumn ){ + return WRC_Prune; + } + } + pWalk->eCode = 0; /* Not a covering index */ + return WRC_Abort; + }else if( pWalk->eCode==2 ){ + int iCur = pWalk->u.pCovIdxCk->iTabCur; + pIdx = pWalk->u.pCovIdxCk->pIdx; + assert( pIdx->aColExpr!=0 ); + aiColumn = pIdx->aiColumn; + nColumn = pIdx->nColumn; + for(i=0; iaColExpr->a[i].pExpr, iCur)==0 + ){ + return WRC_Prune; + } + } + } + return WRC_Continue; } /* -** pIdx is an index that covers all of the low-number columns used by -** pWInfo->pSelect (columns from 0 through 62). But there are columns -** in pWInfo->pSelect beyond 62. This routine tries to answer the question -** of whether pIdx covers *all* columns in the query. +** pIdx is an index for which we cannot determine is covering using +** the SrcItem.colUsed bitmask. We can't use colUsed to make the +** determination for either of these reasons: ** -** Return 0 if pIdx is a covering index. Return non-zero if pIdx is -** not a covering index or if we are unable to determine if pIdx is a -** covering index. +** * pIdx might contains indexed expressions. +** * SrcItem.colUsed indicates that columns beyond the 63rd column +** are used in the query, making bitmap tests ineffective. +** +** This routine does extra work to try to make a more accurate determination +** of whether or not pIdx is covering. Return 0 if we know that pIdx is +** covering. Return non-zero if pIdx is not covering or if unable to +** complete the analysis. ** ** This routine is an optimization. It is always safe to return non-zero. ** But returning zero when non-zero should have been returned can lead to @@ -3310,18 +3332,20 @@ static SQLITE_NOINLINE u32 whereIsCoveringIndex( int i; struct CoveringIndexCheck ck; Walker w; + int bHasHigh = 0; + int bHasExpr = 0; if( pWInfo->pSelect==0 ){ /* We don't have access to the full query, so we cannot check to see ** if pIdx is covering. Assume it is not. */ return 1; } for(i=0; inColumn; i++){ - if( pIdx->aiColumn[i]>=BMS-1 ) break; + if( pIdx->aiColumn[i]>=BMS-1 ) bHasHigh = 1; + if( pIdx->aiColumn[i]==XN_EXPR ) bHasExpr = 1; } - if( i>=pIdx->nColumn ){ - /* pIdx does not index any columns greater than 62, but we know from - ** colMask that columns greater than 62 are used, so this is not a - ** covering index */ + if( bHasHigh==0 && bHasExpr==0 ){ + /* pIdx does not index any columns greater than 62 nor any expression + ** columns. The colMask analysis must have been correct. Not covering. */ return 1; } ck.pIdx = pIdx; @@ -3330,9 +3354,9 @@ static SQLITE_NOINLINE u32 whereIsCoveringIndex( w.xExprCallback = whereIsCoveringIndexWalkCallback; w.xSelectCallback = sqlite3SelectWalkNoop; w.u.pCovIdxCk = &ck; - w.eCode = 0; + w.eCode = 1 + bHasExpr; sqlite3WalkSelect(&w, pWInfo->pSelect); - return w.eCode; + return w.eCode==0; } /* @@ -3552,7 +3576,7 @@ static int whereLoopAddBtree( m = 0; }else{ m = pSrc->colUsed & pProbe->colNotIdxed; - if( m==TOPBIT ){ + if( m==TOPBIT || (pProbe->bHasExpr && m!=0) ){ m = whereIsCoveringIndex(pWInfo, pProbe, pSrc->iCursor); } pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;