Skip to content

Commit 22cc8f9

Browse files
author
Alexander Barkov
committed
Changing a number of functions to aggregate argument character sets
and collations from the global name space into private and protected methods in Item_func_or_sum.
1 parent 9b9e36e commit 22cc8f9

File tree

5 files changed

+94
-147
lines changed

5 files changed

+94
-147
lines changed

sql/item.cc

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,8 +2035,9 @@ void my_coll_agg_error(Item** args, uint count, const char *fname,
20352035
}
20362036

20372037

2038-
bool agg_item_collations(DTCollation &c, const char *fname,
2039-
Item **av, uint count, uint flags, int item_sep)
2038+
bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
2039+
Item **av, uint count,
2040+
uint flags, int item_sep)
20402041
{
20412042
uint i;
20422043
Item **arg;
@@ -2081,16 +2082,10 @@ bool agg_item_collations(DTCollation &c, const char *fname,
20812082
}
20822083

20832084

2084-
bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
2085-
Item **av, uint count, uint flags)
2086-
{
2087-
return (agg_item_collations(c, fname, av, count,
2088-
flags | MY_COLL_DISALLOW_NONE, 1));
2089-
}
2090-
2091-
2092-
bool agg_item_set_converter(DTCollation &coll, const char *fname,
2093-
Item **args, uint nargs, uint flags, int item_sep)
2085+
bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll,
2086+
const char *fname,
2087+
Item **args, uint nargs,
2088+
uint flags, int item_sep)
20942089
{
20952090
Item **arg, *safe_args[2]= {NULL, NULL};
20962091

@@ -2167,46 +2162,6 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname,
21672162
}
21682163

21692164

