diff options
author | Sachin Setiya <sachin.setiya@maridb.com> | 2018-01-23 15:47:54 +0530 |
---|---|---|
committer | Sachin Setiya <sachinsetia1001@gmail.com> | 2018-01-23 17:29:58 +0530 |
commit | 94da1cb4a67ecb2e2590748381eebac072308ce6 (patch) | |
tree | ecb92ec96ec798baad554c5dced8e250db88fb80 /sql/key.cc | |
parent | cc3155415ec1c1c7143fbab51b30e52575bbc36f (diff) | |
download | mariadb-git-94da1cb4a67ecb2e2590748381eebac072308ce6.tar.gz |
MDEV-14586 Assertion `0' failed in retrieve_auto_increment ...
Problem:-
If we create table using myisam/aria then this crashes the server.
CREATE TABLE t1(a bit(1), b int auto_increment , index(a,b));
insert into t1 values(1,1);
Or this query
CREATE TABLE t1 (b BIT(1), pk INTEGER AUTO_INCREMENT PRIMARY KEY);
ALTER TABLE t1 ADD INDEX(b,pk);
INSERT INTO t1 VALUES (1,b'1');
ALTER TABLE t1 DROP PRIMARY KEY;
Reason:-
The reason for this is
1st- find_ref_key() finds what key an auto_increment field belongs to by
comparing key_part->offset and field->ptr. But BIT fields might have
zero length in the record, so a key might have many key parts with the
same offset. That is, comparing offsets cannot uniquely identify the
correct key part.
2nd- Since next_number_key_offset is zero it myisam/aria will think that
auto_increment is in first part of key.
3nd- myisam/aria will call retrieve_auto_key which will see first key_part
field as a bit field and call assert(0)
Solution:-
Many key parts might have the same offset, but BIT fields do not
support auto_increment. So, we can skip all key parts over BIT fields,
and then comparing offsets will be unambiguous.
Diffstat (limited to 'sql/key.cc')
-rw-r--r-- | sql/key.cc | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/sql/key.cc b/sql/key.cc index 110b13000ed..700bf6a05a6 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -62,7 +62,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, i < (int) key_count ; i++, key_info++) { - if (key_info->key_part[0].offset == fieldpos) + if (key_info->key_part[0].offset == fieldpos && + key_info->key_part[0].field->type() != MYSQL_TYPE_BIT) { /* Found key. Calc keylength */ *key_length= *keypart= 0; return i; /* Use this key */ @@ -81,7 +82,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, j < key_info->key_parts ; j++, key_part++) { - if (key_part->offset == fieldpos) + if (key_part->offset == fieldpos && + key_part->field->type() != MYSQL_TYPE_BIT) { *keypart= j; return i; /* Use this key */ |