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''
This commit is contained in:
parent
c2699e1a62
commit
f90f1e306f
@ -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
|
||||||
|
BIN
mysql-test/std_data/bug19371.MYD
Normal file
BIN
mysql-test/std_data/bug19371.MYD
Normal file
Binary file not shown.
BIN
mysql-test/std_data/bug19371.MYI
Normal file
BIN
mysql-test/std_data/bug19371.MYI
Normal file
Binary file not shown.
BIN
mysql-test/std_data/bug19371.frm
Normal file
BIN
mysql-test/std_data/bug19371.frm
Normal file
Binary file not shown.
@ -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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(©->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*)
|
|||||||
// 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()
|
|||||||
{
|
{
|
||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user