<div dir="ltr"><div>Branch: <a href="https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3251-where-like-hanging">https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3251-where-like-hanging</a></div><div>Issue: <a href="https://github.com/tarantool/tarantool/issues/3251">https://github.com/tarantool/tarantool/issues/3251</a></div><div>Issue: <a href="https://github.com/tarantool/tarantool/issues/3334">https://github.com/tarantool/tarantool/issues/3334</a></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">чт, 28 июн. 2018 г. в 15:47, N.Tatunov <<a href="mailto:hollow653@gmail.com">hollow653@gmail.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Currently function that compares pattern and<br>
string for GLOB & LIKE operators doesn't work properly.<br>
It uses ICU reading function which perhaps was working<br>
differently before and the implementation for the<br>
comparison ending isn't paying attention to some<br>
special cases, hence in those cases it works improperly.<br>
Now the checks for comparison should work fine.<br>
<br>
Сloses: #3251<br>
Сloses: #3334<br>
---<br>
 src/box/sql/func.c          |  25 ++++----<br>
 test/sql-tap/like1.test.lua | 152 ++++++++++++++++++++++++++++++++++++++++++++<br>
 2 files changed, 165 insertions(+), 12 deletions(-)<br>
 create mode 100755 test/sql-tap/like1.test.lua<br>
<br>
diff --git a/src/box/sql/func.c b/src/box/sql/func.c<br>
index c06e3bd..dcbd7e0 100644<br>
--- a/src/box/sql/func.c<br>
+++ b/src/box/sql/func.c<br>
@@ -643,6 +643,7 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };<br>
 #define SQLITE_MATCH             0<br>
 #define SQLITE_NOMATCH           1<br>
 #define SQLITE_NOWILDCARDMATCH   2<br>
+#define SQL_NO_SYMBOLS_LEFT      65535<br>
<br>
 /*<br>
  * Compare two UTF-8 strings for equality where the first string is<br>
@@ -698,29 +699,28 @@ patternCompare(const char * pattern,      /* The glob pattern */<br>
        const char * string_end = string + strlen(string);<br>
        UErrorCode status = U_ZERO_ERROR;<br>
