From aca19e19a8934b9d2d237d183b389dad5e519361 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 7 Apr 2017 19:41:31 +0000 Subject: [PATCH 1/3] Proof of concept for the ability to use the expression columns in an index on expressions in place of equivalent expressions in the result set or in the WHERE clause. This check-in compiles but is mostly untested. FossilOrigin-Name: a52ef2ad7c0e14b78b801f16a1f6ea8d8fa9ae5d7d810e18dd24c600b662a312 --- manifest | 29 ++++++++++++---------- manifest.uuid | 2 +- src/expr.c | 4 +++ src/select.c | 2 +- src/sqliteInt.h | 1 + src/where.c | 1 + src/whereInt.h | 1 + src/wherecode.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ tool/addopcodes.tcl | 1 + 9 files changed, 85 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 50c2d8faef..4c47ee7fcd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\s".lint\sfkey"\sshell\scommand\sfor\scases\swhere\sthe\schild\skey\sis\salso\san\nINTEGER\sPRIMARY\sKEY. -D 2017-04-06T14:56:26.887 +C Proof\sof\sconcept\sfor\sthe\sability\sto\suse\sthe\sexpression\scolumns\sin\san\sindex\non\sexpressions\sin\splace\sof\sequivalent\sexpressions\sin\sthe\sresult\sset\sor\sin\nthe\sWHERE\sclause.\s\sThis\scheck-in\scompiles\sbut\sis\smostly\suntested. +D 2017-04-07T19:41:31.032 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a @@ -354,7 +354,7 @@ F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c -F src/expr.c 6bce2cbdd822963cf28e782938a96274cc37f18ac28dec7a4e35ccac09f66ce8 +F src/expr.c 8fd6b7bc10c2c33e017b0f2715efdc83c01e348be27797022ed9eaa3002ca720 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174 @@ -401,12 +401,12 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c afcf31d8ed7c890328a31d3f350467ccd273af345b24562382b398d6d9cd0664 +F src/select.c b24e628a2b76800171f4c86e38b5d93e27f2c40e603b24733aa8e471029e6ecd F src/shell.c e9fede684f847402c0373fe5e270918e6ef47f51e57ba5aebff121d8c2bc1ea8 F src/sqlite.h.in ab77e511620eebbd4ed7e4f52fae697b6870dda66c945acd2d3066f99c98e17e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28 -F src/sqliteInt.h 6cf244eb06119b44e155717708e54f0638c35e9bd8ef59ea570eb1f093f0da44 +F src/sqliteInt.h 9affb53bb405dcea1d86e85198ebaf6232a684cc2b2af6b3c181869f1c8f3e93 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -482,9 +482,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71 F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791 -F src/where.c 49b48b720184fdde747c468d7270feeb1b88c6a71092cea3a1aa168dc8ac0b0f -F src/whereInt.h 2d50c2b74a33be44cb68fdecee30b4d93552f1f4 -F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04 +F src/where.c 1d14e18f32231fa7969e718e7b60ef749b0065e2a7e1b6b00883b20732d280f1 +F src/whereInt.h 7a21ef633e26acbf46df04add2eba6e0a2100c78dc5879049e93f981fc3344df +F src/wherecode.c 38d171e309c7b54d5bdc7d8b663ec16249ad8888e01a77f6c55e9350de8e8349 F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1482,7 +1482,7 @@ F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 -F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189 +F tool/addopcodes.tcl ffa614f3eac5bd6672a5ca7c936500645e01d3a9f8329ab7cbf86582dd17f936 F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x @@ -1570,7 +1570,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 327eff25ba2420267cc8dc49dd3c3aab45f4bf9e060d1ad480e25d016d21f3ba -R 260410c30d599e0993c58e23cef69640 -U dan -Z 25db1dc906fb1b522f7b655980ddd579 +P 48826b222c110a90996a84605318ea6b1e502b8c5129f4d561f8350dbdbcd264 +R c609ef75ab8f5bb5565771cdc08e2586 +T *branch * covering-index-on-expr +T *sym-covering-index-on-expr * +T -sym-trunk * +U drh +Z 9d990a9e03df0f0f8f16d32c22292949 diff --git a/manifest.uuid b/manifest.uuid index 3814e9cddf..26e5bb9e68 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -48826b222c110a90996a84605318ea6b1e502b8c5129f4d561f8350dbdbcd264 \ No newline at end of file +a52ef2ad7c0e14b78b801f16a1f6ea8d8fa9ae5d7d810e18dd24c600b662a312 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index e3db59732e..afdbbb1275 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3192,6 +3192,10 @@ void sqlite3ExprCodeGetColumnOfTable( int iCol, /* Index of the column to extract */ int regOut /* Extract the value into this register */ ){ + if( pTab==0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut); + return; + } if( iCol<0 || iCol==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); }else{ diff --git a/src/select.c b/src/select.c index 334307cce7..55d2584fbe 100644 --- a/src/select.c +++ b/src/select.c @@ -3147,7 +3147,7 @@ static void substSelect(Parse*, Select *, int, ExprList*, int); ** This routine is part of the flattening procedure. A subquery ** whose result set is defined by pEList appears as entry in the ** FROM clause of a SELECT such that the VDBE cursor assigned to that -** FORM clause entry is iTable. This routine make the necessary +** FORM clause entry is iTable. This routine makes the necessary ** changes to pExpr so that it refers directly to the source table ** of the subquery rather the result set of the subquery. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2b3c934ecd..40660aed99 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3324,6 +3324,7 @@ struct Walker { struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ + struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */ } u; }; diff --git a/src/where.c b/src/where.c index 5a0b35bdf1..38183d6849 100644 --- a/src/where.c +++ b/src/where.c @@ -4447,6 +4447,7 @@ WhereInfo *sqlite3WhereBegin( pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->pOrderBy = pOrderBy; + pWInfo->pWhere = pWhere; pWInfo->pResultSet = pResultSet; pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; pWInfo->nLevel = nTabList; diff --git a/src/whereInt.h b/src/whereInt.h index f065fae6ba..6bd4aab2b0 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -417,6 +417,7 @@ struct WhereInfo { SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set of the query */ + Expr *pWhere; /* The complete WHERE clause */ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ int iContinue; /* Jump here to continue with next record */ diff --git a/src/wherecode.c b/src/wherecode.c index 4fd5e16fac..bdf732755e 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1039,6 +1039,61 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ } } +#if 1 /* INDEXEXPRTRANS */ +typedef struct IdxExprTrans { + Expr *pIdxExpr; /* The index expression */ + int iTabCur; /* The cursor of the corresponding table */ + int iIdxCur; /* The cursor for the index */ + int iIdxCol; /* The column for the index */ +} IdxExprTrans; + +static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ + IdxExprTrans *pX = p->u.pIdxTrans; + if( sqlite3ExprCompare(pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + pExpr->op = TK_COLUMN; + pExpr->iTable = pX->iIdxCur; + pExpr->iColumn = pX->iIdxCol; + pExpr->pTab = 0; + return WRC_Prune; + }else{ + return WRC_Continue; + } +} + +/* +** For an indexes on expression X, locate every instance of expression X in pExpr +** and change that subexpression into a reference to the appropriate column of +** the index. +*/ +static void whereIndexExprTrans( + Index *pIdx, /* The Index */ + int iTabCur, /* Cursor of the table that is being indexed */ + int iIdxCur, /* Cursor of the index itself */ + WhereInfo *pWInfo /* Transform expressions in this WHERE clause */ +){ + int iIdxCol; /* Column number of the index */ + ExprList *aColExpr; /* Expressions that are indexed */ + Walker w; + IdxExprTrans x; + aColExpr = pIdx->aColExpr; + if( aColExpr==0 ) return; /* Not an index on expressions */ + memset(&w, 0, sizeof(w)); + w.xExprCallback = whereIndexExprTransNode; + w.u.pIdxTrans = &x; + x.iTabCur = iTabCur; + x.iIdxCur = iIdxCur; + for(iIdxCol=0; iIdxColnExpr; iIdxCol++){ + if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue; + assert( aColExpr->a[iIdxCol].pExpr!=0 ); + x.iIdxCol = iIdxCol; + x.pIdxExpr = aColExpr->a[iIdxCol].pExpr; + sqlite3WalkExpr(&w, pWInfo->pWhere); + sqlite3WalkExprList(&w, pWInfo->pOrderBy); + sqlite3WalkExprList(&w, pWInfo->pResultSet); + } +} +#endif + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -1620,6 +1675,10 @@ Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } +#if 1 /* INDEXEXPRTANS */ + whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); +#endif + /* Record the instruction used to terminate the loop. */ if( pLoop->wsFlags & WHERE_ONEROW ){ pLevel->op = OP_Noop; diff --git a/tool/addopcodes.tcl b/tool/addopcodes.tcl index a6c58f1a25..dc96f2cfbe 100644 --- a/tool/addopcodes.tcl +++ b/tool/addopcodes.tcl @@ -32,6 +32,7 @@ set extras { UNCLOSED_STRING FUNCTION COLUMN + IDXCOLUMN AGG_FUNCTION AGG_COLUMN UMINUS From f1824a77b0d68537831a8b82f08b1d27be389d75 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 7 Apr 2017 19:52:13 +0000 Subject: [PATCH 2/3] Remove an unused token type. FossilOrigin-Name: 13a422230dcf4a8a80434af97434d57e456dcaa6bf0c41e6859f37ded6fa96ca --- manifest | 15 ++++++--------- manifest.uuid | 2 +- tool/addopcodes.tcl | 1 - 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 4c47ee7fcd..99232c34c4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Proof\sof\sconcept\sfor\sthe\sability\sto\suse\sthe\sexpression\scolumns\sin\san\sindex\non\sexpressions\sin\splace\sof\sequivalent\sexpressions\sin\sthe\sresult\sset\sor\sin\nthe\sWHERE\sclause.\s\sThis\scheck-in\scompiles\sbut\sis\smostly\suntested. -D 2017-04-07T19:41:31.032 +C Remove\san\sunused\stoken\stype. +D 2017-04-07T19:52:13.781 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a @@ -1482,7 +1482,7 @@ F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 -F tool/addopcodes.tcl ffa614f3eac5bd6672a5ca7c936500645e01d3a9f8329ab7cbf86582dd17f936 +F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189 F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x @@ -1570,10 +1570,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 48826b222c110a90996a84605318ea6b1e502b8c5129f4d561f8350dbdbcd264 -R c609ef75ab8f5bb5565771cdc08e2586 -T *branch * covering-index-on-expr -T *sym-covering-index-on-expr * -T -sym-trunk * +P a52ef2ad7c0e14b78b801f16a1f6ea8d8fa9ae5d7d810e18dd24c600b662a312 +R ffc8fa52d9e0cf4a5ba4590fbfff02cc U drh -Z 9d990a9e03df0f0f8f16d32c22292949 +Z e6d170fd55537b8013050239f469d07c diff --git a/manifest.uuid b/manifest.uuid index 26e5bb9e68..4bd060a2aa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a52ef2ad7c0e14b78b801f16a1f6ea8d8fa9ae5d7d810e18dd24c600b662a312 \ No newline at end of file +13a422230dcf4a8a80434af97434d57e456dcaa6bf0c41e6859f37ded6fa96ca \ No newline at end of file diff --git a/tool/addopcodes.tcl b/tool/addopcodes.tcl index dc96f2cfbe..a6c58f1a25 100644 --- a/tool/addopcodes.tcl +++ b/tool/addopcodes.tcl @@ -32,7 +32,6 @@ set extras { UNCLOSED_STRING FUNCTION COLUMN - IDXCOLUMN AGG_FUNCTION AGG_COLUMN UMINUS From eac5fc047622aa8d72005b1b3f99968bd14c62e1 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 11 Apr 2017 01:01:27 +0000 Subject: [PATCH 3/3] Improved comments. Fix a problem when an indexed expression is used in an ORDER BY clause. FossilOrigin-Name: c59eaf2b7cd2596733f349fc0fe979f71fd29bd73152a0c57066e0b69d5b7a4a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 27 +++++++++++++++++++-------- src/wherecode.c | 19 +++++++++++++++---- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index 45c8bc8233..09a2684db4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\schanges\sfrom\strunk. -D 2017-04-10T23:42:04.790 +C Improved\scomments.\s\sFix\sa\sproblem\swhen\san\sindexed\sexpression\sis\sused\sin\san\nORDER\sBY\sclause. +D 2017-04-11T01:01:27.332 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a @@ -401,7 +401,7 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c b24e628a2b76800171f4c86e38b5d93e27f2c40e603b24733aa8e471029e6ecd +F src/select.c 9228235fdefe6de138ac01c4c68d07fd95d78780ef85112a76e63e260a6f5897 F src/shell.c 70f4957b988572315e97c56941fdc81fd35907fee36b7b2e7be5ec4c7e9d065d F src/sqlite.h.in 40233103e3e4e10f8a63523498d0259d232e42aba478e2d3fb914799185aced6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -484,7 +484,7 @@ F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71 F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791 F src/where.c 1d14e18f32231fa7969e718e7b60ef749b0065e2a7e1b6b00883b20732d280f1 F src/whereInt.h 7a21ef633e26acbf46df04add2eba6e0a2100c78dc5879049e93f981fc3344df -F src/wherecode.c 38d171e309c7b54d5bdc7d8b663ec16249ad8888e01a77f6c55e9350de8e8349 +F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681 F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1570,7 +1570,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 13a422230dcf4a8a80434af97434d57e456dcaa6bf0c41e6859f37ded6fa96ca e052436d9f54b785facd661adc648512356b831c0547aa8f347ebf4bd8ef1254 -R a0a3c2f64645982d19356fee9ed1bee3 +P 8978465f335925378d3aa99df6190ce6a1ee6b130205ccc493f2399803844760 +R 1b0a9c05391f59848f876fd33c1876bb U drh -Z 41de53ab744a90538b62b8272746f983 +Z 21e604ae631dfab7b9082f6214d51689 diff --git a/manifest.uuid b/manifest.uuid index 68ee565894..f5bcb5c58b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8978465f335925378d3aa99df6190ce6a1ee6b130205ccc493f2399803844760 \ No newline at end of file +c59eaf2b7cd2596733f349fc0fe979f71fd29bd73152a0c57066e0b69d5b7a4a \ No newline at end of file diff --git a/src/select.c b/src/select.c index 55d2584fbe..10519b44ac 100644 --- a/src/select.c +++ b/src/select.c @@ -1530,6 +1530,7 @@ static void generateColumnTypes( NameContext sNC; sNC.pSrcList = pTabList; sNC.pParse = pParse; + sNC.pNext = 0; for(i=0; inExpr; i++){ Expr *p = pEList->a[i].pExpr; const char *zType; @@ -1554,6 +1555,19 @@ static void generateColumnTypes( #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } +/* +** Return the Table objecct in the SrcList that has cursor iCursor. +** Or return NULL if no such Table object exists in the SrcList. +*/ +static Table *tableWithCursor(SrcList *pList, int iCursor){ + int j; + for(j=0; jnSrc; j++){ + if( pList->a[j].iCursor==iCursor ) return pList->a[j].pTab; + } + return 0; +} + + /* ** Generate code that will tell the VDBE the names of columns ** in the result set. This information is used to provide the @@ -1565,7 +1579,8 @@ static void generateColumnNames( ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; - int i, j; + int i; + Table *pTab; sqlite3 *db = pParse->db; int fullNames, shortNames; @@ -1590,15 +1605,11 @@ static void generateColumnNames( if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); - }else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){ - Table *pTab; + }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) + && (pTab = tableWithCursor(pTabList, p->iTable))!=0 + ){ char *zCol; int iCol = p->iColumn; - for(j=0; ALWAYS(jnSrc); j++){ - if( pTabList->a[j].iCursor==p->iTable ) break; - } - assert( jnSrc ); - pTab = pTabList->a[j].pTab; if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); if( iCol<0 ){ diff --git a/src/wherecode.c b/src/wherecode.c index bdf732755e..d429fbb523 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1039,7 +1039,10 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ } } -#if 1 /* INDEXEXPRTRANS */ +/* An instance of the IdxExprTrans object carries information about a +** mapping from an expression on table columns into a column in an index +** down through the Walker. +*/ typedef struct IdxExprTrans { Expr *pIdxExpr; /* The index expression */ int iTabCur; /* The cursor of the corresponding table */ @@ -1047,6 +1050,12 @@ typedef struct IdxExprTrans { int iIdxCol; /* The column for the index */ } IdxExprTrans; +/* The walker node callback used to transform matching expressions into +** a reference to an index column for an index on an expression. +** +** If pExpr matches, then transform it into a reference to the index column +** that contains the value of pExpr. +*/ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ IdxExprTrans *pX = p->u.pIdxTrans; if( sqlite3ExprCompare(pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ @@ -1092,7 +1101,6 @@ static void whereIndexExprTrans( sqlite3WalkExprList(&w, pWInfo->pResultSet); } } -#endif /* ** Generate code for the start of the iLevel-th loop in the WHERE clause @@ -1675,9 +1683,12 @@ Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } -#if 1 /* INDEXEXPRTANS */ + /* If pIdx is an index on one or more expressions, then look through + ** all the expressions in pWInfo and try to transform matching expressions + ** into reference to index columns. + */ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); -#endif + /* Record the instruction used to terminate the loop. */ if( pLoop->wsFlags & WHERE_ONEROW ){