@@ -2153,38 +2153,6 @@ class Item_name_const : public Item
2153
2153
}
2154
2154
};
2155
2155
2156
- bool agg_item_collations (DTCollation &c, const char *name,
2157
- Item **items, uint nitems, uint flags, int item_sep);
2158
- bool agg_item_collations_for_comparison (DTCollation &c, const char *name,
2159
- Item **items, uint nitems, uint flags);
2160
- bool agg_item_set_converter (DTCollation &coll, const char *fname,
2161
- Item **args, uint nargs, uint flags, int item_sep);
2162
- bool agg_item_charsets (DTCollation &c, const char *name,
2163
- Item **items, uint nitems, uint flags, int item_sep);
2164
- inline bool
2165
- agg_item_charsets_for_comparison (DTCollation &c, const char *name,
2166
- Item **items, uint nitems,
2167
- int item_sep= 1 )
2168
- {
2169
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
2170
- MY_COLL_ALLOW_COERCIBLE_CONV |
2171
- MY_COLL_DISALLOW_NONE;
2172
- return agg_item_charsets (c, name, items, nitems, flags, item_sep);
2173
- }
2174
- inline bool
2175
- agg_item_charsets_for_string_result_with_comparison (DTCollation &c,
2176
- const char *name,
2177
- Item **items, uint nitems,
2178
- int item_sep= 1 )
2179
- {
2180
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
2181
- MY_COLL_ALLOW_COERCIBLE_CONV |
2182
- MY_COLL_ALLOW_NUMERIC_CONV |
2183
- MY_COLL_DISALLOW_NONE;
2184
- return agg_item_charsets (c, name, items, nitems, flags, item_sep);
2185
- }
2186
-
2187
-
2188
2156
class Item_num : public Item_basic_constant
2189
2157
{
2190
2158
public:
@@ -3616,7 +3584,50 @@ class Used_tables_and_const_cache
3616
3584
*/
3617
3585
class Item_func_or_sum : public Item_result_field , public Item_args
3618
3586
{
3587
+ bool agg_item_collations (DTCollation &c, const char *name,
3588
+ Item **items, uint nitems,
3589
+ uint flags, int item_sep);
3590
+ bool agg_item_set_converter (const DTCollation &coll, const char *fname,
3591
+ Item **args, uint nargs,
3592
+ uint flags, int item_sep);
3619
3593
protected:
3594
+ /*
3595
+ Collect arguments' character sets together.
3596
+ We allow to apply automatic character set conversion in some cases.
3597
+ The conditions when conversion is possible are:
3598
+ - arguments A and B have different charsets
3599
+ - A wins according to coercibility rules
3600
+ (i.e. a column is stronger than a string constant,
3601
+ an explicit COLLATE clause is stronger than a column)
3602
+ - character set of A is either superset for character set of B,
3603
+ or B is a string constant which can be converted into the
3604
+ character set of A without data loss.
3605
+
3606
+ If all of the above is true, then it's possible to convert
3607
+ B into the character set of A, and then compare according
3608
+ to the collation of A.
3609
+
3610
+ For functions with more than two arguments:
3611
+
3612
+ collect(A,B,C) ::= collect(collect(A,B),C)
3613
+
3614
+ Since this function calls THD::change_item_tree() on the passed Item **
3615
+ pointers, it is necessary to pass the original Item **'s, not copies.
3616
+ Otherwise their values will not be properly restored (see BUG#20769).
3617
+ If the items are not consecutive (eg. args[2] and args[5]), use the
3618
+ item_sep argument, ie.
3619
+
3620
+ agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
3621
+ */
3622
+ bool agg_arg_charsets (DTCollation &c, Item **items, uint nitems,
3623
+ uint flags, int item_sep)
3624
+ {
3625
+ if (agg_item_collations (c, func_name (), items, nitems, flags, item_sep))
3626
+ return true ;
3627
+
3628
+ return agg_item_set_converter (c, func_name (), items, nitems,
3629
+ flags, item_sep);
3630
+ }
3620
3631
/*
3621
3632
Aggregate arguments for string result, e.g: CONCAT(a,b)
3622
3633
- convert to @@character_set_connection if all arguments are numbers
@@ -3629,7 +3640,7 @@ class Item_func_or_sum: public Item_result_field, public Item_args
3629
3640
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
3630
3641
MY_COLL_ALLOW_COERCIBLE_CONV |
3631
3642
MY_COLL_ALLOW_NUMERIC_CONV;
3632
- return agg_item_charsets (c, func_name () , items, nitems, flags, item_sep);
3643
+ return agg_arg_charsets (c , items, nitems, flags, item_sep);
3633
3644
}
3634
3645
/*
3635
3646
Aggregate arguments for string result, when some comparison
@@ -3646,7 +3657,48 @@ class Item_func_or_sum: public Item_result_field, public Item_args
3646
3657
MY_COLL_ALLOW_COERCIBLE_CONV |
3647
3658
MY_COLL_ALLOW_NUMERIC_CONV |
3648
3659
MY_COLL_DISALLOW_NONE;
3649
- return agg_item_charsets (c, func_name (), items, nitems, flags, item_sep);
3660
+ return agg_arg_charsets (c, items, nitems, flags, item_sep);
3661
+ }
3662
+
3663
+ /*
3664
+ Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b
3665
+ - don't convert to @@character_set_connection if all arguments are numbers
3666
+ - don't allow DERIVATION_NONE
3667
+ */
3668
+ bool agg_arg_charsets_for_comparison (DTCollation &c,
3669
+ Item **items, uint nitems,
3670
+ int item_sep= 1 )
3671
+ {
3672
+ uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
3673
+ MY_COLL_ALLOW_COERCIBLE_CONV |
3674
+ MY_COLL_DISALLOW_NONE;
3675
+ return agg_arg_charsets (c, items, nitems, flags, item_sep);
3676
+ }
3677
+
3678
+
3679
+ public:
3680
+ // This method is used by Arg_comparator
3681
+ bool agg_arg_charsets_for_comparison (CHARSET_INFO **cs, Item **a, Item **b)
3682
+ {
3683
+ DTCollation tmp;
3684
+ if (tmp.set ((*a)->collation , (*b)->collation , MY_COLL_CMP_CONV) ||
3685
+ tmp.derivation == DERIVATION_NONE)
3686
+ {
3687
+ my_error (ER_CANT_AGGREGATE_2COLLATIONS,MYF (0 ),
3688
+ (*a)->collation .collation ->name ,
3689
+ (*a)->collation .derivation_name (),
3690
+ (*b)->collation .collation ->name ,
3691
+ (*b)->collation .derivation_name (),
3692
+ func_name ());
3693
+ return true ;
3694
+ }
3695
+ if (agg_item_set_converter (tmp, func_name (),
3696
+ a, 1 , MY_COLL_CMP_CONV, 1 ) ||
3697
+ agg_item_set_converter (tmp, func_name (),
3698
+ b, 1 , MY_COLL_CMP_CONV, 1 ))
3699
+ return true ;
3700
+ *cs= tmp.collation ;
3701
+ return false ;
3650
3702
}
3651
3703
3652
3704
public:
0 commit comments