List:Commits« Previous MessageNext Message »
From:gluh Date:October 11 2007 8:46am
Subject:bk commit into 5.0 tree (gluh:1.2536) BUG#30981
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of gluh. When gluh does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-10-11 13:46:50+05:00, gluh@stripped +9 -0
  Bug#30981 CHAR(0x41 USING ucs2) doesn't add leading zero
  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
  check_well_formed_result moved to Item from Item_str_func
  fixed Item_func_char::val_str for proper ucs symbols converting
  added check for well formed strings for correct conversion of constants with underscore
  charset

  mysql-test/r/ctype_ucs.result@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +3 -0
    test result

  mysql-test/r/ctype_utf8.result@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +64 -2
    test result

  mysql-test/t/ctype_ucs.test@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +5 -0
    test case

  mysql-test/t/ctype_utf8.test@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +19 -0
    test case

  sql/item.cc@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +35 -0
    check_well_formed_result() moved from Item_str_func

  sql/item.h@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +1 -0
    check_well_formed_result() moved from Item_str_func

  sql/item_strfunc.cc@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +3 -32
    check_well_formed_result moved to Item
    fixed Item_func_char::val_str for proper ucs symbols converting

  sql/item_strfunc.h@stripped, 2007-10-11 13:46:48+05:00, gluh@stripped +0 -1
    check_well_formed_result moved to Item

  sql/sql_yacc.yy@stripped, 2007-10-11 13:46:49+05:00, gluh@stripped +18 -4
    added check for well formed string

diff -Nrup a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
--- a/mysql-test/r/ctype_ucs.result	2007-08-03 15:57:13 +05:00
+++ b/mysql-test/r/ctype_ucs.result	2007-10-11 13:46:48 +05:00
@@ -922,4 +922,7 @@ ERROR HY000: Illegal mix of collations (
 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 -Nrup a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
--- a/mysql-test/r/ctype_utf8.result	2007-08-03 15:28:37 +05:00
+++ b/mysql-test/r/ctype_utf8.result	2007-10-11 13:46:48 +05:00
@@ -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 -Nrup a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
--- a/mysql-test/t/ctype_ucs.test	2007-08-03 15:30:29 +05:00
+++ b/mysql-test/t/ctype_ucs.test	2007-10-11 13:46:48 +05:00
@@ -651,4 +651,9 @@ select * from t1 where a=if(b<10,_ucs2 0
 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 -Nrup a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
--- a/mysql-test/t/ctype_utf8.test	2007-08-03 15:28:37 +05:00
+++ b/mysql-test/t/ctype_utf8.test	2007-10-11 13:46:48 +05:00
@@ -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 -Nrup a/sql/item.cc b/sql/item.cc
--- a/sql/item.cc	2007-09-13 18:30:28 +05:00
+++ b/sql/item.cc	2007-10-11 13:46:48 +05:00
@@ -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 -Nrup a/sql/item.h b/sql/item.h
--- a/sql/item.h	2007-08-03 21:59:12 +05:00
+++ b/sql/item.h	2007-10-11 13:46:48 +05:00
@@ -870,6 +870,7 @@ public:
   */
   virtual bool result_as_longlong() { return FALSE; }
   bool is_datetime();
+  String *check_well_formed_result(String *str);
 };
 
 
diff -Nrup a/sql/item_strfunc.cc b/sql/item_strfunc.cc
--- a/sql/item_strfunc.cc	2007-08-03 15:28:38 +05:00
+++ b/sql/item_strfunc.cc	2007-10-11 13:46:48 +05:00
@@ -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 *
 {
   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 *
       } 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 -Nrup a/sql/item_strfunc.h b/sql/item_strfunc.h
--- a/sql/item_strfunc.h	2007-07-27 18:42:24 +05:00
+++ b/sql/item_strfunc.h	2007-10-11 13:46:48 +05:00
@@ -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 -Nrup a/sql/sql_yacc.yy b/sql/sql_yacc.yy
--- a/sql/sql_yacc.yy	2007-09-12 23:39:32 +05:00
+++ b/sql/sql_yacc.yy	2007-10-11 13:46:49 +05:00
@@ -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; }
Thread
bk commit into 5.0 tree (gluh:1.2536) BUG#30981gluh11 Oct