<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hello! thank you for the review.<div class=""><br class=""></div><div class="">Issues:<br class=""><a href="https://github.com/tarantool/tarantool/issues/3251" class="">https://github.com/tarantool/tarantool/issues/3251</a><br class=""><a href="https://github.com/tarantool/tarantool/issues/3334" class="">https://github.com/tarantool/tarantool/issues/3334</a><br class=""><br class="">Branch:<br class=""><a href="https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3251-where-like-hangs" class="">https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3251-where-like-hangs</a></div><div class=""><br class=""><div class="">Please consider following changes:</div><div class=""><br class=""></div><div class="">1. I rebased the whole branch on fresh 2.1.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 29, 2018, at 15:15, Alexander Turenko <<a href="mailto:alexander.turenko@tarantool.org" class="">alexander.turenko@tarantool.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi!<br class=""><br class="">See remaining comments below.<br class=""><br class="">WBR, Alexander Turenko.<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">+static const int case_insensitive_like = 1;<br class="">+static const int case_sensitive_like = 0;<br class=""></blockquote><br class="">Are not they are mutually exclusive? Can we leave just one?<br class=""><br class="">Why they are not defines?<br class=""></blockquote><br class="">I guess it’s a bad idea since we need pointers to them in some functions.<br class="">e.g:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">       </span>int *is_like_ci;<br class=""><span class="Apple-tab-span" style="white-space:pre">       </span>if (is_case_sensitive)<br class=""><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>is_like_ci = (void *)&case_sensitive_like;<br class=""><span class="Apple-tab-span" style="white-space:pre"> </span>else<br class=""><span class="Apple-tab-span" style="white-space:pre">   </span><span class="Apple-tab-span" style="white-space:pre">    </span>is_like_ci = (void *)&case_insensitive_like;<br class=""><span class="Apple-tab-span" style="white-space:pre">       </span>sqlite3CreateFunc(db, "LIKE", 2, 0, is_like_ci, likeFunc, 0, 0, 0);<br class=""><span class="Apple-tab-span" style="white-space:pre">  </span>sqlite3CreateFunc(db, "LIKE", 3, 0, is_like_ci, likeFunc, 0, 0, 0);<br class=""></blockquote><br class="">I think we can use SQLITE_INT_TO_PTR and SQLITE_PTR_TO_INT to pass an<br class="">integer value as a pointer and then cast it back. Maybe we also should<br class="">change LIKEFUNC macro.<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class=""><blockquote type="cite" class="">+       int *is_like_ci;<br class="">+       if (is_case_sensitive)<br class="">+               is_like_ci = (int *)&case_sensitive_like;<br class="">+       else<br class="">+               is_like_ci = (int *)&case_insensitive_like;<br class=""></blockquote><br class="">Discarding const qualifier? It seems not being right thing to do. It is<br class="">better to define is_like_ci pointer as const.<br class=""></blockquote><br class="">It’s not possible due to so-called “down qualification” and will cause<br class="">compiler warnings.<br class=""></blockquote><br class="">We'll anyway discard it here or there, so nevermind. I proposed to<br class="">change it to SQLITE_INT_TO_PTR.<br class=""><br class=""></div></div></blockquote></div></div><div class=""><br class=""></div><div class="">2. Changed manipulations with “sensitiveness” of LIKE using your advice</div><div class="">thus there’s no static consts in func.c anymore.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">diff with the previous version of the patch:</div><div class=""><br class=""></div><div class=""><div class="">diff --git a/src/box/sql/func.c b/src/box/sql/func.c</div><div class="">index b1983e594..5feab52f6 100644</div><div class="">--- a/src/box/sql/func.c</div><div class="">+++ b/src/box/sql/func.c</div><div class="">@@ -627,18 +627,6 @@ total_changes(sqlite3_context * context, int NotUsed, sqlite3_value ** NotUsed2)</div><div class=""> #define SQL_END_OF_STRING        0xffff</div><div class=""> #define SQL_INVALID_UTF8_SYMBOL  0xfffd</div><div class=""> </div><div class="">-/**</div><div class="">- * If SQLITE_CASE_SENSITIVE_LIKE is not defined, then the LIKE</div><div class="">- * operator is not case sensitive.</div><div class="">- */</div><div class="">-static const int case_insensitive_like = 1;</div><div class="">-</div><div class="">-/**</div><div class="">- * If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE</div><div class="">- * operator is case sensitive causing 'a' LIKE 'A' to be false.</div><div class="">- */</div><div class="">-static const int case_sensitive_like = 0;</div><div class="">-</div><div class=""> /**</div><div class="">  * Possible error returns from sql_utf8_pattern_compare().</div><div class="">  */</div><div class="">@@ -819,8 +807,7 @@ sql_utf8_pattern_compare(const char *pattern,</div><div class=""> int</div><div class=""> sql_strlike_cs(const char *zPattern, const char *zStr, unsigned int esc)</div><div class=""> {</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">       </span>return sql_utf8_pattern_compare(zPattern, zStr, case_sensitive_like,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                                     </span>esc);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>return sql_utf8_pattern_compare(zPattern, zStr, 0, esc);</div><div class=""> }</div><div class=""> </div><div class=""> /**</div><div class="">@@ -830,8 +817,7 @@ sql_strlike_cs(const char *zPattern, const char *zStr, unsigned int esc)</div><div class=""> int</div><div class=""> sql_strlike_ci(const char *zPattern, const char *zStr, unsigned int esc)</div><div class=""> {</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">   </span>return sql_utf8_pattern_compare(zPattern, zStr, case_insensitive_like,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                                   </span>esc);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>return sql_utf8_pattern_compare(zPattern, zStr, 1, esc);</div><div class=""> }</div><div class=""> </div><div class=""> /**</div><div class="">@@ -859,7 +845,7 @@ likeFunc(sqlite3_context *context, int argc, sqlite3_value **argv)</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>u32 escape = SQL_END_OF_STRING;</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">     </span>int nPat;</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">   </span>sqlite3 *db = sqlite3_context_db_handle(context);</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">        </span>int *is_like_ci = sqlite3_user_data(context);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">    </span>int is_like_ci = SQLITE_PTR_TO_INT(sqlite3_user_data(context));</div><div class=""> </div><div class=""> #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>if (sqlite3_value_type(argv[0]) == SQLITE_BLOB</div><div class="">@@ -913,7 +899,7 @@ likeFunc(sqlite3_context *context, int argc, sqlite3_value **argv)</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">      </span>sqlite3_like_count++;</div><div class=""> #endif</div><div class=""> <span class="Apple-tab-span" style="white-space:pre"> </span>int res;</div><div class="">-<span class="Apple-tab-span" style="white-space:pre"> </span>res = sql_utf8_pattern_compare(zB, zA, *is_like_ci, escape);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">     </span>res = sql_utf8_pattern_compare(zB, zA, is_like_ci, escape);</div><div class=""> <span class="Apple-tab-span" style="white-space:pre"> </span>if (res == SQL_INVALID_PATTERN) {</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">           </span>const char *const err_msg =</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                 </span>"LIKE pattern can only contain UTF-8 characters";</div><div class="">@@ -1698,24 +1684,20 @@ setLikeOptFlag(sqlite3 * db, const char *zName, u8 flagVal)</div><div class="">  * @retval none.</div><div class="">  */</div><div class=""> void</div><div class="">-sqlite3RegisterLikeFunctions(sqlite3 *db, int is_case_sensitive)</div><div class="">+sqlite3RegisterLikeFunctions(sqlite3 *db, int *is_case_insensitive)</div><div class=""> {</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">   </span>/*</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">  </span> * FIXME: after introducing type <BOOLEAN> LIKE must</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">  </span> * return that type: TRUE if the string matches the</div><div class=""> <span class="Apple-tab-span" style="white-space:pre"> </span> * supplied pattern and FALSE otherwise.</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">    </span> */</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">      </span>int *is_like_ci;</div><div class="">-<span class="Apple-tab-span" style="white-space:pre"> </span>if (is_case_sensitive)</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">           </span>is_like_ci = (void *)&case_sensitive_like;</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">   </span>else</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">             </span>is_like_ci = (void *)&case_insensitive_like;</div><div class="">-<span class="Apple-tab-span" style="white-space:pre"> </span>sqlite3CreateFunc(db, "LIKE", AFFINITY_INTEGER, 2, 0, is_like_ci,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                      </span>  likeFunc, 0, 0, 0);</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">       </span>sqlite3CreateFunc(db, "LIKE", AFFINITY_INTEGER, 3, 0, is_like_ci,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                      </span>  likeFunc, 0, 0, 0);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">       </span>int is_like_ci = SQLITE_PTR_TO_INT(is_case_insensitive);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre"> </span>sqlite3CreateFunc(db, "LIKE", AFFINITY_INTEGER, 2, 0,</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                  </span>  is_case_insensitive, likeFunc, 0, 0, 0);</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">  </span>sqlite3CreateFunc(db, "LIKE", AFFINITY_INTEGER, 3, 0,</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                  </span>  is_case_insensitive, likeFunc, 0, 0, 0);</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">     </span>setLikeOptFlag(db, "LIKE",</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">             </span>       is_case_sensitive ? (SQLITE_FUNC_LIKE |</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">            </span>       !(is_like_ci) ? (SQLITE_FUNC_LIKE |</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">           </span>       SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);</div><div class=""> }</div><div class=""> </div><div class="">@@ -1841,14 +1823,14 @@ sqlite3RegisterBuiltinFunctions(void)</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                        </span>  groupConcatFinalize, AFFINITY_TEXT),</div><div class=""> </div><div class=""> #ifdef SQLITE_CASE_SENSITIVE_LIKE</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">             </span>LIKEFUNC(like, 2, &case_sensitive_like,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                      </span> SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE, AFFINITY_INTEGER),</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">         </span>LIKEFUNC(like, 3, &case_sensitive_like,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                      </span> SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE, AFFINITY_INTEGER),</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">         </span>LIKEFUNC(like, 2, 0,SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE,</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                 </span> AFFINITY_INTEGER),</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">              </span>LIKEFUNC(like, 3, 0,SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE,</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                 </span> AFFINITY_INTEGER),</div><div class=""> #else</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">         </span>LIKEFUNC(like, 2, &case_insensitive_like, SQLITE_FUNC_LIKE,</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">          </span>LIKEFUNC(like, 2, 1, SQLITE_FUNC_LIKE,</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                      </span>AFFINITY_INTEGER),</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">               </span>LIKEFUNC(like, 3, &case_insensitive_like, SQLITE_FUNC_LIKE,</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">          </span>LIKEFUNC(like, 3, 1, SQLITE_FUNC_LIKE,</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                      </span>AFFINITY_INTEGER),</div><div class=""> #endif</div><div class=""> #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION</div><div class="">diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c</div><div class="">index cd6db2b34..546b18ae2 100644</div><div class="">--- a/src/box/sql/pragma.c</div><div class="">+++ b/src/box/sql/pragma.c</div><div class="">@@ -586,9 +586,10 @@ sqlite3Pragma(Parse * pParse, Token * pId,<span class="Apple-tab-span" style="white-space:pre">     </span>/* First part of [schema.]id field */</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">               </span> */</div><div class=""> <span class="Apple-tab-span" style="white-space:pre"> </span>case PragTyp_CASE_SENSITIVE_LIKE:{</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                  </span>if (zRight) {</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                            </span>int *is_like_ci =</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                                        </span>SQLITE_INT_TO_PTR(!(sqlite3GetBoolean(zRight, 0)));</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                         </span>sqlite3RegisterLikeFunctions(db,</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                                                 </span>     sqlite3GetBoolean</div><div class="">-<span class="Apple-tab-span" style="white-space:pre">                                                 </span>     (zRight, 0));</div><div class="">+<span class="Apple-tab-span" style="white-space:pre">                                                     </span>     is_like_ci);</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                 </span>}</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                   </span>break;</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">              </span>}</div><div class="">diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h</div><div class="">index f92d4e6b8..dd819622b 100644</div><div class="">--- a/src/box/sql/sqliteInt.h</div><div class="">+++ b/src/box/sql/sqliteInt.h</div><div class="">@@ -1759,7 +1759,7 @@ struct FuncDestructor {</div><div class="">    pArg, 0, xFunc, 0, #zName, {SQLITE_AFF_STRING, {0}}}</div><div class=""> #define LIKEFUNC(zName, nArg, arg, flags, type) \</div><div class="">   {nArg, SQLITE_FUNC_CONSTANT|flags, \</div><div class="">-   (void *)arg, 0, likeFunc, 0, #zName, {0}, type }</div><div class="">+   (void *)(SQLITE_INT_TO_PTR(arg)), 0, likeFunc, 0, #zName, {0}, type }</div><div class=""> #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, type) \</div><div class="">   {nArg, (nc*SQLITE_FUNC_NEEDCOLL), \</div><div class="">    SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}, type}</div><div class="">@@ -4551,7 +4551,7 @@ sql_key_info_unref(struct sql_key_info *key_info);</div><div class=""> struct key_def *</div><div class=""> sql_key_info_to_key_def(struct sql_key_info *key_info);</div><div class=""> </div><div class="">-void sqlite3RegisterLikeFunctions(sqlite3 *, int);</div><div class="">+void sqlite3RegisterLikeFunctions(sqlite3 *, int *);</div><div class=""> int sql_is_like_func(sqlite3 *, Expr *, int *);</div><div class=""> int sqlite3CreateFunc(sqlite3 *, const char *, enum affinity_type,</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">                </span>      int, int, void *,</div><div class="">diff --git a/test/sql-tap/collation.test.lua b/test/sql-tap/collation.test.lua</div><div class="">index eb4f43a90..dbbe1c0fe 100755</div><div class="">--- a/test/sql-tap/collation.test.lua</div><div class="">+++ b/test/sql-tap/collation.test.lua</div><div class="">@@ -219,7 +219,7 @@ local like_testcases =</div><div class="">         {0, {"Aab", "aaa"}} },</div><div class="">     {"2.1.2",</div><div class="">         "EXPLAIN QUERY PLAN SELECT * FROM tx1 WHERE s1 LIKE 'A%';",</div><div class="">-        {0, {0, 0, 0, "/USING COVERING INDEX I1/"}} },</div><div class="">+        {0, {0, 0, 0, "SEARCH TABLE TX1 USING COVERING INDEX I1 (S1>? AND S1<?)"}}},</div><div class="">     {"2.2.0",</div><div class="">         "PRAGMA case_sensitive_like = true;",</div><div class="">         {0}},</div></div><div class=""><br class=""></div></div></body></html>