summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorevgen@moonbone.local <>2006-06-07 01:10:23 +0400
committerevgen@moonbone.local <>2006-06-07 01:10:23 +0400
commitd027dd7c0d9d2d105e712e6ff89a4483a7dfc177 (patch)
tree2558020fb28cfef9d7c7d41a6a13608b7e7724d7
parentfdc2b921cc529076de68d099b809cb1cb29dfa67 (diff)
downloadmariadb-git-d027dd7c0d9d2d105e712e6ff89a4483a7dfc177.tar.gz
Fixed bug#15962: CONCAT() in UNION may lead to a data trucation.
To calculate its max_length the CONCAT() function is simply sums max_lengths of its arguments but when the collation of an argument differs from the collation of the CONCAT() max_length will be wrong. This may lead to a data truncation when a tmp table is used, in UNIONS for example. The Item_func_concat::fix_length_and_dec() function now recalculates the max_length of an argument when the mbmaxlen of the argument differs from the mbmaxlen of the CONCAT().
-rw-r--r--mysql-test/r/func_concat.result7
-rw-r--r--mysql-test/t/func_concat.test8
-rw-r--r--sql/item_strfunc.cc9
3 files changed, 23 insertions, 1 deletions
diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result
index 0bd53b32dd7..712f0c0495e 100644
--- a/mysql-test/r/func_concat.result
+++ b/mysql-test/r/func_concat.result
@@ -68,3 +68,10 @@ select 'a' union select concat('a', -0.0000);
a
a
a0.0000
+create table t1(f1 varchar(6)) charset=utf8;
+insert into t1 values ("123456");
+select concat(f1, 2) a from t1 union select 'x' a from t1;
+a
+1234562
+x
+drop table t1;
diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test
index 37fc0e105b8..42201961222 100644
--- a/mysql-test/t/func_concat.test
+++ b/mysql-test/t/func_concat.test
@@ -53,3 +53,11 @@ select 'a' union select concat('a', -0.0);
select 'a' union select concat('a', -0.0000);
# End of 4.1 tests
+
+#
+# Bug#15962: CONCAT() in UNION may lead to a data trucation.
+#
+create table t1(f1 varchar(6)) charset=utf8;
+insert into t1 values ("123456");
+select concat(f1, 2) a from t1 union select 'x' a from t1;
+drop table t1;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index ce9897afeed..d8082440f1a 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -389,7 +389,14 @@ void Item_func_concat::fix_length_and_dec()
return;
for (uint i=0 ; i < arg_count ; i++)
- max_result_length+= args[i]->max_length;
+ {
+ if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
+ max_result_length+= (args[i]->max_length /
+ args[i]->collation.collation->mbmaxlen) *
+ collation.collation->mbmaxlen;
+ else
+ max_result_length+= args[i]->max_length;
+ }
if (max_result_length >= MAX_BLOB_WIDTH)
{