<br>
-       while (pattern < pattern_end){<br>
-               c = Utf8Read(pattern, pattern_end);<br>
+       while ((c = Utf8Read(pattern, pattern_end)) != SQL_NO_SYMBOLS_LEFT) {<br>
                if (c == matchAll) {    /* Match "*" */<br>
                        /* Skip over multiple "*" characters in the pattern.  If there<br>
                         * are also "?" characters, skip those as well, but consume a<br>
                         * single character of the input string for each "?" skipped<br>
                         */<br>
-                       while (pattern < pattern_end){<br>
-                               c = Utf8Read(pattern, pattern_end);<br>
+                       while ((c = Utf8Read(pattern, pattern_end)) !=<br>
+                              SQL_NO_SYMBOLS_LEFT) {<br>
                                if (c != matchAll && c != matchOne)<br>
                                        break;<br>
-                               if (c == matchOne<br>
-                                   && Utf8Read(string, string_end) == 0) {<br>
+                               if (c == matchOne &&<br>
+                                   Utf8Read(string, string_end) ==<br>
+                                   SQL_NO_SYMBOLS_LEFT)<br>
                                        return SQLITE_NOWILDCARDMATCH;<br>
-                               }<br>
                        }<br>
                        /* "*" at the end of the pattern matches */<br>
-                       if (pattern == pattern_end)<br>
+                       if (c == SQL_NO_SYMBOLS_LEFT)<br>
                                return SQLITE_MATCH;<br>
                        if (c == matchOther) {<br>
                                if (pInfo->matchSet == 0) {<br>
                                        c = Utf8Read(pattern, pattern_end);<br>
-                                       if (c == 0)<br>
+                                       if (c == SQL_NO_SYMBOLS_LEFT)<br>
                                                return SQLITE_NOWILDCARDMATCH;<br>
                                } else {<br>
                                        /* "[...]" immediately follows the "*".  We have to do a slow<br>
@@ -782,7 +782,7 @@ patternCompare(const char * pattern,        /* The glob pattern */<br>
                if (c == matchOther) {<br>
                        if (pInfo->matchSet == 0) {<br>
                                c = Utf8Read(pattern, pattern_end);<br>
-                               if (c == 0)<br>
+                               if (c == SQL_NO_SYMBOLS_LEFT)<br>
                                        return SQLITE_NOMATCH;<br>
                                zEscaped = pattern;<br>
                        } else {<br>
@@ -802,7 +802,7 @@ patternCompare(const char * pattern,        /* The glob pattern */<br>
                                                seen = 1;<br>
                                        c2 = Utf8Read(pattern, pattern_end);<br>
                                }<br>
-                               while (c2 && c2 != ']') {<br>
+                               while (c2 != SQL_NO_SYMBOLS_LEFT && c2 != ']') {<br>
                                        if (c2 == '-' && pattern[0] != ']'<br>
                                            && pattern < pattern_end<br>
                                            && prior_c > 0) {<br>
@@ -839,7 +839,8 @@ patternCompare(const char * pattern,        /* The glob pattern */<br>
                            c == u_tolower(c2))<br>
                                continue;<br>
                }<br>
-               if (c == matchOne && pattern != zEscaped && c2 != 0)<br>
+               if (c == matchOne && pattern != zEscaped &&<br>
+                   c2 != SQL_NO_SYMBOLS_LEFT)<br>
                        continue;<br>
                return SQLITE_NOMATCH;<br>
        }<br>
diff --git a/test/sql-tap/like1.test.lua b/test/sql-tap/like1.test.lua<br>
new file mode 100755<br>
index 0000000..42b4d43<br>
--- /dev/null<br>
+++ b/test/sql-tap/like1.test.lua<br>
@@ -0,0 +1,152 @@<br>
+#!/usr/bin/env tarantool<br>
+test = require("sqltester")<br>
+test:plan(13)<br>
+<br>
+test:do_catchsql_test(<br>
+       "like-test-1.1",<br>
+       [[<br>
+               CREATE TABLE t2 (column1 INTEGER,<br>
+                                    column2 VARCHAR(100),<br>
+                                    column3 BLOB,<br>
+                                    column4 FLOAT,<br>
+                                    PRIMARY KEY (column1, column2));<br>
+               INSERT INTO t2 VALUES (1, 'AB', X'4142', 5.5);<br>
+               INSERT INTO t2 VALUES (1, 'CD', X'2020', 1E4);<br>
+               INSERT INTO t2 VALUES (2, 'AB', X'2020', 12.34567);<br>
+               INSERT INTO t2 VALUES (-1000, '', X'', 0.0);<br>
+               CREATE TABLE t1 (a INT PRIMARY KEY, str VARCHAR(100));<br>
+               INSERT INTO t1 VALUES (1, 'ab');<br>
+               INSERT INTO t1 VALUES (2, 'abCDF');<br>
+               INSERT INTO t1 VALUES (3, 'CDF');<br>
+               CREATE TABLE t (s1 char(2) primary key, s2 char(2));<br>
+               INSERT INTO t VALUES ('AB', 'AB');<br>
+       ]], {<br>
+               -- <like-test-1.1><br>
+               0<br>
+               -- <like-test-1.1><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.2",<br>
+       [[<br>
+               SELECT column1, column2, column1 * column4 FROM t2 WHERE column2 LIKE '_B';<br>
+       ]], {<br>
+               -- <like-test-1.2><br>
+               1, 'AB', 5.5, 2, 'AB', 24.69134<br>
+               -- <like-test-1.2><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.3",<br>
+       [[<br>
+               SELECT column1, column2 FROM t2 WHERE column2 LIKE '%B';<br>
+       ]], {<br>
+             -- <like-test-1.3><br>
+             1, 'AB', 2, 'AB'<br>
+             -- <like-test-1.3><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.4",<br>
+       [[<br>
+               SELECT column1, column2 FROM t2 WHERE column2 LIKE 'A__';<br>
+       ]], {<br>
+             -- <like-test-1.4><br>
+<br>
+             -- <like-test-1.4><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.5",<br>
+       [[<br>
+               SELECT column1, column2 FROM t2 WHERE column2 LIKE 'A_';<br>
+       ]], {<br>
+             -- <like-test-1.5><br>
+             1, 'AB', 2, 'AB'<br>
+             -- <like-test-1.5><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.6",<br>
+       [[<br>
+               SELECT column1, column2 FROM t2 WHERE column2 LIKE 'A';<br>
+       ]], {<br>
+             -- <like-test-1.6><br>
+<br>
+             -- <like-test-1.6><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.7",<br>
+       [[<br>
+               SELECT column1, column2 FROM t2 WHERE column2 LIKE '_';<br>
+       ]], {<br>
+             -- <like-test-1.7><br>
+<br>
+             -- <like-test-1.7><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.8",<br>
+       [[<br>
+               SELECT * FROM t WHERE s1 LIKE '%A';<br>
+       ]], {<br>
+             -- <like-test-1.8><br>
+<br>
+             -- <like-test-1.8><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.9",<br>
+       [[<br>
+               SELECT * FROM t WHERE s1 LIKE '%C';<br>
+       ]], {<br>
+             -- <like-test-1.9><br>
+<br>
+             -- <like-test-1.9><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.10",<br>
+       [[<br>
+               SELECT * FROM t1 WHERE str LIKE '%df';<br>
+       ]], {<br>
+             -- <like-test-1.10><br>
+             2, 'abCDF', 3, 'CDF'<br>
+             -- <like-test-1.10><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.11",<br>
+       [[<br>
+               SELECT * FROM t1 WHERE str LIKE 'a_';<br>
+       ]], {<br>
+             -- <like-test-1.11><br>
+             1, 'ab'<br>
+             -- <like-test-1.11><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.12",<br>
+       [[<br>
+               select column1, column2 from t2 where column2 like '__';<br>
+       ]], {<br>
+             -- <like-test-1.12><br>
+             1, 'AB', 1, 'CD', 2, 'AB'<br>
+             -- <like-test-1.12><br>
+       })<br>
+<br>
+test:do_execsql_test(<br>
+       "like-test-1.13",<br>
+       [[<br>
+               DROP TABLE t1;<br>
+               DROP TABLE t2;<br>
+               DROP TABLE t;<br>
+       ]], {<br>
+             -- <like-test-1.13><br>
+<br>
+             -- <like-test-1.13><br>
+       })<br>
+<br>
+<br>
+test:finish_test()<br>
-- <br>
2.7.4<br>
<br>
</blockquote></div>