From: drh Date: Thu, 24 Sep 2015 18:47:59 +0000 (+0000) Subject: Enhance the query planner so that it is able to use indexed expressions X-Git-Tag: version-3.9.0~64 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dae26fe518c65f26e7d256a161acfe37910f897e;p=thirdparty%2Fsqlite.git Enhance the query planner so that it is able to use indexed expressions to help fulfill an ORDER BY clause. FossilOrigin-Name: 668fc1ebaf426f9eed3ed7865e41f1023dafebfb --- diff --git a/manifest b/manifest index cb00afceb9..e5079a39f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sover-length\ssource\scode\slines\sin\swhere.c.\s\sNo\slogic\schanges. -D 2015-09-24T17:38:01.215 +C Enhance\sthe\squery\splanner\sso\sthat\sit\sis\sable\sto\suse\sindexed\sexpressions\nto\shelp\sfulfill\san\sORDER\sBY\sclause. +D 2015-09-24T18:47:59.761 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c 6f7156dc7285c4ff4f625e4f4fee57a83f25f89c +F src/where.c 278073aabce8d2020d30dff2edb6fe9430e1762c F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -785,7 +785,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985 -F test/indexexpr1.test 203c83a05accf6f2b748834192f3564321b8c0d8 +F test/indexexpr1.test 4bce4e4b6b1a2d0c34e17d4e04f3957a3bcdc500 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c6ab807b72ddfc1462f61aa91442b6fac04ace8a -R 2adfc3245dccf622041366bbd2c07bc2 +P 1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 +R 292146e62fe1cf1653fb27c4bd570968 U drh -Z 1d5bb04c383d0f49d84249f8afd90c66 +Z 3832f12930eca538f34541b12960504f diff --git a/manifest.uuid b/manifest.uuid index 90d457ac4d..8bdf819c4f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 \ No newline at end of file +668fc1ebaf426f9eed3ed7865e41f1023dafebfb \ No newline at end of file diff --git a/src/where.c b/src/where.c index c99306fa46..e6c7728c3a 100644 --- a/src/where.c +++ b/src/where.c @@ -2421,18 +2421,25 @@ static int indexMightHelpWithOrderBy( int iCursor ){ ExprList *pOB; + ExprList *aColExpr; int ii, jj; if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; iinExpr; ii++){ Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ) return 0; - if( pExpr->iTable==iCursor ){ + if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ if( pExpr->iColumn<0 ) return 1; for(jj=0; jjnKeyCol; jj++){ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; } + }else if( (aColExpr = pIndex->aColExpr)!=0 ){ + for(jj=0; jjnKeyCol; jj++){ + if( pIndex->aiColumn[jj]!=(-2) ) continue; + if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ + return 1; + } + } } } return 0; @@ -3264,9 +3271,15 @@ static i8 wherePathSatisfiesOrderBy( testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - if( pOBExpr->iColumn!=iColumn ) continue; + if( iColumn>=(-1) ){ + if( pOBExpr->op!=TK_COLUMN ) continue; + if( pOBExpr->iTable!=iCur ) continue; + if( pOBExpr->iColumn!=iColumn ) continue; + }else{ + if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ + continue; + } + } if( iColumn>=0 ){ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; diff --git a/test/indexexpr1.test b/test/indexexpr1.test index 1945059f2b..e18cbd8d38 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -88,6 +88,23 @@ do_execsql_test indexexpr1-160eqp { WHERE substr(a,27,3)=='ord' AND d>=29; } {/USING INDEX t1a2/} +# ORDER BY using an indexed expression +# +do_execsql_test indexexpr1-170 { + CREATE INDEX t1alen ON t1(length(a)); + SELECT length(a) FROM t1 ORDER BY length(a); +} {20 25 27 29 38 52} +do_execsql_test indexexpr1-170eqp { + EXPLAIN QUERY PLAN + SELECT length(a) FROM t1 ORDER BY length(a); +} {/SCAN TABLE t1 USING INDEX t1alen/} +do_execsql_test indexexpr1-171 { + SELECT length(a) FROM t1 ORDER BY length(a) DESC; +} {52 38 29 27 25 20} +do_execsql_test indexexpr1-171eqp { + EXPLAIN QUERY PLAN + SELECT length(a) FROM t1 ORDER BY length(a) DESC; +} {/SCAN TABLE t1 USING INDEX t1alen/} do_execsql_test indexexpr1-200 { DROP TABLE t1; @@ -255,4 +272,24 @@ do_execsql_test indexexpr1-710 { ORDER BY +a, +x; } {1 1 | 2 2 |} +# Collating sequences on indexes of expressions +# +do_execsql_test indexexpr1-800 { + DROP TABLE IF EXISTS t8; + CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT); + CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE nocase); + INSERT INTO t8(a,b) VALUES(1,'Alice'),(2,'Bartholemew'),(3,'Cynthia'); + SELECT * FROM t8 WHERE substr(b,2,4)='ARTH' COLLATE nocase; +} {2 Bartholemew} +do_catchsql_test indexexpr1-810 { + INSERT INTO t8(a,b) VALUES(4,'BARTHMERE'); +} {1 {UNIQUE constraint failed: index 't8bx'}} +do_catchsql_test indexexpr1-820 { + DROP INDEX t8bx; + CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE rtrim); + INSERT INTO t8(a,b) VALUES(4,'BARTHMERE'); +} {0 {}} + + + finish_test