Skip to content

Commit

Permalink
MDEV-29954 Unique hash key on column prefix is computed incorrectly
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vuvova committed Jan 23, 2024
1 parent 14d00fd commit a7ee3bc
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 4 deletions.
9 changes: 9 additions & 0 deletions mysql-test/main/long_unique_bugs.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
8 changes: 8 additions & 0 deletions mysql-test/main/long_unique_bugs.test
Original file line number Diff line number Diff line change
Expand Up @@ -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 #
13 changes: 13 additions & 0 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions sql/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
2 changes: 1 addition & 1 deletion sql/key.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 2 additions & 3 deletions sql/table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit a7ee3bc

Please sign in to comment.