summaryrefslogtreecommitdiff
path: root/storage/innobase/handler/handler0alter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/handler/handler0alter.cc')
-rw-r--r--storage/innobase/handler/handler0alter.cc75
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