diff options
author | unknown <bar@mysql.com/bar.intranet.mysql.r18.ru> | 2006-11-07 12:45:48 +0400 |
---|---|---|
committer | unknown <bar@mysql.com/bar.intranet.mysql.r18.ru> | 2006-11-07 12:45:48 +0400 |
commit | d9360eae3b57c7ef4b1a14b270d06c8423df3bfb (patch) | |
tree | 7efe124c16c347e163ec9064f07a8ccfaae1341c /sql/item_sum.cc | |
parent | 2ab335a5b8bb3a25796824aa14325c777ce07a86 (diff) | |
download | mariadb-git-d9360eae3b57c7ef4b1a14b270d06c8423df3bfb.tar.gz |
Bug#23451 GROUP_CONCAT truncates a multibyte utf8 character
Problem: GROUP_CONCAT on a multi-byte column can truncate
in the middle of a multibyte character when applying
group_concat_max_len limit. It produces an invalid
multi-byte character in the result string.
The second, easier version - reusing old "warning_for_row" flag,
instead of introducing of "result_is_full" - which was
added in the previous commit.
mysql-test/r/func_gconcat.result:
Adding test case
mysql-test/t/func_gconcat.test:
Adding test case
sql/item_sum.cc:
Adding well_formed_len() call not to cut
in the middle of a multi-byte character.
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r-- | sql/item_sum.cc | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0b9b10d05d4..4c346357240 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1664,6 +1664,7 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), { char buff[MAX_FIELD_WIDTH]; String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2; + uint old_length= item->result.length(); if (item->no_appended) item->no_appended= FALSE; @@ -1702,8 +1703,22 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), /* stop if length of result more than group_concat_max_len */ if (item->result.length() > item->group_concat_max_len) { + int well_formed_error; + CHARSET_INFO *cs= item->collation.collation; + const char *ptr= item->result.ptr(); + uint add_length; + /* + It's ok to use item->result.length() as the fourth argument + as this is never used to limit the length of the data. + Cut is done with the third argument. + */ + add_length= cs->cset->well_formed_len(cs, + ptr + old_length, + ptr + item->group_concat_max_len, + item->result.length(), + &well_formed_error); + item->result.length(old_length + add_length); item->count_cut_values++; - item->result.length(item->group_concat_max_len); item->warning_for_row= TRUE; return 1; } @@ -1893,8 +1908,7 @@ bool Item_func_group_concat::add() we can dump the row here in case of GROUP_CONCAT(DISTINCT...) instead of doing tree traverse later. */ - if (result.length() <= group_concat_max_len && - !warning_for_row && + if (!warning_for_row && (!tree_mode || (el->count == 1 && distinct && !arg_count_order))) dump_leaf_key(table->record[0], 1, this); |