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
This commit is contained in:
drh 2017-02-10 21:37:57 +00:00
parent 2c338a9d9a
commit 1c84bd4787
5 changed files with 44 additions and 36 deletions

View File

@ -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

View File

@ -1 +1 @@
064445b12f99f76e9a12957be97edd520ab3ae27
158290c0abafde67ee3f2363f0b6646887841df3

View File

@ -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++;

View File

@ -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

View File

@ -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 {