diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 60ae2ed800b..7d70fa8afd2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6313,11 +6313,23 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, the primary key is not added and dropped in the same statement. Otherwise we have to recreate the table. need_copy_table is no-zero at this place. + + Also, in-place is not possible if we add a primary key + and drop another key in the same statement. If the drop fails, + we will not be able to revert adding of primary key. */ if ( pk_changed < 2 ) { - if ((alter_flags & needed_inplace_with_read_flags) == - needed_inplace_with_read_flags) + if ((needed_inplace_with_read_flags & HA_INPLACE_ADD_PK_INDEX_NO_WRITE) && + index_drop_count > 0) + { + /* + Do copy, not in-place ALTER. + Avoid setting ALTER_TABLE_METADATA_ONLY. + */ + } + else if ((alter_flags & needed_inplace_with_read_flags) == + needed_inplace_with_read_flags) { /* All required in-place flags to allow concurrent reads are present. */ need_copy_table= ALTER_TABLE_METADATA_ONLY; @@ -6579,17 +6591,38 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, Tell the handler to prepare for drop indexes. This re-numbers the indexes to get rid of gaps. */ - if ((error= table->file->prepare_drop_index(table, key_numbers, - index_drop_count))) + error= table->file->prepare_drop_index(table, key_numbers, + index_drop_count); + if (!error) { - table->file->print_error(error, MYF(0)); - goto err_new_table_cleanup; + /* Tell the handler to finally drop the indexes. */ + error= table->file->final_drop_index(table); } - /* Tell the handler to finally drop the indexes. */ - if ((error= table->file->final_drop_index(table))) + if (error) { table->file->print_error(error, MYF(0)); + if (index_add_count) // Drop any new indexes added. + { + /* + Temporarily set table-key_info to include information about the + indexes added above that we now need to drop. + */ + KEY *save_key_info= table->key_info; + table->key_info= key_info_buffer; + if ((error= table->file->prepare_drop_index(table, index_add_buffer, + index_add_count))) + table->file->print_error(error, MYF(0)); + else if ((error= table->file->final_drop_index(table))) + table->file->print_error(error, MYF(0)); + table->key_info= save_key_info; + } + + /* + Mark this TABLE instance as stale to avoid + out-of-sync index information. + */ + table->m_needs_reopen= true; goto err_new_table_cleanup; } } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ea47a8160f9..60a62482f9c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8010,10 +8010,15 @@ innobase_get_mysql_key_number_for_index( } } - /* Print an error message if we cannot find the index - ** in the "index translation table". */ - sql_print_error("Cannot find index %s in InnoDB index " - "translation table.", index->name); + /* If index_count in translation table is set to 0, it + is possible we are in the process of rebuilding table, + do not spit error in this case */ + if (share->idx_trans_tbl.index_count) { + /* Print an error message if we cannot find the index + ** in the "index translation table". */ + sql_print_error("Cannot find index %s in InnoDB index " + "translation table.", index->name); + } } /* If we do not have an "index translation table", or not able diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index e8e3cb0e5cd..5e20bea36dd 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -773,7 +773,7 @@ ha_innobase::add_index( row_mysql_lock_data_dictionary(trx); dict_locked = TRUE; - ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE)); + ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE)); /* If a new primary key is defined for the table we need to drop the original table and rebuild all indexes. */ @@ -809,7 +809,7 @@ ha_innobase::add_index( } ut_d(dict_table_check_for_dup_indexes(prebuilt->table, - FALSE)); + TRUE)); mem_heap_free(heap); trx_general_rollback_for_mysql(trx, NULL); row_mysql_unlock_data_dictionary(trx); @@ -1061,7 +1061,7 @@ ha_innobase::final_add_index( trx_commit_for_mysql(prebuilt->trx); } - ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE)); + ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE)); row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); @@ -1104,7 +1104,7 @@ ha_innobase::prepare_drop_index( /* Test and mark all the indexes to be dropped */ row_mysql_lock_data_dictionary(trx); - ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE)); + ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE)); /* Check that none of the indexes have previously been flagged for deletion. */ @@ -1275,7 +1275,7 @@ func_exit: } while (index); } - ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE)); + ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE)); row_mysql_unlock_data_dictionary(trx); DBUG_RETURN(err); @@ -1322,7 +1322,7 @@ ha_innobase::final_drop_index( prebuilt->table->flags, user_thd); row_mysql_lock_data_dictionary(trx); - ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE)); + ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE)); if (UNIV_UNLIKELY(err)) { @@ -1366,7 +1366,7 @@ ha_innobase::final_drop_index( share->idx_trans_tbl.index_count = 0; func_exit: - ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE)); + ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE)); trx_commit_for_mysql(trx); trx_commit_for_mysql(prebuilt->trx); row_mysql_unlock_data_dictionary(trx);