diff options
-rw-r--r-- | mysql-test/r/union.result | 5 | ||||
-rw-r--r-- | mysql-test/t/union.test | 7 | ||||
-rw-r--r-- | sql/item.cc | 16 |
3 files changed, 24 insertions, 4 deletions
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 426387e04f5..19b0211c442 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1351,3 +1351,8 @@ drop table t1; (select avg(1)) union (select avg(1)) union (select avg(1)); avg(1) NULL +select _utf8'12' union select _latin1'12345'; +12 +12 +12345 +End of 5.0 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 7dfe4ac482f..b300cf91a22 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -841,3 +841,10 @@ drop table t1; (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)); +# +# Bug #16881: password() and union select +# (The issue was poor handling of character set aggregation.) +# +select _utf8'12' union select _latin1'12345'; + +--echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index ad8b79182d4..7d6ce031e15 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6053,14 +6053,13 @@ bool Item_type_holder::join_types(THD *thd, Item *item) max_length= my_decimal_precision_to_length(precision, decimals, unsigned_flag); } - else - max_length= max(max_length, display_length(item)); - + switch (Field::result_merge_type(fld_type)) { case STRING_RESULT: { const char *old_cs, *old_derivation; + uint32 old_max_chars= max_length / collation.collation->mbmaxlen; old_cs= collation.collation->name; old_derivation= collation.derivation_name(); if (collation.aggregate(item->collation, MY_COLL_ALLOW_CONV)) @@ -6072,6 +6071,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item) "UNION"); DBUG_RETURN(TRUE); } + /* + To figure out max_length, we have to take into account possible + expansion of the size of the values because of character set + conversions. + */ + max_length= max(old_max_chars * collation.collation->mbmaxlen, + display_length(item) / item->collation.collation->mbmaxlen * + collation.collation->mbmaxlen); break; } case REAL_RESULT: @@ -6090,7 +6097,8 @@ bool Item_type_holder::join_types(THD *thd, Item *item) max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7; break; } - default:; + default: + max_length= max(max_length, display_length(item)); }; maybe_null|= item->maybe_null; get_full_info(item); |