diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-11-01 06:57:20 +0530 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-11-01 08:33:59 +0200 |
commit | 162f475c4be81dfbceed093ad03d114b4c69a3c0 (patch) | |
tree | 60cd5c2d1857a20553e46cbdbb51ef2cc373910c /storage/innobase | |
parent | 6dce6aecebe6ef78a14cb5c5c5daa8a355551e40 (diff) | |
download | mariadb-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.cc | 50 |
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; |