Commit 50ee43be authored by serg@serg.mylan's avatar serg@serg.mylan

BDB: Bug#4531: unique key prefix interacts poorly with utf8,

Bug#4594 column index make = failed for gbk
parent f68219f6
...@@ -25,9 +25,12 @@ ...@@ -25,9 +25,12 @@
#define CHECK_KEYS #define CHECK_KEYS
#define FIX_LENGTH if (length > char_length) \ #define FIX_LENGTH \
char_length= my_charpos(cs, pos, pos+length, char_length); \ do { \
set_if_smaller(char_length,length); \ 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); static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
...@@ -157,7 +160,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -157,7 +160,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
FIX_LENGTH; FIX_LENGTH;
memcpy((byte*) key, pos, char_length); memcpy((byte*) key, pos, char_length);
if (length > 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; key+= length;
} }
_mi_dpointer(info,key,filepos); _mi_dpointer(info,key,filepos);
...@@ -267,7 +270,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, ...@@ -267,7 +270,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
FIX_LENGTH; FIX_LENGTH;
memcpy((byte*) key, pos, char_length); memcpy((byte*) key, pos, char_length);
if (length > 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; key+= length;
k_length-=length; k_length-=length;
} }
......
...@@ -412,6 +412,36 @@ select c as c_a from t1 where c='б'; ...@@ -412,6 +412,36 @@ select c as c_a from t1 where c='б';
c_a c_a
б б
drop table t1; 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))); 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 ('1'),('2'),('3'),('x'),('y'),('z');
insert into t1 values ('aaaaaaaaaa'); insert into t1 values ('aaaaaaaaaa');
...@@ -541,6 +571,36 @@ c_a ...@@ -541,6 +571,36 @@ c_a
б б
drop table t1; drop table t1;
create 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, str varchar(255) character set utf8 not null,
key str (str(2)) key str (str(2))
) engine=myisam; ) engine=myisam;
...@@ -570,3 +630,13 @@ select * from t1 where str='str'; ...@@ -570,3 +630,13 @@ select * from t1 where str='str';
str str
str str
drop table t1; 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;
...@@ -294,6 +294,30 @@ select c as c_a from t1 where c='a'; ...@@ -294,6 +294,30 @@ select c as c_a from t1 where c='a';
select c as c_a from t1 where c='б'; select c as c_a from t1 where c='б';
drop table t1; 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 # Bug 4521: unique key prefix interacts poorly with utf8
...@@ -393,6 +417,31 @@ select c as c_a from t1 where c='a'; ...@@ -393,6 +417,31 @@ select c as c_a from t1 where c='a';
select c as c_a from t1 where c='б'; select c as c_a from t1 where c='б';
drop table t1; 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 # Bug#4594: column index make = failed for gbk, but like works
# Check MYISAM # Check MYISAM
...@@ -429,3 +478,18 @@ INSERT INTO t1 VALUES ('str'); ...@@ -429,3 +478,18 @@ INSERT INTO t1 VALUES ('str');
INSERT INTO t1 VALUES ('str2'); INSERT INTO t1 VALUES ('str2');
select * from t1 where str='str'; select * from t1 where str='str';
drop table t1; 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;
...@@ -4382,7 +4382,7 @@ void Field_string::sql_type(String &res) const ...@@ -4382,7 +4382,7 @@ void Field_string::sql_type(String &res) const
(field_length > 3 && (field_length > 3 &&
(table->db_options_in_use & (table->db_options_in_use &
HA_OPTION_PACK_RECORD) ? HA_OPTION_PACK_RECORD) ?
(has_charset() ? "varchar" : "varbinary") : (has_charset() ? "varchar" : "varbinary") :
(has_charset() ? "char" : "binary")), (has_charset() ? "char" : "binary")),
(int) field_length / charset()->mbmaxlen); (int) field_length / charset()->mbmaxlen);
res.length(length); res.length(length);
...@@ -4401,6 +4401,24 @@ char *Field_string::pack(char *to, const char *from, uint max_length) ...@@ -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) const char *Field_string::unpack(char *to, const char *from)
{ {
uint length= (uint) (uchar) *from++; uint length= (uint) (uchar) *from++;
...@@ -4564,6 +4582,24 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length) ...@@ -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) const char *Field_varstring::unpack(char *to, const char *from)
{ {
uint length; uint length;
...@@ -5139,16 +5175,17 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) ...@@ -5139,16 +5175,17 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
char *save=ptr; char *save=ptr;
ptr=(char*) from; ptr=(char*) from;
uint32 length=get_length(); // Length of from string uint32 length=get_length(); // Length of from string
if (length > max_length) uint char_length= (field_charset->mbmaxlen > 1) ?
length=max_length; 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; *to++= (uchar) length;
if (max_length > 255) // 2 byte length if (max_length > 255) // 2 byte length
*to++= (uchar) (length >> 8); *to++= (uchar) (length >> 8);
if (length) memcpy(to, from, length);
{
get_ptr((char**) &from);
memcpy(to, from, length);
}
ptr=save; // Restore org row pointer ptr=save; // Restore org row pointer
return to+length; return to+length;
} }
......
...@@ -917,6 +917,7 @@ class Field_string :public Field_str { ...@@ -917,6 +917,7 @@ class Field_string :public Field_str {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
void sql_type(String &str) const; void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0); 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); 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 *a,const char *b,uint key_length);
int pack_cmp(const char *b,uint key_length); int pack_cmp(const char *b,uint key_length);
...@@ -965,6 +966,7 @@ class Field_varstring :public Field_str { ...@@ -965,6 +966,7 @@ class Field_varstring :public Field_str {
void set_key_image(char *buff,uint length, CHARSET_INFO *cs); void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
void sql_type(String &str) const; void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0); 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); 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 *a, const char *b, uint key_length);
int pack_cmp(const char *b, uint key_length); int pack_cmp(const char *b, uint key_length);
......
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