<div dir="ltr">Hello, thank you for review!<div>Diff in the end.<br><br><br><div class="gmail_quote"><div dir="ltr">пт, 27 июл. 2018 г. в 23:22, 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">Minor comments are below. Looks good for me in general.<br>
<br>
Please, review the patch with Lesha after the fixes.<br>
<br>
WBR, Alexander Turenko.<br>
<br>
> > > 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>
> ><br>
> I guess commit message is about changes. Do I really need to<br>
> mention valid cases that didn't change?<br>
> <br>
<br>
Ok, now I got that 'it' is 'invalid symbol'. Misunderstood it before as<br>
description of the one case when a pattern has invalid UTF-8 symbols.<br>
The sentence is correct. Maybe it can be clarified like so: '& correct<br>
UTF-8 pattern will not be matched with a string with invalid UTF-8<br>
symbols'. Or in another way you like.<br>
<br>
'Some minor corrections to function were made as well' -- describe<br>
certain behaviour or code changes (like 'fixed infinite loop during<br>
pattern matching and incorrect matching as well') or remove this<br>
abstract sentence.<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">
> > The function itself looks good except lines longer then 80 columns.<br>
> ><br>
> <br>
> As i said before I don't think breaking these lines will increase<br>
> readability.<br>
> <br>
<br>
There are two little length exceed place in the code, it needs some<br>
refactoring to decrease code blocks nesting level. I think we can lease<br>
it as is for now (if other reviewer don't ask for that).<br>
<br>
But comments within the function are worth to fix to fit the limit.<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">
> +test:do_catchsql_set_test(like_test_cases, prefix)<br>
> +<br>
> +-- Invalid testcases.<br>
> +<br>
> +for i, tested_string in ipairs(invalid_testcases) do<br>
> +<br>
> +-- We should raise an error if pattern contains invalid characters.<br>
<br>
Again, indent comments to the same level as code in the block.<br>
<br>
If a comment is related to several code blocks (with empty lines btw),<br>
then separate it with the empty line from the code (to don't<br>
misinterpret it as related to the first block).<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">
> + local test_name = prefix .. "2." .. tostring(i)<br>
> + local test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "';"<br>
> + test:do_catchsql_test(<br>
> + test_name,<br>
> + test_itself, {<br>
> + -- <test_name><br>
> + 1, "LIKE or GLOB pattern can only contain UTF-8 characters"<br>
> + -- <test_name><br>
> + })<br>
> +<br>
<br>
Are there reason to format it like so? Maybe just:<br>
<br>
test:do_catchsql_test(test_name, test_itself,<br>
    {1, "LIKE or GLOB pattern can only contain UTF-8 characters"})<br></blockquote><div><br></div><div>Fixed. </div><div><br></div><div><div>diff --git a/src/box/sql/func.c b/src/box/sql/func.c</div><div>index 2f989d4..7f93ef6 100644</div><div>--- a/src/box/sql/func.c</div><div>+++ b/src/box/sql/func.c</div><div>@@ -703,11 +703,16 @@ sql_utf8_pattern_compare(const char * pattern,</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>-<span style="white-space:pre"> </span>UChar32 matchAll = pInfo->matchAll;<span style="white-space:pre">       </span>/* "*" or "%" */</div><div>-<span style="white-space:pre"> </span>UChar32 noCase = pInfo->noCase;<span style="white-space:pre">   </span>/* True if uppercase==lowercase */</div><div>-<span style="white-space:pre">   </span>const char *zEscaped = 0;<span style="white-space:pre">    </span>/* One past the last escaped input char */</div><div>+<span style="white-space:pre">   </span>/* Next pattern and input string chars */</div><div>+<span style="white-space:pre">    </span>UChar32 c, c2;</div><div>+<span style="white-space:pre">       </span>/* "?" or "_" */</div><div>+<span style="white-space:pre"> </span>UChar32 matchOne = pInfo->matchOne;</div><div>+<span style="white-space:pre">       </span>/* "*" or "%" */</div><div>+<span style="white-space:pre"> </span>UChar32 matchAll = pInfo->matchAll;</div><div>+<span style="white-space:pre">       </span>/* True if uppercase==lowercase */</div><div>+<span style="white-space:pre">   </span>UChar32 noCase = pInfo->noCase;</div><div>+<span style="white-space:pre">   </span>/* One past the last escaped input char */</div><div>+<span style="white-space:pre">   </span>const char *zEscaped = 0;</div><div> <span style="white-space:pre">   </span>const char * pattern_end = pattern + strlen(pattern);</div><div> <span style="white-space:pre">       </span>const char * string_end = string + strlen(string);</div><div> <span style="white-space:pre">  </span>UErrorCode status = U_ZERO_ERROR;</div><div>@@ -716,9 +721,11 @@ sql_utf8_pattern_compare(const char * pattern,</div><div> <span style="white-space:pre">         </span>if (c == SQL_INVALID_UTF8_SYMBOL)</div><div> <span style="white-space:pre">                   </span>return SQL_PROHIBITED_PATTERN;</div><div> <span style="white-space:pre">              </span>if (c == matchAll) {<span style="white-space:pre"> </span>/* Match "*" */</div><div>-<span style="white-space:pre">                    </span>/* Skip over multiple "*" characters in the pattern.  If there</div><div>-<span style="white-space:pre">                    </span> * are also "?" characters, skip those as well, but consume a</div><div>-<span style="white-space:pre">                      </span> * single character of the input string for each "?" skipped</div><div>+<span style="white-space:pre">                       </span>/* Skip over multiple "*" characters in</div><div>+<span style="white-space:pre">                    </span> * the pattern. If there are also "?"</div><div>+<span style="white-space:pre">                      </span> * characters, skip those as well, but</div><div>+<span style="white-space:pre">                       </span> * consume a single character of the</div><div>+<span style="white-space:pre">                 </span> * input string for each "?" skipped.</div><div> <span style="white-space:pre">                     </span> */</div><div> <span style="white-space:pre">                 </span>while ((c = Utf8Read(pattern, pattern_end)) !=</div><div> <span style="white-space:pre">                      </span>       SQL_END_OF_STRING) {</div><div>@@ -733,7 +740,9 @@ sql_utf8_pattern_compare(const char * pattern,</div><div> <span style="white-space:pre">                            </span>if (c2 == SQL_INVALID_UTF8_SYMBOL)</div><div> <span style="white-space:pre">                                  </span>return SQLITE_NOMATCH;</div><div> <span style="white-space:pre">                      </span>}</div><div>-<span style="white-space:pre">                    </span>/* "*" at the end of the pattern matches */</div><div>+<span style="white-space:pre">                        </span>/*</div><div>+<span style="white-space:pre">                   </span> * "*" at the end of the pattern matches.</div><div>+<span style="white-space:pre">                  </span> */</div><div> <span style="white-space:pre">                 </span>if (c == SQL_END_OF_STRING) {</div><div> <span style="white-space:pre">                               </span>while ((c2 = Utf8Read(string, string_end)) !=</div><div> <span style="white-space:pre">                               </span>       SQL_END_OF_STRING)</div><div>@@ -749,10 +758,14 @@ sql_utf8_pattern_compare(const char * pattern,</div><div> <span style="white-space:pre">                                    </span>if (c == SQL_END_OF_STRING)</div><div> <span style="white-space:pre">                                         </span>return SQLITE_NOWILDCARDMATCH;</div><div> <span style="white-space:pre">                              </span>} else {</div><div>-<span style="white-space:pre">                                     </span>/* "[...]" immediately follows the "*".  We have to do a slow</div><div>-<span style="white-space:pre">                                   </span> * recursive search in this case, but it is an unusual case.</div><div>+<span style="white-space:pre">                                 </span>/* "[...]" immediately</div><div>+<span style="white-space:pre">                                     </span> * follows the "*". We</div><div>+<span style="white-space:pre">                                     </span> * have to do a slow</div><div>+<span style="white-space:pre">                                 </span> * recursive search in</div><div>+<span style="white-space:pre">                                       </span> * this case, but it is</div><div>+<span style="white-space:pre">                                      </span> * an unusual case.</div><div> <span style="white-space:pre">                                 </span> */</div><div>-<span style="white-space:pre">                                  </span>assert(matchOther < 0x80);<span style="white-space:pre">        </span>/* '[' is a single-byte character */</div><div>+<span style="white-space:pre">                                 </span>assert(matchOther < 0x80);</div><div> <span style="white-space:pre">                                       </span>while (string < string_end) {</div><div> <span style="white-space:pre">                                            </span>int bMatch =</div><div> <span style="white-space:pre">                                                </span>    sql_utf8_pattern_compare(</div><div>@@ -770,14 +783,17 @@ sql_utf8_pattern_compare(const char * pattern,</div><div> <span style="white-space:pre">                          </span>}</div><div> <span style="white-space:pre">                   </span>}</div><div> </div><div>-<span style="white-space:pre">                   </span>/* At this point variable c contains the first character of the</div><div>-<span style="white-space:pre">                      </span> * pattern string past the "*".  Search in the input string for the</div><div>-<span style="white-space:pre">                       </span> * first matching character and recursively continue the match from</div><div>-<span style="white-space:pre">                  </span> * that point.</div><div>+<span style="white-space:pre">                       </span>/* At this point variable c contains the</div><div>+<span style="white-space:pre">                     </span> * first character of the pattern string</div><div>+<span style="white-space:pre">                     </span> * past the "*". Search in the input</div><div>+<span style="white-space:pre">                       </span> * string for the first matching</div><div>+<span style="white-space:pre">                     </span> * character and recursively continue the</div><div>+<span style="white-space:pre">                    </span> * match from that point.</div><div> <span style="white-space:pre">                   </span> *</div><div>-<span style="white-space:pre">                   </span> * For a case-insensitive search, set variable cx to be the same as</div><div>-<span style="white-space:pre">                  </span> * c but in the other case and search the input string for either</div><div>-<span style="white-space:pre">                    </span> * c or cx.</div><div>+<span style="white-space:pre">                  </span> * For a case-insensitive search, set</div><div>+<span style="white-space:pre">                        </span> * variable cx to be the same as c but in</div><div>+<span style="white-space:pre">                    </span> * the other case and search the input</div><div>+<span style="white-space:pre">                       </span> * string for either c or cx.</div><div> <span style="white-space:pre">                       </span> */</div><div> </div><div> <span style="white-space:pre">                        </span>int bMatch;</div><div>@@ -785,12 +801,14 @@ sql_utf8_pattern_compare(const char * pattern,</div><div> <span style="white-space:pre">                              </span>c = u_tolower(c);</div><div> <span style="white-space:pre">                   </span>while (string < string_end){</div><div> <span style="white-space:pre">                             </span>/**</div><div>-<span style="white-space:pre">                          </span> * This loop could have been implemented</div><div>-<span style="white-space:pre">                             </span> * without if converting c2 to lower case</div><div>-<span style="white-space:pre">                            </span> * (by holding c_upper and c_lower), however</div><div>-<span style="white-space:pre">                         </span> * it is implemented this way because lower</div><div>-<span style="white-space:pre">                          </span> * works better with German and Turkish</div><div>-<span style="white-space:pre">                              </span> * languages.</div><div>+<span style="white-space:pre">                                </span> * This loop could have been</div><div>+<span style="white-space:pre">                         </span> * implemented without if</div><div>+<span style="white-space:pre">                            </span> * converting c2 to lower case</div><div>+<span style="white-space:pre">                               </span> * by holding c_upper and</div><div>+<span style="white-space:pre">                            </span> * c_lower,however it is</div><div>+<span style="white-space:pre">                             </span> * implemented this way because</div><div>+<span style="white-space:pre">                              </span> * lower works better with German</div><div>+<span style="white-space:pre">                            </span> * and Turkish languages.</div><div> <span style="white-space:pre">                           </span> */</div><div> <span style="white-space:pre">                         </span>c2 = Utf8Read(string, string_end);</div><div> <span style="white-space:pre">                          </span>if (c2 == SQL_INVALID_UTF8_SYMBOL)</div><div>@@ -878,11 +896,12 @@ sql_utf8_pattern_compare(const char * pattern,</div><div> <span style="white-space:pre">                       </span>continue;</div><div> <span style="white-space:pre">           </span>if (noCase){</div><div> <span style="white-space:pre">                        </span>/**</div><div>-<span style="white-space:pre">                  </span> * Small optimisation. Reduce number of calls</div><div>-<span style="white-space:pre">                        </span> * to u_tolower function.</div><div>-<span style="white-space:pre">                    </span> * SQL standards suggest use to_upper for symbol</div><div>-<span style="white-space:pre">                     </span> * normalisation. However, using to_lower allows to</div><div>-<span style="white-space:pre">                  </span> * respect Turkish 'İ' in default locale.</div><div>+<span style="white-space:pre">                   </span> * Small optimisation. Reduce number of</div><div>+<span style="white-space:pre">                      </span> * calls to u_tolower function. SQL</div><div>+<span style="white-space:pre">                  </span> * standards suggest use to_upper for</div><div>+<span style="white-space:pre">                        </span> * symbol normalisation. However, using</div><div>+<span style="white-space:pre">                      </span> * to_lower allows to respect Turkish 'İ'</div><div>+<span style="white-space:pre">                   </span> * in default locale.</div><div> <span style="white-space:pre">                       </span> */</div><div> <span style="white-space:pre">                 </span>if (u_tolower(c) == c2 ||</div><div> <span style="white-space:pre">                   </span>    c == u_tolower(c2))</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>index a823bc6..a8e4a12 100755</div><div>--- a/test/sql-tap/gh-3251-string-pattern-comparison.test.lua</div><div>+++ b/test/sql-tap/gh-3251-string-pattern-comparison.test.lua</div><div>@@ -6,276 +6,208 @@ 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>+    '\x01',</div><div>+    '\x09',</div><div>+    '\x1F',</div><div>+    '\x7F',</div><div>+    '\xC2\x80',</div><div>+    '\xC2\x90',</div><div>+    '\xC2\x9F',</div><div>+    '\xE2\x80\xA8',</div><div>+    '\x20\x0B',</div><div>+    '\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>+    '\xE2\x80',</div><div>+    '\xFE\xFF',</div><div>+    '\xC2',</div><div>+    '\xED\xB0\x80',</div><div>+    '\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>+    {"1.1",</div><div>+        "SELECT 'AB' LIKE '_B';",</div><div>+        {0, {1}} },</div><div>+    {"1.2",</div><div>+        "SELECT 'CD' LIKE '_B';",</div><div>+        {0, {0}} },</div><div>+    {"1.3",</div><div>+        "SELECT '' LIKE '_B';",</div><div>+        {0, {0}} },</div><div>+    {"1.4",</div><div>+        "SELECT 'AB' LIKE '%B';",</div><div>+        {0, {1}} },</div><div>+    {"1.5",</div><div>+        "SELECT 'CD' LIKE '%B';",</div><div>+        {0, {0}} },</div><div>+    {"1.6",</div><div>+        "SELECT '' LIKE '%B';",</div><div>+        {0, {0}} },</div><div>+    {"1.7",</div><div>+        "SELECT 'AB' LIKE 'A__';",</div><div>+        {0, {0}} },</div><div>+    {"1.8",</div><div>+        "SELECT 'CD' LIKE 'A__';",</div><div>+        {0, {0}} },</div><div>+    {"1.9",</div><div>+        "SELECT '' LIKE 'A__';",</div><div>+        {0, {0}} },</div><div>+    {"1.10",</div><div>+        "SELECT 'AB' LIKE 'A_';",</div><div>+        {0, {1}} },</div><div>+    {"1.11",</div><div>+        "SELECT 'CD' LIKE 'A_';",</div><div>+        {0, {0}} },</div><div>+    {"1.12",</div><div>+        "SELECT '' LIKE 'A_';",</div><div>+        {0, {0}} },</div><div>+    {"1.13",</div><div>+        "SELECT 'AB' LIKE 'A';",</div><div>+        {0, {0}} },</div><div>+    {"1.14",</div><div>+        "SELECT 'CD' LIKE 'A';",</div><div>+        {0, {0}} },</div><div>+    {"1.15",</div><div>+        "SELECT '' LIKE 'A';",</div><div>+        {0, {0}} },</div><div>+    {"1.16",</div><div>+        "SELECT 'AB' LIKE '_';",</div><div>+        {0, {0}} },</div><div>+    {"1.17",</div><div>+        "SELECT 'CD' LIKE '_';",</div><div>+        {0, {0}} },</div><div>+    {"1.18",</div><div>+        "SELECT '' LIKE '_';",</div><div>+        {0, {0}} },</div><div>+    {"1.19",</div><div>+        "SELECT 'AB' LIKE '__';",</div><div>+        {0, {1}} },</div><div>+    {"1.20",</div><div>+        "SELECT 'CD' LIKE '__';",</div><div>+        {0, {1}} },</div><div>+    {"1.21",</div><div>+        "SELECT '' LIKE '__';",</div><div>+        {0, {0}} },</div><div>+    {"1.22",</div><div>+        "SELECT 'AB' LIKE '%A';",</div><div>+        {0, {0}} },</div><div>+    {"1.23",</div><div>+        "SELECT 'AB' LIKE '%C';",</div><div>+        {0, {0}} },</div><div>+    {"1.24",</div><div>+        "SELECT 'ab' LIKE '%df';",</div><div>+        {0, {0}} },</div><div>+    {"1.25",</div><div>+        "SELECT 'abCDF' LIKE '%df';",</div><div>+        {0, {1}} },</div><div>+    {"1.26",</div><div>+        "SELECT 'CDF' LIKE '%df';",</div><div>+        {0, {1}} },</div><div>+    {"1.27",</div><div>+        "SELECT 'ab' LIKE 'a_';",</div><div>+        {0, {1}} },</div><div>+    {"1.28",</div><div>+        "SELECT 'abCDF' LIKE 'a_';",</div><div>+        {0, {0}} },</div><div>+    {"1.29",</div><div>+        "SELECT 'CDF' LIKE 'a_';",</div><div>+        {0, {0}} },</div><div>+    {"1.30",</div><div>+        "SELECT 'ab' LIKE 'ab%';",</div><div>+        {0, {1}} },</div><div>+    {"1.31",</div><div>+        "SELECT 'abCDF' LIKE 'ab%';",</div><div>+        {0, {1}} },</div><div>+    {"1.32",</div><div>+        "SELECT 'CDF' LIKE 'ab%';",</div><div>+        {0, {0}} },</div><div>+    {"1.33",</div><div>+        "SELECT 'ab' LIKE 'abC%';",</div><div>+        {0, {0}} },</div><div>+    {"1.34",</div><div>+        "SELECT 'abCDF' LIKE 'abC%';",</div><div>+        {0, {1}} },</div><div>+    {"1.35",</div><div>+        "SELECT 'CDF' LIKE 'abC%';",</div><div>+        {0, {0}} },</div><div>+    {"1.36",</div><div>+        "SELECT 'ab' LIKE 'a_%';",</div><div>+        {0, {1}} },</div><div>+    {"1.37",</div><div>+        "SELECT 'abCDF' LIKE 'a_%';",</div><div>+        {0, {1}} },</div><div>+    {"1.38",</div><div>+        "SELECT 'CDF' LIKE 'a_%';",</div><div>+        {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>+    -- We should raise an error in case</div><div>+    -- pattern contains invalid characters.</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>+    local test_name = prefix .. "2." .. tostring(i)</div><div>+    local test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "';"</div><div>+    test:do_catchsql_test(test_name, test_itself,</div><div>+                          {1, "LIKE or GLOB pattern can only contain UTF-8 characters"})</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>+    test_name = prefix .. "3." .. tostring(i)</div><div>+    test_itself = "SELECT 'abc' LIKE 'abc" .. tested_string .. "';"</div><div>+    test:do_catchsql_test(test_name, test_itself,</div><div>+                          {1, "LIKE or GLOB pattern can only contain UTF-8 characters"})</div><div> </div><div>--- Just skipping if row value predicand contains invalid character.</div><div>+    test_name = prefix .. "4." .. tostring(i)</div><div>+    test_itself = "SELECT 'abc' LIKE 'ab" .. tested_string .. "c';"</div><div>+    test:do_catchsql_test(test_name, test_itself,</div><div>+                          {1, "LIKE or GLOB pattern can only contain UTF-8 characters"})</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>+    -- Just skipping if row value predicand contains invalid character.</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>+    test_name = prefix .. "5." .. tostring(i)</div><div>+    test_itself = "SELECT 'ab" .. tested_string .. "' LIKE 'abc';"</div><div>+    test:do_execsql_test(test_name, test_itself, {0})</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>+    test_name = prefix .. "6." .. tostring(i)</div><div>+    test_itself = "SELECT 'abc" .. tested_string .. "' LIKE 'abc';"</div><div>+    test:do_execsql_test(test_name, test_itself, {0})</div><div>+</div><div>+    test_name = prefix .. "7." .. tostring(i)</div><div>+    test_itself = "SELECT 'ab" .. tested_string .. "c' LIKE 'abc';"</div><div>+    test:do_execsql_test(test_name, test_itself, {0})</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>+<span style="white-space:pre">   </span>test:do_execsql_test(test_name, test_itself, {0})</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>+<span style="white-space:pre">   </span>test:do_execsql_test(test_name, test_itself, {0})</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:do_execsql_test(test_name,<span style="white-space:pre">      </span>test_itself, {0})</div><div>+</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>+<span style="white-space:pre">   </span>test:do_execsql_test(test_name,<span style="white-space:pre">      </span>test_itself, {0})</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>+<span style="white-space:pre">   </span>test:do_execsql_test(test_name, test_itself, {0})</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>+<span style="white-space:pre">   </span>test:do_execsql_test(test_name, test_itself, {0})</div><div> end</div><div> </div><div> test:finish_test()</div></div><div><br></div><div><br></div></div></div></div>