Commit a7ee3bc5 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-29954 Unique hash key on column prefix is computed incorrectly

use the original, not the truncated, field in the long unique prefix,
that is, in the hash(left(field, length)) expression.

because MyISAM CHECK/REPAIR in compute_vcols() moves table->field
but not prefix fields from keyparts.

Also, implement Field_string::cmp_prefix() for prefix comparison
of CHAR columns to work.
parent 14d00fdb
......@@ -651,5 +651,14 @@ f1 f2 f3 f4 f5 f6 f7
4 00004 0001009089999 netstes psit e
drop table t1;
#
# MDEV-29954 Unique hash key on column prefix is computed incorrectly
#
create table t1 (c char(10),unique key a using hash (c(1)));
insert into t1 values (0);
check table t1 extended;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
#
# End of 10.5 tests
#
......@@ -634,6 +634,14 @@ replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netst
select * from t1;
drop table t1;
--echo #
--echo # MDEV-29954 Unique hash key on column prefix is computed incorrectly
--echo #
create table t1 (c char(10),unique key a using hash (c(1)));
insert into t1 values (0);
check table t1 extended;
drop table t1;
--echo #
--echo # End of 10.5 tests
--echo #
......@@ -7566,6 +7566,19 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) const
}
int Field_string::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr,
size_t prefix_char_len) const
{
size_t field_len= table->field[field_index]->field_length;
return field_charset()->coll->strnncollsp_nchars(field_charset(),
a_ptr, field_len,
b_ptr, field_len,
prefix_char_len,
0);
}
void Field_string::sort_string(uchar *to,uint length)
{
#ifdef DBUG_ASSERT_EXISTS
......
......@@ -4038,6 +4038,8 @@ class Field_string final :public Field_longstr {
String *val_str(String *, String *) override;
my_decimal *val_decimal(my_decimal *) override;
int cmp(const uchar *,const uchar *) const override;
int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const
override;
void sort_string(uchar *buff,uint length) override;
void update_data_type_statistics(Data_type_statistics *st) const override
{
......
......@@ -605,7 +605,7 @@ int key_rec_cmp(void *key_p, uchar *first_rec, uchar *second_rec)
}
/*
No null values in the fields
We use the virtual method cmp_max with a max length parameter.
We use the virtual method cmp_prefix with a max length parameter.
For most field types this translates into a cmp without
max length. The exceptions are the BLOB and VARCHAR field types
that take the max length into account.
......
......@@ -1272,12 +1272,11 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
if (keypart->key_part_flag & HA_PART_KEY_SEG)
{
int length= keypart->length/keypart->field->charset()->mbmaxlen;
Field *kpf= table->field[keypart->field->field_index];
list_item= new (mem_root) Item_func_left(thd,
new (mem_root) Item_field(thd, keypart->field),
new (mem_root) Item_field(thd, kpf),
new (mem_root) Item_int(thd, length));
list_item->fix_fields(thd, NULL);
keypart->field->vcol_info=
table->field[keypart->field->field_index]->vcol_info;
}
else
list_item= new (mem_root) Item_field(thd, keypart->field);
......
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