summaryrefslogtreecommitdiff
path: root/sql/key.cc
diff options
context:
space:
mode:
authorSachin Setiya <sachin.setiya@maridb.com>2018-01-23 15:47:54 +0530
committerSachin Setiya <sachinsetia1001@gmail.com>2018-01-23 17:29:58 +0530
commit94da1cb4a67ecb2e2590748381eebac072308ce6 (patch)
treeecb92ec96ec798baad554c5dced8e250db88fb80 /sql/key.cc
parentcc3155415ec1c1c7143fbab51b30e52575bbc36f (diff)
downloadmariadb-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.cc6
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 */