diff options
author | unknown <bar@mysql.com> | 2004-08-16 19:58:50 +0500 |
---|---|---|
committer | unknown <bar@mysql.com> | 2004-08-16 19:58:50 +0500 |
commit | 952f456e83aa5e9f1b05846275f2f2f7e3f4d280 (patch) | |
tree | 96cc85487a04e03225d2a6e94f898124f7caf1b2 | |
parent | a5f1fea0396a491241474d4183224e080ae7fffd (diff) | |
download | mariadb-git-952f456e83aa5e9f1b05846275f2f2f7e3f4d280.tar.gz |
ctype_utf8.test:
Bug#4521: unique prefix keys, fix for HEAP HASH and HEAP BTREE case insensitive collations.
mysql-test/t/ctype_utf8.test:
Bug#4521: unique prefix keys, fix for HEAP HASH and HEAP BTREE case insensitive collations.
-rw-r--r-- | heap/hp_hash.c | 101 | ||||
-rw-r--r-- | mysql-test/r/ctype_utf8.result | 72 | ||||
-rw-r--r-- | mysql-test/t/ctype_utf8.test | 47 |
3 files changed, 210 insertions, 10 deletions
diff --git a/heap/hp_hash.c b/heap/hp_hash.c index 2014b2b0adc..8feae19a480 100644 --- a/heap/hp_hash.c +++ b/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) { - 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 { @@ -280,7 +288,14 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec) } 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 { @@ -401,9 +416,26 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2) } 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, - (uchar*) rec1+seg->start,seg->length, - (uchar*) rec2+seg->start,seg->length)) + pos1,char_length1, + pos2,char_length2)) return 1; } else @@ -435,9 +467,27 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key) } 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, - (uchar*) rec+seg->start, seg->length, - (uchar*) key, seg->length)) + (uchar*) pos, char_length_rec, + (uchar*) key, char_length_key)) return 1; } 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++) { + 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) *key++= test(rec[seg->null_pos] & seg->null_bit); - memcpy(key,rec+seg->start,(size_t) seg->length); - key+=seg->length; + if (seg->length > char_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++) { + uint char_length; if (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; } - 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; } 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; seg < endseg && (int) k_len > 0; old+= seg->length, seg++) { + uint char_length; if (seg->null_bit) { k_len--; @@ -551,7 +623,16 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len) } 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; k_len-= seg->length; } diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 17059e6e2a9..793e2ceff19 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -325,3 +325,75 @@ insert into t1 values ('ꪪꪪ'); insert into t1 values ('ꪪꪪꪪ'); ERROR 23000: Duplicate entry 'ꪪꪪ' for key 1 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; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 9a383e66603..808e04c56d8 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -236,3 +236,50 @@ insert into t1 values ('ꪪꪪ'); insert into t1 values ('ꪪꪪꪪ'); 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; |