From e49c7ae45fb5dc301700cf9a890889a24ab91c69 Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Tue, 30 Dec 2003 19:23:38 +0400 Subject: [PATCH 1/2] Fix for the bug #2231: string column, INDEX+LIKE, don't take the ESCAPE character. (acctually i don't like the fix, any suggestions?) --- mysql-test/r/func_like.result | 6 ++++++ mysql-test/t/func_like.test | 9 +++++++++ sql/item_cmpfunc.h | 9 ++++----- sql/opt_range.cc | 11 +++++++---- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result index f923c16b2ac..0f94348a5f8 100644 --- a/mysql-test/r/func_like.result +++ b/mysql-test/r/func_like.result @@ -37,3 +37,9 @@ select * from t1 where a like "%abc\d%"; a abcd drop table t1; +create table t1 (a varchar(10), key(a)); +insert into t1 values ('a'), ('a\\b'); +select * from t1 where a like 'a\\%' escape '#'; +a +a\b +drop table t1; diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test index a5d1193fd74..1e14c70a76a 100644 --- a/mysql-test/t/func_like.test +++ b/mysql-test/t/func_like.test @@ -21,3 +21,12 @@ select * from t1 where a like "%abcd%"; select * from t1 where a like "%abc\d%"; drop table t1; + +# +# Bug #2231 +# + +create table t1 (a varchar(10), key(a)); +insert into t1 values ('a'), ('a\\b'); +select * from t1 where a like 'a\\%' escape '#'; +drop table t1; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 58c7ea8d00d..9f19e7575d5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -505,8 +505,6 @@ public: class Item_func_like :public Item_bool_func2 { - char escape; - // Turbo Boyer-Moore data bool canDoTurboBM; // pattern is '%abcd%' case const char* pattern; @@ -523,10 +521,11 @@ class Item_func_like :public Item_bool_func2 enum { alphabet_size = 256 }; public: + char escape; + Item_func_like(Item *a,Item *b, char* escape_arg) - :Item_bool_func2(a,b), escape(*escape_arg), canDoTurboBM(false), - pattern(0), pattern_len(0), bmGs(0), bmBc(0) - {} + :Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0), + bmGs(0), bmBc(0), escape(*escape_arg) {} longlong val_int(); enum Functype functype() const { return LIKE_FUNC; } optimize_type select_optimize() const; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7e5ca50d349..c918635b61f 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -290,6 +290,7 @@ typedef struct st_qsel_param { char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH], max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; bool quick; // Don't calulate possible keys + char escape; } PARAM; static SEL_TREE * get_mm_parts(PARAM *param,Field *field, @@ -637,7 +638,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, param.table=head; param.keys=0; param.mem_root= &alloc; - + if (cond->type() == Item::FUNC_ITEM && + ((Item_func*)cond)->functype() == Item_func::LIKE_FUNC) + param.escape= ((Item_func_like*)cond)->escape; param.thd->no_errors=1; // Don't warn about NULL init_sql_alloc(&alloc, param.thd->variables.range_alloc_block_size, 0); if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc, @@ -994,7 +997,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, if (maybe_null) max_str[0]= min_str[0]=0; if (field->binary()) - like_error=like_range(res->ptr(),res->length(),wild_prefix,field_length, + like_error=like_range(res->ptr(),res->length(),param->escape,field_length, min_str+offset,max_str+offset,(char) 255, &min_length,&max_length); else @@ -1002,12 +1005,12 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, #ifdef USE_STRCOLL if (use_strcoll(default_charset_info)) like_error= my_like_range(default_charset_info, - res->ptr(),res->length(),wild_prefix, + res->ptr(),res->length(),param->escape, field_length, min_str+maybe_null, max_str+maybe_null,&min_length,&max_length); else #endif - like_error=like_range(res->ptr(),res->length(),wild_prefix, + like_error=like_range(res->ptr(),res->length(),param->escape, field_length, min_str+offset,max_str+offset, max_sort_char,&min_length,&max_length); From 75df01727697988b52e616c1f82ab9324ae2663d Mon Sep 17 00:00:00 2001 From: "ram@gw.mysql.r18.ru" <> Date: Thu, 8 Jan 2004 12:24:36 +0400 Subject: [PATCH 2/2] An improvement of the fix for the bug #2231: string column, INDEX+LIKE, don't take the ESCAPE character. (ver. 2) --- mysql-test/r/func_like.result | 3 +++ mysql-test/t/func_like.test | 1 + sql/opt_range.cc | 32 +++++++++++++++++--------------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result index 0f94348a5f8..b196b50f53b 100644 --- a/mysql-test/r/func_like.result +++ b/mysql-test/r/func_like.result @@ -42,4 +42,7 @@ insert into t1 values ('a'), ('a\\b'); select * from t1 where a like 'a\\%' escape '#'; a a\b +select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b'; +a +a\b drop table t1; diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test index 1e14c70a76a..6d6ee8f86a3 100644 --- a/mysql-test/t/func_like.test +++ b/mysql-test/t/func_like.test @@ -29,4 +29,5 @@ drop table t1; create table t1 (a varchar(10), key(a)); insert into t1 values ('a'), ('a\\b'); select * from t1 where a like 'a\\%' escape '#'; +select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b'; drop table t1; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c918635b61f..bed1b52a79a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -290,7 +290,7 @@ typedef struct st_qsel_param { char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH], max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; bool quick; // Don't calulate possible keys - char escape; + COND *cond; } PARAM; static SEL_TREE * get_mm_parts(PARAM *param,Field *field, @@ -638,9 +638,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, param.table=head; param.keys=0; param.mem_root= &alloc; - if (cond->type() == Item::FUNC_ITEM && - ((Item_func*)cond)->functype() == Item_func::LIKE_FUNC) - param.escape= ((Item_func_like*)cond)->escape; param.thd->no_errors=1; // Don't warn about NULL init_sql_alloc(&alloc, param.thd->variables.range_alloc_block_size, 0); if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc, @@ -821,6 +818,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE) DBUG_RETURN(0); // Can't be calculated + param->cond= cond; + if (cond_func->functype() == Item_func::BETWEEN) { if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM) @@ -997,23 +996,26 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, if (maybe_null) max_str[0]= min_str[0]=0; if (field->binary()) - like_error=like_range(res->ptr(),res->length(),param->escape,field_length, - min_str+offset,max_str+offset,(char) 255, - &min_length,&max_length); + like_error=like_range(res->ptr(), res->length(), + ((Item_func_like*)(param->cond))->escape, + field_length, min_str + offset, max_str + offset, + (char) 255, &min_length, &max_length); else { #ifdef USE_STRCOLL if (use_strcoll(default_charset_info)) - like_error= my_like_range(default_charset_info, - res->ptr(),res->length(),param->escape, - field_length, min_str+maybe_null, - max_str+maybe_null,&min_length,&max_length); + like_error= my_like_range(default_charset_info, res->ptr(), + res->length(), + ((Item_func_like*)(param->cond))->escape, + field_length, min_str + maybe_null, + max_str + maybe_null, &min_length, + &max_length); else #endif - like_error=like_range(res->ptr(),res->length(),param->escape, - field_length, - min_str+offset,max_str+offset, - max_sort_char,&min_length,&max_length); + like_error=like_range(res->ptr(), res->length(), + ((Item_func_like*)(param->cond))->escape, + field_length, min_str + offset, max_str + offset, + max_sort_char, &min_length, &max_length); } if (like_error) // Can't optimize with LIKE DBUG_RETURN(0);