From f90f1e306fe1b25fabfecc0e64875dd9109b2a20 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Nov 2006 12:00:27 +0100 Subject: [PATCH] Bug#19371 VARBINARY() have trailing zeros after upgrade from 4.1 - Detect if a table has field of type MYSQL_TYPE_VAR_STRING while running "CHECK TABLE t FOR UPGRADE" and indicate it need to be fixed with "REPAIR TABLE t". - When running a "REPAIR TABLE t" or "ALTER TABLE t FORCE" on the above table, install a special copy function to trim off the trailing spaces which we safely can say that the pre 5.0 mysqld didn't put there. mysql-test/r/varbinary.result: Add test to see that a table with varbinary from 4.1 can be REPAIRED mysql-test/t/varbinary.test: Add test to see that a table with varbinary from 4.1 can be REPAIRED sql/field_conv.cc: Add new field copy function 'do_field_varbinary_pre50' used for copying between MYSQL_TYPE_VAR_STRING and MYSQL_TYPE_VARCHAR. It will remove trailing spaces from the field as MySQL <= 4.1 never stores the trailing spaces for a MYSQL_TYPE_VAR_STRING. Install this new copy function in ALTER TABLEs list of functions to use for copying data during and alter if from field is a <= 4.1 varbinary and to field is 5.0 varbinary. sql/handler.cc: If the table has a pre 5.0 varbinary, table not to be altered so the field type is upgraded to 5.0 version and trailing space can be trimmed. mysql-test/std_data/bug19371.MYD: New BitKeeper file ``mysql-test/std_data/bug19371.MYD'' mysql-test/std_data/bug19371.MYI: New BitKeeper file ``mysql-test/std_data/bug19371.MYI'' mysql-test/std_data/bug19371.frm: New BitKeeper file ``mysql-test/std_data/bug19371.frm'' --- mysql-test/r/varbinary.result | 52 +++++++++++++++++++++++++++++++ mysql-test/std_data/bug19371.MYD | Bin 0 -> 40 bytes mysql-test/std_data/bug19371.MYI | Bin 0 -> 1024 bytes mysql-test/std_data/bug19371.frm | Bin 0 -> 8578 bytes mysql-test/t/varbinary.test | 40 ++++++++++++++++++++++++ sql/field_conv.cc | 24 ++++++++++++++ sql/handler.cc | 4 +++ 7 files changed, 120 insertions(+) create mode 100644 mysql-test/std_data/bug19371.MYD create mode 100644 mysql-test/std_data/bug19371.MYI create mode 100644 mysql-test/std_data/bug19371.frm diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result index e62051df5cd..2b8a9c625a5 100644 --- a/mysql-test/r/varbinary.result +++ b/mysql-test/r/varbinary.result @@ -26,3 +26,55 @@ select x,xx from t1; x xx 1 2 drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varbinary(255) default NULL, + `b` varchar(255) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select length(a), length(b) from t1; +length(a) length(b) +255 3 +255 3 +CHECK TABLE t1 FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check error Table upgrade required. Please do "REPAIR TABLE `t1`" to fix it! +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varbinary(255) default NULL, + `b` varchar(255) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select length(a), length(b) from t1; +length(a) length(b) +3 3 +3 3 +insert into t1 values("ccc", "ddd"); +select length(a), length(b) from t1; +length(a) length(b) +3 3 +3 3 +3 3 +select hex(a), hex(b) from t1; +hex(a) hex(b) +616161 636363 +626262 646464 +636363 646464 +select concat("'", a, "'"), concat("'", b, "'") from t1; +concat("'", a, "'") concat("'", b, "'") +'aaa' 'ccc' +'bbb' 'ddd' +'ccc' 'ddd' +drop table t1; +create table t1(a varbinary(255)); +insert into t1 values("aaa "); +select length(a) from t1; +length(a) +6 +alter table t1 modify a varchar(255); +select length(a) from t1; +length(a) +6 diff --git a/mysql-test/std_data/bug19371.MYD b/mysql-test/std_data/bug19371.MYD new file mode 100644 index 0000000000000000000000000000000000000000..1b58a70832fd265c905eb935049ff73af5cf51ef GIT binary patch literal 40 jcmZQ(;9_I`!Jal>86jF)%@C7{&A-3LpY3FmVkS12=7U4Jao9m4}<_ z>LrwctOuQsEC*r3?ZlKq5n%-S0fZTV8kj)#f$U}mVn!A)31l%aK)efP!U;wYi;>|! Thz3${r@|GCGDbsSID`NI%jguS literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/bug19371.frm b/mysql-test/std_data/bug19371.frm new file mode 100644 index 0000000000000000000000000000000000000000..7be45d6f8da3d128b42f6b4fe863f559cab9d694 GIT binary patch literal 8578 zcmeI&u?~VT5XSMZ2N>8Gj5Dhf&MZEGiLU@pVtj8o4?~$9jr?!9>kV!5OQ*JTYMMf7 zlXQtBk75n0)vRTmdu=Xq?t7`r12O^#Abtmp.set_quick(buff,sizeof(buff),copy->tmp.charset()); + copy->from_field->val_str(©->tmp); + + /* Use the same function as in 4.1 to trim trailing spaces */ + uint length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(), + copy->from_field->field_length); + + copy->to_field->store(copy->tmp.c_ptr_quick(), length, + copy->tmp.charset()); +} + + static void do_field_int(Copy_field *copy) { longlong value= copy->from_field->val_int(); @@ -570,6 +585,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) // Check if identical fields if (from->result_type() == STRING_RESULT) { + /* + Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and + use special copy function that removes trailing spaces and thus + repairs data. + */ + if (from->type() == MYSQL_TYPE_VAR_STRING && !from->has_charset() && + to->type() == MYSQL_TYPE_VARCHAR && !to->has_charset()) + return do_field_varbinary_pre50; + /* If we are copying date or datetime's we have to check the dates if we don't allow 'all' dates. diff --git a/sql/handler.cc b/sql/handler.cc index 4accc746664..09e83247bb5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1972,6 +1972,10 @@ int handler::check_old_types() { return HA_ADMIN_NEEDS_ALTER; } + if ((*field)->type() == MYSQL_TYPE_VAR_STRING) + { + return HA_ADMIN_NEEDS_ALTER; + } } } return 0;