From 0e1c167e168a69bedf20b048ae1adf37a7d2dbb1 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 12 Nov 2010 13:12:15 +0300 Subject: [PATCH] Bug#58005 utf8 + get_format causes failed assertion: !str || str != Ptr' Problem: When GET_FORMAT() is called two times from the upper level function (e.g. LEAST in the bug report), on the second call "res= args[0]->val_str(...)" and str point to the same String object. 1. Fix: changing the order from - get val_str into tmp_value then convert to str to - get val_str into str then convert to tmp_value The new order is more correct: the purpose of "str" parameter is exactly to call val_str() for arguments. The purpose of String class members (like tmp_value) is to do further actions on the result. Doing it in the other way around give unexpected surprises. 2. Using str_value instead of str to do padding, for the same reason. --- mysql-test/r/date_formats.result | 14 ++++++++++++++ mysql-test/t/date_formats.test | 16 ++++++++++++++++ sql/item_timefunc.cc | 14 +++++++------- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result index 7e185daa668..a919a6f8c5e 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -609,3 +609,17 @@ SELECT DATE_FORMAT("2009-01-01",'%W %d %M %Y') as valid_date; valid_date Thursday 01 January 2009 "End of 5.0 tests" +# +# Start of 5.1 tests +# +# +# Bug#58005 utf8 + get_format causes failed assertion: !str || str != Ptr' +# +SET NAMES utf8; +SELECT LEAST('%', GET_FORMAT(datetime, 'eur'), CAST(GET_FORMAT(datetime, 'eur') AS CHAR(65535))); +LEAST('%', GET_FORMAT(datetime, 'eur'), CAST(GET_FORMAT(datetime, 'eur') AS CHAR(65535))) +% +SET NAMES latin1; +# +# End of 5.1 tests +# diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index e5dc7ffa53e..2a5de8ca9ba 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -359,3 +359,19 @@ SELECT DATE_FORMAT("0000-02-28",'%W %d %M %Y') as valid_date; SELECT DATE_FORMAT("2009-01-01",'%W %d %M %Y') as valid_date; --echo "End of 5.0 tests" + + +--echo # +--echo # Start of 5.1 tests +--echo # + +--echo # +--echo # Bug#58005 utf8 + get_format causes failed assertion: !str || str != Ptr' +--echo # +SET NAMES utf8; +SELECT LEAST('%', GET_FORMAT(datetime, 'eur'), CAST(GET_FORMAT(datetime, 'eur') AS CHAR(65535))); +SET NAMES latin1; + +--echo # +--echo # End of 5.1 tests +--echo # diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 103bd96efd4..6335199b8de 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2456,14 +2456,14 @@ String *Item_char_typecast::val_str(String *str) { // Convert character set if differ uint dummy_errors; - if (!(res= args[0]->val_str(&tmp_value)) || - str->copy(res->ptr(), res->length(), from_cs, - cast_cs, &dummy_errors)) + if (!(res= args[0]->val_str(str)) || + tmp_value.copy(res->ptr(), res->length(), from_cs, + cast_cs, &dummy_errors)) { null_value= 1; return 0; } - res= str; + res= &tmp_value; } res->set_charset(cast_cs); @@ -2497,9 +2497,9 @@ String *Item_char_typecast::val_str(String *str) { if (res->alloced_length() < (uint) cast_length) { - str->alloc(cast_length); - str->copy(*res); - res= str; + str_value.alloc(cast_length); + str_value.copy(*res); + res= &str_value; } bzero((char*) res->ptr() + res->length(), (uint) cast_length - res->length());