summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2004-08-16 19:58:50 +0500
committerunknown <bar@mysql.com>2004-08-16 19:58:50 +0500
commit952f456e83aa5e9f1b05846275f2f2f7e3f4d280 (patch)
tree96cc85487a04e03225d2a6e94f898124f7caf1b2
parenta5f1fea0396a491241474d4183224e080ae7fffd (diff)
downloadmariadb-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.c101
-rw-r--r--mysql-test/r/ctype_utf8.result72
-rw-r--r--mysql-test/t/ctype_utf8.test47
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;