summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgkodinov/kgeorge@magare.gmz <>2007-10-12 14:11:27 +0300
committergkodinov/kgeorge@magare.gmz <>2007-10-12 14:11:27 +0300
commitd330469f107d06eed95f14965017d8da48407984 (patch)
tree963af75491a6cd2cb627474f52ab7ce954fccb52
parent99f1606e942985d4a803c2914eb25fe4fc61c338 (diff)
parentdb39976a0658d2e17273b4816289ef6093071591 (diff)
downloadmariadb-git-d330469f107d06eed95f14965017d8da48407984.tar.gz
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into magare.gmz:/home/kgeorge/mysql/autopush/B31440-5.0-opt
-rw-r--r--mysql-test/r/ctype_ucs.result3
-rw-r--r--mysql-test/r/ctype_utf8.result66
-rw-r--r--mysql-test/t/ctype_ucs.test5
-rw-r--r--mysql-test/t/ctype_utf8.test19
-rw-r--r--sql/item.cc35
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_strfunc.cc35
-rw-r--r--sql/item_strfunc.h1
-rw-r--r--sql/sql_yacc.yy22
9 files changed, 148 insertions, 39 deletions
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 023267c227c..262055436b8 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -922,4 +922,7 @@ ERROR HY000: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (ucs2_gen
select * from t1 where a=if(b<10,_ucs2 0x0062,_ucs2 0x00C0);
ERROR HY000: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (ucs2_general_ci,COERCIBLE) for operation '='
drop table t1;
+select hex(char(0x41 using ucs2));
+hex(char(0x41 using ucs2))
+0041
End of 5.0 tests
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 710cac388a5..a86dfbc190d 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -1538,12 +1538,12 @@ char(53647 using utf8)
я
select char(0xff,0x8f using utf8);
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;
@@ -1730,3 +1730,65 @@ i
1
н1234567890
DROP TABLE t1, t2;
+set sql_mode=traditional;
+select hex(char(0xFF using utf8));
+hex(char(0xFF using utf8))
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF'
+select hex(convert(0xFF using utf8));
+hex(convert(0xFF using utf8))
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF'
+select hex(_utf8 0x616263FF);
+hex(_utf8 0x616263FF)
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF'
+select hex(_utf8 X'616263FF');
+hex(_utf8 X'616263FF')
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF'
+select hex(_utf8 B'001111111111');
+hex(_utf8 B'001111111111')
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF'
+select (_utf8 X'616263FF');
+(_utf8 X'616263FF')
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF'
+set sql_mode=default;
+select hex(char(0xFF using utf8));
+hex(char(0xFF using utf8))
+
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF'
+select hex(convert(0xFF using utf8));
+hex(convert(0xFF using utf8))
+
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF'
+select hex(_utf8 0x616263FF);
+hex(_utf8 0x616263FF)
+616263
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF'
+select hex(_utf8 X'616263FF');
+hex(_utf8 X'616263FF')
+616263
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF'
+select hex(_utf8 B'001111111111');
+hex(_utf8 B'001111111111')
+03
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF'
+select (_utf8 X'616263FF');
+(_utf8 X'616263FF')
+abc
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF'
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index bca3a9c3a96..5525a5beb6f 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -651,4 +651,9 @@ select * from t1 where a=if(b<10,_ucs2 0x00C0,_ucs2 0x0062);
select * from t1 where a=if(b<10,_ucs2 0x0062,_ucs2 0x00C0);
drop table t1;
+#
+# Bug#30981 CHAR(0x41 USING ucs2) doesn't add leading zero
+#
+select hex(char(0x41 using ucs2));
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index f8eed0bae9a..e10fb708f5c 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1403,3 +1403,22 @@ SELECT b FROM t2 UNION SELECT c FROM t1;
SELECT i FROM t2 UNION SELECT c FROM t1;
DROP TABLE t1, t2;
+
+#
+# Bug#30982: CHAR(..USING..) can return a not-well-formed string
+# Bug #30986: Character set introducer followed by a HEX string can return bad result
+#
+set sql_mode=traditional;
+select hex(char(0xFF using utf8));
+select hex(convert(0xFF using utf8));
+select hex(_utf8 0x616263FF);
+select hex(_utf8 X'616263FF');
+select hex(_utf8 B'001111111111');
+select (_utf8 X'616263FF');
+set sql_mode=default;
+select hex(char(0xFF using utf8));
+select hex(convert(0xFF using utf8));
+select hex(_utf8 0x616263FF);
+select hex(_utf8 X'616263FF');
+select hex(_utf8 B'001111111111');
+select (_utf8 X'616263FF');
diff --git a/sql/item.cc b/sql/item.cc
index e9b2904e3da..b4d1e1e2f52 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4247,6 +4247,41 @@ bool Item::is_datetime()
}
+String *Item::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;
+ str->length(wlen);
+ }
+ push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
+ ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
+ }
+ return str;
+}
+
+
/*
Create a field to hold a string value from an item
diff --git a/sql/item.h b/sql/item.h
index cd0be343a62..a2a06f7d917 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -870,6 +870,7 @@ public:
*/
virtual bool result_as_longlong() { return FALSE; }
bool is_datetime();
+ String *check_well_formed_result(String *str);
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 0c11c9eece8..4e72f117869 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -38,36 +38,6 @@ C_MODE_END
String my_empty_string("",default_charset_info);
-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;
-}
bool Item_str_func::fix_fields(THD *thd, Item **ref)
@@ -2229,11 +2199,13 @@ String *Item_func_char::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
str->length(0);
+ str->set_charset(collation.collation);
for (uint i=0 ; i < arg_count ; i++)
{
int32 num=(int32) args[i]->val_int();
if (!args[i]->null_value)
{
+ char char_num= (char) num;
if (num&0xFF000000L) {
str->append((char)(num>>24));
goto b2;
@@ -2243,10 +2215,9 @@ String *Item_func_char::val_str(String *str)
} else if (num&0xFF00L) {
b1: str->append((char)(num>>8));
}
- str->append((char) num);
+ str->append(&char_num, 1);
}
}
- str->set_charset(collation.collation);
str->realloc(str->length()); // Add end 0 (for Purify)
return check_well_formed_result(str);
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 6ca0b89a22b..ea6229068fe 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -35,7 +35,6 @@ public:
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
- String *check_well_formed_result(String *str);
bool fix_fields(THD *thd, Item **ref);
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 553cc6d24d5..c651c5b1f64 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7716,11 +7716,19 @@ literal:
String *str= tmp ?
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
(String*) 0;
- $$= new Item_string(str ? str->ptr() : "",
+ $$= new Item_string(NULL, /* name will be set in select_item */
+ str ? str->ptr() : "",
str ? str->length() : 0,
Lex->underscore_charset);
if ($$)
+ {
((Item_string *) $$)->set_repertoire_from_value();
+ if (!$$->check_well_formed_result(&$$->str_value))
+ {
+ $$= new Item_null();
+ $$->set_name(NULL, 0, system_charset_info);
+ }
+ }
}
| UNDERSCORE_CHARSET BIN_NUM
{
@@ -7732,9 +7740,15 @@ literal:
String *str= tmp ?
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
(String*) 0;
- $$= new Item_string(str ? str->ptr() : "",
- str ? str->length() : 0,
- Lex->charset);
+ $$= new Item_string(NULL, /* name will be set in select_item */
+ str ? str->ptr() : "",
+ str ? str->length() : 0,
+ Lex->underscore_charset);
+ if ($$ && !$$->check_well_formed_result(&$$->str_value))
+ {
+ $$= new Item_null();
+ $$->set_name(NULL, 0, system_charset_info);
+ }
}
| DATE_SYM text_literal { $$ = $2; }
| TIME_SYM text_literal { $$ = $2; }