diff options
-rw-r--r-- | mysql-test/r/func_str.result | 6 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 8 | ||||
-rw-r--r-- | sql/item_func.cc | 55 | ||||
-rw-r--r-- | sql/item_func.h | 3 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 75 |
5 files changed, 90 insertions, 57 deletions
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 42b96956cef..c2a921e1a54 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -278,6 +278,12 @@ row('A','b','c') = row('a' COLLATE latin1_bin,'b','c') 0 select row('A' COLLATE latin1_general_ci,'b','c') = row('a' COLLATE latin1_bin,'b','c'); ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation '=' +select concat(_latin1'a',_latin2'a'); +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat' +select concat(_latin1'a',_latin2'a',_latin5'a'); +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin5_turkish_ci,COERCIBLE) for operation 'concat' +select concat(_latin1'a',_latin2'a',_latin5'a',_latin7'a'); +ERROR HY000: Illegal mix of collations for operation 'concat' select FIELD('b','A','B'); FIELD('b','A','B') 2 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 79d2b082d01..c9e7b1a529d 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -152,6 +152,14 @@ select row('A','b','c') = row('a' COLLATE latin1_bin,'b','c'); --error 1265 select row('A' COLLATE latin1_general_ci,'b','c') = row('a' COLLATE latin1_bin,'b','c'); +--error 1265 +select concat(_latin1'a',_latin2'a'); +--error 1268 +select concat(_latin1'a',_latin2'a',_latin5'a'); +--error 1269 +select concat(_latin1'a',_latin2'a',_latin5'a',_latin7'a'); + + # # Test FIELD() and collations # diff --git a/sql/item_func.cc b/sql/item_func.cc index eba6a2cc8d1..df1bce37581 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -39,6 +39,61 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fnam fname); } +static void my_coll_agg_error(DTCollation &c1, + DTCollation &c2, + DTCollation &c3, + const char *fname) +{ + my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + c3.collation->name,c3.derivation_name(), + fname); +} + +static void my_coll_agg_error(Item** args, uint ac, const char *fname) +{ + if (2 == ac) + my_coll_agg_error(args[0]->collation, args[1]->collation, fname); + else if (3 == ac) + my_coll_agg_error(args[0]->collation, + args[1]->collation, + args[2]->collation, + fname); + else + my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname); +} + +bool Item_func::agg_arg_collations(DTCollation &c, uint from, uint argc) +{ + uint i; + c.set(args[from]->collation); + for (i= from+1; i < argc; i++) + { + if (c.aggregate(args[i]->collation)) + { + my_coll_agg_error(args+from, argc-from, func_name()); + return TRUE; + } + } + return FALSE; +} + +bool Item_func::agg_arg_collations_for_comparison(DTCollation &c, + uint from, uint argc) +{ + if (agg_arg_collations(c, from, argc)) + return FALSE; + + if (c.derivation == DERIVATION_NONE) + { + my_coll_agg_error(args+from, argc-from, func_name()); + return TRUE; + } + return FALSE; +} + + /* return TRUE if item is a constant */ bool diff --git a/sql/item_func.h b/sql/item_func.h index 6a08d961bc3..c7f227051f3 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -135,6 +135,9 @@ public: Field *tmp_table_field(TABLE *t_arg); void set_outer_resolving(); Item *get_tmp_table_item(THD *thd); + + bool agg_arg_collations(DTCollation &c, uint from, uint argc); + bool agg_arg_collations_for_comparison(DTCollation &c, uint from, uint argc); }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index cbfe98bfd21..8c3784a5d4e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -44,18 +44,6 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fnam fname); } -static void my_coll_agg3_error(DTCollation &c1, - DTCollation &c2, - DTCollation &c3, - const char *fname) -{ - my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0), - c1.collation->name,c1.derivation_name(), - c2.collation->name,c2.derivation_name(), - c3.collation->name,c3.derivation_name(), - fname); -} - uint nr_of_decimals(const char *str) { if ((str=strchr(str,'.'))) @@ -336,16 +324,11 @@ void Item_func_concat::fix_length_and_dec() bool first_coll= 1; max_length=0; - collation.set(args[0]->collation); + if (agg_arg_collations(collation, 0, arg_count)) + return; + for (uint i=0 ; i < arg_count ; i++) - { max_length+=args[i]->max_length; - if (collation.aggregate(args[i]->collation)) - { - my_coll_agg_error(collation, args[i]->collation, func_name()); - break; - } - } if (max_length > MAX_BLOB_WIDTH) { @@ -840,13 +823,8 @@ void Item_func_replace::fix_length_and_dec() maybe_null=1; } - collation.set(args[0]->collation); - if (!collation.aggregate(args[1]->collation)) - collation.aggregate(args[2]->collation); - - if (collation.derivation == DERIVATION_NONE) - my_coll_agg3_error(args[0]->collation, args[1]->collation, - args[2]->collation, func_name()); + if (agg_arg_collations_for_comparison(collation, 0, 3)) + return; } @@ -1050,9 +1028,9 @@ void Item_func_substr::fix_length_and_dec() void Item_func_substr_index::fix_length_and_dec() { max_length= args[0]->max_length; - if (collation.set(args[0]->collation, args[1]->collation) || - (collation.derivation == DERIVATION_NONE)) - my_coll_agg_error(args[0]->collation, args[1]->collation, func_name()); + + if (agg_arg_collations_for_comparison(collation, 0, 2)) + return; } @@ -1680,20 +1658,13 @@ void Item_func_elt::fix_length_and_dec() max_length=0; decimals=0; + if (agg_arg_collations(collation, 0, arg_count)) + return; + for (uint i=0 ; i < arg_count ; i++) { set_if_bigger(max_length,args[i]->max_length); set_if_bigger(decimals,args[i]->decimals); - if (i == 0) - collation.set(args[0]->collation); - else - { - if (collation.aggregate(args[i]->collation)) - { - my_coll_agg_error(collation, args[i]->collation, func_name()); - break; - } - } } maybe_null=1; // NULL if wrong first arg with_sum_func= with_sum_func || item->with_sum_func; @@ -1786,16 +1757,13 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array, void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; - collation.set(args[0]->collation); + + if (agg_arg_collations(collation, 0, arg_count)) + return; + for (uint i=0 ; i < arg_count ; i++) - { max_length+=args[i]->max_length; - if (collation.aggregate(args[i]->collation)) - { - my_coll_agg_error(collation, args[i]->collation, func_name()); - break; - } - } + used_tables_cache|=item->used_tables(); const_item_cache&=item->const_item(); with_sum_func= with_sum_func || item->with_sum_func; @@ -2463,15 +2431,8 @@ void Item_func_export_set::fix_length_and_dec() uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; - collation.set(args[1]->collation); - for (i=2 ; i < 4 && i < arg_count ; i++) - { - if (collation.aggregate(args[i]->collation)) - { - my_coll_agg_error(collation, args[i]->collation, func_name()); - break; - } - } + if (agg_arg_collations(collation,1, min(4,arg_count))) + return; } String* Item_func_inet_ntoa::val_str(String* str) |