diff options
-rw-r--r-- | mysql-test/r/alter_table.result | 1 | ||||
-rw-r--r-- | mysql-test/r/ctype_recoding.result | 8 | ||||
-rw-r--r-- | mysql-test/r/fulltext.result | 5 | ||||
-rw-r--r-- | mysql-test/t/alter_table.test | 1 | ||||
-rw-r--r-- | mysql-test/t/ctype_recoding.test | 10 | ||||
-rw-r--r-- | sql/field.cc | 32 | ||||
-rw-r--r-- | sql/sql_string.cc | 21 | ||||
-rw-r--r-- | sql/sql_string.h | 4 |
8 files changed, 66 insertions, 16 deletions
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index e85ad303564..89b8bd66848 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -349,6 +349,7 @@ alter table t1 change a a char(10) character set koi8r; select a,hex(a) from t1; a hex(a) ÔÅÓÔ D4C5D3D4 +delete from t1; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index be792c007fc..72d19885101 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -166,3 +166,11 @@ ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ' SET NAMES utf8; CREATE TABLE `goodÐÌÏÈÏ` (a int); ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ` (a int)' +set names latin1; +create table t1 (a char(10) character set koi8r, b text character set koi8r); +insert into t1 values ('test','test'); +insert into t1 values ('ÊÃÕË','ÊÃÕË'); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +Warning 1265 Data truncated for column 'b' at row 1 +drop table t1; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 30c4c75f3d1..d07e4df6e73 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -356,6 +356,11 @@ SELECT t, collation(t),MATCH t AGAINST ('Osnabruck') FROM t1 WHERE MATCH t AGAIN t collation(t) MATCH t AGAINST ('Osnabruck') aus Osnabrück utf8_general_ci 1.591139793396 alter table t1 modify t varchar(200) collate latin1_german2_ci not null; +Warnings: +Warning 1265 Data truncated for column 't' at row 3 +Warning 1265 Data truncated for column 't' at row 4 +Warning 1265 Data truncated for column 't' at row 5 +Warning 1265 Data truncated for column 't' at row 6 SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück'); t collation(t) aus Osnabrück latin1_german2_ci diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index eb35aa90fe2..e46027ae8d9 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -207,6 +207,7 @@ alter table t1 change a a text character set cp1251; select a,hex(a) from t1; alter table t1 change a a char(10) character set koi8r; select a,hex(a) from t1; +delete from t1; # # Test ALTER TABLE .. CHARACTER SET .. diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 82d0643b577..5f417352d95 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -121,3 +121,13 @@ CREATE TABLE `goodÐÌÏÈÏ` (a int); SET NAMES utf8; --error 1300 CREATE TABLE `goodÐÌÏÈÏ` (a int); + + +# +# Test that we produce a warnign when conversion loses data. +# +set names latin1; +create table t1 (a char(10) character set koi8r, b text character set koi8r); +insert into t1 values ('test','test'); +insert into t1 values ('ÊÃÕË','ÊÃÕË'); +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 3e625f3a582..261494d2125 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4275,9 +4275,12 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) /* Convert character set if nesessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used)) { - tmpstr.copy(from, length, cs, field_charset); + uint conv_errors; + tmpstr.copy(from, length, cs, field_charset, &conv_errors); from= tmpstr.ptr(); length= tmpstr.length(); + if (conv_errors) + error= 1; } /* @@ -4300,11 +4303,11 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); if (from != end) - { - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); - error=1; - } + error= 1; } + if (error) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); + return error; } @@ -4528,16 +4531,20 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) /* Convert character set if nesessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used)) { - tmpstr.copy(from, length, cs, field_charset); + uint conv_errors; + tmpstr.copy(from, length, cs, field_charset, &conv_errors); from= tmpstr.ptr(); length= tmpstr.length(); + if (conv_errors) + error= 1; } if (length > field_length) { length=field_length; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); error= 1; } + if (error) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length); int2store(ptr, length); return error; @@ -4865,6 +4872,7 @@ void Field_blob::put_length(char *pos, uint32 length) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) { + int error= 0; if (!length) { bzero(ptr,Field_blob::pack_length()); @@ -4881,9 +4889,12 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) if ((was_conversion= String::needs_conversion(length, cs, field_charset, ¬_used))) { - tmpstr.copy(from, length, cs, field_charset); + uint conv_errors; + tmpstr.copy(from, length, cs, field_charset, &conv_errors); from= tmpstr.ptr(); length= tmpstr.length(); + if (conv_errors) + error= 1; } copy_length= max_data_length(); @@ -4897,8 +4908,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) min(length, copy_length), copy_length); if (copy_length < length) - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); - + error= 1; Field_blob::store_length(copy_length); if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH) { // Must make a copy @@ -4910,6 +4920,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) } bmove(ptr+packlength,(char*) &from,sizeof(char*)); } + if (error) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); return 0; } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 1044dc4e58e..30559496fde 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -331,19 +331,26 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, /* Copy with charset convertion */ bool String::copy(const char *str, uint32 arg_length, - CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) + CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors) { uint32 offset; if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) + { + if (errors) + *errors= 0; return copy(str, arg_length, to_cs); + } if ((from_cs == &my_charset_bin) && offset) + { + if (errors) + *errors= 0; return copy_aligned(str, arg_length, offset, to_cs); - + } uint32 new_length= to_cs->mbmaxlen*arg_length; if (alloc(new_length)) return TRUE; str_length=copy_and_convert((char*) Ptr, new_length, to_cs, - str, arg_length, from_cs); + str, arg_length, from_cs, errors); str_charset=to_cs; return FALSE; } @@ -769,7 +776,8 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, - const char *from, uint32 from_length, CHARSET_INFO *from_cs) + const char *from, uint32 from_length, CHARSET_INFO *from_cs, + uint *errors) { int cnvres; my_wc_t wc; @@ -780,6 +788,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const uchar *) = from_cs->cset->mb_wc; int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)= to_cs->cset->wc_mb; + uint error_count= 0; while (1) { @@ -788,6 +797,7 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, from+= cnvres; else if (cnvres == MY_CS_ILSEQ) { + error_count++; from++; wc= '?'; } @@ -799,12 +809,15 @@ outp: to+= cnvres; else if (cnvres == MY_CS_ILUNI && wc != '?') { + error_count++; wc= '?'; goto outp; } else break; } + if (errors) + *errors= error_count; return (uint32) (to - to_start); } diff --git a/sql/sql_string.h b/sql/sql_string.h index 2d368991159..de8f4af58d9 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -29,7 +29,7 @@ int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const char *from, uint32 from_length, - CHARSET_INFO *from_cs); + CHARSET_INFO *from_cs, uint *errors= 0); class String { @@ -199,7 +199,7 @@ public: CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, - CHARSET_INFO *csto); + CHARSET_INFO *csto, uint *errors= 0); bool append(const String &s); bool append(const char *s); bool append(const char *s,uint32 arg_length); |