Loading myisam/mi_key.c +8 −5 Original line number Diff line number Diff line Loading @@ -25,9 +25,12 @@ #define CHECK_KEYS #define FIX_LENGTH if (length > char_length) \ #define FIX_LENGTH \ do { \ if (length > char_length) \ char_length= my_charpos(cs, pos, pos+length, char_length); \ set_if_smaller(char_length,length); \ } while(0) static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record); Loading Loading @@ -157,7 +160,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, FIX_LENGTH; memcpy((byte*) key, pos, char_length); if (length > char_length) bfill(key+char_length, length-char_length, ' '); cs->cset->fill(cs, key+char_length, length-char_length, ' '); key+= length; } _mi_dpointer(info,key,filepos); Loading Loading @@ -267,7 +270,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, FIX_LENGTH; memcpy((byte*) key, pos, char_length); if (length > char_length) bfill(key+char_length, length-char_length, ' '); cs->cset->fill(cs,key+char_length, length-char_length, ' '); key+= length; k_length-=length; } Loading mysql-test/r/ctype_utf8.result +70 −0 Original line number Diff line number Diff line Loading @@ -412,6 +412,36 @@ select c as c_a from t1 where c='б'; c_a б drop table t1; create table t1 ( c char(10) character set utf8, unique key a (c(1)) ) engine=bdb; insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 insert into t1 values ('aaa'); ERROR 23000: Duplicate entry 'aaa' for key 1 insert into t1 values ('б'); insert into t1 values ('бб'); ERROR 23000: Duplicate entry 'б' for key 1 insert into t1 values ('ббб'); ERROR 23000: Duplicate entry 'б' for key 1 select c as c_all from t1 order by c; c_all a b c d e f б select c as c_a from t1 where c='a'; c_a a select c as c_a from t1 where c='б'; c_a б drop table t1; create table t1 (c varchar(30) character set utf8 collate utf8_bin, unique(c(10))); insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z'); insert into t1 values ('aaaaaaaaaa'); Loading Loading @@ -541,6 +571,36 @@ c_a б drop table t1; create table t1 ( c char(10) character set utf8 collate utf8_bin, unique key a (c(1)) ) engine=bdb; insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 insert into t1 values ('aaa'); ERROR 23000: Duplicate entry 'aaa' for key 1 insert into t1 values ('б'); insert into t1 values ('бб'); ERROR 23000: Duplicate entry 'б' for key 1 insert into t1 values ('ббб'); ERROR 23000: Duplicate entry 'б' for key 1 select c as c_all from t1 order by c; c_all a b c d e f б select c as c_a from t1 where c='a'; c_a a select c as c_a from t1 where c='б'; c_a б drop table t1; create table t1 ( str varchar(255) character set utf8 not null, key str (str(2)) ) engine=myisam; Loading Loading @@ -570,3 +630,13 @@ select * from t1 where str='str'; str str drop table t1; create table t1 ( str varchar(255) character set utf8 not null, key str (str(2)) ) engine=bdb; INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; str str drop table t1; mysql-test/t/ctype_utf8.test +64 −0 Original line number Diff line number Diff line Loading @@ -294,6 +294,30 @@ select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # # Bug 4531: unique key prefix interacts poorly with utf8 # Check BDB, case insensitive collation # --disable_warnings create table t1 ( c char(10) character set utf8, unique key a (c(1)) ) engine=bdb; --enable_warnings insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); --error 1062 insert into t1 values ('aa'); --error 1062 insert into t1 values ('aaa'); insert into t1 values ('б'); --error 1062 insert into t1 values ('бб'); --error 1062 insert into t1 values ('ббб'); select c as c_all from t1 order by c; select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # # Bug 4521: unique key prefix interacts poorly with utf8 Loading Loading @@ -393,6 +417,31 @@ select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # # Bug 4531: unique key prefix interacts poorly with utf8 # Check BDB, binary collation # --disable_warnings create table t1 ( c char(10) character set utf8 collate utf8_bin, unique key a (c(1)) ) engine=bdb; --enable_warnings insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); --error 1062 insert into t1 values ('aa'); --error 1062 insert into t1 values ('aaa'); insert into t1 values ('б'); --error 1062 insert into t1 values ('бб'); --error 1062 insert into t1 values ('ббб'); select c as c_all from t1 order by c; select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # Bug#4594: column index make = failed for gbk, but like works # Check MYISAM Loading Loading @@ -429,3 +478,18 @@ INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; drop table t1; # the same for BDB # --disable_warnings create table t1 ( str varchar(255) character set utf8 not null, key str (str(2)) ) engine=bdb; --enable_warnings INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; drop table t1; sql/field.cc +45 −8 Original line number Diff line number Diff line Loading @@ -4401,6 +4401,24 @@ char *Field_string::pack(char *to, const char *from, uint max_length) } char *Field_string::pack_key(char *to, const char *from, uint max_length) { const char *end=from+min(field_length,max_length); int length; while (end > from && end[-1] == ' ') end--; length= end-from; uint char_length= (field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length; if (length > char_length) char_length= my_charpos(field_charset, from, end, char_length); set_if_smaller(length, char_length); *to= (uchar)length; memcpy(to+1, from, length); return to+1+length; } const char *Field_string::unpack(char *to, const char *from) { uint length= (uint) (uchar) *from++; Loading Loading @@ -4564,6 +4582,24 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length) } char *Field_varstring::pack_key(char *to, const char *from, uint max_length) { uint length=uint2korr(from); uint char_length= (field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length; from+=HA_KEY_BLOB_LENGTH; if (length > char_length) char_length= my_charpos(field_charset, from, from+length, char_length); set_if_smaller(length, char_length); *to++= (char) (length & 255); if (max_length > 255) *to++= (char) (length >> 8); if (length) memcpy(to, from, length); return to+length; } const char *Field_varstring::unpack(char *to, const char *from) { uint length; Loading Loading @@ -5139,16 +5175,17 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) char *save=ptr; ptr=(char*) from; uint32 length=get_length(); // Length of from string if (length > max_length) length=max_length; uint char_length= (field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length; if (length) get_ptr((char**) &from); if (length > char_length) char_length= my_charpos(field_charset, from, from+length, char_length); set_if_smaller(length, char_length); *to++= (uchar) length; if (max_length > 255) // 2 byte length *to++= (uchar) (length >> 8); if (length) { get_ptr((char**) &from); memcpy(to, from, length); } ptr=save; // Restore org row pointer return to+length; } Loading sql/field.h +2 −0 Original line number Diff line number Diff line Loading @@ -917,6 +917,7 @@ class Field_string :public Field_str { void sort_string(char *buff,uint length); void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); const char *unpack(char* to, const char *from); int pack_cmp(const char *a,const char *b,uint key_length); int pack_cmp(const char *b,uint key_length); Loading Loading @@ -965,6 +966,7 @@ class Field_varstring :public Field_str { void set_key_image(char *buff,uint length, CHARSET_INFO *cs); void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); const char *unpack(char* to, const char *from); int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *b, uint key_length); Loading Loading
myisam/mi_key.c +8 −5 Original line number Diff line number Diff line Loading @@ -25,9 +25,12 @@ #define CHECK_KEYS #define FIX_LENGTH if (length > char_length) \ #define FIX_LENGTH \ do { \ if (length > char_length) \ char_length= my_charpos(cs, pos, pos+length, char_length); \ set_if_smaller(char_length,length); \ } while(0) static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record); Loading Loading @@ -157,7 +160,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, FIX_LENGTH; memcpy((byte*) key, pos, char_length); if (length > char_length) bfill(key+char_length, length-char_length, ' '); cs->cset->fill(cs, key+char_length, length-char_length, ' '); key+= length; } _mi_dpointer(info,key,filepos); Loading Loading @@ -267,7 +270,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, FIX_LENGTH; memcpy((byte*) key, pos, char_length); if (length > char_length) bfill(key+char_length, length-char_length, ' '); cs->cset->fill(cs,key+char_length, length-char_length, ' '); key+= length; k_length-=length; } Loading
mysql-test/r/ctype_utf8.result +70 −0 Original line number Diff line number Diff line Loading @@ -412,6 +412,36 @@ select c as c_a from t1 where c='б'; c_a б drop table t1; create table t1 ( c char(10) character set utf8, unique key a (c(1)) ) engine=bdb; insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 insert into t1 values ('aaa'); ERROR 23000: Duplicate entry 'aaa' for key 1 insert into t1 values ('б'); insert into t1 values ('бб'); ERROR 23000: Duplicate entry 'б' for key 1 insert into t1 values ('ббб'); ERROR 23000: Duplicate entry 'б' for key 1 select c as c_all from t1 order by c; c_all a b c d e f б select c as c_a from t1 where c='a'; c_a a select c as c_a from t1 where c='б'; c_a б drop table t1; create table t1 (c varchar(30) character set utf8 collate utf8_bin, unique(c(10))); insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z'); insert into t1 values ('aaaaaaaaaa'); Loading Loading @@ -541,6 +571,36 @@ c_a б drop table t1; create table t1 ( c char(10) character set utf8 collate utf8_bin, unique key a (c(1)) ) engine=bdb; insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 insert into t1 values ('aaa'); ERROR 23000: Duplicate entry 'aaa' for key 1 insert into t1 values ('б'); insert into t1 values ('бб'); ERROR 23000: Duplicate entry 'б' for key 1 insert into t1 values ('ббб'); ERROR 23000: Duplicate entry 'б' for key 1 select c as c_all from t1 order by c; c_all a b c d e f б select c as c_a from t1 where c='a'; c_a a select c as c_a from t1 where c='б'; c_a б drop table t1; create table t1 ( str varchar(255) character set utf8 not null, key str (str(2)) ) engine=myisam; Loading Loading @@ -570,3 +630,13 @@ select * from t1 where str='str'; str str drop table t1; create table t1 ( str varchar(255) character set utf8 not null, key str (str(2)) ) engine=bdb; INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; str str drop table t1;
mysql-test/t/ctype_utf8.test +64 −0 Original line number Diff line number Diff line Loading @@ -294,6 +294,30 @@ select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # # Bug 4531: unique key prefix interacts poorly with utf8 # Check BDB, case insensitive collation # --disable_warnings create table t1 ( c char(10) character set utf8, unique key a (c(1)) ) engine=bdb; --enable_warnings insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); --error 1062 insert into t1 values ('aa'); --error 1062 insert into t1 values ('aaa'); insert into t1 values ('б'); --error 1062 insert into t1 values ('бб'); --error 1062 insert into t1 values ('ббб'); select c as c_all from t1 order by c; select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # # Bug 4521: unique key prefix interacts poorly with utf8 Loading Loading @@ -393,6 +417,31 @@ select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # # Bug 4531: unique key prefix interacts poorly with utf8 # Check BDB, binary collation # --disable_warnings create table t1 ( c char(10) character set utf8 collate utf8_bin, unique key a (c(1)) ) engine=bdb; --enable_warnings insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); --error 1062 insert into t1 values ('aa'); --error 1062 insert into t1 values ('aaa'); insert into t1 values ('б'); --error 1062 insert into t1 values ('бб'); --error 1062 insert into t1 values ('ббб'); select c as c_all from t1 order by c; select c as c_a from t1 where c='a'; select c as c_a from t1 where c='б'; drop table t1; # Bug#4594: column index make = failed for gbk, but like works # Check MYISAM Loading Loading @@ -429,3 +478,18 @@ INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; drop table t1; # the same for BDB # --disable_warnings create table t1 ( str varchar(255) character set utf8 not null, key str (str(2)) ) engine=bdb; --enable_warnings INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; drop table t1;
sql/field.cc +45 −8 Original line number Diff line number Diff line Loading @@ -4401,6 +4401,24 @@ char *Field_string::pack(char *to, const char *from, uint max_length) } char *Field_string::pack_key(char *to, const char *from, uint max_length) { const char *end=from+min(field_length,max_length); int length; while (end > from && end[-1] == ' ') end--; length= end-from; uint char_length= (field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length; if (length > char_length) char_length= my_charpos(field_charset, from, end, char_length); set_if_smaller(length, char_length); *to= (uchar)length; memcpy(to+1, from, length); return to+1+length; } const char *Field_string::unpack(char *to, const char *from) { uint length= (uint) (uchar) *from++; Loading Loading @@ -4564,6 +4582,24 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length) } char *Field_varstring::pack_key(char *to, const char *from, uint max_length) { uint length=uint2korr(from); uint char_length= (field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length; from+=HA_KEY_BLOB_LENGTH; if (length > char_length) char_length= my_charpos(field_charset, from, from+length, char_length); set_if_smaller(length, char_length); *to++= (char) (length & 255); if (max_length > 255) *to++= (char) (length >> 8); if (length) memcpy(to, from, length); return to+length; } const char *Field_varstring::unpack(char *to, const char *from) { uint length; Loading Loading @@ -5139,16 +5175,17 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) char *save=ptr; ptr=(char*) from; uint32 length=get_length(); // Length of from string if (length > max_length) length=max_length; uint char_length= (field_charset->mbmaxlen > 1) ? max_length/field_charset->mbmaxlen : max_length; if (length) get_ptr((char**) &from); if (length > char_length) char_length= my_charpos(field_charset, from, from+length, char_length); set_if_smaller(length, char_length); *to++= (uchar) length; if (max_length > 255) // 2 byte length *to++= (uchar) (length >> 8); if (length) { get_ptr((char**) &from); memcpy(to, from, length); } ptr=save; // Restore org row pointer return to+length; } Loading
sql/field.h +2 −0 Original line number Diff line number Diff line Loading @@ -917,6 +917,7 @@ class Field_string :public Field_str { void sort_string(char *buff,uint length); void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); const char *unpack(char* to, const char *from); int pack_cmp(const char *a,const char *b,uint key_length); int pack_cmp(const char *b,uint key_length); Loading Loading @@ -965,6 +966,7 @@ class Field_varstring :public Field_str { void set_key_image(char *buff,uint length, CHARSET_INFO *cs); void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); const char *unpack(char* to, const char *from); int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *b, uint key_length); Loading