From 94da1cb4a67ecb2e2590748381eebac072308ce6 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 23 Jan 2018 15:47:54 +0530 Subject: 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. --- sql/key.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sql/key.cc') 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 */ -- cgit v1.2.1