MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:bar Date:April 13 2007 5:06am
Subject:bk commit into 5.0 tree (bar:1.2428) BUG#20095
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of bar. When bar 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
  1.2428 07/04/13 10:05:55 bar@stripped +3 -0
  Bug#20095 Changing length of VARCHAR field with UTF8 collation does not truncate values
  Problem: single byte do_varstring1() function was called, which didn't
  check limit on "number of character", and checked only "number of bytes".
  Fix: adding a multi-byte aware function do_varstring1_mb(),
  to limit on "number of characters"

  sql/field_conv.cc
    1.64 07/04/13 10:05:52 bar@stripped +30 -2
    Adding missing function to copy VARCHAR strings
    having one length byte.

  mysql-test/t/ctype_utf8.test
    1.96 07/04/13 10:05:52 bar@stripped +35 -0
    Adding test case

  mysql-test/r/ctype_utf8.result
    1.105 07/04/13 10:05:52 bar@stripped +43 -0
    Adding test case

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	bar
# Host:	bar.myoffice.izhnet.ru
# Root:	/home/bar/mysql-5.0.b20095

--- 1.63/sql/field_conv.cc	2007-03-30 19:08:54 +05:00
+++ 1.64/sql/field_conv.cc	2007-04-13 10:05:52 +05:00
@@ -434,6 +434,26 @@ static void do_varstring1(Copy_field *co
 }
 
 
+static void do_varstring1_mb(Copy_field *copy)
+{
+  int well_formed_error;
+  CHARSET_INFO *cs= copy->from_field->charset();
+  uint from_length= (uint) *(uchar*) copy->from_ptr;
+  const char *from_ptr= copy->from_ptr + 1;
+  uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
+  uint length= cs->cset->well_formed_len(cs, from_ptr, from_ptr + from_length,
+                                         to_char_length, &well_formed_error);
+  if (length < from_length)
+  {
+    if (current_thd->count_cuted_fields)
+      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+                                  WARN_DATA_TRUNCATED, 1);
+  }
+  *(uchar*) copy->to_ptr= (uchar) length;
+  memcpy(copy->to_ptr + 1, from_ptr, length);
+}
+
+
 static void do_varstring2(Copy_field *copy)
 {
   uint length=uint2korr(copy->from_ptr);
@@ -459,6 +479,12 @@ static void do_varstring2_mb(Copy_field 
   const char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
   uint length= cs->cset->well_formed_len(cs, from_beg, from_beg + from_length,
                                          char_length, &well_formed_error);
+  if (length < from_length)
+  {
+    if (current_thd->count_cuted_fields)
+      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+                                  WARN_DATA_TRUNCATED, 1);
+  }  
   int2store(copy->to_ptr, length);
   memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
 }
@@ -634,8 +660,10 @@ void (*Copy_field::get_copy_func(Field *
           return do_field_string;
         if (to_length != from_length)
           return (((Field_varstring*) to)->length_bytes == 1 ?
-                  do_varstring1 : (from->charset()->mbmaxlen == 1 ?
-                                   do_varstring2 : do_varstring2_mb));
+                  (from->charset()->mbmaxlen == 1 ? do_varstring1 :
+                                                    do_varstring1_mb) :
+                  (from->charset()->mbmaxlen == 1 ? do_varstring2 :
+                                                    do_varstring2_mb));
       }
       else if (to_length < from_length)
 	return (from->charset()->mbmaxlen == 1 ?

--- 1.104/mysql-test/r/ctype_utf8.result	2007-03-28 18:57:27 +05:00
+++ 1.105/mysql-test/r/ctype_utf8.result	2007-04-13 10:05:52 +05:00
@@ -1480,6 +1480,49 @@ aa
 xxx
 yyy
 DROP TABLE t1;
+create table t1 (
+a varchar(26) not null
+) default character set utf8;
+insert into t1 (a) values ('abcdefghijklmnopqrstuvwxyz');
+select * from t1;
+a
+abcdefghijklmnopqrstuvwxyz
+alter table t1 change a a varchar(20) character set utf8 not null;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+select * from t1;
+a
+abcdefghijklmnopqrst
+alter table t1 change a a char(15) character set utf8 not null;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+select * from t1;
+a
+abcdefghijklmno
+alter table t1 change a a char(10) character set utf8 not null;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+select * from t1;
+a
+abcdefghij
+alter table t1 change a a varchar(5) character set utf8 not null;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+select * from t1;
+a
+abcde
+drop table t1;
+create table t1 (
+a varchar(4000) not null
+) default character set utf8;
+insert into t1 values (repeat('a',4000));
+alter table t1 change a a varchar(3000) character set utf8 not null;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+select length(a) from t1;
+length(a)
+3000
+drop table t1;
 set names utf8;
 select hex(char(1 using utf8));
 hex(char(1 using utf8))

--- 1.95/mysql-test/t/ctype_utf8.test	2007-03-28 18:57:27 +05:00
+++ 1.96/mysql-test/t/ctype_utf8.test	2007-04-13 10:05:52 +05:00
@@ -1193,6 +1193,41 @@ SELECT DISTINCT id FROM t1 ORDER BY id;
 DROP TABLE t1;
 
 #
+# Bug#20095 Changing length of VARCHAR field with UTF8
+# collation does not truncate values
+#
+create table t1 (
+  a varchar(26) not null
+) default character set utf8;
+insert into t1 (a) values ('abcdefghijklmnopqrstuvwxyz');
+select * from t1;
+# varchar to varchar
+alter table t1 change a a varchar(20) character set utf8 not null;
+select * from t1;
+# varchar to char
+alter table t1 change a a char(15) character set utf8 not null;
+select * from t1;
+# char to char
+alter table t1 change a a char(10) character set utf8 not null;
+select * from t1;
+# char to varchar
+alter table t1 change a a varchar(5) character set utf8 not null;
+select * from t1;
+drop table t1;
+
+#
+# Check that do_varstring2_mb produces a warning
+#
+create table t1 (
+  a varchar(4000) not null
+) default character set utf8;
+insert into t1 values (repeat('a',4000));
+alter table t1 change a a varchar(3000) character set utf8 not null;
+select length(a) from t1;
+drop table t1;
+
+
+#
 #  Bug#10504: Character set does not support traditional mode
 #  Bug#14146: CHAR(...USING ...) and CONVERT(CHAR(...) USING...)
 #             produce different results
Thread
bk commit into 5.0 tree (bar:1.2428) BUG#20095bar13 Apr