From 74e463e68f04d0429fff095ce7efe638234cebfc Mon Sep 17 00:00:00 2001
From: unknown <bar@mysql.com>
Date: Mon, 11 Jul 2005 13:20:07 +0500
Subject: [PATCH] field_conv.cc:   Bug#11591   CHAR column with utf8 does not
 work properly   (more chars than expected)   do_cut_string didn't call
 well_formed_length,   and copied all data, which was wrong in the   case of
 multibyte character set. ctype_utf8.result, ctype_utf8.test:   adding test
 case

sql/field_conv.cc:
  Bug#11591
  CHAR column with utf8 does not work properly
  (more chars than expected)
  do_cut_string didn't call well_formed_length,
  and copied all data, which was wrong in the
  case of multibyte character set.
mysql-test/t/ctype_utf8.test:
  adding test case
mysql-test/r/ctype_utf8.result:
  adding test caser
---
 mysql-test/r/ctype_utf8.result | 11 +++++++++++
 mysql-test/t/ctype_utf8.test   | 10 ++++++++++
 sql/field_conv.cc              | 33 ++++++++++++++++++++-------------
 3 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index d4e12ea84b7..665387e476c 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -939,6 +939,17 @@ content	msisdn
 ERR Имри.Афимим.Аеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ад.Д имдимримрад.Адимримримрмдиримримримр м.Дадимфшьмримд им.Адимимрн имадми	1234567890
 11 g	1234567890
 DROP TABLE t1,t2;
+create table t1 (a char(20) character set utf8);
+insert into t1 values ('123456'),('андрей');
+alter table t1 modify a char(2) character set utf8;
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+Warning	1265	Data truncated for column 'a' at row 2
+select char_length(a), length(a), a from t1 order by a;
+char_length(a)	length(a)	a
+2	2	12
+2	4	ан
+drop table t1;
 CREATE TABLE t1 (
 a varchar(255) NOT NULL default '',
 KEY a (a)
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 0a847057258..737dcbcf1ed 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -789,6 +789,16 @@ SELECT content, t2.msisdn FROM t1, t2 WHERE t1.msisdn = '1234567890';
 
 DROP TABLE t1,t2;
 
+#
+# Bug#11591: CHAR column with utf8 does not work properly
+# (more chars than expected)
+#
+create table t1 (a char(20) character set utf8);
+insert into t1 values ('123456'),('андрей');
+alter table t1 modify a char(2) character set utf8;
+select char_length(a), length(a), a from t1 order by a;
+drop table t1;
+
 #
 # Bug#9557 MyISAM utf8 table crash
 #
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 8b362bbf807..625586d8c9b 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -326,21 +326,28 @@ static void do_field_real(Copy_field *copy)
 
 static void do_cut_string(Copy_field *copy)
 {						// Shorter string field
-  memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
-
-  /* Check if we loosed any important characters */
-  char *ptr,*end;
-  for (ptr=copy->from_ptr+copy->to_length,end=copy->from_ptr+copy->from_length ;
-       ptr != end ;
-       ptr++)
+  int well_formed_error;
+  CHARSET_INFO *cs= copy->from_field->charset();
+  const char *from_end= copy->from_ptr + copy->from_length;
+  uint copy_length= cs->cset->well_formed_len(cs, copy->from_ptr, from_end, 
+                                              copy->to_length / cs->mbmaxlen,
+                                              &well_formed_error);
+  if (copy->to_length < copy_length)
+    copy_length= copy->to_length;
+  memcpy(copy->to_ptr, copy->from_ptr, copy_length);
+
+  /* Check if we lost any important characters */
+  if (well_formed_error ||
+      cs->cset->scan(cs, copy->from_ptr + copy_length, from_end,
+                     MY_SEQ_SPACES) < (copy->from_length - copy_length))
   {
-    if (!my_isspace(system_charset_info, *ptr))	// QQ: ucs incompatible
-    {
-      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
-                                  ER_WARN_DATA_TRUNCATED, 1);
-      break;
-    }
+    copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+                                ER_WARN_DATA_TRUNCATED, 1);
   }
+
+  if (copy_length < copy->to_length)
+    cs->cset->fill(cs, copy->to_ptr + copy_length,
+                       copy->to_length - copy_length, ' ');
 }
 
 
-- 
2.30.9