Fix for bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0,

file .\ha_innodb.

Problem: if a partial unique key followed by a non-partial one we declare
the second one as a primary key.

Fix: sort non-partial unique keys before partial ones.
parent 3494f691
...@@ -224,7 +224,7 @@ enum ha_base_keytype { ...@@ -224,7 +224,7 @@ enum ha_base_keytype {
#define HA_SPATIAL 1024 /* For spatial search */ #define HA_SPATIAL 1024 /* For spatial search */
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */ #define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
#define HA_GENERATED_KEY 8192 /* Automaticly generated key */ #define HA_GENERATED_KEY 8192 /* Automaticly generated key */
#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */
/* Automatic bits in key-flag */ /* Automatic bits in key-flag */
#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */
......
...@@ -1211,4 +1211,19 @@ a b ...@@ -1211,4 +1211,19 @@ a b
3 2 3 2
1 1 1 1
DROP TABLE t1; DROP TABLE t1;
create table t1(a char(10) not null, unique key aa(a(1)),
b char(4) not null, unique key bb(b(4))) engine=innodb;
desc t1;
Field Type Null Key Default Extra
a char(10) NO UNI NULL
b char(4) NO PRI NULL
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) NOT NULL,
`b` char(4) NOT NULL,
UNIQUE KEY `bb` (`b`),
UNIQUE KEY `aa` (`a`(1))
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1;
End of 5.0 tests End of 5.0 tests
...@@ -462,4 +462,48 @@ EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a); ...@@ -462,4 +462,48 @@ EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1 1 SIMPLE t1 system NULL NULL NULL NULL 1
DROP TABLE t1; DROP TABLE t1;
create table t1(a int not null, key aa(a),
b char(10) not null, unique key bb(b(1)),
c char(4) not null, unique key cc(c));
desc t1;
Field Type Null Key Default Extra
a int(11) NO MUL NULL
b char(10) NO UNI NULL
c char(4) NO PRI NULL
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` char(10) NOT NULL,
`c` char(4) NOT NULL,
UNIQUE KEY `cc` (`c`),
UNIQUE KEY `bb` (`b`(1)),
KEY `aa` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1(a int not null, key aa(a),
b char(10) not null, unique key bb(b(1)),
c char(4) not null);
desc t1;
Field Type Null Key Default Extra
a int(11) NO MUL NULL
b char(10) NO UNI NULL
c char(4) NO NULL
alter table t1 add unique key cc(c);
desc t1;
Field Type Null Key Default Extra
a int(11) NO MUL NULL
b char(10) NO UNI NULL
c char(4) NO PRI NULL
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` char(10) NOT NULL,
`c` char(4) NOT NULL,
UNIQUE KEY `cc` (`c`),
UNIQUE KEY `bb` (`b`(1)),
KEY `aa` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
End of 5.0 tests. End of 5.0 tests.
...@@ -960,4 +960,13 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC; ...@@ -960,4 +960,13 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0
#
create table t1(a char(10) not null, unique key aa(a(1)),
b char(4) not null, unique key bb(b(4))) engine=innodb;
desc t1;
show create table t1;
drop table t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -443,4 +443,22 @@ ALTER TABLE t1 DISABLE KEYS; ...@@ -443,4 +443,22 @@ ALTER TABLE t1 DISABLE KEYS;
EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a); EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a);
DROP TABLE t1; DROP TABLE t1;
#
# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0
#
create table t1(a int not null, key aa(a),
b char(10) not null, unique key bb(b(1)),
c char(4) not null, unique key cc(c));
desc t1;
show create table t1;
drop table t1;
create table t1(a int not null, key aa(a),
b char(10) not null, unique key bb(b(1)),
c char(4) not null);
desc t1;
alter table t1 add unique key cc(c);
desc t1;
show create table t1;
drop table t1;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -361,7 +361,8 @@ int quick_rm_table(enum db_type base,const char *db, ...@@ -361,7 +361,8 @@ int quick_rm_table(enum db_type base,const char *db,
/* /*
Sort keys in the following order: Sort keys in the following order:
- PRIMARY KEY - PRIMARY KEY
- UNIQUE keyws where all column are NOT NULL - UNIQUE keys where all column are NOT NULL
- UNIQUE keys that don't contain partial segments
- Other UNIQUE keys - Other UNIQUE keys
- Normal keys - Normal keys
- Fulltext keys - Fulltext keys
...@@ -372,26 +373,31 @@ int quick_rm_table(enum db_type base,const char *db, ...@@ -372,26 +373,31 @@ int quick_rm_table(enum db_type base,const char *db,
static int sort_keys(KEY *a, KEY *b) static int sort_keys(KEY *a, KEY *b)
{ {
if (a->flags & HA_NOSAME) ulong a_flags= a->flags, b_flags= b->flags;
if (a_flags & HA_NOSAME)
{ {
if (!(b->flags & HA_NOSAME)) if (!(b_flags & HA_NOSAME))
return -1; return -1;
if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
{ {
/* Sort NOT NULL keys before other keys */ /* Sort NOT NULL keys before other keys */
return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
} }
if (a->name == primary_key_name) if (a->name == primary_key_name)
return -1; return -1;
if (b->name == primary_key_name) if (b->name == primary_key_name)
return 1; return 1;
/* Sort keys don't containing partial segments before others */
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
} }
else if (b->flags & HA_NOSAME) else if (b_flags & HA_NOSAME)
return 1; // Prefer b return 1; // Prefer b
if ((a->flags ^ b->flags) & HA_FULLTEXT) if ((a_flags ^ b_flags) & HA_FULLTEXT)
{ {
return (a->flags & HA_FULLTEXT) ? 1 : -1; return (a_flags & HA_FULLTEXT) ? 1 : -1;
} }
/* /*
Prefer original key order. usable_key_parts contains here Prefer original key order. usable_key_parts contains here
...@@ -1421,6 +1427,10 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1421,6 +1427,10 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
else else
key_info->flags|= HA_PACK_KEY; key_info->flags|= HA_PACK_KEY;
} }
/* Check if the key segment is partial, set the key flag accordingly */
if (length != sql_field->key_length)
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
key_length+=length; key_length+=length;
key_part_info++; key_part_info++;
......
...@@ -87,7 +87,7 @@ typedef struct st_key_part_info { /* Info about a key part */ ...@@ -87,7 +87,7 @@ typedef struct st_key_part_info { /* Info about a key part */
typedef struct st_key { typedef struct st_key {
uint key_length; /* Tot length of key */ uint key_length; /* Tot length of key */
uint flags; /* dupp key and pack flags */ ulong flags; /* dupp key and pack flags */
uint key_parts; /* How many key_parts */ uint key_parts; /* How many key_parts */
uint extra_length; uint extra_length;
uint usable_key_parts; /* Should normally be = key_parts */ uint usable_key_parts; /* Should normally be = key_parts */
......
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