Commit 57ec14d9 authored by bar@mysql.com's avatar bar@mysql.com

Bug#7302: UCS2 data in ENUM field get truncated when new column is added

parent ecd85b18
...@@ -581,3 +581,14 @@ x,y 0078002C0079 ...@@ -581,3 +581,14 @@ x,y 0078002C0079
z 007A z 007A
x,y,z,,, 0078002C0079002C007A002C00E4002C00F6002C00FC x,y,z,,, 0078002C0079002C007A002C00E4002C00F6002C00FC
drop table t1; drop table t1;
create table t1(a enum('a','b','c')) default character set ucs2;
insert into t1 values('a'),('b'),('c');
alter table t1 add b char(1);
show warnings;
Level Code Message
select * from t1 order by a;
a b
a NULL
b NULL
c NULL
drop table t1;
...@@ -374,3 +374,13 @@ insert into t1 values ('x,y'); ...@@ -374,3 +374,13 @@ insert into t1 values ('x,y');
insert into t1 values ('x,y,z,,,'); insert into t1 values ('x,y,z,,,');
select a, hex(a) from t1 order by a; select a, hex(a) from t1 order by a;
drop table t1; drop table t1;
#
# Bug#7302 UCS2 data in ENUM fields get truncated when new column is added
#
create table t1(a enum('a','b','c')) default character set ucs2;
insert into t1 values('a'),('b'),('c');
alter table t1 add b char(1);
show warnings;
select * from t1 order by a;
drop table t1;
...@@ -815,6 +815,7 @@ ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs, ...@@ -815,6 +815,7 @@ ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs,
char **err_pos, uint *err_len, bool *set_warning); char **err_pos, uint *err_len, bool *set_warning);
uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match); uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match);
uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs); uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs);
void unhex_type2(TYPELIB *lib);
uint check_word(TYPELIB *lib, const char *val, const char *end, uint check_word(TYPELIB *lib, const char *val, const char *end,
const char **end_of_word); const char **end_of_word);
......
...@@ -169,6 +169,43 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs) ...@@ -169,6 +169,43 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
} /* find_type */ } /* find_type */
/*
Un-hex all elements in a typelib
SYNOPSIS
unhex_type2()
interval TYPELIB (struct of pointer to values + lengths + count)
NOTES
RETURN
N/A
*/
void unhex_type2(TYPELIB *interval)
{
for (uint pos= 0; pos < interval->count; pos++)
{
char *from, *to;
for (from= to= (char*) interval->type_names[pos]; *from; )
{
/*
Note, hexchar_to_int(*from++) doesn't work
one some compilers, e.g. IRIX. Looks like a compiler
bug in inline functions in combination with arguments
that have a side effect. So, let's use from[0] and from[1]
and increment 'from' by two later.
*/
*to++= (char) (hexchar_to_int(from[0]) << 4) +
hexchar_to_int(from[1]);
from+= 2;
}
interval->type_lengths[pos] /= 2;
}
}
/* /*
Check if the first word in a string is one of the ones in TYPELIB Check if the first word in a string is one of the ones in TYPELIB
......
...@@ -490,25 +490,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -490,25 +490,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{ {
/* Unescape UCS2 intervals from HEX notation */ /* Unescape UCS2 intervals from HEX notation */
TYPELIB *interval= outparam->intervals + interval_nr - 1; TYPELIB *interval= outparam->intervals + interval_nr - 1;
for (uint pos= 0; pos < interval->count; pos++) unhex_type2(interval);
{
char *from, *to;
for (from= to= (char*) interval->type_names[pos]; *from; )
{
/*
Note, hexchar_to_int(*from++) doesn't work
one some compilers, e.g. IRIX. Looks like a compiler
bug in inline functions in combination with arguments
that have a side effect. So, let's use from[0] and from[1]
and increment 'from' by two later.
*/
*to++= (char) (hexchar_to_int(from[0]) << 4) +
hexchar_to_int(from[1]);
from+= 2;
}
interval->type_lengths[pos] /= 2;
}
} }
*field_ptr=reg_field= *field_ptr=reg_field=
......
...@@ -174,6 +174,17 @@ bool mysql_create_frm(THD *thd, my_string file_name, ...@@ -174,6 +174,17 @@ bool mysql_create_frm(THD *thd, my_string file_name,
goto err2; goto err2;
if (my_close(file,MYF(MY_WME))) if (my_close(file,MYF(MY_WME)))
goto err3; goto err3;
{
/* Unescape all UCS2 intervals: were escaped in pack_headers */
List_iterator<create_field> it(create_fields);
create_field *field;
while ((field=it++))
{
if (field->interval && field->charset->mbminlen > 1)
unhex_type2(field->interval);
}
}
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
......
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