@@ -5920,7 +5920,7 @@ Item_equal::Item_equal(THD *thd, Item *f1, Item *f2, bool with_const_item):
5920
5920
with_const= with_const_item;
5921
5921
equal_items.push_back (f1, thd->mem_root );
5922
5922
equal_items.push_back (f2, thd->mem_root );
5923
- compare_as_dates= with_const_item && f2->cmp_type () == TIME_RESULT ;
5923
+ cmp. cmp_collation . set ( f2->collation ) ;
5924
5924
cmp.set_compare_type (item_cmp_type (f1, f2));
5925
5925
upper_levels= NULL ;
5926
5926
}
@@ -5950,7 +5950,7 @@ Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
5950
5950
equal_items.push_back (item, thd->mem_root );
5951
5951
}
5952
5952
with_const= item_equal->with_const ;
5953
- compare_as_dates= item_equal->compare_as_dates ;
5953
+ cmp. cmp_collation . set ( item_equal->cmp . cmp_collation ) ;
5954
5954
cmp.set_compare_type (item_equal->cmp .compare_type ());
5955
5955
cond_false= item_equal->cond_false ;
5956
5956
upper_levels= item_equal->upper_levels ;
@@ -5971,41 +5971,85 @@ Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
5971
5971
the list. Otherwise the value of c is compared with the value of the
5972
5972
constant item from equal_items. If they are not equal cond_false is set
5973
5973
to TRUE. This serves as an indicator that this Item_equal is always FALSE.
5974
- The optional parameter f is used to adjust the flag compare_as_dates.
5975
5974
*/
5976
5975
5977
- void Item_equal::add_const (THD *thd, Item *c, Item *f )
5976
+ void Item_equal::add_const (THD *thd, Item *c)
5978
5977
{
5979
5978
if (cond_false)
5980
5979
return ;
5981
5980
if (!with_const)
5982
5981
{
5983
5982
with_const= TRUE ;
5984
- if (f)
5985
- compare_as_dates= f->cmp_type () == TIME_RESULT;
5986
5983
equal_items.push_front (c, thd->mem_root );
5987
5984
return ;
5988
5985
}
5989
5986
Item *const_item= get_const ();
5990
- if (compare_as_dates)
5991
- {
5992
- cmp.set_datetime_cmp_func (this , &c, &const_item);
5993
- cond_false= cmp.compare ();
5994
- }
5995
- else
5996
- {
5997
- Item_func_eq *func= new (thd->mem_root ) Item_func_eq (thd, c, const_item);
5998
- if (func->set_cmp_func ())
5987
+ switch (cmp.compare_type ()) {
5988
+ case TIME_RESULT:
5999
5989
{
5990
+ cmp.set_datetime_cmp_func (this , &c, &const_item);
5991
+ cond_false= cmp.compare ();
5992
+ break ;
5993
+ }
5994
+ case STRING_RESULT:
5995
+ {
5996
+ String *str1, *str2;
6000
5997
/*
6001
- Setting a comparison function fails when trying to compare
6002
- incompatible charsets. Charset compatibility is checked earlier,
6003
- except for constant subqueries where we may do it here.
5998
+ Suppose we have an expression (with a string type field) like this:
5999
+ WHERE field=const1 AND field=const2 ...
6000
+
6001
+ For all pairs field=constXXX we know that:
6002
+
6003
+ - Item_func_eq::fix_length_and_dec() performed collation and character
6004
+ set aggregation and added character set converters when needed.
6005
+ Note, the case like:
6006
+ WHERE field=const1 COLLATE latin1_bin AND field=const2
6007
+ is not handled here, because the field would be replaced to
6008
+ Item_func_set_collation, which cannot get into Item_equal.
6009
+ So all constXXX that are handled by Item_equal
6010
+ already have compatible character sets with "field".
6011
+
6012
+ - Also, Field_str::test_if_equality_guarantees_uniqueness() guarantees
6013
+ that the comparison collation of all equalities handled by Item_equal
6014
+ match the the collation of the field.
6015
+
6016
+ Therefore, at Item_equal::add_const() time all constants constXXX
6017
+ should be directly comparable to each other without an additional
6018
+ character set conversion.
6019
+ It's safe to do val_str() for "const_item" and "c" and compare
6020
+ them according to the collation of the *field*.
6021
+
6022
+ So in a script like this:
6023
+ CREATE TABLE t1 (a VARCHAR(10) COLLATE xxx);
6024
+ INSERT INTO t1 VALUES ('a'),('A');
6025
+ SELECT * FROM t1 WHERE a='a' AND a='A';
6026
+ Item_equal::add_const() effectively rewrites the condition to:
6027
+ SELECT * FROM t1 WHERE a='a' AND 'a' COLLATE xxx='A';
6028
+ and then to:
6029
+ SELECT * FROM t1 WHERE a='a'; // if the two constants were equal
6030
+ // e.g. in case of latin1_swedish_ci
6031
+ or to:
6032
+ SELECT * FROM t1 WHERE FALSE; // if the two constants were not equal
6033
+ // e.g. in case of latin1_bin
6034
+
6035
+ Note, both "const_item" and "c" can return NULL, e.g.:
6036
+ SELECT * FROM t1 WHERE a=NULL AND a='const';
6037
+ SELECT * FROM t1 WHERE a='const' AND a=NULL;
6038
+ SELECT * FROM t1 WHERE a='const' AND a=(SELECT MAX(a) FROM t2)
6004
6039
*/
6005
- return ;
6040
+ cond_false= !(str1= const_item->val_str (&cmp.value1 )) ||
6041
+ !(str2= c->val_str (&cmp.value2 )) ||
6042
+ !str1->eq (str2, compare_collation ());
6043
+ break ;
6044
+ }
6045
+ default :
6046
+ {
6047
+ Item_func_eq *func= new (thd->mem_root ) Item_func_eq (thd, c, const_item);
6048
+ if (func->set_cmp_func ())
6049
+ return ;
6050
+ func->quick_fix_field ();
6051
+ cond_false= !func->val_int ();
6006
6052
}
6007
- func->quick_fix_field ();
6008
- cond_false= !func->val_int ();
6009
6053
}
6010
6054
if (with_const && equal_items.elements == 1 )
6011
6055
cond_true= TRUE ;
@@ -6482,14 +6526,6 @@ void Item_equal::print(String *str, enum_query_type query_type)
6482
6526
}
6483
6527
6484
6528
6485
- CHARSET_INFO *Item_equal::compare_collation () const
6486
- {
6487
- Item_equal_fields_iterator it (*((Item_equal*) this ));
6488
- Item *item= it++;
6489
- return item->collation .collation ;
6490
- }
6491
-
6492
-
6493
6529
/*
6494
6530
@brief Get the first equal field of multiple equality.
6495
6531
@param[in] field the field to get equal field to
0 commit comments