maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #08625
Please review: MDEV-8222 "string_field LIKE int_const" returns a wrong result in case of UCS2
Hi Sergey,
please review my patch for MDEV-8222.
It also moves Arg_compatator from Item_bool_func2 to
Item_bool_rowready_func2.
Thanks.
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 740319a..5b4d132 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -5542,5 +5542,14 @@ select collation(cast("a" as char(10) binary unicode));
collation(cast("a" as char(10) binary unicode))
ucs2_bin
#
+# MDEV-8222 "string_field LIKE int_const" returns a wrong result in case of UCS2
+#
+CREATE TABLE t1 (a VARCHAR(10) CHARSET ucs2);
+INSERT INTO t1 VALUES ('1');
+SELECT * FROM t1 WHERE a LIKE 1;
+a
+1
+DROP TABLE t1;
+#
# End of 10.1 tests
#
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 1dee393..6e5b085 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -925,5 +925,13 @@ select collation(cast("a" as char(10) unicode binary));
select collation(cast("a" as char(10) binary unicode));
--echo #
+--echo # MDEV-8222 "string_field LIKE int_const" returns a wrong result in case of UCS2
+--echo #
+CREATE TABLE t1 (a VARCHAR(10) CHARSET ucs2);
+INSERT INTO t1 VALUES ('1');
+SELECT * FROM t1 WHERE a LIKE 1;
+DROP TABLE t1;
+
+--echo #
--echo # End of 10.1 tests
--echo #
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 5bea5da..a192675 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -503,15 +503,15 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
args[0]->cmp_context= args[1]->cmp_context=
item_cmp_type(args[0]->result_type(), args[1]->result_type());
- // Convert constants when compared to int/year field, unless this is LIKE
- if (functype() != LIKE_FUNC)
- convert_const_compared_to_int_field(thd);
+ // Convert constants when compared to int/year field
+ DBUG_ASSERT(functype() != LIKE_FUNC);
+ convert_const_compared_to_int_field(thd);
return cmp->set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
}
-void Item_bool_func2::fix_length_and_dec()
+void Item_bool_rowready_func2::fix_length_and_dec()
{
max_length= 1; // Function returns 0 or 1
@@ -1881,7 +1881,7 @@ longlong Item_func_eq::val_int()
void Item_func_equal::fix_length_and_dec()
{
- Item_bool_func2::fix_length_and_dec();
+ Item_bool_rowready_func2::fix_length_and_dec();
maybe_null=null_value=0;
}
@@ -4784,13 +4784,13 @@ void Item_func_isnotnull::print(String *str, enum_query_type query_type)
longlong Item_func_like::val_int()
{
DBUG_ASSERT(fixed == 1);
- String* res = args[0]->val_str(&cmp.value1);
+ String* res= args[0]->val_str(&cmp_value1);
if (args[0]->null_value)
{
null_value=1;
return 0;
}
- String* res2 = args[1]->val_str(&cmp.value2);
+ String* res2= args[1]->val_str(&cmp_value2);
if (args[1]->null_value)
{
null_value=1;
@@ -4799,7 +4799,7 @@ longlong Item_func_like::val_int()
null_value=0;
if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
- return my_wildcmp(cmp.cmp_collation.collation,
+ return my_wildcmp(cmp_collation.collation,
res->ptr(),res->ptr()+res->length(),
res2->ptr(),res2->ptr()+res2->length(),
escape,wild_one,wild_many) ? 0 : 1;
@@ -4815,7 +4815,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const
if (!args[1]->const_item() || args[1]->is_expensive())
return OPTIMIZE_NONE;
- String* res2= args[1]->val_str((String *)&cmp.value2);
+ String* res2= args[1]->val_str((String *) &cmp_value2);
if (!res2)
return OPTIMIZE_NONE;
@@ -4845,7 +4845,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
if (escape_item->const_item())
{
/* If we are on execution stage */
- String *escape_str= escape_item->val_str(&cmp.value1);
+ String *escape_str= escape_item->val_str(&cmp_value1);
if (escape_str)
{
const char *escape_str_ptr= escape_str->ptr();
@@ -4858,7 +4858,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
return TRUE;
}
- if (use_mb(cmp.cmp_collation.collation))
+ if (use_mb(cmp_collation.collation))
{
CHARSET_INFO *cs= escape_str->charset();
my_wc_t wc;
@@ -4875,7 +4875,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
code instead of Unicode code as "escape" argument.
Convert to "cs" if charset of escape differs.
*/
- CHARSET_INFO *cs= cmp.cmp_collation.collation;
+ CHARSET_INFO *cs= cmp_collation.collation;
uint32 unused;
if (escape_str->needs_conversion(escape_str->length(),
escape_str->charset(), cs, &unused))
@@ -4901,7 +4901,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
!args[1]->is_expensive())
{
- String* res2 = args[1]->val_str(&cmp.value2);
+ String* res2= args[1]->val_str(&cmp_value2);
if (!res2)
return FALSE; // Null argument
@@ -5182,7 +5182,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
int f = 0;
int g = plm1;
int *const splm1 = suff + plm1;
- CHARSET_INFO *cs= cmp.cmp_collation.collation;
+ CHARSET_INFO *cs= cmp_collation.collation;
*splm1 = pattern_len;
@@ -5282,7 +5282,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
int *end = bmBc + alphabet_size;
int j;
const int plm1 = pattern_len - 1;
- CHARSET_INFO *cs= cmp.cmp_collation.collation;
+ CHARSET_INFO *cs= cmp_collation.collation;
for (i = bmBc; i < end; i++)
*i = pattern_len;
@@ -5314,7 +5314,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
int shift = pattern_len;
int j = 0;
int u = 0;
- CHARSET_INFO *cs= cmp.cmp_collation.collation;
+ CHARSET_INFO *cs= cmp_collation.collation;
const int plm1= pattern_len - 1;
const int tlmpl= text_len - pattern_len;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 06a0c39..f2d0032 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -290,18 +290,10 @@ class Item_in_optimizer: public Item_bool_func
};
class Item_bool_func2 :public Item_bool_func
-{ /* Bool with 2 string args */
-protected:
- Arg_comparator cmp;
-
+{ /* Bool with 2 string args */
public:
Item_bool_func2(Item *a,Item *b)
- :Item_bool_func(a,b), cmp(tmp_arg, tmp_arg+1) { sargable= TRUE; }
- void fix_length_and_dec();
- int set_cmp_func()
- {
- return cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, TRUE);
- }
+ :Item_bool_func(a,b) { sargable= TRUE; }
optimize_type select_optimize() const { return OPTIMIZE_OP; }
virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
@@ -312,14 +304,6 @@ class Item_bool_func2 :public Item_bool_func
}
bool is_null() { return MY_TEST(args[0]->is_null() || args[1]->is_null()); }
- CHARSET_INFO *compare_collation() const
- { return cmp.cmp_collation.collation; }
- Arg_comparator *get_comparator() { return &cmp; }
- void cleanup()
- {
- Item_bool_func::cleanup();
- cmp.cleanup();
- }
COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
bool top_level);
@@ -327,8 +311,11 @@ class Item_bool_func2 :public Item_bool_func
class Item_bool_rowready_func2 :public Item_bool_func2
{
+protected:
+ Arg_comparator cmp;
public:
- Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
+ Item_bool_rowready_func2(Item *a, Item *b)
+ :Item_bool_func2(a, b), cmp(tmp_arg, tmp_arg+1)
{
allowed_arg_cols= 0; // Fetch this value from first argument
}
@@ -338,6 +325,19 @@ class Item_bool_rowready_func2 :public Item_bool_func2
{
return (*arg != NULL);
}
+ void fix_length_and_dec();
+ int set_cmp_func()
+ {
+ return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
+ }
+ CHARSET_INFO *compare_collation() const
+ { return cmp.cmp_collation.collation; }
+ Arg_comparator *get_comparator() { return &cmp; }
+ void cleanup()
+ {
+ Item_bool_func2::cleanup();
+ cmp.cleanup();
+ }
bool can_optimize_group_min_max(Item_field *min_max_arg_item,
const Item *const_item) const
{
@@ -1490,6 +1490,8 @@ class Item_func_like :public Item_bool_func2
bool escape_used_in_parsing;
bool use_sampling;
+ DTCollation cmp_collation;
+ String cmp_value1, cmp_value2;
public:
int escape;
@@ -1500,6 +1502,8 @@ class Item_func_like :public Item_bool_func2
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const;
+ CHARSET_INFO *compare_collation() const
+ { return cmp_collation.collation; }
cond_result eq_cmp_result() const
{
/**
@@ -1539,6 +1543,12 @@ class Item_func_like :public Item_bool_func2
table_map usable_tables, SARGABLE_PARAM **sargables);
const char *func_name() const { return "like"; }
bool fix_fields(THD *thd, Item **ref);
+ void fix_length_and_dec()
+ {
+ max_length= 1;
+ args[0]->cmp_context= args[1]->cmp_context= STRING_RESULT;
+ agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ }
void cleanup();
bool find_selective_predicates_list_processor(uchar *arg);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index dccad7a..0638910 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -13887,7 +13887,8 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
if ((tmp2=new COND_CMP(and_father,func)))
save_list->push_back(tmp2);
}
- func->set_cmp_func();
+ if (functype != Item_func::LIKE_FUNC)
+ ((Item_bool_rowready_func2*) func)->set_cmp_func();
}
}
else if (can_change_cond_ref_to_const(func, left_item, right_item,
@@ -13910,7 +13911,8 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
if ((tmp2=new COND_CMP(and_father,func)))
save_list->push_back(tmp2);
}
- func->set_cmp_func();
+ if (functype != Item_func::LIKE_FUNC)
+ ((Item_bool_rowready_func2*)func)->set_cmp_func();
}
}
}