Commit f90f1e30 authored by unknown's avatar unknown

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''
parent c2699e1a
...@@ -26,3 +26,55 @@ select x,xx from t1; ...@@ -26,3 +26,55 @@ select x,xx from t1;
x xx x xx
1 2 1 2
drop table t1; 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
...@@ -37,3 +37,43 @@ select x,xx from t1; ...@@ -37,3 +37,43 @@ select x,xx from t1;
drop table t1; drop table t1;
# End of 4.1 tests # End of 4.1 tests
#
# Bug #19371 VARBINARY() have trailing zeros after upgrade from 4.1
#
# Test with a saved table from 4.1
copy_file std_data/bug19371.frm $MYSQLTEST_VARDIR/master-data/test/t1.frm;
copy_file std_data/bug19371.MYD $MYSQLTEST_VARDIR/master-data/test/t1.MYD;
copy_file std_data/bug19371.MYI $MYSQLTEST_VARDIR/master-data/test/t1.MYI;
# Everything _looks_ fine
show create table t1;
# But the length of the varbinary columns are too long
select length(a), length(b) from t1;
# Run CHECK TABLE, it should indicate table need a REPAIR TABLE
CHECK TABLE t1 FOR UPGRADE;
# Run REPAIR TABLE to alter the table and repair
# the varbinary fields
REPAIR TABLE t1;
# Now check it's back to normal
show create table t1;
select length(a), length(b) from t1;
insert into t1 values("ccc", "ddd");
select length(a), length(b) from t1;
select hex(a), hex(b) from t1;
select concat("'", a, "'"), concat("'", b, "'") from t1;
drop table t1;
# Check that the fix does not affect table created with current version
create table t1(a varbinary(255));
insert into t1 values("aaa ");
select length(a) from t1;
alter table t1 modify a varchar(255);
select length(a) from t1;
...@@ -309,6 +309,21 @@ static void do_field_string(Copy_field *copy) ...@@ -309,6 +309,21 @@ static void do_field_string(Copy_field *copy)
} }
static void do_field_varbinary_pre50(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
copy->from_field->val_str(&copy->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) static void do_field_int(Copy_field *copy)
{ {
longlong value= copy->from_field->val_int(); longlong value= copy->from_field->val_int();
...@@ -570,6 +585,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) ...@@ -570,6 +585,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
// Check if identical fields // Check if identical fields
if (from->result_type() == STRING_RESULT) 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 are copying date or datetime's we have to check the dates
if we don't allow 'all' dates. if we don't allow 'all' dates.
......
...@@ -1972,6 +1972,10 @@ int handler::check_old_types() ...@@ -1972,6 +1972,10 @@ int handler::check_old_types()
{ {
return HA_ADMIN_NEEDS_ALTER; return HA_ADMIN_NEEDS_ALTER;
} }
if ((*field)->type() == MYSQL_TYPE_VAR_STRING)
{
return HA_ADMIN_NEEDS_ALTER;
}
} }
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment