From: drh Date: Mon, 10 Sep 2018 12:40:57 +0000 (+0000) Subject: Fix the LIKE optimization so that it is disabled when the LHS of the X-Git-Tag: version-3.25.0~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b7a002f8367d74c7377a8c70b40c8680009b1b4e;p=thirdparty%2Fsqlite.git Fix the LIKE optimization so that it is disabled when the LHS of the expression does not have TEXT affinity and the RHS is the pattern '/%' or the RHS begins with the escape character. Fix for ticket [c94369cae9b561b1f996d0054b]. FossilOrigin-Name: f191431d63aba187000b5cbaf3e072ff5f1b1eef6a2a407fb4d1629bda4e4e8f --- diff --git a/manifest b/manifest index fd0a13639c..7cace8ddff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sprocessing\sa\s"vtab.col\sIS\sNULL"\sexpression\swithin\nthe\sWHERE\sclause\sof\sa\squery\swhen\s"vtab"\sis\sa\svirtual\stable\son\sthe\srhs\sof\sa\nLEFT\sJOIN. -D 2018-09-10T12:17:16.759 +C Fix\sthe\sLIKE\soptimization\sso\sthat\sit\sis\sdisabled\swhen\sthe\sLHS\sof\sthe\nexpression\sdoes\snot\shave\sTEXT\saffinity\sand\sthe\sRHS\sis\sthe\spattern\s'/%'\nor\sthe\sRHS\sbegins\swith\sthe\sescape\scharacter.\sFix\sfor\sticket\n[c94369cae9b561b1f996d0054b]. +D 2018-09-10T12:40:57.241 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 @@ -589,7 +589,7 @@ F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4 F src/where.c 071572677469d54899ef0d9fc3ad380a849b860375df5af5ebdc4f49f1dc20cc F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 F src/wherecode.c 2b6cd1b27736cc803060289e04ecf9849976106f4077aa67d1a2c0e3ec420159 -F src/whereexpr.c d87df2c00ecc0c2ef4409562608d19cec259a6a03ca72b86fc999db9c07ce119 +F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44 F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1051,7 +1051,7 @@ F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6 F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da -F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4 +F test/like3.test cf0ff2d06c9d8456283aeff405b911642298441206306aeaeaa93973233b1195 F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9 @@ -1765,7 +1765,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 5a954533edbde58aa7158572ece7ceeb1c6e610b71f3ae45d0b8371d74f9fea5 -R 756e7ce3d56663b883e7e3032dfd4880 -U dan -Z f6d9c644621f4f427fb7da91247b3ddb +P 83da4d4104ee1870a2a95bb5fa15ee6584c655d8b314b6b8ab97592dad4ee811 +R 535b9d3fa97af3ca58d7939267f6f9d0 +U drh +Z 4f900079726ee27aee5deedbf4c96ffb diff --git a/manifest.uuid b/manifest.uuid index 7770ef4c64..09c56b72f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -83da4d4104ee1870a2a95bb5fa15ee6584c655d8b314b6b8ab97592dad4ee811 \ No newline at end of file +f191431d63aba187000b5cbaf3e072ff5f1b1eef6a2a407fb4d1629bda4e4e8f \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index 38ec801d93..808c0d21c7 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -230,23 +230,6 @@ static int isLikeOrGlob( } 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; - } - } - /* Count the number of prefix characters prior to the first wildcard */ cnt = 0; while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ @@ -279,6 +262,32 @@ static int isLikeOrGlob( zNew[iTo++] = zNew[iFrom]; } zNew[iTo] = 0; + + /* 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. + ** + ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033 + ** The RHS pattern must not be '/%' because the termination condition + ** will then become "x<'0'" and if the affinity is numeric, will then + ** be converted into "x<0", which is incorrect. + */ + if( sqlite3Isdigit(zNew[0]) + || zNew[0]=='-' + || (zNew[0]+1=='0' && iTo==1) + ){ + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || IsVirtual(pLeft->pTab) /* Value might be numeric */ + ){ + sqlite3ExprDelete(db, pPrefix); + sqlite3ValueFree(pVal); + return 0; + } + } } *ppPrefix = pPrefix; diff --git a/test/like3.test b/test/like3.test index 9280c2c5d2..a7225ee055 100644 --- a/test/like3.test +++ b/test/like3.test @@ -112,4 +112,68 @@ do_execsql_test like3-4.2ck { SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x ASC; } {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} +# 2018-09-10 ticket https://www.sqlite.org/src/tktview/c94369cae9b561b1f996 +# The like optimization fails for a column with numeric affinity if +# the pattern '/%' or begins with the escape character. +# +do_execsql_test like3-5.100 { + CREATE TABLE t5a(x INT UNIQUE COLLATE nocase); + INSERT INTO t5a(x) VALUES('/abc'),(123),(-234); + SELECT x FROM t5a WHERE x LIKE '/%'; +} {/abc} +do_eqp_test like3-5.101 { + SELECT x FROM t5a WHERE x LIKE '/%'; +} { + QUERY PLAN + `--SCAN TABLE t5a +} +do_execsql_test like3-5.110 { + SELECT x FROM t5a WHERE x LIKE '/a%'; +} {/abc} +do_eqp_test like3-5.111 { + SELECT x FROM t5a WHERE x LIKE '/a%'; +} { + QUERY PLAN + `--SEARCH TABLE t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x? AND x