diff options
author | evgen@moonbone.local <> | 2006-06-07 01:10:23 +0400 |
---|---|---|
committer | evgen@moonbone.local <> | 2006-06-07 01:10:23 +0400 |
commit | d027dd7c0d9d2d105e712e6ff89a4483a7dfc177 (patch) | |
tree | 2558020fb28cfef9d7c7d41a6a13608b7e7724d7 | |
parent | fdc2b921cc529076de68d099b809cb1cb29dfa67 (diff) | |
download | mariadb-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.result | 7 | ||||
-rw-r--r-- | mysql-test/t/func_concat.test | 8 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 9 |
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) { |