Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
When temporary tables is used for result sorting result field for gconcat function is created using group_concat_max_len size. It leads to result truncation when character_set_results is multi-byte character set due to insufficient tmp table field size. The fix is to increase temporary table field size for gconcat. Method make_string_field() is overloaded for Item_func_group_concat class and uses max_characters * collation.collation->mbmaxlen size for result field. max_characters is maximum number of characters what can fit into max_length size.
This commit is contained in:
parent
9de021c753
commit
b195e6f943
@ -1126,5 +1126,19 @@ NULL
|
|||||||
Warnings:
|
Warnings:
|
||||||
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
|
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
|
||||||
#
|
#
|
||||||
|
# Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
|
||||||
|
#
|
||||||
|
SET NAMES utf8, @@character_set_connection=utf16;
|
||||||
|
SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l
|
||||||
|
FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1
|
||||||
|
GROUP BY id
|
||||||
|
ORDER BY l DESC;
|
||||||
|
id l
|
||||||
|
a 512
|
||||||
|
Warnings:
|
||||||
|
Warning 1260 Row 1 was cut by GROUP_CONCAT()
|
||||||
|
#
|
||||||
# End of 5.5 tests
|
# End of 5.5 tests
|
||||||
#
|
#
|
||||||
|
@ -1167,5 +1167,19 @@ CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END
|
|||||||
b
|
b
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
|
||||||
|
#
|
||||||
|
SET NAMES utf8, @@character_set_connection=utf32;
|
||||||
|
SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l
|
||||||
|
FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1
|
||||||
|
GROUP BY id
|
||||||
|
ORDER BY l DESC;
|
||||||
|
id l
|
||||||
|
a 256
|
||||||
|
Warnings:
|
||||||
|
Warning 1260 Row 1 was cut by GROUP_CONCAT()
|
||||||
|
#
|
||||||
# End of 5.5 tests
|
# End of 5.5 tests
|
||||||
#
|
#
|
||||||
|
@ -2788,7 +2788,7 @@ create table t1 as select group_concat(1,2,3) as c1;
|
|||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`c1` varchar(342) CHARACTER SET utf8 DEFAULT NULL
|
`c1` text CHARACTER SET utf8
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 as select 1 as c1 union select 'a';
|
create table t1 as select 1 as c1 union select 'a';
|
||||||
@ -5010,5 +5010,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select 'abcdÁÂÃÄÅ' AS `abcdÁÂÃÄÅ`,_latin1'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÃÂÃÄÅ`,_utf8'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÁÂÃÄÅ`
|
Note 1003 select 'abcdÁÂÃÄÅ' AS `abcdÁÂÃÄÅ`,_latin1'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÃÂÃÄÅ`,_utf8'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÁÂÃÄÅ`
|
||||||
#
|
#
|
||||||
|
# Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
|
||||||
|
#
|
||||||
|
SET NAMES utf8;
|
||||||
|
SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l
|
||||||
|
FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1
|
||||||
|
GROUP BY id
|
||||||
|
ORDER BY l DESC;
|
||||||
|
id l
|
||||||
|
a 1024
|
||||||
|
Warnings:
|
||||||
|
Warning 1260 Row 2 was cut by GROUP_CONCAT()
|
||||||
|
#
|
||||||
# End of 5.5 tests
|
# End of 5.5 tests
|
||||||
#
|
#
|
||||||
|
@ -762,6 +762,20 @@ DROP TABLE t1;
|
|||||||
|
|
||||||
SELECT space(date_add(101, INTERVAL CHAR('1' USING utf16) hour_second));
|
SELECT space(date_add(101, INTERVAL CHAR('1' USING utf16) hour_second));
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET NAMES utf8, @@character_set_connection=utf16;
|
||||||
|
SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l
|
||||||
|
FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1
|
||||||
|
GROUP BY id
|
||||||
|
ORDER BY l DESC;
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
## TODO: add tests for all engines
|
## TODO: add tests for all engines
|
||||||
#
|
#
|
||||||
|
@ -840,6 +840,19 @@ INSERT INTO t1 VALUES ('a');
|
|||||||
SELECT CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END FROM t1;
|
SELECT CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET NAMES utf8, @@character_set_connection=utf32;
|
||||||
|
SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l
|
||||||
|
FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1
|
||||||
|
GROUP BY id
|
||||||
|
ORDER BY l DESC;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 5.5 tests
|
--echo # End of 5.5 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -1561,6 +1561,18 @@ EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁ
|
|||||||
SET NAMES utf8;
|
SET NAMES utf8;
|
||||||
EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁÂÃÄÅ';
|
EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁÂÃÄÅ';
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#11750518 41090: ORDER BY TRUNCATES GROUP_CONCAT RESULT
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET NAMES utf8;
|
||||||
|
SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l
|
||||||
|
FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1
|
||||||
|
GROUP BY id
|
||||||
|
ORDER BY l DESC;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 5.5 tests
|
--echo # End of 5.5 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -592,7 +592,7 @@ public:
|
|||||||
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
virtual void make_field(Send_field *field);
|
virtual void make_field(Send_field *field);
|
||||||
Field *make_string_field(TABLE *table);
|
virtual Field *make_string_field(TABLE *table);
|
||||||
virtual bool fix_fields(THD *, Item **);
|
virtual bool fix_fields(THD *, Item **);
|
||||||
/*
|
/*
|
||||||
should be used in case where we are sure that we do not need
|
should be used in case where we are sure that we do not need
|
||||||
|
@ -3128,6 +3128,31 @@ void Item_func_group_concat::cleanup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Item_func_group_concat::make_string_field(TABLE *table)
|
||||||
|
{
|
||||||
|
Field *field;
|
||||||
|
DBUG_ASSERT(collation.collation);
|
||||||
|
/*
|
||||||
|
max_characters is maximum number of characters
|
||||||
|
what can fit into max_length size. It's necessary
|
||||||
|
to use field size what allows to store group_concat
|
||||||
|
result without truncation. For this purpose we use
|
||||||
|
max_characters * CS->mbmaxlen.
|
||||||
|
*/
|
||||||
|
const uint32 max_characters= max_length / collation.collation->mbminlen;
|
||||||
|
if (max_characters > CONVERT_IF_BIGGER_TO_BLOB)
|
||||||
|
field= new Field_blob(max_characters * collation.collation->mbmaxlen,
|
||||||
|
maybe_null, name, collation.collation, TRUE);
|
||||||
|
else
|
||||||
|
field= new Field_varstring(max_characters * collation.collation->mbmaxlen,
|
||||||
|
maybe_null, name, table->s, collation.collation);
|
||||||
|
|
||||||
|
if (field)
|
||||||
|
field->init(table);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Item_func_group_concat::copy_or_same(THD* thd)
|
Item *Item_func_group_concat::copy_or_same(THD* thd)
|
||||||
{
|
{
|
||||||
return new (thd->mem_root) Item_func_group_concat(thd, this);
|
return new (thd->mem_root) Item_func_group_concat(thd, this);
|
||||||
|
@ -1411,6 +1411,7 @@ public:
|
|||||||
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
|
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
|
||||||
const char *func_name() const { return "group_concat"; }
|
const char *func_name() const { return "group_concat"; }
|
||||||
virtual Item_result result_type () const { return STRING_RESULT; }
|
virtual Item_result result_type () const { return STRING_RESULT; }
|
||||||
|
virtual Field *make_string_field(TABLE *table);
|
||||||
enum_field_types field_type() const
|
enum_field_types field_type() const
|
||||||
{
|
{
|
||||||
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB )
|
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user