diff --git a/mysql-test/r/ext_key_noPK_6794.result b/mysql-test/r/ext_key_noPK_6794.result new file mode 100644 index 00000000000..59344522887 --- /dev/null +++ b/mysql-test/r/ext_key_noPK_6794.result @@ -0,0 +1,20 @@ +create table t1 (c1 int not null, c2 int, unique index(c1), index (c2)) engine=innodb; +insert into t1 (c1, c2) select 1, round(rand()*100); +insert into t1 (c1, c2) select (select max(c1) from t1) + c1, c1*93563%100 from t1; +insert into t1 (c1, c2) select (select max(c1) from t1) + c1, c1*93563%100 from t1; +insert into t1 (c1, c2) select (select max(c1) from t1) + c1, c1*93563%100 from t1; +select count(*) from t1; +count(*) +8 +explain select * from t1 where c2 = 1 order by c1; +id 1 +select_type SIMPLE +table t1 +type ref +possible_keys c2 +key c2 +key_len 5 +ref const +rows 1 +Extra Using where; Using index +drop table t1; diff --git a/mysql-test/t/ext_key_noPK_6794.test b/mysql-test/t/ext_key_noPK_6794.test new file mode 100644 index 00000000000..fc8a2724c22 --- /dev/null +++ b/mysql-test/t/ext_key_noPK_6794.test @@ -0,0 +1,15 @@ +# +# MDEV-6794 XtraDB no longer using UNIQUE as clustered index when PK missing +# + +--source include/have_innodb.inc + +create table t1 (c1 int not null, c2 int, unique index(c1), index (c2)) engine=innodb; +insert into t1 (c1, c2) select 1, round(rand()*100); +insert into t1 (c1, c2) select (select max(c1) from t1) + c1, c1*93563%100 from t1; +insert into t1 (c1, c2) select (select max(c1) from t1) + c1, c1*93563%100 from t1; +insert into t1 (c1, c2) select (select max(c1) from t1) + c1, c1*93563%100 from t1; +select count(*) from t1; +--query_vertical explain select * from t1 where c2 = 1 order by c1 +drop table t1; + diff --git a/sql/table.cc b/sql/table.cc index 9b7d9b274a0..f23823bdf4f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1666,10 +1666,44 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (key_parts) { uint add_first_key_parts= 0; - uint primary_key=(uint) (find_type(primary_key_name, &share->keynames, - FIND_TYPE_NO_PREFIX) - 1); longlong ha_option= handler_file->ha_table_flags(); keyinfo= share->key_info; + uint primary_key= my_strcasecmp(system_charset_info, share->keynames.type_names[0], + primary_key_name) ? MAX_KEY : 0; + + if (primary_key >= MAX_KEY && keyinfo->flags & HA_NOSAME) + { + /* + If the UNIQUE key doesn't have NULL columns and is not a part key + declare this as a primary key. + */ + primary_key= 0; + key_part= keyinfo->key_part; + for (i=0 ; i < keyinfo->user_defined_key_parts ;i++) + { + DBUG_ASSERT(key_part[i].fieldnr > 0); + // Table field corresponding to the i'th key part. + Field *table_field= share->field[key_part[i].fieldnr - 1]; + + /* + If the key column is of NOT NULL BLOB type, then it + will definitly have key prefix. And if key part prefix size + is equal to the BLOB column max size, then we can promote + it to primary key. + */ + if (!table_field->real_maybe_null() && + table_field->type() == MYSQL_TYPE_BLOB && + table_field->field_length == key_part[i].length) + continue; + + if (table_field->real_maybe_null() || + table_field->key_length() != key_part[i].length) + { + primary_key= MAX_KEY; // Can't be used + break; + } + } + } if (share->use_ext_keys) { @@ -1764,40 +1798,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (share->key_info[key].flags & HA_FULLTEXT) share->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT; - if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) - { - /* - If the UNIQUE key doesn't have NULL columns and is not a part key - declare this as a primary key. - */ - primary_key=key; - key_part= keyinfo->key_part; - for (i=0 ; i < keyinfo->user_defined_key_parts ;i++) - { - DBUG_ASSERT(key_part[i].fieldnr > 0); - // Table field corresponding to the i'th key part. - Field *table_field= share->field[key_part[i].fieldnr - 1]; - - /* - If the key column is of NOT NULL BLOB type, then it - will definitly have key prefix. And if key part prefix size - is equal to the BLOB column max size, then we can promote - it to primary key. - */ - if (!table_field->real_maybe_null() && - table_field->type() == MYSQL_TYPE_BLOB && - table_field->field_length == key_part[i].length) - continue; - - if (table_field->real_maybe_null() || - table_field->key_length() != key_part[i].length) - { - primary_key= MAX_KEY; // Can't be used - break; - } - } - } - key_part= keyinfo->key_part; uint key_parts= share->use_ext_keys ? keyinfo->ext_key_parts : keyinfo->user_defined_key_parts;