]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the LIKE optimization so that it is disabled when the LHS of the
authordrh <drh@noemail.net>
Mon, 10 Sep 2018 12:40:57 +0000 (12:40 +0000)
committerdrh <drh@noemail.net>
Mon, 10 Sep 2018 12:40:57 +0000 (12:40 +0000)
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

manifest
manifest.uuid
src/whereexpr.c
test/like3.test

index fd0a13639cd513b52f289f3272e50674a0a59163..7cace8ddff14d7dfb5654fa59097bcac8bfcb159 100644 (file)
--- 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
index 7770ef4c64bc4ae346d5e7fbd719016f04655232..09c56b72f61a07c753041362b5cb74de7511b265 100644 (file)
@@ -1 +1 @@
-83da4d4104ee1870a2a95bb5fa15ee6584c655d8b314b6b8ab97592dad4ee811
\ No newline at end of file
+f191431d63aba187000b5cbaf3e072ff5f1b1eef6a2a407fb4d1629bda4e4e8f
\ No newline at end of file
index 38ec801d938affd52b57957d363b880dd7476f4b..808c0d21c740c4beef880a38ad075950dd1fd874 100644 (file)
@@ -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;
 
index 9280c2c5d2d1c72e6082cbc9b38be3d29b71c8fb..a7225ee0559151b9a4539816b819124c89d17455 100644 (file)
@@ -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<?)
+}
+do_execsql_test like3-5.120 {
+  SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
+} {123}
+do_eqp_test like3-5.121 {
+  SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
+} {
+  QUERY PLAN
+  `--SCAN TABLE t5a
+}
+do_execsql_test like3-5.122 {
+  SELECT x FROM t5a WHERE x LIKE '^-2%' ESCAPE '^';
+} {-234}
+do_eqp_test like3-5.123 {
+  SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
+} {
+  QUERY PLAN
+  `--SCAN TABLE t5a
+}
+
+do_execsql_test like3-5.200 {
+  CREATE TABLE t5b(x INT UNIQUE COLLATE binary);
+  INSERT INTO t5b(x) VALUES('/abc'),(123),(-234);
+  SELECT x FROM t5b WHERE x GLOB '/*';
+} {/abc}
+do_eqp_test like3-5.201 {
+  SELECT x FROM t5b WHERE x GLOB '/*';
+} {
+  QUERY PLAN
+  `--SCAN TABLE t5b
+}
+do_execsql_test like3-5.210 {
+  SELECT x FROM t5b WHERE x GLOB '/a*';
+} {/abc}
+do_eqp_test like3-5.211 {
+  SELECT x FROM t5b WHERE x GLOB '/a*';
+} {
+  QUERY PLAN
+  `--SEARCH TABLE t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x<?)
+}
+
 finish_test