diff options
author | Alexander Barkov <bar@mysql.com> | 2010-08-19 15:55:35 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mysql.com> | 2010-08-19 15:55:35 +0400 |
commit | 7f98714247d601c353779d8615a5624cf00b5e6a (patch) | |
tree | 0da012c099ad33a789a218b378cd58bbe76ccb47 /sql/item_cmpfunc.cc | |
parent | 27f5c57cb0c622281b2dd4a9e9c5b327b2bcc6d7 (diff) | |
download | mariadb-git-7f98714247d601c353779d8615a5624cf00b5e6a.tar.gz |
Bug#54916 GROUP_CONCAT + IFNULL truncates output
Problem: a few functions did not calculate their max_length correctly.
This is an after-fix for WL#2649 Number-to-string conversions".
Fix: changing the buggy functions to calculate max_length
using fix_char_length() introduced in WL#2649,
instead of setting max_length directly
mysql-test/include/ctype_numconv.inc
Adding new tests
mysql-test/r/ctype_binary.result
Adding new tests
mysql-test/r/ctype_cp1251.result
Adding new tests
mysql-test/r/ctype_latin1.result
Adding new tests
mysql-test/r/ctype_ucs.result
Adding new tests
mysql-test/r/ctype_utf8.result
Adding new tests
mysql-test/t/ctype_utf8.test
Including ctype_numconv
sql/item.h
- Introducing new method fix_char_length_ulonglong(),
for the cases when length is potentially greater
than UINT_MAX32. This method removes a few
instances of duplicate code, e.g. in item_strfunc.cc.
- Setting collation in Item_copy properly. This change
fixes wrong metadata on client side in some cases, when
"binary" instead of the real character set was reported.
sql/item_cmpfunc.cc
- Using fix_char_length() and max_char_length() methods,
instead of direct access to max_length, to calculate
item length properly.
- Moving count_only_length() in COALESCE after
agg_arg_charsets_for_string_result(). The old
order was incorrect and led to wrong length
calucation in case of multi-byte character sets.
sql/item_func.cc
Fixing that count_only_length() didn't work
properly for multi-byte character sets.
Using fix_char_length() and max_char_length()
instead of direct access to max_length.
sql/item_strfunc.cc
- Using fix_char_length(), fix_char_length_ulonglong(),
max_char_length() instead of direct access to max_length.
- Removing wierd condition: "if (collation.collation->mbmaxlen > 0)",
which is never FALSE.
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c18b79371df..641d3726aca 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2374,6 +2374,7 @@ void Item_func_between::print(String *str, enum_query_type query_type) void Item_func_ifnull::fix_length_and_dec() { + uint32 char_length; agg_result_type(&hybrid_type, args, 2); maybe_null=args[1]->maybe_null; decimals= max(args[0]->decimals, args[1]->decimals); @@ -2381,20 +2382,21 @@ Item_func_ifnull::fix_length_and_dec() if (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) { - int len0= args[0]->max_length - args[0]->decimals + int len0= args[0]->max_char_length() - args[0]->decimals - (args[0]->unsigned_flag ? 0 : 1); - int len1= args[1]->max_length - args[1]->decimals + int len1= args[1]->max_char_length() - args[1]->decimals - (args[1]->unsigned_flag ? 0 : 1); - max_length= max(len0, len1) + decimals + (unsigned_flag ? 0 : 1); + char_length= max(len0, len1) + decimals + (unsigned_flag ? 0 : 1); } else - max_length= max(args[0]->max_length, args[1]->max_length); + char_length= max(args[0]->max_char_length(), args[1]->max_char_length()); switch (hybrid_type) { case STRING_RESULT: - agg_arg_charsets_for_comparison(collation, args, arg_count); + if (agg_arg_charsets_for_comparison(collation, args, arg_count)) + return; break; case DECIMAL_RESULT: case REAL_RESULT: @@ -2406,6 +2408,7 @@ Item_func_ifnull::fix_length_and_dec() default: DBUG_ASSERT(0); } + fix_char_length(char_length); cached_field_type= agg_field_type(args, 2); } @@ -2579,6 +2582,7 @@ Item_func_if::fix_length_and_dec() cached_field_type= agg_field_type(args + 1, 2); } + uint32 char_length; if ((cached_result_type == DECIMAL_RESULT ) || (cached_result_type == INT_RESULT)) { @@ -2588,10 +2592,11 @@ Item_func_if::fix_length_and_dec() int len2= args[2]->max_length - args[2]->decimals - (args[2]->unsigned_flag ? 0 : 1); - max_length=max(len1, len2) + decimals + (unsigned_flag ? 0 : 1); + char_length= max(len1, len2) + decimals + (unsigned_flag ? 0 : 1); } else - max_length= max(args[1]->max_length, args[2]->max_length); + char_length= max(args[1]->max_char_length(), args[2]->max_char_length()); + fix_char_length(char_length); } @@ -2901,7 +2906,7 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) void Item_func_case::agg_str_lengths(Item* arg) { - set_if_bigger(max_length, arg->max_length); + fix_char_length(max(max_char_length(), arg->max_char_length())); set_if_bigger(decimals, arg->decimals); unsigned_flag= unsigned_flag && arg->unsigned_flag; } @@ -3129,9 +3134,10 @@ void Item_func_coalesce::fix_length_and_dec() agg_result_type(&hybrid_type, args, arg_count); switch (hybrid_type) { case STRING_RESULT: - count_only_length(); decimals= NOT_FIXED_DEC; - agg_arg_charsets_for_string_result(collation, args, arg_count); + if (agg_arg_charsets_for_string_result(collation, args, arg_count)) + return; + count_only_length(); break; case DECIMAL_RESULT: count_decimal_length(); |