diff options
Diffstat (limited to 'storage/innobase/handler/handler0alter.cc')
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 75 |
1 files changed, 42 insertions, 33 deletions
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 587ae7f5402..58de40761c5 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -6570,12 +6570,14 @@ check_if_ok_to_rename: continue; } + dict_foreign_t* foreign; + for (dict_foreign_set::iterator it = m_prebuilt->table->foreign_set.begin(); it != m_prebuilt->table->foreign_set.end(); ++it) { - dict_foreign_t* foreign = *it; + foreign = *it; const char* fid = strchr(foreign->id, '/'); DBUG_ASSERT(fid); @@ -6586,7 +6588,6 @@ check_if_ok_to_rename: if (!my_strcasecmp(system_charset_info, fid, drop->name)) { - drop_fk[n_drop_fk++] = foreign; goto found_fk; } } @@ -6595,13 +6596,20 @@ check_if_ok_to_rename: drop->type_name(), drop->name); goto err_exit; found_fk: + for (ulint i = n_drop_fk; i--; ) { + if (drop_fk[i] == foreign) { + goto dup_fk; + } + } + drop_fk[n_drop_fk++] = foreign; +dup_fk: continue; } DBUG_ASSERT(n_drop_fk > 0); DBUG_ASSERT(n_drop_fk - == ha_alter_info->alter_info->drop_list.elements); + <= ha_alter_info->alter_info->drop_list.elements); } else { drop_fk = NULL; } @@ -7756,7 +7764,7 @@ err_exit: rename_foreign: trx->op_info = "renaming column in SYS_FOREIGN_COLS"; - std::list<dict_foreign_t*> fk_evict; + std::set<dict_foreign_t*> fk_evict; bool foreign_modified; for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin(); @@ -7796,7 +7804,7 @@ rename_foreign: } if (foreign_modified) { - fk_evict.push_back(foreign); + fk_evict.insert(foreign); } } @@ -7838,7 +7846,7 @@ rename_foreign: } if (foreign_modified) { - fk_evict.push_back(foreign); + fk_evict.insert(foreign); } } @@ -8630,6 +8638,8 @@ commit_try_rebuild( DBUG_ASSERT(!(ha_alter_info->handler_flags & ALTER_DROP_FOREIGN_KEY) || ctx->num_to_drop_fk > 0); + DBUG_ASSERT(ctx->num_to_drop_fk + <= ha_alter_info->alter_info->drop_list.elements); for (dict_index_t* index = dict_table_get_first_index(rebuilt_table); index; @@ -8929,7 +8939,7 @@ commit_try_norebuild( & ALTER_DROP_FOREIGN_KEY) || ctx->num_to_drop_fk > 0); DBUG_ASSERT(ctx->num_to_drop_fk - == ha_alter_info->alter_info->drop_list.elements + <= ha_alter_info->alter_info->drop_list.elements || ctx->num_to_drop_vcol == ha_alter_info->alter_info->drop_list.elements); @@ -9428,7 +9438,6 @@ ha_innobase::commit_inplace_alter_table( Alter_inplace_info* ha_alter_info, bool commit) { - dberr_t error; ha_innobase_inplace_ctx*ctx0; struct mtr_buf_copy_t logs; @@ -9516,7 +9525,7 @@ ha_innobase::commit_inplace_alter_table( transactions collected during crash recovery could be holding InnoDB locks only, not MySQL locks. */ - error = row_merge_lock_table( + dberr_t error = row_merge_lock_table( m_prebuilt->trx, ctx->old_table, LOCK_X); if (error != DB_SUCCESS) { @@ -9706,9 +9715,9 @@ ha_innobase::commit_inplace_alter_table( file operations that will be performed in commit_cache_rebuild(), and if none, generate the redo log for these operations. */ - error = fil_mtr_rename_log(ctx->old_table, - ctx->new_table, - ctx->tmp_name, &mtr); + dberr_t error = fil_mtr_rename_log( + ctx->old_table, ctx->new_table, ctx->tmp_name, + &mtr); if (error != DB_SUCCESS) { /* Out of memory or a problem will occur when renaming files. */ @@ -9844,30 +9853,30 @@ ha_innobase::commit_inplace_alter_table( /* Rename the tablespace files. */ commit_cache_rebuild(ctx); - error = innobase_update_foreign_cache(ctx, m_user_thd); - if (error != DB_SUCCESS) { - goto foreign_fail; - } - } else { - error = innobase_update_foreign_cache(ctx, m_user_thd); - - if (error != DB_SUCCESS) { + if (innobase_update_foreign_cache(ctx, m_user_thd) + != DB_SUCCESS + && m_prebuilt->trx->check_foreigns) { foreign_fail: - /* The data dictionary cache - should be corrupted now. The - best solution should be to - kill and restart the server, - but the *.frm file has not - been replaced yet. */ push_warning_printf( m_user_thd, Sql_condition::WARN_LEVEL_WARN, ER_ALTER_INFO, - "InnoDB: Could not add foreign" - " key constraints."); - } else { - commit_cache_norebuild(ha_alter_info, ctx, - table, trx); + "failed to load FOREIGN KEY" + " constraints"); + } + } else { + bool fk_fail = innobase_update_foreign_cache( + ctx, m_user_thd) != DB_SUCCESS; + + commit_cache_norebuild(ha_alter_info, ctx, + table, trx); + innobase_rename_or_enlarge_columns_cache( + ha_alter_info, table, ctx->new_table); +#ifdef MYSQL_RENAME_INDEX + rename_indexes_in_cache(ctx, ha_alter_info); +#endif + if (fk_fail && m_prebuilt->trx->check_foreigns) { + goto foreign_fail; } } @@ -10074,7 +10083,7 @@ foreign_fail: before this is completed, some orphan tables with ctx->tmp_name may be recovered. */ trx_start_for_ddl(trx, TRX_DICT_OP_TABLE); - error = row_merge_drop_table(trx, ctx->old_table); + dberr_t error = row_merge_drop_table(trx, ctx->old_table); if (error != DB_SUCCESS) { ib::error() << "Inplace alter table " << ctx->old_table->name |