Commit 01389ee8 authored by Marko Mäkelä's avatar Marko Mäkelä Committed by Marko Mäkelä

Bug#24397406 INNODB: ALGORITHM=INPLACE FAILS TO PROMOTE UNIQUE KEY TO CLUSTERED INDEX

When a table has no PRIMARY KEY, but there is a UNIQUE INDEX
defined on NOT NULL columns that are not column prefixes,
that unique index must be treated as the primary key.

This property was being violated by InnoDB when a column was changed
to NOT NULL, such that a UNIQUE INDEX on that column became eligible
to being treated as a primary key.

innobase_create_key_defs(): Instead of checking each ADD [UNIQUE] INDEX
request, check if a GEN_CLUST_INDEX can be replaced with any unique index
in the altered_table definition. So, we can have new_primary even
if n_add==0.

prepare_inplace_alter_table_dict(): When the table is not being rebuilt,
assert that TABLE_SHARE::primary_key is not changing.

RB: 13595
Reviewed-by: default avatarKevin Lewis <kevin.lewis@oracle.com>
parent 92f7f81b
......@@ -2469,6 +2469,7 @@ innobase_fts_check_doc_id_index_in_def(
return(FTS_NOT_EXIST_DOC_ID_INDEX);
}
/*******************************************************************//**
Create an index table where indexes are ordered as follows:
......@@ -2537,35 +2538,16 @@ innobase_create_key_defs(
(only prefix/part of the column is indexed), MySQL will treat the
index as a PRIMARY KEY unless the table already has one. */
if (n_add > 0 && !new_primary && got_default_clust
&& (key_info[*add].flags & HA_NOSAME)
&& !(key_info[*add].flags & HA_KEY_HAS_PART_KEY_SEG)) {
uint key_part = key_info[*add].user_defined_key_parts;
new_primary = true;
while (key_part--) {
const uint maybe_null
= key_info[*add].key_part[key_part].key_type
& FIELDFLAG_MAYBE_NULL;
bool is_v
= innobase_is_v_fld(
key_info[*add].key_part[key_part].field);
DBUG_ASSERT(!maybe_null
== !key_info[*add].key_part[key_part].
field->real_maybe_null());
if (maybe_null || is_v) {
new_primary = false;
break;
}
}
ut_ad(altered_table->s->primary_key == 0
|| altered_table->s->primary_key == MAX_KEY);
if (got_default_clust && !new_primary) {
new_primary = (altered_table->s->primary_key != MAX_KEY);
}
const bool rebuild = new_primary || add_fts_doc_id
|| innobase_need_rebuild(ha_alter_info, table);
/* Reserve one more space if new_primary is true, and we might
need to add the FTS_DOC_ID_INDEX */
indexdef = indexdefs = static_cast<index_def_t*>(
......@@ -2579,8 +2561,14 @@ innobase_create_key_defs(
ulint primary_key_number;
if (new_primary) {
DBUG_ASSERT(n_add > 0);
primary_key_number = *add;
if (n_add == 0) {
DBUG_ASSERT(got_default_clust);
DBUG_ASSERT(altered_table->s->primary_key
== 0);
primary_key_number = 0;
} else {
primary_key_number = *add;
}
} else if (got_default_clust) {
/* Create the GEN_CLUST_INDEX */
index_def_t* index = indexdef++;
......@@ -4785,6 +4773,8 @@ prepare_inplace_alter_table_dict(
ctx->add_cols = add_cols;
} else {
DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info, old_table));
DBUG_ASSERT(old_table->s->primary_key
== altered_table->s->primary_key);
for (dict_index_t* index
= dict_table_get_first_index(user_table);
......
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