summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/union.result5
-rw-r--r--mysql-test/t/union.test7
-rw-r--r--sql/item.cc16
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);