mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
ctype_utf8.test:
Bug#4521: unique prefix keys, fix for HEAP HASH and HEAP BTREE case insensitive collations.
This commit is contained in:
101
heap/hp_hash.c
101
heap/hp_hash.c
@ -245,7 +245,15 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
|||||||
}
|
}
|
||||||
if (seg->type == HA_KEYTYPE_TEXT)
|
if (seg->type == HA_KEYTYPE_TEXT)
|
||||||
{
|
{
|
||||||
seg->charset->coll->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,&nr2);
|
CHARSET_INFO *cs= seg->charset;
|
||||||
|
uint length= ((uchar*)key) - pos;
|
||||||
|
uint char_length= length / cs->mbmaxlen;
|
||||||
|
if (length > char_length)
|
||||||
|
{
|
||||||
|
char_length= my_charpos(cs, pos, pos + length, char_length);
|
||||||
|
set_if_smaller(char_length, length);
|
||||||
|
}
|
||||||
|
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -280,7 +288,14 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
|||||||
}
|
}
|
||||||
if (seg->type == HA_KEYTYPE_TEXT)
|
if (seg->type == HA_KEYTYPE_TEXT)
|
||||||
{
|
{
|
||||||
seg->charset->coll->hash_sort(seg->charset,pos,end-pos,&nr,&nr2);
|
CHARSET_INFO *cs= seg->charset;
|
||||||
|
uint char_length= seg->length / cs->mbmaxlen;
|
||||||
|
if (seg->length > char_length)
|
||||||
|
{
|
||||||
|
char_length= my_charpos(cs, pos, pos + seg->length, char_length);
|
||||||
|
set_if_smaller(char_length, seg->length);
|
||||||
|
}
|
||||||
|
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -401,9 +416,26 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
|||||||
}
|
}
|
||||||
if (seg->type == HA_KEYTYPE_TEXT)
|
if (seg->type == HA_KEYTYPE_TEXT)
|
||||||
{
|
{
|
||||||
|
CHARSET_INFO *cs= seg->charset;
|
||||||
|
uint char_length= seg->length / cs->mbmaxlen;
|
||||||
|
uint char_length1;
|
||||||
|
uint char_length2;
|
||||||
|
uchar *pos1= (uchar*)rec1 + seg->start;
|
||||||
|
uchar *pos2= (uchar*)rec2 + seg->start;
|
||||||
|
if (seg->length > char_length)
|
||||||
|
{
|
||||||
|
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
|
||||||
|
set_if_smaller(char_length1, seg->length);
|
||||||
|
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
|
||||||
|
set_if_smaller(char_length2, seg->length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char_length1= char_length2= seg->length;
|
||||||
|
}
|
||||||
if (seg->charset->coll->strnncollsp(seg->charset,
|
if (seg->charset->coll->strnncollsp(seg->charset,
|
||||||
(uchar*) rec1+seg->start,seg->length,
|
pos1,char_length1,
|
||||||
(uchar*) rec2+seg->start,seg->length))
|
pos2,char_length2))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -435,9 +467,27 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
|||||||
}
|
}
|
||||||
if (seg->type == HA_KEYTYPE_TEXT)
|
if (seg->type == HA_KEYTYPE_TEXT)
|
||||||
{
|
{
|
||||||
|
CHARSET_INFO *cs= seg->charset;
|
||||||
|
uint char_length= seg->length / cs->mbmaxlen;
|
||||||
|
uint char_length_key;
|
||||||
|
uint char_length_rec;
|
||||||
|
uchar *pos= (uchar*) rec + seg->start;
|
||||||
|
if (seg->length > char_length)
|
||||||
|
{
|
||||||
|
char_length_key= my_charpos(cs, key, key + seg->length, char_length);
|
||||||
|
set_if_smaller(char_length_key, seg->length);
|
||||||
|
char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
|
||||||
|
set_if_smaller(char_length_rec, seg->length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char_length_key= seg->length;
|
||||||
|
char_length_rec= seg->length;
|
||||||
|
}
|
||||||
|
|
||||||
if (seg->charset->coll->strnncollsp(seg->charset,
|
if (seg->charset->coll->strnncollsp(seg->charset,
|
||||||
(uchar*) rec+seg->start, seg->length,
|
(uchar*) pos, char_length_rec,
|
||||||
(uchar*) key, seg->length))
|
(uchar*) key, char_length_key))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -458,10 +508,19 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
|||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
|
CHARSET_INFO *cs= seg->charset;
|
||||||
|
uint char_length= (cs && cs->mbmaxlen > 1) ? seg->length / cs->mbmaxlen :
|
||||||
|
seg->length;
|
||||||
|
uchar *pos= (uchar*) rec + seg->start;
|
||||||
if (seg->null_bit)
|
if (seg->null_bit)
|
||||||
*key++= test(rec[seg->null_pos] & seg->null_bit);
|
*key++= test(rec[seg->null_pos] & seg->null_bit);
|
||||||
memcpy(key,rec+seg->start,(size_t) seg->length);
|
if (seg->length > char_length)
|
||||||
key+=seg->length;
|
{
|
||||||
|
char_length= my_charpos(cs, pos, pos + seg->length, char_length);
|
||||||
|
set_if_smaller(char_length, seg->length);
|
||||||
|
}
|
||||||
|
memcpy(key,rec+seg->start,(size_t) char_length);
|
||||||
|
key+= char_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +532,7 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
|||||||
|
|
||||||
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
|
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
|
||||||
{
|
{
|
||||||
|
uint char_length;
|
||||||
if (seg->null_bit)
|
if (seg->null_bit)
|
||||||
{
|
{
|
||||||
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
|
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
|
||||||
@ -515,7 +575,18 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
memcpy(key, rec + seg->start, (size_t) seg->length);
|
char_length= seg->length / (seg->charset ? seg->charset->mbmaxlen : 1);
|
||||||
|
if (seg->length > char_length)
|
||||||
|
{
|
||||||
|
char_length= my_charpos(seg->charset,
|
||||||
|
rec + seg->start, rec + seg->start + seg->length,
|
||||||
|
char_length);
|
||||||
|
set_if_smaller(char_length, seg->length);
|
||||||
|
if (char_length < seg->length)
|
||||||
|
seg->charset->cset->fill(seg->charset, key + char_length,
|
||||||
|
seg->length - char_length, ' ');
|
||||||
|
}
|
||||||
|
memcpy(key, rec + seg->start, (size_t) char_length);
|
||||||
key+= seg->length;
|
key+= seg->length;
|
||||||
}
|
}
|
||||||
memcpy(key, &recpos, sizeof(byte*));
|
memcpy(key, &recpos, sizeof(byte*));
|
||||||
@ -530,6 +601,7 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
|
|||||||
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
|
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
|
||||||
seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
|
seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
|
||||||
{
|
{
|
||||||
|
uint char_length;
|
||||||
if (seg->null_bit)
|
if (seg->null_bit)
|
||||||
{
|
{
|
||||||
k_len--;
|
k_len--;
|
||||||
@ -551,7 +623,16 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
memcpy((byte*) key, old, seg->length);
|
char_length= seg->length / (seg->charset ? seg->charset->mbmaxlen : 1);
|
||||||
|
if (seg->length > char_length)
|
||||||
|
{
|
||||||
|
char_length= my_charpos(seg->charset, old, old+seg->length, char_length);
|
||||||
|
set_if_smaller(char_length, seg->length);
|
||||||
|
if (char_length < seg->length)
|
||||||
|
seg->charset->cset->fill(seg->charset, key + char_length,
|
||||||
|
seg->length - char_length, ' ');
|
||||||
|
}
|
||||||
|
memcpy(key, old, (size_t) char_length);
|
||||||
key+= seg->length;
|
key+= seg->length;
|
||||||
k_len-= seg->length;
|
k_len-= seg->length;
|
||||||
}
|
}
|
||||||
|
@ -325,3 +325,75 @@ insert into t1 values ('ꪪꪪ');
|
|||||||
insert into t1 values ('ꪪꪪꪪ');
|
insert into t1 values ('ꪪꪪꪪ');
|
||||||
ERROR 23000: Duplicate entry 'ꪪꪪ' for key 1
|
ERROR 23000: Duplicate entry 'ꪪꪪ' for key 1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (
|
||||||
|
c char(10) character set utf8,
|
||||||
|
unique key a using hash (c(1))
|
||||||
|
) engine=heap;
|
||||||
|
show create table t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`c` char(10) character set utf8 default NULL,
|
||||||
|
UNIQUE KEY `a` (`c`(1))
|
||||||
|
) ENGINE=HEAP DEFAULT CHARSET=latin1
|
||||||
|
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 char(10) character set utf8 collate utf8_bin,
|
||||||
|
unique key a using btree (c(1))
|
||||||
|
) engine=heap;
|
||||||
|
show create table t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`c` char(10) character set utf8 collate utf8_bin default NULL,
|
||||||
|
UNIQUE KEY `a` TYPE BTREE (`c`(1))
|
||||||
|
) ENGINE=HEAP DEFAULT CHARSET=latin1
|
||||||
|
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;
|
||||||
|
@ -236,3 +236,50 @@ insert into t1 values ('ꪪꪪ');
|
|||||||
insert into t1 values ('ꪪꪪꪪ');
|
insert into t1 values ('ꪪꪪꪪ');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug 4531: unique key prefix interacts poorly with utf8
|
||||||
|
# Check HEAP+HASH, case insensitive collation
|
||||||
|
#
|
||||||
|
create table t1 (
|
||||||
|
c char(10) character set utf8,
|
||||||
|
unique key a using hash (c(1))
|
||||||
|
) engine=heap;
|
||||||
|
show create table t1;
|
||||||
|
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 4531: unique key prefix interacts poorly with utf8
|
||||||
|
# Check HEAP+BTREE, case insensitive collation
|
||||||
|
#
|
||||||
|
create table t1 (
|
||||||
|
c char(10) character set utf8 collate utf8_bin,
|
||||||
|
unique key a using btree (c(1))
|
||||||
|
) engine=heap;
|
||||||
|
show create table t1;
|
||||||
|
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;
|
||||||
|
Reference in New Issue
Block a user