Loading mysql-test/r/ctype_utf8.result +10 −0 Original line number Diff line number Diff line Loading @@ -1095,6 +1095,11 @@ char(0xff,0x8f using utf8) Warnings: Warning 1300 Invalid utf8 character string: 'FF8F' select convert(char(0xff,0x8f) using utf8); convert(char(0xff,0x8f) using utf8) Warnings: Warning 1300 Invalid utf8 character string: 'FF8F' set sql_mode=traditional; select char(0xff,0x8f using utf8); char(0xff,0x8f using utf8) Loading @@ -1116,6 +1121,11 @@ char(2557 using utf8) NULL Warnings: Error 1300 Invalid utf8 character string: 'FD' select convert(char(0xff,0x8f) using utf8); convert(char(0xff,0x8f) using utf8) NULL Warnings: Error 1300 Invalid utf8 character string: 'FF8F' select hex(convert(char(2557 using latin1) using utf8)); hex(convert(char(2557 using latin1) using utf8)) 09C3BD Loading mysql-test/t/ctype_utf8.test +5 −1 Original line number Diff line number Diff line Loading @@ -884,7 +884,9 @@ SELECT DISTINCT id FROM t1 ORDER BY id; DROP TABLE t1; # # Bugs#10504: Character set does not support traditional mode # Bug#10504: Character set does not support traditional mode # Bug#14146: CHAR(...USING ...) and CONVERT(CHAR(...) USING...) # produce different results # set names utf8; # correct value Loading @@ -894,12 +896,14 @@ select char(0xd18f using utf8); select char(53647 using utf8); # incorrect value: return with warning select char(0xff,0x8f using utf8); select convert(char(0xff,0x8f) using utf8); # incorrect value in strict mode: return NULL with "Error" level warning set sql_mode=traditional; select char(0xff,0x8f using utf8); select char(195 using utf8); select char(196 using utf8); select char(2557 using utf8); select convert(char(0xff,0x8f) using utf8); # # Check convert + char + using Loading sql/item_strfunc.cc +34 −29 Original line number Diff line number Diff line Loading @@ -48,6 +48,38 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, } String *Item_str_func::check_well_formed_result(String *str) { /* Check whether we got a well-formed string */ CHARSET_INFO *cs= str->charset(); int well_formed_error; uint wlen= cs->cset->well_formed_len(cs, str->ptr(), str->ptr() + str->length(), str->length(), &well_formed_error); if (wlen < str->length()) { THD *thd= current_thd; char hexbuf[7]; enum MYSQL_ERROR::enum_warning_level level; uint diff= str->length() - wlen; set_if_smaller(diff, 3); octet2hex(hexbuf, str->ptr() + wlen, diff); if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) { level= MYSQL_ERROR::WARN_LEVEL_ERROR; null_value= 1; str= 0; } else level= MYSQL_ERROR::WARN_LEVEL_WARN; push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); } return str; } double Item_str_func::val_real() { DBUG_ASSERT(fixed == 1); Loading Loading @@ -1984,34 +2016,7 @@ String *Item_func_char::val_str(String *str) } str->set_charset(collation.collation); str->realloc(str->length()); // Add end 0 (for Purify) /* Check whether we got a well-formed string */ CHARSET_INFO *cs= collation.collation; int well_formed_error; uint wlen= cs->cset->well_formed_len(cs, str->ptr(), str->ptr() + str->length(), str->length(), &well_formed_error); if (wlen < str->length()) { THD *thd= current_thd; char hexbuf[7]; enum MYSQL_ERROR::enum_warning_level level; uint diff= str->length() - wlen; set_if_smaller(diff, 3); octet2hex(hexbuf, str->ptr() + wlen, diff); if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) { level= MYSQL_ERROR::WARN_LEVEL_ERROR; null_value= 1; str= 0; } else level= MYSQL_ERROR::WARN_LEVEL_WARN; push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); } return str; return check_well_formed_result(str); } Loading Loading @@ -2320,7 +2325,7 @@ String *Item_func_conv_charset::val_str(String *str) } null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(), conv_charset, &dummy_errors); return null_value ? 0 : &str_value; return null_value ? 0 : check_well_formed_result(&str_value); } void Item_func_conv_charset::fix_length_and_dec() Loading sql/item_strfunc.h +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ class Item_str_func :public Item_func double val_real(); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); String *check_well_formed_result(String *str); }; class Item_func_md5 :public Item_str_func Loading Loading
mysql-test/r/ctype_utf8.result +10 −0 Original line number Diff line number Diff line Loading @@ -1095,6 +1095,11 @@ char(0xff,0x8f using utf8) Warnings: Warning 1300 Invalid utf8 character string: 'FF8F' select convert(char(0xff,0x8f) using utf8); convert(char(0xff,0x8f) using utf8) Warnings: Warning 1300 Invalid utf8 character string: 'FF8F' set sql_mode=traditional; select char(0xff,0x8f using utf8); char(0xff,0x8f using utf8) Loading @@ -1116,6 +1121,11 @@ char(2557 using utf8) NULL Warnings: Error 1300 Invalid utf8 character string: 'FD' select convert(char(0xff,0x8f) using utf8); convert(char(0xff,0x8f) using utf8) NULL Warnings: Error 1300 Invalid utf8 character string: 'FF8F' select hex(convert(char(2557 using latin1) using utf8)); hex(convert(char(2557 using latin1) using utf8)) 09C3BD Loading
mysql-test/t/ctype_utf8.test +5 −1 Original line number Diff line number Diff line Loading @@ -884,7 +884,9 @@ SELECT DISTINCT id FROM t1 ORDER BY id; DROP TABLE t1; # # Bugs#10504: Character set does not support traditional mode # Bug#10504: Character set does not support traditional mode # Bug#14146: CHAR(...USING ...) and CONVERT(CHAR(...) USING...) # produce different results # set names utf8; # correct value Loading @@ -894,12 +896,14 @@ select char(0xd18f using utf8); select char(53647 using utf8); # incorrect value: return with warning select char(0xff,0x8f using utf8); select convert(char(0xff,0x8f) using utf8); # incorrect value in strict mode: return NULL with "Error" level warning set sql_mode=traditional; select char(0xff,0x8f using utf8); select char(195 using utf8); select char(196 using utf8); select char(2557 using utf8); select convert(char(0xff,0x8f) using utf8); # # Check convert + char + using Loading
sql/item_strfunc.cc +34 −29 Original line number Diff line number Diff line Loading @@ -48,6 +48,38 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, } String *Item_str_func::check_well_formed_result(String *str) { /* Check whether we got a well-formed string */ CHARSET_INFO *cs= str->charset(); int well_formed_error; uint wlen= cs->cset->well_formed_len(cs, str->ptr(), str->ptr() + str->length(), str->length(), &well_formed_error); if (wlen < str->length()) { THD *thd= current_thd; char hexbuf[7]; enum MYSQL_ERROR::enum_warning_level level; uint diff= str->length() - wlen; set_if_smaller(diff, 3); octet2hex(hexbuf, str->ptr() + wlen, diff); if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) { level= MYSQL_ERROR::WARN_LEVEL_ERROR; null_value= 1; str= 0; } else level= MYSQL_ERROR::WARN_LEVEL_WARN; push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); } return str; } double Item_str_func::val_real() { DBUG_ASSERT(fixed == 1); Loading Loading @@ -1984,34 +2016,7 @@ String *Item_func_char::val_str(String *str) } str->set_charset(collation.collation); str->realloc(str->length()); // Add end 0 (for Purify) /* Check whether we got a well-formed string */ CHARSET_INFO *cs= collation.collation; int well_formed_error; uint wlen= cs->cset->well_formed_len(cs, str->ptr(), str->ptr() + str->length(), str->length(), &well_formed_error); if (wlen < str->length()) { THD *thd= current_thd; char hexbuf[7]; enum MYSQL_ERROR::enum_warning_level level; uint diff= str->length() - wlen; set_if_smaller(diff, 3); octet2hex(hexbuf, str->ptr() + wlen, diff); if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) { level= MYSQL_ERROR::WARN_LEVEL_ERROR; null_value= 1; str= 0; } else level= MYSQL_ERROR::WARN_LEVEL_WARN; push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); } return str; return check_well_formed_result(str); } Loading Loading @@ -2320,7 +2325,7 @@ String *Item_func_conv_charset::val_str(String *str) } null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(), conv_charset, &dummy_errors); return null_value ? 0 : &str_value; return null_value ? 0 : check_well_formed_result(&str_value); } void Item_func_conv_charset::fix_length_and_dec() Loading
sql/item_strfunc.h +1 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ class Item_str_func :public Item_func double val_real(); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); String *check_well_formed_result(String *str); }; class Item_func_md5 :public Item_str_func Loading