From: drh Date: Fri, 10 Feb 2017 21:37:57 +0000 (+0000) Subject: Enhance the LIKE optimization so that it works for arbitrary expressions on X-Git-Tag: version-3.18.0~134 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1c84bd478776a79b7ba5f8c73743a873ee7c4994;p=thirdparty%2Fsqlite.git Enhance the LIKE optimization so that it works for arbitrary expressions on the LHS as long as the pattern on the RHS does not begin with a digit or a minus sign. FossilOrigin-Name: 158290c0abafde67ee3f2363f0b6646887841df3 --- diff --git a/manifest b/manifest index 53d7e16ed6..9d7931aab5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s","\sflag\sto\sprintf(). -D 2017-02-10T19:38:36.506 +C Enhance\sthe\sLIKE\soptimization\sso\sthat\sit\sworks\sfor\sarbitrary\sexpressions\son\nthe\sLHS\sas\slong\sas\sthe\spattern\son\sthe\sRHS\sdoes\snot\sbegin\swith\sa\sdigit\sor\na\sminus\ssign. +D 2017-02-10T21:37:57.808 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 067a6766f800cc8d72845ab61f8de4ffe8f3fc99 @@ -478,7 +478,7 @@ F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0 F src/where.c bc71775e23d23334e8f449aa31012d692dc09cb2 F src/whereInt.h 2bcc3d176e6091cb8f50a30b65c006e88a73614d F src/wherecode.c 99a8ced164c75edf41b3a865a75381c9adb38b28 -F src/whereexpr.c 35ad025389a632a3987a35617c878be3b3d70dc6 +F src/whereexpr.c 980109826ba02750421c3fa7ab0ecabbac0a639d F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1374,7 +1374,7 @@ F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab -F test/vtab1.test 7c4b81abd88361ada9cbe414c459efca26be6bda +F test/vtab1.test ed4a576231d8a36e70fd18e2b79b621b31e7f22a F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 @@ -1389,7 +1389,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b -F test/vtabH.test a2912cd3ea3386aecc3cb74ebfdfcc4e6d4b7dd3 +F test/vtabH.test 5f9253eb9e41ba9fe94f4aa3e9230191893d7764 F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 @@ -1555,7 +1555,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 798fb9d70d2e5f95e64237b04d6692360133381a -R c3dc7f748658995c87bb25e10706fab3 +P 064445b12f99f76e9a12957be97edd520ab3ae27 +R db970521e4fc7396c9c380bbcef0e8ad U drh -Z 3add84968b9ef1dfcf3d7b3eaefd30ad +Z 2c915b2d7e6621ed4f4d2fbc11d0cc6c diff --git a/manifest.uuid b/manifest.uuid index 8090b2db36..0e09e9b731 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -064445b12f99f76e9a12957be97edd520ab3ae27 \ No newline at end of file +158290c0abafde67ee3f2363f0b6646887841df3 \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index 826d329b7f..f511452e52 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -213,15 +213,6 @@ static int isLikeOrGlob( #endif pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ - ){ - /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must - ** be the name of an indexed column with TEXT affinity. */ - return 0; - } - assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); op = pRight->op; @@ -238,6 +229,23 @@ static int isLikeOrGlob( z = pRight->u.zToken; } if( z ){ + + /* If the RHS begins with a digit or a minus sign, then the LHS must + ** be an ordinary column (not a virtual table column) with TEXT affinity. + ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false + ** even though "lhs LIKE rhs" is true. But if the RHS does not start + ** with a digit or '-', then "lhs LIKE rhs" will always be false if + ** the LHS is numeric and so the optimization still works. + */ + if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || IsVirtual(pLeft->pTab) /* Value might be numeric */ + ){ + sqlite3ValueFree(pVal); + return 0; + } + } cnt = 0; while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; diff --git a/test/vtab1.test b/test/vtab1.test index 6b6a0e2683..59ab959746 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -1295,25 +1295,25 @@ do_execsql_test 18.1.0 { CREATE INDEX i6 ON t6(b, a); INSERT INTO t6 VALUES(1, 'Peter'); INSERT INTO t6 VALUES(2, 'Andrew'); - INSERT INTO t6 VALUES(3, 'James'); - INSERT INTO t6 VALUES(4, 'John'); + INSERT INTO t6 VALUES(3, '8James'); + INSERT INTO t6 VALUES(4, '8John'); INSERT INTO t6 VALUES(5, 'Phillip'); INSERT INTO t6 VALUES(6, 'Bartholomew'); CREATE VIRTUAL TABLE e6 USING echo(t6); } foreach {tn sql res filter} { - 1.1 "SELECT a FROM e6 WHERE b>'James'" {4 1 5} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} James} + 1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James} - 1.2 "SELECT a FROM e6 WHERE b>='J' AND b<'K'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} J K} + 1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9} - 1.3 "SELECT a FROM e6 WHERE b LIKE 'J%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} J%} + 1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%} - 1.4 "SELECT a FROM e6 WHERE b LIKE 'j%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} j%} + 1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%} } { set echo_module {} do_execsql_test 18.$tn.1 $sql $res @@ -1322,11 +1322,11 @@ foreach {tn sql res filter} { do_execsql_test 18.2.0 { PRAGMA case_sensitive_like = ON } foreach {tn sql res filter} { - 2.1 "SELECT a FROM e6 WHERE b LIKE 'J%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} J%} + 2.1 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%} - 2.2 "SELECT a FROM e6 WHERE b LIKE 'j%'" {} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} j%} + 2.2 "SELECT a FROM e6 WHERE b LIKE '8j%'" {} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%} } { set echo_module {} do_execsql_test 18.$tn.1 $sql $res diff --git a/test/vtabH.test b/test/vtabH.test index 3ce457ff0b..c5684ff516 100644 --- a/test/vtabH.test +++ b/test/vtabH.test @@ -31,14 +31,14 @@ do_execsql_test 1.0 { } foreach {tn sql expect} { - 1 "SELECT * FROM e6 WHERE b LIKE 'abc'" { + 1 "SELECT * FROM e6 WHERE b LIKE '8abc'" { xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} abc + xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8abc } - 2 "SELECT * FROM e6 WHERE b GLOB 'abc'" { + 2 "SELECT * FROM e6 WHERE b GLOB '8abc'" { xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} abc + xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8abc } } { do_test 1.$tn {