diff options
author | Alexander Barkov <bar@mariadb.org> | 2015-09-21 19:04:32 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2015-09-21 19:04:32 +0400 |
commit | 22cc8f990bae759b564fdd1b403b8c67a4b59333 (patch) | |
tree | 09b72cc09847a205f0a188c1e2428b8028e65c21 /sql | |
parent | 9b9e36ed4926edd896aa274e15286f64cfec4313 (diff) | |
download | mariadb-git-22cc8f990bae759b564fdd1b403b8c67a4b59333.tar.gz |
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 59 | ||||
-rw-r--r-- | sql/item.h | 120 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 44 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 | ||||
-rw-r--r-- | sql/item_func.h | 17 |
5 files changed, 94 insertions, 147 deletions
diff --git a/sql/item.cc b/sql/item.cc index 7839351fcd0..c75e0562526 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2035,8 +2035,9 @@ void my_coll_agg_error(Item** args, uint count, const char *fname, } -bool agg_item_collations(DTCollation &c, const char *fname, - Item **av, uint count, uint flags, int item_sep) +bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname, + Item **av, uint count, + uint flags, int item_sep) { uint i; Item **arg; @@ -2081,16 +2082,10 @@ bool agg_item_collations(DTCollation &c, const char *fname, } -bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, - Item **av, uint count, uint flags) -{ - return (agg_item_collations(c, fname, av, count, - flags | MY_COLL_DISALLOW_NONE, 1)); -} - - -bool agg_item_set_converter(DTCollation &coll, const char *fname, - Item **args, uint nargs, uint flags, int item_sep) +bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll, + const char *fname, + Item **args, uint nargs, + uint flags, int item_sep) { Item **arg, *safe_args[2]= {NULL, NULL}; @@ -2167,46 +2162,6 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, } -/* - Collect arguments' character sets together. - We allow to apply automatic character set conversion in some cases. - The conditions when conversion is possible are: - - arguments A and B have different charsets - - A wins according to coercibility rules - (i.e. a column is stronger than a string constant, - an explicit COLLATE clause is stronger than a column) - - character set of A is either superset for character set of B, - or B is a string constant which can be converted into the - character set of A without data loss. - - If all of the above is true, then it's possible to convert - B into the character set of A, and then compare according - to the collation of A. - - For functions with more than two arguments: - - collect(A,B,C) ::= collect(collect(A,B),C) - - Since this function calls THD::change_item_tree() on the passed Item ** - pointers, it is necessary to pass the original Item **'s, not copies. - Otherwise their values will not be properly restored (see BUG#20769). - If the items are not consecutive (eg. args[2] and args[5]), use the - item_sep argument, ie. - - agg_item_charsets(coll, fname, &args[2], 2, flags, 3) - -*/ - -bool agg_item_charsets(DTCollation &coll, const char *fname, - Item **args, uint nargs, uint flags, int item_sep) -{ - if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) - return TRUE; - - return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep); -} - - void Item_ident_for_show::make_field(Send_field *tmp_field) { tmp_field->table_name= tmp_field->org_table_name= table_name; diff --git a/sql/item.h b/sql/item.h index 50970c0dd9a..13f65b36404 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2153,38 +2153,6 @@ public: } }; -bool agg_item_collations(DTCollation &c, const char *name, - Item **items, uint nitems, uint flags, int item_sep); -bool agg_item_collations_for_comparison(DTCollation &c, const char *name, - Item **items, uint nitems, uint flags); -bool agg_item_set_converter(DTCollation &coll, const char *fname, - Item **args, uint nargs, uint flags, int item_sep); -bool agg_item_charsets(DTCollation &c, const char *name, - Item **items, uint nitems, uint flags, int item_sep); -inline bool -agg_item_charsets_for_comparison(DTCollation &c, const char *name, - Item **items, uint nitems, - int item_sep= 1) -{ - uint flags= MY_COLL_ALLOW_SUPERSET_CONV | - MY_COLL_ALLOW_COERCIBLE_CONV | - MY_COLL_DISALLOW_NONE; - return agg_item_charsets(c, name, items, nitems, flags, item_sep); -} -inline bool -agg_item_charsets_for_string_result_with_comparison(DTCollation &c, - const char *name, - Item **items, uint nitems, - int item_sep= 1) -{ - uint flags= MY_COLL_ALLOW_SUPERSET_CONV | - MY_COLL_ALLOW_COERCIBLE_CONV | - MY_COLL_ALLOW_NUMERIC_CONV | - MY_COLL_DISALLOW_NONE; - return agg_item_charsets(c, name, items, nitems, flags, item_sep); -} - - class Item_num: public Item_basic_constant { public: @@ -3616,8 +3584,51 @@ public: */ class Item_func_or_sum: public Item_result_field, public Item_args { + bool agg_item_collations(DTCollation &c, const char *name, + Item **items, uint nitems, + uint flags, int item_sep); + bool agg_item_set_converter(const DTCollation &coll, const char *fname, + Item **args, uint nargs, + uint flags, int item_sep); protected: /* + Collect arguments' character sets together. + We allow to apply automatic character set conversion in some cases. + The conditions when conversion is possible are: + - arguments A and B have different charsets + - A wins according to coercibility rules + (i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column) + - character set of A is either superset for character set of B, + or B is a string constant which can be converted into the + character set of A without data loss. + + If all of the above is true, then it's possible to convert + B into the character set of A, and then compare according + to the collation of A. + + For functions with more than two arguments: + + collect(A,B,C) ::= collect(collect(A,B),C) + + Since this function calls THD::change_item_tree() on the passed Item ** + pointers, it is necessary to pass the original Item **'s, not copies. + Otherwise their values will not be properly restored (see BUG#20769). + If the items are not consecutive (eg. args[2] and args[5]), use the + item_sep argument, ie. + + agg_item_charsets(coll, fname, &args[2], 2, flags, 3) + */ + bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, + uint flags, int item_sep) + { + if (agg_item_collations(c, func_name(), items, nitems, flags, item_sep)) + return true; + + return agg_item_set_converter(c, func_name(), items, nitems, + flags, item_sep); + } + /* Aggregate arguments for string result, e.g: CONCAT(a,b) - convert to @@character_set_connection if all arguments are numbers - allow DERIVATION_NONE @@ -3629,7 +3640,7 @@ protected: uint flags= MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV | MY_COLL_ALLOW_NUMERIC_CONV; - return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep); + return agg_arg_charsets(c, items, nitems, flags, item_sep); } /* Aggregate arguments for string result, when some comparison @@ -3646,7 +3657,48 @@ protected: MY_COLL_ALLOW_COERCIBLE_CONV | MY_COLL_ALLOW_NUMERIC_CONV | MY_COLL_DISALLOW_NONE; - return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep); + return agg_arg_charsets(c, items, nitems, flags, item_sep); + } + + /* + Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b + - don't convert to @@character_set_connection if all arguments are numbers + - don't allow DERIVATION_NONE + */ + bool agg_arg_charsets_for_comparison(DTCollation &c, + Item **items, uint nitems, + int item_sep= 1) + { + uint flags= MY_COLL_ALLOW_SUPERSET_CONV | + MY_COLL_ALLOW_COERCIBLE_CONV | + MY_COLL_DISALLOW_NONE; + return agg_arg_charsets(c, items, nitems, flags, item_sep); + } + + +public: + // This method is used by Arg_comparator + bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b) + { + DTCollation tmp; + if (tmp.set((*a)->collation, (*b)->collation, MY_COLL_CMP_CONV) || + tmp.derivation == DERIVATION_NONE) + { + my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), + (*a)->collation.collation->name, + (*a)->collation.derivation_name(), + (*b)->collation.collation->name, + (*b)->collation.derivation_name(), + func_name()); + return true; + } + if (agg_item_set_converter(tmp, func_name(), + a, 1, MY_COLL_CMP_CONV, 1) || + agg_item_set_converter(tmp, func_name(), + b, 1, MY_COLL_CMP_CONV, 1)) + return true; + *cs= tmp.collation; + return false; } public: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index e79e73dc015..0e2802fe794 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -253,15 +253,6 @@ static uint collect_cmp_types(Item **items, uint nitems, bool skip_nulls= FALSE) return found_types; } -static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, - const char *fname) -{ - my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), - c1.collation->name,c1.derivation_name(), - c2.collation->name,c2.derivation_name(), - fname); -} - /* Test functions @@ -654,39 +645,6 @@ bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, /** - Aggregate comparator argument charsets for comparison. - One of the arguments ("a" or "b") can be replaced, - typically by Item_string or Item_func_conv_charset. - - @return Aggregation result - @retval false - if no conversion is needed, - or if one of the arguments was converted - @retval true - on error, if arguments are not comparable. - - TODO: get rid of this method eventually and refactor the calling code. - Argument conversion should happen on the Item_func level. - Arg_comparator should get comparable arguments. -*/ -bool Arg_comparator::agg_arg_charsets_for_comparison() -{ - DTCollation tmp; - if (tmp.set((*a)->collation, (*b)->collation, MY_COLL_CMP_CONV) || - tmp.derivation == DERIVATION_NONE) - { - my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name()); - return true; - } - if (agg_item_set_converter(tmp, owner->func_name(), - a, 1, MY_COLL_CMP_CONV, 1) || - agg_item_set_converter(tmp, owner->func_name(), - b, 1, MY_COLL_CMP_CONV, 1)) - return true; - m_compare_collation= tmp.collation; - return false; -} - - -/** Prepare the comparator (set the comparison function) for comparing 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, We must set cmp_collation here as we may be called from for an automatic generated item, like in natural join */ - if (agg_arg_charsets_for_comparison()) + if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b)) return 1; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 350d9d07565..a742fb58250 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -60,7 +60,6 @@ class Arg_comparator: public Sql_alloc // when one of arguments is NULL. int set_compare_func(Item_func_or_sum *owner, Item_result type); int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2); - bool agg_arg_charsets_for_comparison(); int compare_temporal(enum_field_types type); int compare_e_temporal(enum_field_types type); diff --git a/sql/item_func.h b/sql/item_func.h index a33138a6530..ea8a5a88b35 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -187,23 +187,6 @@ public: else max_length= (uint32) max_result_length; } - bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, - uint flags, int item_sep) - { - return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep); - } - /* - Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b - - don't convert to @@character_set_connection if all arguments are numbers - - don't allow DERIVATION_NONE - */ - bool agg_arg_charsets_for_comparison(DTCollation &c, - Item **items, uint nitems, - int item_sep= 1) - { - return agg_item_charsets_for_comparison(c, func_name(), - items, nitems, item_sep); - } Item *transform(THD *thd, Item_transformer transformer, uchar *arg); Item* compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t); |