diff options
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1434e0d61d4..471783c280b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4291,7 +4291,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } create_info->period_info.unique_keys++; } - + key_info->is_ignored= key->key_create_info.is_ignored; key_info++; } @@ -6829,6 +6829,32 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key, return result; } + +/** + Look-up KEY object by index name using case-insensitive comparison. + + @param key_name Index name. + @param key_start Start of array of KEYs for table. + @param key_end End of array of KEYs for table. + + @note Case-insensitive comparison is necessary to correctly + handle renaming of keys. + + @retval non-NULL - pointer to KEY object for index found. + @retval NULL - no index with such name found (or it is marked + as renamed). +*/ + +static KEY *find_key_ci(const char *key_name, KEY *key_start, KEY *key_end) { + for (KEY *key = key_start; key < key_end; key++) + { + if (!my_strcasecmp(system_charset_info, key_name, key->name.str)) + return key; + } + return NULL; +} + + /** Compare original and new versions of a table and fill Alter_inplace_info describing differences between those versions. @@ -6888,7 +6914,10 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, ! (ha_alter_info->index_add_buffer= (uint*) thd->alloc(sizeof(uint) * alter_info->key_list.elements)) || - ha_alter_info->rename_keys.reserve(ha_alter_info->index_add_count)) + ha_alter_info->rename_keys.reserve(ha_alter_info->index_add_count) || + ! (ha_alter_info->index_altered_ignorability_buffer= + (KEY_PAIR*)thd->alloc(sizeof(KEY_PAIR) * + alter_info->alter_index_ignorability_list.elements))) DBUG_RETURN(true); /* @@ -7294,6 +7323,29 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, } } + List_iterator<Alter_index_ignorability> + ignorability_index_it(alter_info->alter_index_ignorability_list); + Alter_index_ignorability *alter_index_ignorability; + while((alter_index_ignorability= ignorability_index_it++)) + { + const char *name= alter_index_ignorability->name(); + + KEY *old_key, *new_key; + old_key= find_key_ci(name, table->key_info, table_key_end); + new_key= find_key_ci(name, ha_alter_info->key_info_buffer, new_key_end); + + DBUG_ASSERT(old_key != NULL); + + if (new_key == NULL) + { + my_error(ER_KEY_DOES_NOT_EXISTS, MYF(0), name, table->s->table_name.str); + DBUG_RETURN(true); + } + new_key->is_ignored= alter_index_ignorability->is_ignored(); + ha_alter_info->handler_flags|= ALTER_RENAME_INDEX; + ha_alter_info->add_altered_index_ignorability(old_key, new_key); + } + /* Sort index_add_buffer according to how key_info_buffer is sorted. I.e. with primary keys first - see sort_keys(). @@ -8128,6 +8180,17 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, /* New key definitions are added here */ List<Key> new_key_list; List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list); + + /* + Create a deep copy of the list of visibility for indexes, as it will be + altered here. + */ + List<Alter_index_ignorability> + alter_index_ignorability_list(alter_info->alter_index_ignorability_list, + thd->mem_root); + + list_copy_and_replace_each_value(alter_index_ignorability_list, thd->mem_root); + List_iterator<Alter_drop> drop_it(alter_info->drop_list); List_iterator<Create_field> def_it(alter_info->create_list); List_iterator<Alter_column> alter_it(alter_info->alter_list); @@ -8594,6 +8657,18 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, continue; } + List_iterator<Alter_index_ignorability> + ignorability_index_it(alter_index_ignorability_list); + + Alter_index_ignorability *index_ignorability; + while((index_ignorability= ignorability_index_it++)) + { + const char* name= index_ignorability->name(); + if (!my_strcasecmp(system_charset_info, key_name, name)) + ignorability_index_it.remove(); + } + + /* If this index is to stay in the table check if it has to be renamed. */ List_iterator<Alter_rename_key> rename_key_it(rename_key_list); Alter_rename_key *rename_key; @@ -8742,6 +8817,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, key_create_info.parser_name= *plugin_name(key_info->parser); if (key_info->flags & HA_USES_COMMENT) key_create_info.comment= key_info->comment; + key_create_info.is_ignored= key_info->is_ignored; /* We're refreshing an already existing index. Since the index is not @@ -8773,6 +8849,24 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, else key_type= Key::MULTIPLE; + List_iterator<Alter_index_ignorability> + ignorability_index_it(alter_info->alter_index_ignorability_list); + Alter_index_ignorability *index_ignorability; + while((index_ignorability= ignorability_index_it++)) + { + const char *name= index_ignorability->name(); + if (!my_strcasecmp(system_charset_info, key_name, name)) + { + if (table->s->primary_key <= MAX_KEY && + table->key_info + table->s->primary_key == key_info) + { + my_error(ER_PK_INDEX_CANT_BE_IGNORED, MYF(0)); + goto err; + } + key_create_info.is_ignored= index_ignorability->is_ignored(); + } + } + tmp_name.str= key_name; tmp_name.length= strlen(key_name); /* We dont need LONG_UNIQUE_HASH_FIELD flag because it will be autogenerated */ @@ -8975,6 +9069,14 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, goto err; } + if (alter_index_ignorability_list.elements) + { + my_error(ER_KEY_DOES_NOT_EXISTS, MYF(0), + alter_index_ignorability_list.head()->name(), + table->s->table_name.str); + goto err; + } + if (!create_info->comment.str) { create_info->comment.str= table->s->comment.str; |