2170-
/*
2171-
Collect arguments' character sets together.
2172-
We allow to apply automatic character set conversion in some cases.
2173-
The conditions when conversion is possible are:
2174-
- arguments A and B have different charsets
2175-
- A wins according to coercibility rules
2176-
(i.e. a column is stronger than a string constant,
2177-
an explicit COLLATE clause is stronger than a column)
2178-
- character set of A is either superset for character set of B,
2179-
or B is a string constant which can be converted into the
2180-
character set of A without data loss.
2181-
2182-
If all of the above is true, then it's possible to convert
2183-
B into the character set of A, and then compare according
2184-
to the collation of A.
2185-
2186-
For functions with more than two arguments:
2187-
2188-
collect(A,B,C) ::= collect(collect(A,B),C)
2189-
2190-
Since this function calls THD::change_item_tree() on the passed Item **
2191-
pointers, it is necessary to pass the original Item **'s, not copies.
2192-
Otherwise their values will not be properly restored (see BUG#20769).
2193-
If the items are not consecutive (eg. args[2] and args[5]), use the
2194-
item_sep argument, ie.
2195-
2196-
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
2197-
2198-
*/
2199-
2200-
bool agg_item_charsets(DTCollation &coll, const char *fname,
2201-
Item **args, uint nargs, uint flags, int item_sep)
2202-
{
2203-
if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
2204-
return TRUE;
2205-
2206-
return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep);
2207-
}
2208-
2209-
22102165
void Item_ident_for_show::make_field(Send_field *tmp_field)
22112166
{
22122167
tmp_field->table_name= tmp_field->org_table_name= table_name;

sql/item.h

Lines changed: 86 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,38 +2153,6 @@ class Item_name_const : public Item
21532153
}
21542154
};
21552155

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-
21882156
class Item_num: public Item_basic_constant
21892157
{
21902158
public:
@@ -3616,7 +3584,50 @@ class Used_tables_and_const_cache
36163584
*/
36173585
class Item_func_or_sum: public Item_result_field, public Item_args
36183586
{
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);
36193593
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+
}
36203631
/*
36213632
Aggregate arguments for string result, e.g: CONCAT(a,b)
36223633
- 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
36293640
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
36303641
MY_COLL_ALLOW_COERCIBLE_CONV |
36313642
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);
36333644
}
36343645
/*
36353646
Aggregate arguments for string result, when some comparison
@@ -3646,7 +3657,48 @@ class Item_func_or_sum: public Item_result_field, public Item_args
36463657
MY_COLL_ALLOW_COERCIBLE_CONV |
36473658
MY_COLL_ALLOW_NUMERIC_CONV |
36483659
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;
36503702
}
36513703

36523704
public:

sql/item_cmpfunc.cc

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,6 @@ static uint collect_cmp_types(Item **items, uint nitems, bool skip_nulls= FALSE)
253253
return found_types;
254254
}
255255

256-
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
257-
const char *fname)
258-
{
259-
my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
260-
c1.collation->name,c1.derivation_name(),
261-
c2.collation->name,c2.derivation_name(),
262-
fname);
263-
}
264-
265256

266257
/*
267258
Test functions
@@ -653,39 +644,6 @@ bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
653644
}
654645

655646

656-
/**
657-
Aggregate comparator argument charsets for comparison.
658-
One of the arguments ("a" or "b") can be replaced,
659-
typically by Item_string or Item_func_conv_charset.
660-
661-
@return Aggregation result
662-
@retval false - if no conversion is needed,
663-
or if one of the arguments was converted
664-
@retval true - on error, if arguments are not comparable.
665-
666-
TODO: get rid of this method eventually and refactor the calling code.
667-
Argument conversion should happen on the Item_func level.
668-
Arg_comparator should get comparable arguments.
669-
*/
670-
bool Arg_comparator::agg_arg_charsets_for_comparison()
671-
{
672-
DTCollation tmp;
673-
if (tmp.set((*a)->collation, (*b)->collation, MY_COLL_CMP_CONV) ||
674-
tmp.derivation == DERIVATION_NONE)
675-
{
676-
my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name());
677-
return true;
678-
}
679-
if (agg_item_set_converter(tmp, owner->func_name(),
680-
a, 1, MY_COLL_CMP_CONV, 1) ||
681-
agg_item_set_converter(tmp, owner->func_name(),
682-
b, 1, MY_COLL_CMP_CONV, 1))
683-
return true;
684-
m_compare_collation= tmp.collation;
685-
return false;
686-
}
687-
688-
689647
/**
690648
Prepare the comparator (set the comparison function) for comparing
691649
items *a1 and *a2 in the context of 'type'.
@@ -717,7 +675,7 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
717675
We must set cmp_collation here as we may be called from for an automatic
718676
generated item, like in natural join
719677
*/
720-
if (agg_arg_charsets_for_comparison())
678+
if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b))
721679
return 1;
722680
}
723681

sql/item_cmpfunc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class Arg_comparator: public Sql_alloc
6060
// when one of arguments is NULL.
6161
int set_compare_func(Item_func_or_sum *owner, Item_result type);
6262
int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2);
63-
bool agg_arg_charsets_for_comparison();
6463

6564
int compare_temporal(enum_field_types type);
6665
int compare_e_temporal(enum_field_types type);

sql/item_func.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -187,23 +187,6 @@ class Item_func :public Item_func_or_sum, public Used_tables_and_const_cache
187187
else
188188
max_length= (uint32) max_result_length;
189189
}
190-
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
191-
uint flags, int item_sep)
192-
{
193-
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
194-
}
195-
/*
196-
Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b
197-
- don't convert to @@character_set_connection if all arguments are numbers
198-
- don't allow DERIVATION_NONE
199-
*/
200-
bool agg_arg_charsets_for_comparison(DTCollation &c,
201-
Item **items, uint nitems,
202-
int item_sep= 1)
203-
{
204-
return agg_item_charsets_for_comparison(c, func_name(),
205-
items, nitems, item_sep);
206-
}
207190
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
208191
Item* compile(THD *thd, Item_analyzer analyzer, uchar **arg_p,
209192
Item_transformer transformer, uchar *arg_t);

0 commit comments

Comments
 (0)