summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-11-01 06:57:20 +0530
committerMarko Mäkelä <marko.makela@mariadb.com>2019-11-01 08:33:59 +0200
commit162f475c4be81dfbceed093ad03d114b4c69a3c0 (patch)
tree60cd5c2d1857a20553e46cbdbb51ef2cc373910c /storage/innobase
parent6dce6aecebe6ef78a14cb5c5c5daa8a355551e40 (diff)
downloadmariadb-git-162f475c4be81dfbceed093ad03d114b4c69a3c0.tar.gz
MDEV-20938 Double free of dict_foreign_t during instant ALTER TABLE
innobase_drop_foreign_try(): Don't evict and reload the dict_foreign_t during instant ALTER TABLE if the FOREIGN KEY constraint is being dropped. The MDEV-19630 fix (commit 07b1a26c33b28812a4fd8c814de0fe7d943bbd6b) was incomplete, because it did not cover a case where the FOREIGN KEY constraint is being dropped.
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/handler/handler0alter.cc50
1 files changed, 26 insertions, 24 deletions
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 1450624c0c2..7b7afa6d1df 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -7428,27 +7428,23 @@ innobase_drop_foreign_try(
}
/** Rename a column in the data dictionary tables.
-@param[in] user_table InnoDB table that was being altered
-@param[in] trx Data dictionary transaction
+@param[in] ctx ALTER TABLE context
+@param[in,out] trx Data dictionary transaction
@param[in] table_name Table name in MySQL
@param[in] nth_col 0-based index of the column
@param[in] from old column name
@param[in] to new column name
-@param[in] new_clustered whether the table has been rebuilt
-@param[in] evict_fk_cache Evict the fk info from cache
@retval true Failure
@retval false Success */
static MY_ATTRIBUTE((nonnull, warn_unused_result))
bool
innobase_rename_column_try(
- const dict_table_t* user_table,
- trx_t* trx,
- const char* table_name,
- ulint nth_col,
- const char* from,
- const char* to,
- bool new_clustered,
- bool evict_fk_cache)
+ const ha_innobase_inplace_ctx& ctx,
+ trx_t* trx,
+ const char* table_name,
+ ulint nth_col,
+ const char* from,
+ const char* to)
{
pars_info_t* info;
dberr_t error;
@@ -7460,13 +7456,13 @@ innobase_rename_column_try(
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- if (new_clustered) {
+ if (ctx.need_rebuild()) {
goto rename_foreign;
}
info = pars_info_create();
- pars_info_add_ull_literal(info, "tableid", user_table->id);
+ pars_info_add_ull_literal(info, "tableid", ctx.old_table->id);
pars_info_add_int4_literal(info, "nth", nth_col);
pars_info_add_str_literal(info, "new", to);
@@ -7496,7 +7492,7 @@ err_exit:
trx->op_info = "renaming column in SYS_FIELDS";
for (const dict_index_t* index = dict_table_get_first_index(
- user_table);
+ ctx.old_table);
index != NULL;
index = dict_table_get_next_index(index)) {
@@ -7549,8 +7545,8 @@ rename_foreign:
std::set<dict_foreign_t*> fk_evict;
bool foreign_modified;
- for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin();
- it != user_table->foreign_set.end();
+ for (dict_foreign_set::const_iterator it = ctx.old_table->foreign_set.begin();
+ it != ctx.old_table->foreign_set.end();
++it) {
dict_foreign_t* foreign = *it;
@@ -7563,6 +7559,14 @@ rename_foreign:
continue;
}
+ /* Ignore the foreign key rename if fk info
+ is being dropped. */
+ if (innobase_dropping_foreign(
+ foreign, ctx.drop_fk,
+ ctx.num_to_drop_fk)) {
+ continue;
+ }
+
info = pars_info_create();
pars_info_add_str_literal(info, "id", foreign->id);
@@ -7591,8 +7595,8 @@ rename_foreign:
}
for (dict_foreign_set::const_iterator it
- = user_table->referenced_set.begin();
- it != user_table->referenced_set.end();
+ = ctx.old_table->referenced_set.begin();
+ it != ctx.old_table->referenced_set.end();
++it) {
foreign_modified = false;
@@ -7633,7 +7637,7 @@ rename_foreign:
}
/* Reload the foreign key info for instant table too. */
- if (new_clustered || evict_fk_cache) {
+ if (ctx.need_rebuild() || ctx.is_instant()) {
std::for_each(fk_evict.begin(), fk_evict.end(),
dict_foreign_remove_from_cache);
}
@@ -7684,12 +7688,10 @@ innobase_rename_columns_try(
: i - num_v;
if (innobase_rename_column_try(
- ctx->old_table, trx, table_name,
+ *ctx, trx, table_name,
col_n,
cf->field->field_name.str,
- cf->field_name.str,
- ctx->need_rebuild(),
- ctx->is_instant())) {
+ cf->field_name.str)) {
return(true);
}
goto processed_field;