From 4bc1cc18476aaa674f8a24f859e1ed754c365505 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 13 Oct 2022 21:08:34 +0000 Subject: [PATCH 1/9] This experimental branch attempts to use columns for an index-on-expression in place of the expression that is being indexed. This particular check-in mostly works, but there are still issues. FossilOrigin-Name: 2e8d4fd4cfd9e82f33c707ba246fe2bb3ca01762cf5ac5905058fbc7adf0abe7 --- manifest | 31 ++++++++++++++++------------- manifest.uuid | 2 +- src/analyze.c | 1 + src/build.c | 1 + src/expr.c | 28 ++++++++++++++++++++++++++ src/insert.c | 1 + src/sqliteInt.h | 20 +++++++++++++++++++ src/upsert.c | 1 + src/where.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ src/whereexpr.c | 1 + 10 files changed, 123 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 13be78b776..f752561d83 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sthe\srest\sof\stesting1.js\sinto\stester1.js\sand\seliminate\sthe\sdependency\son\sjaccwabyt_test.c.\sExtend\sthe\slist\sof\sdefault\sconfig-related\s#defines\sin\ssqlite3-wasm.c\sand\sreorganize\sthem\sfor\smaintainability. -D 2022-10-13T16:48:35.302 +C This\sexperimental\sbranch\sattempts\sto\suse\scolumns\sfor\san\sindex-on-expression\nin\splace\sof\sthe\sexpression\sthat\sis\sbeing\sindexed.\s\sThis\sparticular\scheck-in\nmostly\sworks,\sbut\sthere\sare\sstill\sissues. +D 2022-10-13T21:08:34.457 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -550,7 +550,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2 F src/alter.c 0390ca1d69ec3626cfa9f153114b7ab233e6b2bada6a9eb91361ed385fe90deb -F src/analyze.c aabdf3769c7fd9954a8ec508eb7041ae174b66f88d12c47199fabbea9a646467 +F src/analyze.c d2fce73f6a024897593012c6ca25368629fa4aeb49960d88a52fac664582e483 F src/attach.c 4431f82f0247bf3aaf91589acafdff77d1882235c95407b36da1585c765fbbc8 F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7 @@ -559,7 +559,7 @@ F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca F src/btree.c 74fc5f6a0577df703d6f98d0c51ee0d8d91d22dbc0ba86e42e056517e2b45576 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e -F src/build.c 6e3ee380a4f0ff95de4b53bf510f66600cff08e4e04b92e95fae789072563f8f +F src/build.c e9b3adf21cdae3c9ca9450ee8463f2094f133c23734b81fd371f23b3d5d345ca F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 428b47a2548c7c2c2f885189b42fdcc178fb03c276a2d58b3008b10da29373d5 @@ -567,7 +567,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c d199850a925665df7f8ac29fa938909f65a2bd32354aa206aa8c25fc74ff3d3d +F src/expr.c b60036e4bb9080c741a970df3b3cfffc6292aadec3670b7b04bfae6f662ff245 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c 8f72e88cccdee22185133c10f96ccd61dc34c5ea4b1fa9a73c237ef59b2e64f1 @@ -576,7 +576,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c aea5361767817f917b0f0f647a1f0b1621bd858938ae6ae545c3b6b9814b798f +F src/insert.c b972b1642cd0f7d5ae4964d713b65158a7bfa6a6e8786a9e8e57bd9c0b4a896d F src/json.c 7749b98c62f691697c7ee536b570c744c0583cab4a89200fdd0fc2aa8cc8cbd6 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 853385cc7a604157e137585097949252d5d0c731768e16b044608e5c95c3614b @@ -622,7 +622,7 @@ F src/shell.c.in 2915eaf22bda89ad6533851a051de4773c249185360fe1fc7b4477b8f9063b2 F src/sqlite.h.in d9c8a6243fc0a1c270d69db33758e34b810af3462f9bc5b4af113b347e07c69d F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 5336beea1868d99d2f62e628dbea55e97267dbff8193291ab175e960c5df9141 -F src/sqliteInt.h d15694b228fe5082587e13ac14f3e449621a5fe6d5933f5dee6e3c9491260da3 +F src/sqliteInt.h a856afa8ff20886d1b0c668b9e3c62daf7875989a1db79e60f121778d48015e1 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -685,7 +685,7 @@ F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082 F src/treeview.c 07787f67cd297a6d09d04b8d70c06769c60c9c1d9080378f93929c16f8fd3298 F src/trigger.c 4163ada044af89d51caba1cb713a73165347b2ec05fe84a283737c134d61fcd5 F src/update.c 5b0302c47cf31b533d5dff04c497ca1d8b9d89c39727e633fbe7b882fd5ac5aa -F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 +F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f F src/vacuum.c bb346170b0b54c6683bba4a5983aea40485597fdf605c87ec8bc2e199fe88cd8 @@ -704,10 +704,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 63e712bcad47f70e94c2150976cd7da5040933699e3938d4189d064acbe40891 +F src/where.c 5cd2a96f99841e0ba3e5564d53b5ad397d3e8a42ce6e4694cd332da4e2c527f1 F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c bb88be457df3a6a01c844074ab79a9ba74279e73185f1362383aa697e3cae5dc -F src/whereexpr.c 55a39f42aaf982574fbf52906371a84cceed98a994422198dfd03db4fce4cc46 +F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 F src/window.c 928e215840e2f2d9a2746e018c9643ef42c66c4ab6630ef0df7fa388fa145e86 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -2031,8 +2031,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 cb94350185f555c333b628ee846c47bcc9df5f76bb82de569b8322f30dbbe1bc -R 32dab828066657d904ede486bb592456 -U stephan -Z 3fd1b23c49b42c2df54d60ffd9b89d7f +P 4e2a8aff2dd4b6e148f45184e2523ebe47815257eca97fa3d32bcbf9625f0def +R 6b28e91c7f03fb2da80daeebeb46b73a +T *branch * index-expr-opt +T *sym-index-expr-opt * +T -sym-trunk * +U drh +Z 4c1c25db22a8599a4330b36a4516d3d7 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 7e72bfdd21..c689c214d4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e2a8aff2dd4b6e148f45184e2523ebe47815257eca97fa3d32bcbf9625f0def \ No newline at end of file +2e8d4fd4cfd9e82f33c707ba246fe2bb3ca01762cf5ac5905058fbc7adf0abe7 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 39009899ab..8562b9d7f1 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -953,6 +953,7 @@ static void analyzeVdbeCommentIndexWithColumnName( if( NEVER(i==XN_ROWID) ){ VdbeComment((v,"%s.rowid",pIdx->zName)); }else if( i==XN_EXPR ){ + assert( pIdx->bHasExpr ); VdbeComment((v,"%s.expr(%d)",pIdx->zName, k)); }else{ VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName)); diff --git a/src/build.c b/src/build.c index be6b01eb08..502826bfc8 100644 --- a/src/build.c +++ b/src/build.c @@ -4192,6 +4192,7 @@ void sqlite3CreateIndex( j = XN_EXPR; pIndex->aiColumn[i] = XN_EXPR; pIndex->uniqNotNull = 0; + pIndex->bHasExpr = 1; }else{ j = pCExpr->iColumn; assert( j<=0x7fff ); diff --git a/src/expr.c b/src/expr.c index bceb5efb08..3630b47aa8 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4043,6 +4043,26 @@ static int exprCodeInlineFunction( return target; } +/* +** Check to see if pExpr is one of the indexed expression on pParse->pIdxExpr. +** If it is, then resolve the expression by reading from the index and +** return the register into which the value has been read. If there is +** no match, return negative. +*/ +static SQLITE_NOINLINE int sqlite3ExprIndexLookup( + Parse *pParse, /* The parsing context */ + Expr *pExpr, /* The expression to potentially bypass */ + int target /* Where to store the result of the expression */ +){ + IndexExpr *p; + for(p=pParse->pIdxExpr; p; p=p->pIENext){ + if( sqlite3ExprCompare(0, pExpr, p->pExpr, p->iDataCur)!=0 ) continue; + sqlite3VdbeAddOp3(pParse->pVdbe, OP_Column, p->iIdxCur, p->iIdxCol, target); + return target; + } + return -1; /* Not found */ +} + /* ** Generate code into the current Vdbe to evaluate the given @@ -4068,6 +4088,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( target>0 && target<=pParse->nMem ); assert( v!=0 ); + if( pParse->pIdxExpr!=0 + && pExpr!=0 + && !ExprHasProperty(pExpr, EP_Leaf) + && (r1 = sqlite3ExprIndexLookup(pParse, pExpr, target))>=0 + ){ + return r1; + } + expr_code_doover: if( pExpr==0 ){ op = TK_NULL; diff --git a/src/insert.c b/src/insert.c index 6c71391a1b..3e0d696d74 100644 --- a/src/insert.c +++ b/src/insert.c @@ -96,6 +96,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ aff = SQLITE_AFF_INTEGER; }else{ assert( x==XN_EXPR ); + assert( pIdx->bHasExpr ); assert( pIdx->aColExpr!=0 ); aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6f1109f2f6..caf7610adb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1189,6 +1189,7 @@ typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; +typedef struct IndexExpr IndexExpr; typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; @@ -2616,6 +2617,7 @@ struct Index { unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ + unsigned bHasExpr:1; /* This is an index on an expression */ #ifdef SQLITE_ENABLE_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ @@ -3563,6 +3565,23 @@ struct TriggerPrg { # define DbMaskNonZero(M) (M)!=0 #endif +/* +** If there is an index on an expression in scope such that the value +** of the expression pExpr can be read out of the index with cursor iCur +** at column iCol, then an instance of this object records that fact. +** +** A linked list of these objects is attached to Parse and records all +** expressions that can be short-circuited by extracting a valid from +** an index. +*/ +struct IndexExpr { + Expr *pExpr; /* The expression contained in the index */ + int iDataCur; /* The data cursor associated with the index */ + int iIdxCur; /* The index cursor */ + int iIdxCol; /* The column of the index that contains pExpr */ + IndexExpr *pIENext; /* Next in a list of all indexed expressions */ +}; + /* ** An instance of the ParseCleanup object specifies an operation that ** should be performed after parsing to deallocation resources obtained @@ -3621,6 +3640,7 @@ struct Parse { int nLabelAlloc; /* Number of slots in aLabel */ int *aLabel; /* Space to hold the labels */ ExprList *pConstExpr;/* Constant expressions */ + IndexExpr *pIdxExpr; /* List of all expression in active indexes */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ diff --git a/src/upsert.c b/src/upsert.c index fb6c7c0c07..85994020cf 100644 --- a/src/upsert.c +++ b/src/upsert.c @@ -166,6 +166,7 @@ int sqlite3UpsertAnalyzeTarget( if( pIdx->aiColumn[ii]==XN_EXPR ){ assert( pIdx->aColExpr!=0 ); assert( pIdx->aColExpr->nExpr>ii ); + assert( pIdx->bHasExpr ); pExpr = pIdx->aColExpr->a[ii].pExpr; if( pExpr->op!=TK_COLLATE ){ sCol[0].pLeft = pExpr; diff --git a/src/where.c b/src/where.c index b0c0ea7d4e..220ea5139d 100644 --- a/src/where.c +++ b/src/where.c @@ -5383,6 +5383,55 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( } } +/* +** This is an sqlite3ParserAddCleanup() callback that is invoked to +** free the Parse->pIdxExpr list when the Parse object is destroyed. +*/ +static void whereIndexExprCleanup(sqlite3 *db, void *pObject){ + Parse *pParse = (Parse*)pObject; + while( pParse->pIdxExpr!=0 ){ + IndexExpr *p = pParse->pIdxExpr; + pParse->pIdxExpr = p->pIENext; + sqlite3ExprDelete(db, p->pExpr); + sqlite3DbFreeNN(db, p); + } +} + +/* +** The index pIdx is used by a query and contains one or more expressions. +** In other words pIdx is an index on an expression. iIdxCur is the cursor +** number for the index and iDataCur is the cursor number for the corresponding +** table. +** +** This routine adds IndexExpr entries to the Parse->pIdxExpr field for +** each of the expressions in the index so that the expression code generator +** will know to replace occurrences of the indexed expression with +** references to the corresponding column of the index. +*/ +static SQLITE_NOINLINE void whereAddIndexExpr( + Parse *pParse, /* Add IndexExpr entries to pParse->pIdxExpr */ + Index *pIdx, /* The index-on-expression that contains the expressions */ + int iIdxCur, /* Cursor number for pIdx */ + int iDataCur /* Cursor for the corresponding table */ +){ + int i; + IndexExpr *p; + for(i=0; inColumn; i++){ + if( pIdx->aiColumn[i]!=XN_EXPR ) continue; + p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexExpr)); + if( p==0 ) break; + p->pIENext = pParse->pIdxExpr; + p->pExpr = sqlite3ExprDup(pParse->db, pIdx->aColExpr->a[i].pExpr, 0); + p->iDataCur = iDataCur; + p->iIdxCur = iIdxCur; + p->iIdxCol = i; + pParse->pIdxExpr = p; + if( p->pIENext==0 ){ + sqlite3ParserAddCleanup(pParse, whereIndexExprCleanup, pParse); + } + } +} + /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains @@ -5928,6 +5977,9 @@ WhereInfo *sqlite3WhereBegin( op = OP_ReopenIdx; }else{ iIndexCur = pParse->nTab++; + if( pIx->bHasExpr ){ + whereAddIndexExpr(pParse, pIx, iIndexCur, pTabItem->iCursor); + } } pLevel->iIdxCur = iIndexCur; assert( pIx!=0 ); diff --git a/src/whereexpr.c b/src/whereexpr.c index 8c9233ebd3..20e569642a 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -989,6 +989,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2( if( pIdx->aColExpr==0 ) continue; for(i=0; inKeyCol; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; + assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ aiCurCol[0] = iCur; aiCurCol[1] = XN_EXPR; From 859434d049a41edd3eb961b85b1b930cebac6540 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 14 Oct 2022 02:00:54 +0000 Subject: [PATCH 2/9] Cancel IndexExpr objects when they go out of scope. FossilOrigin-Name: 0963519371bb7ac02adb323430855760fb9b82a23745e47c504aaf393d22ac34 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/where.c | 11 +++++++++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index f752561d83..573214d62d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C This\sexperimental\sbranch\sattempts\sto\suse\scolumns\sfor\san\sindex-on-expression\nin\splace\sof\sthe\sexpression\sthat\sis\sbeing\sindexed.\s\sThis\sparticular\scheck-in\nmostly\sworks,\sbut\sthere\sare\sstill\sissues. -D 2022-10-13T21:08:34.457 +C Cancel\sIndexExpr\sobjects\swhen\sthey\sgo\sout\sof\sscope. +D 2022-10-14T02:00:54.507 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -704,7 +704,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 5cd2a96f99841e0ba3e5564d53b5ad397d3e8a42ce6e4694cd332da4e2c527f1 +F src/where.c 39889861616d7751efacb9e5aa84ec5635dbf12a137725f57aa25fc6b622e15c F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c bb88be457df3a6a01c844074ab79a9ba74279e73185f1362383aa697e3cae5dc F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 @@ -2031,11 +2031,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4e2a8aff2dd4b6e148f45184e2523ebe47815257eca97fa3d32bcbf9625f0def -R 6b28e91c7f03fb2da80daeebeb46b73a -T *branch * index-expr-opt -T *sym-index-expr-opt * -T -sym-trunk * +P 2e8d4fd4cfd9e82f33c707ba246fe2bb3ca01762cf5ac5905058fbc7adf0abe7 +R 6e639b412a6a288ed64157bd3e723cf0 U drh -Z 4c1c25db22a8599a4330b36a4516d3d7 +Z c5e6e161a1559a577698a45d0fdb903e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c689c214d4..78c84b6668 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e8d4fd4cfd9e82f33c707ba246fe2bb3ca01762cf5ac5905058fbc7adf0abe7 \ No newline at end of file +0963519371bb7ac02adb323430855760fb9b82a23745e47c504aaf393d22ac34 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 220ea5139d..0bba48883e 100644 --- a/src/where.c +++ b/src/where.c @@ -6376,6 +6376,17 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ }else{ last = pWInfo->iEndWhere; } + if( pIdx->bHasExpr ){ + IndexExpr *p = pParse->pIdxExpr; + while( p ){ + if( p->iIdxCur==pLevel->iIdxCur ){ + p->iDataCur = -1; + p->iIdxCur = -1; + p->pExpr->op = TK_ILLEGAL; + } + p = p->pIENext; + } + } k = pLevel->addrBody + 1; #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeAddopTrace ){ From 7a98937db2414e60a75991e637c0da6b87dd6336 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 15 Oct 2022 11:27:01 +0000 Subject: [PATCH 3/9] Only extract an expression from an index when the index is not a null row in an outer join. FossilOrigin-Name: 08b033c737d1a84859291f50e2985c9dad8d660a50185d55d3171165a8e08d4c --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 22 +++++++++++++++++++++- src/sqliteInt.h | 1 + src/where.c | 16 ++++++++-------- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index e6e98f6967..697406e18c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sfixes\sfrom\strunk. -D 2022-10-14T19:56:58.085 +C Only\sextract\san\sexpression\sfrom\san\sindex\swhen\sthe\sindex\sis\snot\sa\snull\srow\nin\san\souter\sjoin. +D 2022-10-15T11:27:01.598 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -567,7 +567,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c b60036e4bb9080c741a970df3b3cfffc6292aadec3670b7b04bfae6f662ff245 +F src/expr.c 8e260b0082700cb009238eb41cb28a8fce0290356b9fd25a72017c7fb48cb463 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c fe2a795ad647ce42054873ac91c43beb7b5d204892903a67f6e7e314379b9d4a @@ -622,7 +622,7 @@ F src/shell.c.in 2915eaf22bda89ad6533851a051de4773c249185360fe1fc7b4477b8f9063b2 F src/sqlite.h.in d9c8a6243fc0a1c270d69db33758e34b810af3462f9bc5b4af113b347e07c69d F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 5336beea1868d99d2f62e628dbea55e97267dbff8193291ab175e960c5df9141 -F src/sqliteInt.h a856afa8ff20886d1b0c668b9e3c62daf7875989a1db79e60f121778d48015e1 +F src/sqliteInt.h 30e6fdc957f09dbdbe1bcf73874263427bbd9a321cd2a583de74bdb030c9fa78 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -704,7 +704,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 39889861616d7751efacb9e5aa84ec5635dbf12a137725f57aa25fc6b622e15c +F src/where.c 8517a0ee4a3169368176fda649e2693ee013d7bdca72d485050e91cd640735f7 F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c bb88be457df3a6a01c844074ab79a9ba74279e73185f1362383aa697e3cae5dc F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 @@ -2031,8 +2031,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0963519371bb7ac02adb323430855760fb9b82a23745e47c504aaf393d22ac34 ed14863dd72e35fa3a23320c3d5a8166515faea39a555c28a27b2d35e701eac4 -R a9b714ce8ec9ca5df691ed405bb47472 +P 1cb65f36c3539302767f551ed53082f054666a7cb2696cef0990ab6747edbc52 +R b4967a409c773c44f7c239bcdd51f4f2 U drh -Z 5b8c2826f1d75c8b25b3831a35d10fbe +Z 10f741f9b8a389bcee87379894e97dc0 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2169956f70..8ced3b3665 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1cb65f36c3539302767f551ed53082f054666a7cb2696cef0990ab6747edbc52 \ No newline at end of file +08b033c737d1a84859291f50e2985c9dad8d660a50185d55d3171165a8e08d4c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 3630b47aa8..0ff364ddca 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4055,9 +4055,29 @@ static SQLITE_NOINLINE int sqlite3ExprIndexLookup( int target /* Where to store the result of the expression */ ){ IndexExpr *p; + Vdbe *v; for(p=pParse->pIdxExpr; p; p=p->pIENext){ + if( p->iDataCur<0 ) continue; if( sqlite3ExprCompare(0, pExpr, p->pExpr, p->iDataCur)!=0 ) continue; - sqlite3VdbeAddOp3(pParse->pVdbe, OP_Column, p->iIdxCur, p->iIdxCol, target); + v = pParse->pVdbe; + assert( v!=0 ); + if( p->bMaybeNullRow ){ + /* If the index is on a NULL row due to an outer join, then we + ** cannot extract the value from the index. The value must be + ** computed using the original expression. */ + int addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); + sqlite3VdbeGoto(v, 0); + p = pParse->pIdxExpr; + pParse->pIdxExpr = 0; + sqlite3ExprCode(pParse, pExpr, target); + pParse->pIdxExpr = p; + sqlite3VdbeJumpHere(v, addr+2); + }else{ + sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); + } return target; } return -1; /* Not found */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index caf7610adb..fffe981488 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3579,6 +3579,7 @@ struct IndexExpr { int iDataCur; /* The data cursor associated with the index */ int iIdxCur; /* The index cursor */ int iIdxCol; /* The column of the index that contains pExpr */ + u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ IndexExpr *pIENext; /* Next in a list of all indexed expressions */ }; diff --git a/src/where.c b/src/where.c index 0bba48883e..d43c2b2050 100644 --- a/src/where.c +++ b/src/where.c @@ -5409,22 +5409,23 @@ static void whereIndexExprCleanup(sqlite3 *db, void *pObject){ ** references to the corresponding column of the index. */ static SQLITE_NOINLINE void whereAddIndexExpr( - Parse *pParse, /* Add IndexExpr entries to pParse->pIdxExpr */ - Index *pIdx, /* The index-on-expression that contains the expressions */ - int iIdxCur, /* Cursor number for pIdx */ - int iDataCur /* Cursor for the corresponding table */ + Parse *pParse, /* Add IndexExpr entries to pParse->pIdxExpr */ + Index *pIdx, /* The index-on-expression that contains the expressions */ + int iIdxCur, /* Cursor number for pIdx */ + SrcItem *pTabItem /* The FROM clause entry for the table */ ){ int i; IndexExpr *p; for(i=0; inColumn; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; - p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexExpr)); + p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxExpr; p->pExpr = sqlite3ExprDup(pParse->db, pIdx->aColExpr->a[i].pExpr, 0); - p->iDataCur = iDataCur; + p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; + p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0; pParse->pIdxExpr = p; if( p->pIENext==0 ){ sqlite3ParserAddCleanup(pParse, whereIndexExprCleanup, pParse); @@ -5978,7 +5979,7 @@ WhereInfo *sqlite3WhereBegin( }else{ iIndexCur = pParse->nTab++; if( pIx->bHasExpr ){ - whereAddIndexExpr(pParse, pIx, iIndexCur, pTabItem->iCursor); + whereAddIndexExpr(pParse, pIx, iIndexCur, pTabItem); } } pLevel->iIdxCur = iIndexCur; @@ -6382,7 +6383,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ if( p->iIdxCur==pLevel->iIdxCur ){ p->iDataCur = -1; p->iIdxCur = -1; - p->pExpr->op = TK_ILLEGAL; } p = p->pIENext; } From f3adb7c43092d6af97a71e32e3cb4f714afe63ea Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 15 Oct 2022 12:01:40 +0000 Subject: [PATCH 4/9] Enable the index-on-expression optimization even when the expression is used as an argument to an aggregate function. FossilOrigin-Name: 462b3c7f39724dc814f55e7a225e7d0c48f81c524cdda797a66e9e198c35ce58 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 8 +++++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 697406e18c..af4a5b033e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Only\sextract\san\sexpression\sfrom\san\sindex\swhen\sthe\sindex\sis\snot\sa\snull\srow\nin\san\souter\sjoin. -D 2022-10-15T11:27:01.598 +C Enable\sthe\sindex-on-expression\soptimization\seven\swhen\sthe\sexpression\sis\nused\sas\san\sargument\sto\san\saggregate\sfunction. +D 2022-10-15T12:01:40.334 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -567,7 +567,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c 8e260b0082700cb009238eb41cb28a8fce0290356b9fd25a72017c7fb48cb463 +F src/expr.c 4a13a0e5c30be801b0adc295ef74e0f1aa8c041aefdcb5d0d424337ecefa2806 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c fe2a795ad647ce42054873ac91c43beb7b5d204892903a67f6e7e314379b9d4a @@ -2031,8 +2031,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1cb65f36c3539302767f551ed53082f054666a7cb2696cef0990ab6747edbc52 -R b4967a409c773c44f7c239bcdd51f4f2 +P 08b033c737d1a84859291f50e2985c9dad8d660a50185d55d3171165a8e08d4c +R a01b27e71bf0d1c060a37cd77d73f0f5 U drh -Z 10f741f9b8a389bcee87379894e97dc0 +Z 807c2ee5a3bf759378437d2cb1bbfe03 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8ced3b3665..ce95dd861c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -08b033c737d1a84859291f50e2985c9dad8d660a50185d55d3171165a8e08d4c \ No newline at end of file +462b3c7f39724dc814f55e7a225e7d0c48f81c524cdda797a66e9e198c35ce58 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 0ff364ddca..4bff004119 100644 --- a/src/expr.c +++ b/src/expr.c @@ -5618,7 +5618,13 @@ int sqlite3ExprCompare( if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){ return 1; } - return 2; + if( pA->op==TK_AGG_COLUMN && pB->op==TK_COLUMN + && pB->iTable<0 && pA->iTable==iTab + ){ + /* fall through */ + }else{ + return 2; + } } assert( !ExprHasProperty(pA, EP_IntValue) ); assert( !ExprHasProperty(pB, EP_IntValue) ); From 08535840c6a279a69a421a3be3b23fac355d80ac Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 17 Oct 2022 14:30:01 +0000 Subject: [PATCH 5/9] Get the indexed expression optimization working for virtual generated columns. FossilOrigin-Name: 8a510cb0880349370ad19b0852f270ca072bff7871f0dc272964af31c32a7c37 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 1 + src/where.c | 15 +++++++++++++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e2d3074db5..cf96d243eb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\senhancements\sinto\sindex-expr-opt\sbranch. -D 2022-10-17T14:29:04.031 +C Get\sthe\sindexed\sexpression\soptimization\sworking\sfor\svirtual\sgenerated\scolumns. +D 2022-10-17T14:30:01.606 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -561,7 +561,7 @@ F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca F src/btree.c 74fc5f6a0577df703d6f98d0c51ee0d8d91d22dbc0ba86e42e056517e2b45576 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e -F src/build.c e9b3adf21cdae3c9ca9450ee8463f2094f133c23734b81fd371f23b3d5d345ca +F src/build.c 13bcc04821ad260ef00d87e0704424e0ae4e6cd66c7e384b4cedb379a6cb738b F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 428b47a2548c7c2c2f885189b42fdcc178fb03c276a2d58b3008b10da29373d5 @@ -706,7 +706,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 a1c42bab8e840fa2cc90f6caf0f7133c35972e2f93b5899a90036d85e665c107 +F src/where.c 5d687c1f910b9b52284e0f7881a4d9b0ea9e9902b222dcc38e07a02ebeea3550 F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c 8ec5a413f12af06638dcca36d0954be2151eea6f293d3c67397cef6a90d6adf1 F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 @@ -2033,8 +2033,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 462b3c7f39724dc814f55e7a225e7d0c48f81c524cdda797a66e9e198c35ce58 45752471521f8d4a6cad4bce40f907018acd403ffd3b8170020c34e4e0b6b91b -R 6f3970b0a66900429c4532002ac9cf64 +P 56ef97e64efb84176df570819474901d492209ff80ce4355ff896dea9d2b8a51 +R de79047dd54e7d5b7736aaaf7de5ad42 U drh -Z f2ec0a1b95a0b19c496d987488a36bd5 +Z 08d869d5cc79e1976c4600c81c421785 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ff66fa27b1..8e5d83ed47 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -56ef97e64efb84176df570819474901d492209ff80ce4355ff896dea9d2b8a51 \ No newline at end of file +8a510cb0880349370ad19b0852f270ca072bff7871f0dc272964af31c32a7c37 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 502826bfc8..8578a71275 100644 --- a/src/build.c +++ b/src/build.c @@ -4204,6 +4204,7 @@ void sqlite3CreateIndex( } if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){ pIndex->bHasVCol = 1; + pIndex->bHasExpr = 1; } } pIndex->aiColumn[i] = (i16)j; diff --git a/src/where.c b/src/where.c index c5a6438791..32daa6e80e 100644 --- a/src/where.c +++ b/src/where.c @@ -5413,12 +5413,23 @@ static SQLITE_NOINLINE void whereAddIndexExpr( ){ int i; IndexExpr *p; + Table *pTab; + assert( pIdx->bHasExpr ); + pTab = pIdx->pTable; for(i=0; inColumn; i++){ - if( pIdx->aiColumn[i]!=XN_EXPR ) continue; + Expr *pExpr; + int j = pIdx->aiColumn[i]; + if( j==XN_EXPR ){ + pExpr = pIdx->aColExpr->a[i].pExpr; + }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ + pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); + }else{ + continue; + } p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxExpr; - p->pExpr = sqlite3ExprDup(pParse->db, pIdx->aColExpr->a[i].pExpr, 0); + p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; From e70d458340146bf20cc48224b8ddd9a18120d3c0 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 17 Oct 2022 14:46:39 +0000 Subject: [PATCH 6/9] Improved comments and function names. No logic changes. FossilOrigin-Name: 8f460b3b15bf4b88a224907d2f83e4ed6bf84d6b3f480008a1b187ea49c6ce1d --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 12 ++++++------ src/sqliteInt.h | 26 ++++++++++++++------------ src/where.c | 20 ++++++++++---------- 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index cf96d243eb..99d55d9f43 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\sthe\sindexed\sexpression\soptimization\sworking\sfor\svirtual\sgenerated\scolumns. -D 2022-10-17T14:30:01.606 +C Improved\scomments\sand\sfunction\snames.\s\sNo\slogic\schanges. +D 2022-10-17T14:46:39.146 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -569,7 +569,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c 4a13a0e5c30be801b0adc295ef74e0f1aa8c041aefdcb5d0d424337ecefa2806 +F src/expr.c ba67701bd7621ebba9c472fcc2dbd4f6444260530e694fa9d87281f9aedec93c F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c fe2a795ad647ce42054873ac91c43beb7b5d204892903a67f6e7e314379b9d4a @@ -624,7 +624,7 @@ F src/shell.c.in 2915eaf22bda89ad6533851a051de4773c249185360fe1fc7b4477b8f9063b2 F src/sqlite.h.in d9c8a6243fc0a1c270d69db33758e34b810af3462f9bc5b4af113b347e07c69d F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 5336beea1868d99d2f62e628dbea55e97267dbff8193291ab175e960c5df9141 -F src/sqliteInt.h 2a182a906ac614eb240a68abba8eaf4b018693fd2410ddaa133c08de00507e0a +F src/sqliteInt.h ed402c12a8b0920ae28cf79631d31490376ca3eed76b386b646712a1dda9e945 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -706,7 +706,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 5d687c1f910b9b52284e0f7881a4d9b0ea9e9902b222dcc38e07a02ebeea3550 +F src/where.c 3ab52180ad3a4eea7a2061bd804850f443298adbdc9264642d0a28affe26fb4c F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c 8ec5a413f12af06638dcca36d0954be2151eea6f293d3c67397cef6a90d6adf1 F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 @@ -2033,8 +2033,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 56ef97e64efb84176df570819474901d492209ff80ce4355ff896dea9d2b8a51 -R de79047dd54e7d5b7736aaaf7de5ad42 +P 8a510cb0880349370ad19b0852f270ca072bff7871f0dc272964af31c32a7c37 +R 2b7b8043aec8092eea598ea28e3a1178 U drh -Z 08d869d5cc79e1976c4600c81c421785 +Z e241a4932bd8de7b16432b2f0cb5fca6 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8e5d83ed47..6dd4259d17 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a510cb0880349370ad19b0852f270ca072bff7871f0dc272964af31c32a7c37 \ No newline at end of file +8f460b3b15bf4b88a224907d2f83e4ed6bf84d6b3f480008a1b187ea49c6ce1d \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 4bff004119..30f9031e21 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4044,17 +4044,17 @@ static int exprCodeInlineFunction( } /* -** Check to see if pExpr is one of the indexed expression on pParse->pIdxExpr. +** Check to see if pExpr is one of the indexed expressions on pParse->pIdxExpr. ** If it is, then resolve the expression by reading from the index and -** return the register into which the value has been read. If there is -** no match, return negative. +** return the register into which the value has been read. If pExpr is +** not an indexed expression, then return negative. */ -static SQLITE_NOINLINE int sqlite3ExprIndexLookup( +static SQLITE_NOINLINE int sqlite3IndexedExprLookup( Parse *pParse, /* The parsing context */ Expr *pExpr, /* The expression to potentially bypass */ int target /* Where to store the result of the expression */ ){ - IndexExpr *p; + IndexedExpr *p; Vdbe *v; for(p=pParse->pIdxExpr; p; p=p->pIENext){ if( p->iDataCur<0 ) continue; @@ -4111,7 +4111,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pParse->pIdxExpr!=0 && pExpr!=0 && !ExprHasProperty(pExpr, EP_Leaf) - && (r1 = sqlite3ExprIndexLookup(pParse, pExpr, target))>=0 + && (r1 = sqlite3IndexedExprLookup(pParse, pExpr, target))>=0 ){ return r1; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8b9bdf474a..0e02db8cc8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1189,7 +1189,7 @@ typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; -typedef struct IndexExpr IndexExpr; +typedef struct IndexedExpr IndexedExpr; typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; @@ -2617,7 +2617,8 @@ struct Index { unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ - unsigned bHasExpr:1; /* This is an index on an expression */ + unsigned bHasExpr:1; /* Index contains an expression, either a literal + ** expression, or a reference to a VIRTUAL column */ #ifdef SQLITE_ENABLE_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ @@ -3566,21 +3567,22 @@ struct TriggerPrg { #endif /* -** If there is an index on an expression in scope such that the value -** of the expression pExpr can be read out of the index with cursor iCur -** at column iCol, then an instance of this object records that fact. +** For each index X that has as one of its arguments either an expression +** or the name of a virtual generated column, and if X is in scope such that +** the value of the expression can simply be read from the index, then +** there is an instance of this object on the Parse.pIdxExpr list. ** -** A linked list of these objects is attached to Parse and records all -** expressions that can be short-circuited by extracting a valid from -** an index. +** During code generation, while generating code to evaluate expressions, +** this list is consulted and if a matching expression is found, the value +** is read from the index rather than being recomputed. */ -struct IndexExpr { +struct IndexedExpr { Expr *pExpr; /* The expression contained in the index */ int iDataCur; /* The data cursor associated with the index */ int iIdxCur; /* The index cursor */ - int iIdxCol; /* The column of the index that contains pExpr */ + int iIdxCol; /* The index column that contains value of pExpr */ u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ - IndexExpr *pIENext; /* Next in a list of all indexed expressions */ + IndexedExpr *pIENext; /* Next in a list of all indexed expressions */ }; /* @@ -3641,7 +3643,7 @@ struct Parse { int nLabelAlloc; /* Number of slots in aLabel */ int *aLabel; /* Space to hold the labels */ ExprList *pConstExpr;/* Constant expressions */ - IndexExpr *pIdxExpr; /* List of all expression in active indexes */ + IndexedExpr *pIdxExpr;/* List of expressions used by active indexes */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ diff --git a/src/where.c b/src/where.c index 32daa6e80e..39bbf7d64c 100644 --- a/src/where.c +++ b/src/where.c @@ -5384,10 +5384,10 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( ** This is an sqlite3ParserAddCleanup() callback that is invoked to ** free the Parse->pIdxExpr list when the Parse object is destroyed. */ -static void whereIndexExprCleanup(sqlite3 *db, void *pObject){ +static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){ Parse *pParse = (Parse*)pObject; while( pParse->pIdxExpr!=0 ){ - IndexExpr *p = pParse->pIdxExpr; + IndexedExpr *p = pParse->pIdxExpr; pParse->pIdxExpr = p->pIENext; sqlite3ExprDelete(db, p->pExpr); sqlite3DbFreeNN(db, p); @@ -5400,19 +5400,19 @@ static void whereIndexExprCleanup(sqlite3 *db, void *pObject){ ** number for the index and iDataCur is the cursor number for the corresponding ** table. ** -** This routine adds IndexExpr entries to the Parse->pIdxExpr field for +** This routine adds IndexedExpr entries to the Parse->pIdxExpr field for ** each of the expressions in the index so that the expression code generator ** will know to replace occurrences of the indexed expression with ** references to the corresponding column of the index. */ -static SQLITE_NOINLINE void whereAddIndexExpr( - Parse *pParse, /* Add IndexExpr entries to pParse->pIdxExpr */ +static SQLITE_NOINLINE void whereAddIndexedExpr( + Parse *pParse, /* Add IndexedExpr entries to pParse->pIdxExpr */ Index *pIdx, /* The index-on-expression that contains the expressions */ int iIdxCur, /* Cursor number for pIdx */ SrcItem *pTabItem /* The FROM clause entry for the table */ ){ int i; - IndexExpr *p; + IndexedExpr *p; Table *pTab; assert( pIdx->bHasExpr ); pTab = pIdx->pTable; @@ -5426,7 +5426,7 @@ static SQLITE_NOINLINE void whereAddIndexExpr( }else{ continue; } - p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexExpr)); + p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxExpr; p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); @@ -5436,7 +5436,7 @@ static SQLITE_NOINLINE void whereAddIndexExpr( p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0; pParse->pIdxExpr = p; if( p->pIENext==0 ){ - sqlite3ParserAddCleanup(pParse, whereIndexExprCleanup, pParse); + sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse); } } } @@ -5987,7 +5987,7 @@ WhereInfo *sqlite3WhereBegin( }else{ iIndexCur = pParse->nTab++; if( pIx->bHasExpr ){ - whereAddIndexExpr(pParse, pIx, iIndexCur, pTabItem); + whereAddIndexedExpr(pParse, pIx, iIndexCur, pTabItem); } } pLevel->iIdxCur = iIndexCur; @@ -6386,7 +6386,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ last = pWInfo->iEndWhere; } if( pIdx->bHasExpr ){ - IndexExpr *p = pParse->pIdxExpr; + IndexedExpr *p = pParse->pIdxExpr; while( p ){ if( p->iIdxCur==pLevel->iIdxCur ){ p->iDataCur = -1; From a331cf7e5792949ada1371bf61fdbf3b26e9d8d5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 18 Oct 2022 16:47:41 +0000 Subject: [PATCH 7/9] Fix the indexed expression resolver for generated columns so that it picks the correct table in a self-join. FossilOrigin-Name: 54c3eb085aca92da2b819f3532ee4750b377265f7e1e914600ea3c3d535efe51 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 20 +++++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 7dd1de75d8..8307bc415b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\strunk\sfixes\sinto\sthe\sindex-expr-opt\sbranch. -D 2022-10-18T16:32:22.335 +C Fix\sthe\sindexed\sexpression\sresolver\sfor\sgenerated\scolumns\sso\sthat\sit\spicks\nthe\scorrect\stable\sin\sa\sself-join. +D 2022-10-18T16:47:41.814 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -571,7 +571,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c ba67701bd7621ebba9c472fcc2dbd4f6444260530e694fa9d87281f9aedec93c +F src/expr.c 74a947891247873696385bf910e60c60e50283bbc0e8ef90b571ac60bc4b6279 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c fe2a795ad647ce42054873ac91c43beb7b5d204892903a67f6e7e314379b9d4a @@ -2036,8 +2036,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c7b9cc645b394a1b638a9a13ca83d321215aaa78d69ca70c6baa0ee692ed21bf 740a2eb0928d54fdf735a8e573c6a61a34dbd295b46e5b6ef39e957fd2623293 -R f7f5f954c4cc82eef2f394d97ecd28bc +P 6198ab4b871c464448ae303072bde0a810cac566a516cc29b1bf806fbd0a6c7b +R 51dcaf4cc6cc82ca16d600c0c30b38d8 U drh -Z 298a7ba276579f138f35bb1c8d732eed +Z c6035e9224ad1746d908acc7b5320c40 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 52c2ac163e..9e3658c558 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6198ab4b871c464448ae303072bde0a810cac566a516cc29b1bf806fbd0a6c7b \ No newline at end of file +54c3eb085aca92da2b819f3532ee4750b377265f7e1e914600ea3c3d535efe51 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 30f9031e21..c2e399f119 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4057,8 +4057,13 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup( IndexedExpr *p; Vdbe *v; for(p=pParse->pIdxExpr; p; p=p->pIENext){ - if( p->iDataCur<0 ) continue; - if( sqlite3ExprCompare(0, pExpr, p->pExpr, p->iDataCur)!=0 ) continue; + int iDataCur = p->iDataCur; + if( iDataCur<0 ) continue; + if( pParse->iSelfTab ){ + if( p->iDataCur!=pParse->iSelfTab-1 ) continue; + iDataCur = -1; + } + if( sqlite3ExprCompare(0, pExpr, p->pExpr, iDataCur)!=0 ) continue; v = pParse->pVdbe; assert( v!=0 ); if( p->bMaybeNullRow ){ @@ -4108,17 +4113,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( target>0 && target<=pParse->nMem ); assert( v!=0 ); - if( pParse->pIdxExpr!=0 - && pExpr!=0 +expr_code_doover: + if( pExpr==0 ){ + op = TK_NULL; + }else if( pParse->pIdxExpr!=0 && !ExprHasProperty(pExpr, EP_Leaf) && (r1 = sqlite3IndexedExprLookup(pParse, pExpr, target))>=0 ){ return r1; - } - -expr_code_doover: - if( pExpr==0 ){ - op = TK_NULL; }else{ assert( !ExprHasVVAProperty(pExpr,EP_Immutable) ); op = pExpr->op; From 7a2a8cee5a8f8117a0960be062c3107900d335b2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 18 Oct 2022 20:27:02 +0000 Subject: [PATCH 8/9] Improved byte-code comments for the OP_Column opcodes used by the indexed expression optimization. FossilOrigin-Name: bf6d837fddbf74d5b3f40ad01ea4564edfac00b651d6f3f0e996cc5dc18bb06c --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 2 ++ src/sqliteInt.h | 3 +++ src/where.c | 3 +++ 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 8307bc415b..dbc666f750 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sindexed\sexpression\sresolver\sfor\sgenerated\scolumns\sso\sthat\sit\spicks\nthe\scorrect\stable\sin\sa\sself-join. -D 2022-10-18T16:47:41.814 +C Improved\sbyte-code\scomments\sfor\sthe\sOP_Column\sopcodes\sused\sby\sthe\nindexed\sexpression\soptimization. +D 2022-10-18T20:27:02.327 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -571,7 +571,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c 74a947891247873696385bf910e60c60e50283bbc0e8ef90b571ac60bc4b6279 +F src/expr.c 3ac1d9e87c018f804d10ab9ffa8bf55efef79c376e7ca90d21ac4ef67bfa8f25 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c fe2a795ad647ce42054873ac91c43beb7b5d204892903a67f6e7e314379b9d4a @@ -626,7 +626,7 @@ F src/shell.c.in a4c0754470d4fcc2c3da2f0cda0363cecf4a84273d3cc3865325c2df06d5e56 F src/sqlite.h.in d9c8a6243fc0a1c270d69db33758e34b810af3462f9bc5b4af113b347e07c69d F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 5336beea1868d99d2f62e628dbea55e97267dbff8193291ab175e960c5df9141 -F src/sqliteInt.h ed402c12a8b0920ae28cf79631d31490376ca3eed76b386b646712a1dda9e945 +F src/sqliteInt.h 872ab50cc285de11f7fdc0ce1f0481018f14905e4e0b75da43d8cba5a03b8d8d F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -708,7 +708,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 3ab52180ad3a4eea7a2061bd804850f443298adbdc9264642d0a28affe26fb4c +F src/where.c cd5b21856c18ccf739f8b2eb29a2eb97ee69cf6381b10b783a6a2a9f57b99125 F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c 8ec5a413f12af06638dcca36d0954be2151eea6f293d3c67397cef6a90d6adf1 F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 @@ -2036,8 +2036,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6198ab4b871c464448ae303072bde0a810cac566a516cc29b1bf806fbd0a6c7b -R 51dcaf4cc6cc82ca16d600c0c30b38d8 +P 54c3eb085aca92da2b819f3532ee4750b377265f7e1e914600ea3c3d535efe51 +R ae1b5d3a3c2ab2b867842bafa6837a36 U drh -Z c6035e9224ad1746d908acc7b5320c40 +Z cb3bd1c1a3ec2d75a54535d3d8da6ebd # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 9e3658c558..54e63697ea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54c3eb085aca92da2b819f3532ee4750b377265f7e1e914600ea3c3d535efe51 \ No newline at end of file +bf6d837fddbf74d5b3f40ad01ea4564edfac00b651d6f3f0e996cc5dc18bb06c \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index c2e399f119..1a743ee5ce 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4074,6 +4074,7 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup( sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); + VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); sqlite3VdbeGoto(v, 0); p = pParse->pIdxExpr; pParse->pIdxExpr = 0; @@ -4082,6 +4083,7 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup( sqlite3VdbeJumpHere(v, addr+2); }else{ sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); + VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); } return target; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0e02db8cc8..a437cc0d25 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3583,6 +3583,9 @@ struct IndexedExpr { int iIdxCol; /* The index column that contains value of pExpr */ u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ IndexedExpr *pIENext; /* Next in a list of all indexed expressions */ +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + const char *zIdxName; /* Name of index, used only for bytecode comments */ +#endif }; /* diff --git a/src/where.c b/src/where.c index 39bbf7d64c..dccf493873 100644 --- a/src/where.c +++ b/src/where.c @@ -5434,6 +5434,9 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( p->iIdxCur = iIdxCur; p->iIdxCol = i; p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0; +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + p->zIdxName = pIdx->zName; +#endif pParse->pIdxExpr = p; if( p->pIENext==0 ){ sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse); From 72ab36619233cdf216716f5f17541dfc78d60abd Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 18 Oct 2022 22:37:07 +0000 Subject: [PATCH 9/9] If a virtual column whose value is constant gets indexed, do not include that column in the IndexedExpr list. dbsqlfuzz 59ac17a99b9a5c4930ee71cc153c9428a0c0e794 FossilOrigin-Name: c21eb903f06a16d4fafa5f895be08414fa58e6a91c148030aec8676b40c2d66d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index dbc666f750..d02cffb63f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sbyte-code\scomments\sfor\sthe\sOP_Column\sopcodes\sused\sby\sthe\nindexed\sexpression\soptimization. -D 2022-10-18T20:27:02.327 +C If\sa\svirtual\scolumn\swhose\svalue\sis\sconstant\sgets\sindexed,\sdo\snot\sinclude\nthat\scolumn\sin\sthe\sIndexedExpr\slist.\ndbsqlfuzz\s59ac17a99b9a5c4930ee71cc153c9428a0c0e794 +D 2022-10-18T22:37:07.303 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -708,7 +708,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 cd5b21856c18ccf739f8b2eb29a2eb97ee69cf6381b10b783a6a2a9f57b99125 +F src/where.c 5dcd88d080ad302da4278f55acce12fd1c1f91eff2bcbfa2c0806d33fa230a5f F src/whereInt.h 70cd30de9ed784aa33fa6bd1245f060617de7a00d992469b6d8e419eed915743 F src/wherecode.c 8ec5a413f12af06638dcca36d0954be2151eea6f293d3c67397cef6a90d6adf1 F src/whereexpr.c bf8c155212c886621d71c951053660de6fcc4ee907b17aa02da0a96a39aa9405 @@ -2036,8 +2036,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 54c3eb085aca92da2b819f3532ee4750b377265f7e1e914600ea3c3d535efe51 -R ae1b5d3a3c2ab2b867842bafa6837a36 +P bf6d837fddbf74d5b3f40ad01ea4564edfac00b651d6f3f0e996cc5dc18bb06c +R 4b10826dbdabc43e45460aaf0b235a26 U drh -Z cb3bd1c1a3ec2d75a54535d3d8da6ebd +Z be3c5dec512d6ceddfe2e2950bc8e7bf # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 54e63697ea..5b7598c5ff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bf6d837fddbf74d5b3f40ad01ea4564edfac00b651d6f3f0e996cc5dc18bb06c \ No newline at end of file +c21eb903f06a16d4fafa5f895be08414fa58e6a91c148030aec8676b40c2d66d \ No newline at end of file diff --git a/src/where.c b/src/where.c index dccf493873..8c65dc7b02 100644 --- a/src/where.c +++ b/src/where.c @@ -5426,6 +5426,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr( }else{ continue; } + if( sqlite3ExprIsConstant(pExpr) ) continue; p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxExpr;