<div dir="ltr">Hello!<br><br><div class="gmail_quote"><div dir="ltr">пт, 27 июл. 2018 г. в 16:06, Alexander Turenko <<a href="mailto:alexander.turenko@tarantool.org">alexander.turenko@tarantool.org</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
See comments below.<br>
<br>
Don't sure we should return 'no match' situation when a left hand<br>
expression in not correct unicode string. How other DBs handle that?<br>
<br></blockquote><div><br></div><div>The main point is that since pattern is always valid (otherwise we return an error)</div><div>it cannot be matched with a string that contains an invalid utf-8 character.</div><div><br></div><div>- PostgreSQL doesn't allow storing invalid characters in text types and</div><div>  even explicit E'\xD1' anywhere results an error.</div><div>- MySQL Doesn't allow using invalid characters in text types.</div><div> </div><div>May be it's reasons for thinking about prohibiting invalid characters in text?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
WBR, Alexander Turenko.<br>
<br>
> sql: LIKE & GLOB pattern comparison issue<br>
><br>
> Currently function that compares pattern and string for GLOB & LIKE<br>
> operators doesn't work properly. It uses ICU reading function which<br>
> perhaps was working differently before and the implementation for the<br>
> comparison ending isn't paying attention to some special cases, hence<br>
> in those cases it works improperly.<br>
><br>
<br>
It used non-ICU function before, consider commit 198d59ce.<br>
<br></blockquote><div><br></div><div>Thank you, I've got it now.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> With the patch applied an error will be returned in case there's<br>
> invalid UTF-8 symbol in pattern & pattern will not be matched<br>
> with the string that contains it. Some minor corrections to function<br>
> were made as well.<br>
><br>
<br>
Nitpicking: 'error will be returned' is third situatuon, other then<br>
'matched' and 'not matched'.<br>
<br></blockquote><div><br></div><div>I guess commit message is about changes. Do I really need to</div><div>mention valid cases that didn't change?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> Сloses #3251<br>
> Сloses #3334<br>
> Part of #3572<br>
<br>
> > 2. The thing you test is not related to a table and other columns.<br>
> >     Please, convert the tests to the next format: {[[select '' like<br>
> > '_B';]], {1}]]}.<br>
> >     To make it more readable, you can do it like `like_testcases` in<br>
> > `sql-tap/collation.test.lua`.<br>
> ><br>
> <br>
> Done.<br>
<br>
You are still perform comparisons with table columns.<br></blockquote><div><br></div><div>Thank you, fixed it.  More tests now tho.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> -/*<br>
> - * For LIKE and GLOB matching on EBCDIC machines, assume that every<br>
> - * character is exactly one byte in size.  Also, provde the Utf8Read()<br>
> - * macro for fast reading of the next character in the common case where<br>
> - * the next character is ASCII.<br>
> +/**<br>
> + * Providing there are symbols in string s this<br>
> + * macro returns UTF-8 code of character and<br>
> + * promotes pointer to the next symbol in the string.<br>
> + * Otherwise return code is SQL_END_OF_STRING.<br>
>   */<br>
> -#define Utf8Read(s, e)    ucnv_getNextUChar(pUtf8conv, &s, e, &status)<br>
> +#define Utf8Read(s, e) (((s) < (e)) ?\<br>
> + ucnv_getNextUChar(pUtf8conv, &(s), (e), &(status)) : 0)<br>
<br>
I suggest to add a whitespace before backslash to make it looks better.<br>
<br></blockquote><div><br></div><div>Guess so.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> @@ -643,51 +647,61 @@ static const struct compareInfo likeInfoAlt = { '%',<br>
> '_', 0, 0 };<br>
>  #define SQLITE_MATCH             0<br>
>  #define SQLITE_NOMATCH           1<br>
>  #define SQLITE_NOWILDCARDMATCH   2<br>
> +#define SQL_PROHIBITED_PATTERN   3<br>
<br>
Update comment before that has a reference to 'patternMatch' function.<br>
<br></blockquote><div><br></div><div>Didn't notice it, thnx.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>   *<br>
>   * Globbing rules:<br>
>   *<br>
> - *      '*'       Matches any sequence of zero or more characters.<br>
> + *      '*'      Matches any sequence of zero or more characters.<br>
<br>
Why?<br>
<br>
>   *<br>
> - *      '?'       Matches exactly one character.<br>
> + *      '?'      Matches exactly one character.<br>
>   *<br>
> - *     [...]      Matches one character from the enclosed list of<br>
> - *                characters.<br>
> + *     [...]     Matches one character from the enclosed list of<br>
> + *               characters.<br>
>   *<br>
> - *     [^...]     Matches one character not in the enclosed list.<br>
> + *     [^...]    Matches one character not in the enclosed list.<br>
>   *<br>
<br>
The same question.<br>
<br></blockquote><div><br></div><div>It was looking like the indentation for similar table below was different.</div><div>I was wrong.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> + * @retval SQLITE_MATCH:            Match.<br>
> + *    SQLITE_NOMATCH:          No match.<br>
> + *    SQLITE_NOWILDCARDMATCH:  No match in spite of having *<br>
> + *     or % wildcards.<br>
> + *    SQL_PROHIBITED_PATTERN   Pattern contains invalid<br>
> + *     symbol.<br>
<br>
Nitpicking: no colon after SQL_PROHIBITED_PATTERN.<br></blockquote><div><br></div><div>Fixed.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>   */<br>
>  static int<br>
> -patternCompare(const char * pattern, /* The glob pattern */<br>
> -        const char * string, /* The string to compare against the glob */<br>
> -        const struct compareInfo *pInfo, /* Information about how to do<br>
> the compare */<br>
> -        UChar32 matchOther /* The escape char (LIKE) or '[' (GLOB) */<br>
> -    )<br>
> +sql_utf8_pattern_compare(const char * pattern,<br>
> +        const char * string,<br>
> +        const struct compareInfo *pInfo,<br>
> +        UChar32 matchOther)<br>
<br>
Don't get why indent is tabulation + 7 spaces.<br>
<br></blockquote><div><br></div><div>Me neither :thinking:. Thank you!</div><div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
The function itself looks good except lines longer then 80 columns.<br></blockquote><div><br></div><div>As i said before I don't think breaking these lines will increase readability.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> @@ -853,8 +903,7 @@ patternCompare(const char * pattern, /* The glob<br>
> pattern */<br>
>  int<br>
>  sqlite3_strglob(const char *zGlobPattern, const char *zString)<br>
>  {<br>
> - return patternCompare(zGlobPattern, zString, &globInfo,<br>
> -       '[');<br>
> + return sql_utf8_pattern_compare(zGlobPattern, zString, &globInfo, '[');<br>
>  }<br>
> <br>
>  /*<br>
> @@ -864,7 +913,7 @@ sqlite3_strglob(const char *zGlobPattern, const char<br>
> *zString)<br>
>  int<br>
>  sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc)<br>
>  {<br>
> - return patternCompare(zPattern, zStr, &likeInfoNorm, esc);<br>
> + return sql_utf8_pattern_compare(zPattern, zStr, &likeInfoNorm, esc);<br>
>  }<br>
> <br>
<br>
Should we add sqlite3_result_error is case of SQL_PROHIBITED_PATTERN for<br>
these two functions?<br>
<br></blockquote><div><br></div><div>It doesn't matter for "sqlite3_strglob()", since it's only used internally</div><div>with valid explicitly given pattern in "analysis_loader()".</div><div>Same for "sqlite3_strlike()".</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> -    {"LIKE", "like"},<br>
> -    {"GLOB", "glob"},<br>
> +-- NOTE: This test needs refactoring after deletion of GLOB &<br>
> +-- type restrictions for LIKE.<br>
> +--    {"LIKE", "like"},<br>
> +--    {"GLOB", "glob"},<br>
<br>
I would add related issue number.<br>
<br></blockquote><div><br></div><div>True. Done.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>      {"AND", "and"},<br>
>      {"OR", "or"},<br>
>      {"MATCH", "match"},<br>
> @@ -96,7 +98,7 @@ operations = {<br>
>      {"+", "-"},<br>
>      {"<<", ">>", "&", "|"},<br>
>      {"<", "<=", ">", ">="},<br>
> -    {"=", "==", "!=", "<>", "LIKE", "GLOB"}, --"MATCH", "REGEXP"},<br>
> +    {"=", "==", "!=", "<>"}, --"LIKE", "GLOB"}, "MATCH", "REGEXP"},<br>
<br>
Leave comment before MATCH and REGEXP to avoid surprises after removing<br>
your comment.<br>
<br></blockquote><div><br></div><div>Done.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> --- /dev/null<br>
> +++ b/test/sql-tap/gh-3251-string-pattern-comparison.lua<br>
> @@ -0,0 +1,238 @@<br>
> +#!/usr/bin/env tarantool<br>
> +test = require("sqltester")<br>
> +test:plan(106)<br>
> +<br>
> +local prefix = "like-test-"<br>
> +<br>
> +-- Unciode byte sequences.<br>
> +<br>
<br>
1. Typo: unicode.<br>
2. Extra empty line.<br>
<br></blockquote><div><br></div><div>Fixed.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +-- Invalid testcases.<br>
> +<br>
> +for i, tested_string in ipairs(invalid_testcases) do<br>
> + local test_name = prefix .. "2." .. tostring(i)<br>
> + local test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "';"<br>
> +<br>
> +-- We should raise an error if pattern contains invalid characters.<br>
> +<br>
<br>
1. Trailing whitespaces.<br>
2. Why comments are not indented as the other code?<br>
3. test_name and test_itself before the section comment looks strange<br>
   for me here.<br></blockquote><div><br></div><div>diff --git a/src/box/sql/func.c b/src/box/sql/func.c</div><div>index 5b53076..2f989d4 100644</div><div>--- a/src/box/sql/func.c</div><div>+++ b/src/box/sql/func.c</div><div>@@ -623,7 +623,7 @@ struct compareInfo {</div><div>  * promotes pointer to the next symbol in the string.</div><div>  * Otherwise return code is SQL_END_OF_STRING.</div><div>  */</div><div>-#define Utf8Read(s, e) (((s) < (e)) ?\</div><div>+#define Utf8Read(s, e) (((s) < (e)) ? \</div><div> <span style="white-space:pre">      </span>ucnv_getNextUChar(pUtf8conv, &(s), (e), &(status)) : 0)</div><div> </div><div> #define SQL_END_OF_STRING        0</div><div>@@ -642,7 +642,7 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };</div><div> static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };</div><div> </div><div> /*</div><div>- * Possible error returns from patternMatch()</div><div>+ * Possible error returns from sql_utf8_pattern_compare()</div><div>  */</div><div> #define SQLITE_MATCH             0</div><div> #define SQLITE_NOMATCH           1</div><div>@@ -655,14 +655,14 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };</div><div>  *</div><div>  * Globbing rules:</div><div>  *</div><div>- *      '*'      Matches any sequence of zero or more characters.</div><div>+ *      '*'       Matches any sequence of zero or more characters.</div><div>  *</div><div>- *      '?'      Matches exactly one character.</div><div>+ *      '?'       Matches exactly one character.</div><div>  *</div><div>- *     [...]     Matches one character from the enclosed list of</div><div>- *               characters.</div><div>+ *     [...]      Matches one character from the enclosed list of</div><div>+ *                characters.</div><div>  *</div><div>- *     [^...]    Matches one character not in the enclosed list.</div><div>+ *     [^...]     Matches one character not in the enclosed list.</div><div>  *</div><div>  * With the [...] and [^...] matching, a ']' character can be</div><div>  * included in the list by making it the first character after</div><div>@@ -694,14 +694,14 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };</div><div>  *<span style="white-space:pre">       </span>   SQLITE_NOMATCH:          No match.</div><div>  *<span style="white-space:pre">      </span>   SQLITE_NOWILDCARDMATCH:  No match in spite of having *</div><div>  *<span style="white-space:pre">                              </span>    or % wildcards.</div><div>- *<span style="white-space:pre">      </span>   SQL_PROHIBITED_PATTERN   Pattern contains invalid</div><div>+ *<span style="white-space:pre">   </span>   SQL_PROHIBITED_PATTERN:  Pattern contains invalid</div><div>  *<span style="white-space:pre">                           </span>    symbol.</div><div>  */</div><div> static int</div><div> sql_utf8_pattern_compare(const char * pattern,</div><div>-<span style="white-space:pre">  </span>       const char * string,</div><div>-<span style="white-space:pre">      </span>       const struct compareInfo *pInfo,</div><div>-<span style="white-space:pre">  </span>       UChar32 matchOther)</div><div>+<span style="white-space:pre">                       </span> const char * string,</div><div>+<span style="white-space:pre">                        </span> const struct compareInfo *pInfo,</div><div>+<span style="white-space:pre">                    </span> UChar32 matchOther)</div><div> {</div><div> <span style="white-space:pre">      </span>UChar32 c, c2;<span style="white-space:pre">               </span>/* Next pattern and input string chars */</div><div> <span style="white-space:pre">   </span>UChar32 matchOne = pInfo->matchOne;<span style="white-space:pre">       </span>/* "?" or "_" */</div><div>diff --git a/test/sql-tap/e_expr.test.lua b/test/sql-tap/e_expr.test.lua</div><div>index 051210a..9780d2c 100755</div><div>--- a/test/sql-tap/e_expr.test.lua</div><div>+++ b/test/sql-tap/e_expr.test.lua</div><div>@@ -78,7 +78,7 @@ local operations = {</div><div>     {"!=", "ne2"},</div><div>     {"IS", "is"},</div><div> -- NOTE: This test needs refactoring after deletion of GLOB &</div><div>---<span style="white-space:pre">  </span> type restrictions for LIKE.</div><div>+--<span style="white-space:pre">       </span> type restrictions for LIKE. (See #3572)</div><div> --    {"LIKE", "like"},</div><div> --    {"GLOB", "glob"},</div><div>     {"AND", "and"},</div><div>@@ -98,7 +98,12 @@ operations = {</div><div>     {"+", "-"},</div><div>     {"<<", ">>", "&", "|"},</div><div>     {"<", "<=", ">", ">="},</div><div>-    {"=", "==", "!=", "<>"}, --"LIKE", "GLOB"}, "MATCH", "REGEXP"},</div><div>+-- NOTE: This test needs refactoring after deletion of GLOB &</div><div>+--<span style="white-space:pre">   </span> type restrictions for LIKE. (See #3572)</div><div>+-- Another NOTE: MATCH & REGEXP aren't supported in Tarantool &</div><div>+-- <span style="white-space:pre">               </span> are waiting for their hour, don't confuse them</div><div>+--<span style="white-space:pre">                </span> being commented with ticket above.</div><div>+    {"=", "==", "!=", "<>"}, --"LIKE", "GLOB"}, --"MATCH", "REGEXP"},</div><div>     {"AND"},</div><div>     {"OR"},</div><div> }</div><div>diff --git a/test/sql-tap/gh-3251-string-pattern-comparison.test.lua b/test/sql-tap/gh-3251-string-pattern-comparison.test.lua</div><div>new file mode 100755</div><div>index 0000000..a823bc6</div><div>--- /dev/null</div><div>+++ b/test/sql-tap/gh-3251-string-pattern-comparison.test.lua</div><div>@@ -0,0 +1,281 @@</div><div>+#!/usr/bin/env tarantool</div><div>+test = require("sqltester")</div><div>+test:plan(128)</div><div>+</div><div>+local prefix = "like-test-"</div><div>+</div><div>+-- Unicode byte sequences.</div><div>+local valid_testcases = {</div><div>+<span style="white-space:pre">  </span>'\x01',</div><div>+<span style="white-space:pre">      </span>'\x09',</div><div>+<span style="white-space:pre">      </span>'\x1F',</div><div>+<span style="white-space:pre">      </span>'\x7F',</div><div>+<span style="white-space:pre">      </span>'\xC2\x80',</div><div>+<span style="white-space:pre">  </span>'\xC2\x90',</div><div>+<span style="white-space:pre">  </span>'\xC2\x9F',</div><div>+<span style="white-space:pre">  </span>'\xE2\x80\xA8',</div><div>+<span style="white-space:pre">      </span>'\x20\x0B',</div><div>+<span style="white-space:pre">  </span>'\xE2\x80\xA9',</div><div>+}</div><div>+</div><div>+-- Non-Unicode byte sequences.</div><div>+local invalid_testcases = {</div><div>+<span style="white-space:pre">    </span>'\xE2\x80',</div><div>+<span style="white-space:pre">  </span>'\xFE\xFF',</div><div>+<span style="white-space:pre">  </span>'\xC2',</div><div>+<span style="white-space:pre">      </span>'\xED\xB0\x80',</div><div>+<span style="white-space:pre">      </span>'\xD0',</div><div>+}</div><div>+</div><div>+local like_test_cases =</div><div>+{</div><div>+<span style="white-space:pre">     </span>{"1.1",</div><div>+<span style="white-space:pre">            </span>"SELECT 'AB' LIKE '_B';",</div><div>+<span style="white-space:pre">          </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.2",</div><div>+<span style="white-space:pre">            </span>"SELECT 'CD' LIKE '_B';",</div><div>+<span style="white-space:pre">          </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.3",</div><div>+<span style="white-space:pre">            </span>"SELECT '' LIKE '_B';",</div><div>+<span style="white-space:pre">            </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.4",</div><div>+<span style="white-space:pre">            </span>"SELECT 'AB' LIKE '%B';",</div><div>+<span style="white-space:pre">          </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.5",</div><div>+<span style="white-space:pre">            </span>"SELECT 'CD' LIKE '%B';",</div><div>+<span style="white-space:pre">          </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.6",</div><div>+<span style="white-space:pre">            </span>"SELECT '' LIKE '%B';",</div><div>+<span style="white-space:pre">            </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.7",</div><div>+<span style="white-space:pre">            </span>"SELECT 'AB' LIKE 'A__';",</div><div>+<span style="white-space:pre">         </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.8",</div><div>+<span style="white-space:pre">            </span>"SELECT 'CD' LIKE 'A__';",</div><div>+<span style="white-space:pre">         </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.9",</div><div>+<span style="white-space:pre">            </span>"SELECT '' LIKE 'A__';",</div><div>+<span style="white-space:pre">           </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.10",</div><div>+<span style="white-space:pre">           </span>"SELECT 'AB' LIKE 'A_';",</div><div>+<span style="white-space:pre">          </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.11",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CD' LIKE 'A_';",</div><div>+<span style="white-space:pre">          </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.12",</div><div>+<span style="white-space:pre">           </span>"SELECT '' LIKE 'A_';",</div><div>+<span style="white-space:pre">            </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.13",</div><div>+<span style="white-space:pre">           </span>"SELECT 'AB' LIKE 'A';",</div><div>+<span style="white-space:pre">           </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.14",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CD' LIKE 'A';",</div><div>+<span style="white-space:pre">           </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.15",</div><div>+<span style="white-space:pre">           </span>"SELECT '' LIKE 'A';",</div><div>+<span style="white-space:pre">             </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.16",</div><div>+<span style="white-space:pre">           </span>"SELECT 'AB' LIKE '_';",</div><div>+<span style="white-space:pre">           </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.17",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CD' LIKE '_';",</div><div>+<span style="white-space:pre">           </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.18",</div><div>+<span style="white-space:pre">           </span>"SELECT '' LIKE '_';",</div><div>+<span style="white-space:pre">             </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.19",</div><div>+<span style="white-space:pre">           </span>"SELECT 'AB' LIKE '__';",</div><div>+<span style="white-space:pre">          </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.20",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CD' LIKE '__';",</div><div>+<span style="white-space:pre">          </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.21",</div><div>+<span style="white-space:pre">           </span>"SELECT '' LIKE '__';",</div><div>+<span style="white-space:pre">            </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.22",</div><div>+<span style="white-space:pre">           </span>"SELECT 'AB' LIKE '%A';",</div><div>+<span style="white-space:pre">          </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.23",</div><div>+<span style="white-space:pre">           </span>"SELECT 'AB' LIKE '%C';",</div><div>+<span style="white-space:pre">          </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.24",</div><div>+<span style="white-space:pre">           </span>"SELECT 'ab' LIKE '%df';",</div><div>+<span style="white-space:pre">         </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.25",</div><div>+<span style="white-space:pre">           </span>"SELECT 'abCDF' LIKE '%df';",</div><div>+<span style="white-space:pre">              </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.26",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CDF' LIKE '%df';",</div><div>+<span style="white-space:pre">                </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.27",</div><div>+<span style="white-space:pre">           </span>"SELECT 'ab' LIKE 'a_';",</div><div>+<span style="white-space:pre">          </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.28",</div><div>+<span style="white-space:pre">           </span>"SELECT 'abCDF' LIKE 'a_';",</div><div>+<span style="white-space:pre">               </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.29",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CDF' LIKE 'a_';",</div><div>+<span style="white-space:pre">         </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.30",</div><div>+<span style="white-space:pre">           </span>"SELECT 'ab' LIKE 'ab%';",</div><div>+<span style="white-space:pre">         </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.31",</div><div>+<span style="white-space:pre">           </span>"SELECT 'abCDF' LIKE 'ab%';",</div><div>+<span style="white-space:pre">              </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.32",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CDF' LIKE 'ab%';",</div><div>+<span style="white-space:pre">                </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.33",</div><div>+<span style="white-space:pre">           </span>"SELECT 'ab' LIKE 'abC%';",</div><div>+<span style="white-space:pre">                </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.34",</div><div>+<span style="white-space:pre">           </span>"SELECT 'abCDF' LIKE 'abC%';",</div><div>+<span style="white-space:pre">             </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.35",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CDF' LIKE 'abC%';",</div><div>+<span style="white-space:pre">               </span>{0, {0}} },</div><div>+<span style="white-space:pre">  </span>{"1.36",</div><div>+<span style="white-space:pre">           </span>"SELECT 'ab' LIKE 'a_%';",</div><div>+<span style="white-space:pre">         </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.37",</div><div>+<span style="white-space:pre">           </span>"SELECT 'abCDF' LIKE 'a_%';",</div><div>+<span style="white-space:pre">              </span>{0, {1}} },</div><div>+<span style="white-space:pre">  </span>{"1.38",</div><div>+<span style="white-space:pre">           </span>"SELECT 'CDF' LIKE 'a_%';",</div><div>+<span style="white-space:pre">                </span>{0, {0}} },</div><div>+}</div><div>+</div><div>+test:do_catchsql_set_test(like_test_cases, prefix)</div><div>+</div><div>+-- Invalid testcases.</div><div>+</div><div>+for i, tested_string in ipairs(invalid_testcases) do</div><div>+</div><div>+-- We should raise an error if pattern contains invalid characters.</div><div>+<span style="white-space:pre">   </span>local test_name = prefix .. "2." .. tostring(i)</div><div>+<span style="white-space:pre">    </span>local test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "';"</div><div>+<span style="white-space:pre">     </span>test:do_catchsql_test(</div><div>+<span style="white-space:pre">               </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>1, "LIKE or GLOB pattern can only contain UTF-8 characters"</div><div>+<span style="white-space:pre">                        </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "3." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>test_itself = "SELECT 'abc' LIKE 'abc" .. tested_string .. "';"</div><div>+<span style="white-space:pre">  </span>test:do_catchsql_test(</div><div>+<span style="white-space:pre">               </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>1, "LIKE or GLOB pattern can only contain UTF-8 characters"</div><div>+<span style="white-space:pre">                        </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "4." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "c';"</div><div>+<span style="white-space:pre">  </span>test:do_catchsql_test(</div><div>+<span style="white-space:pre">               </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>1, "LIKE or GLOB pattern can only contain UTF-8 characters"</div><div>+<span style="white-space:pre">                        </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+-- Just skipping if row value predicand contains invalid character.</div><div>+</div><div>+<span style="white-space:pre">        </span>test_name = prefix .. "5." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>test_itself = "SELECT 'ab" .. tested_string .. "' LIKE 'abc';"</div><div>+<span style="white-space:pre">   </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "6." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>test_itself = "SELECT 'abc" .. tested_string .. "' LIKE 'abc';"</div><div>+<span style="white-space:pre">  </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "7." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>test_itself = "SELECT 'ab" .. tested_string .. "c' LIKE 'abc';"</div><div>+<span style="white-space:pre">  </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+end</div><div>+</div><div>+-- Valid testcases.</div><div>+</div><div>+for i, tested_string in ipairs(valid_testcases) do</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "8." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>local test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "';"</div><div>+<span style="white-space:pre">     </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "9." .. tostring(i)</div><div>+<span style="white-space:pre">  </span>test_itself = "SELECT 'abc' LIKE 'abc" .. tested_string .. "';"</div><div>+<span style="white-space:pre">  </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "10." .. tostring(i)</div><div>+<span style="white-space:pre"> </span>test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "c';"</div><div>+<span style="white-space:pre">  </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "11." .. tostring(i)</div><div>+<span style="white-space:pre"> </span>test_itself = "SELECT 'ab" .. tested_string .. "' LIKE 'abc';"</div><div>+<span style="white-space:pre">   </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "12." .. tostring(i)</div><div>+<span style="white-space:pre"> </span>test_itself = "SELECT 'abc" .. tested_string .. "' LIKE 'abc';"</div><div>+<span style="white-space:pre">  </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+</div><div>+<span style="white-space:pre">   </span>test_name = prefix .. "13." .. tostring(i)</div><div>+<span style="white-space:pre"> </span>test_itself = "SELECT 'ab" .. tested_string .. "c' LIKE 'abc';"</div><div>+<span style="white-space:pre">  </span>test:do_execsql_test(</div><div>+<span style="white-space:pre">                </span>test_name,</div><div>+<span style="white-space:pre">           </span>test_itself, {</div><div>+<span style="white-space:pre">                       </span>-- <test_name></div><div>+<span style="white-space:pre">                 </span>0</div><div>+<span style="white-space:pre">                    </span>-- <test_name></div><div>+<span style="white-space:pre">         </span>})</div><div>+end</div><div>+</div><div>+test:finish_test()</div><div> </div></div></div>