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.cc108
1 files changed, 59 insertions, 49 deletions
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 363cf50aa90..a76b465d009 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2020, MariaDB Corporation.
+Copyright (c) 2013, 2021, 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
@@ -10073,6 +10073,54 @@ innobase_page_compression_try(
DBUG_RETURN(false);
}
+static
+void
+dict_stats_try_drop_table(THD *thd, const table_name_t &name,
+ const LEX_CSTRING &table_name)
+{
+ char errstr[1024];
+ if (dict_stats_drop_table(name.m_name, errstr, sizeof(errstr)) != DB_SUCCESS)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_ALTER_INFO,
+ "Deleting persistent statistics"
+ " for table '%s' in InnoDB failed: %s",
+ table_name.str,
+ errstr);
+ }
+}
+
+/** Evict the table from cache and reopen it. Drop outdated statistics.
+@param thd mariadb THD entity
+@param table innodb table
+@param table_name user-friendly table name for errors
+@param ctx ALTER TABLE context
+@return newly opened table */
+static dict_table_t *innobase_reload_table(THD *thd, dict_table_t *table,
+ const LEX_CSTRING &table_name,
+ ha_innobase_inplace_ctx &ctx)
+{
+ char *tb_name= strdup(table->name.m_name);
+ dict_table_close(table, true, false);
+
+ if (ctx.is_instant())
+ {
+ for (auto i = ctx.old_n_v_cols; i--; )
+ {
+ ctx.old_v_cols[i].~dict_v_col_t();
+ const_cast<unsigned&>(ctx.old_n_v_cols) = 0;
+ }
+ }
+
+ dict_sys.remove(table);
+ table= dict_table_open_on_name(tb_name, TRUE, TRUE,
+ DICT_ERR_IGNORE_FK_NOKEY);
+
+ /* Drop outdated table stats. */
+ dict_stats_try_drop_table(thd, table->name, table_name);
+ free(tb_name);
+ return table;
+}
+
/** Commit the changes made during prepare_inplace_alter_table()
and inplace_alter_table() inside the data dictionary tables,
when not rebuilding the table.
@@ -11189,44 +11237,19 @@ foreign_fail:
Currently dict_load_column_low() is the only place where
num_base for virtual columns is assigned to nonzero. */
if (ctx0->num_to_drop_vcol || ctx0->num_to_add_vcol
+ || (ctx0->new_table->n_v_cols && !new_clustered
+ && (ha_alter_info->alter_info->drop_list.elements
+ || ha_alter_info->alter_info->create_list.elements))
|| (ctx0->is_instant()
&& m_prebuilt->table->n_v_cols
&& ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) {
- /* FIXME: this workaround does not seem to work with
- partitioned tables */
DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1);
-
trx_commit_for_mysql(m_prebuilt->trx);
- char tb_name[NAME_LEN * 2 + 1 + 1];
- strcpy(tb_name, m_prebuilt->table->name.m_name);
- dict_table_close(m_prebuilt->table, true, false);
- if (ctx0->is_instant()) {
- for (unsigned i = ctx0->old_n_v_cols; i--; ) {
- ctx0->old_v_cols[i].~dict_v_col_t();
- }
- const_cast<unsigned&>(ctx0->old_n_v_cols) = 0;
- }
- dict_sys.remove(m_prebuilt->table);
- m_prebuilt->table = dict_table_open_on_name(
- tb_name, TRUE, TRUE, DICT_ERR_IGNORE_FK_NOKEY);
-
- /* Drop outdated table stats. */
- char errstr[1024];
- if (dict_stats_drop_table(
- m_prebuilt->table->name.m_name,
- errstr, sizeof(errstr))
- != DB_SUCCESS) {
- push_warning_printf(
- m_user_thd,
- Sql_condition::WARN_LEVEL_WARN,
- ER_ALTER_INFO,
- "Deleting persistent statistics"
- " for table '%s' in"
- " InnoDB failed: %s",
- table->s->table_name.str,
- errstr);
- }
+ m_prebuilt->table = innobase_reload_table(m_user_thd,
+ m_prebuilt->table,
+ table->s->table_name,
+ *ctx0);
row_mysql_unlock_data_dictionary(trx);
trx->free();
@@ -11286,25 +11309,12 @@ foreign_fail:
old copy of the table (which was renamed to
ctx->tmp_name). */
- char errstr[1024];
-
DBUG_ASSERT(0 == strcmp(ctx->old_table->name.m_name,
ctx->tmp_name));
- if (dict_stats_drop_table(
- ctx->new_table->name.m_name,
- errstr, sizeof(errstr))
- != DB_SUCCESS) {
- push_warning_printf(
- m_user_thd,
- Sql_condition::WARN_LEVEL_WARN,
- ER_ALTER_INFO,
- "Deleting persistent statistics"
- " for rebuilt table '%s' in"
- " InnoDB failed: %s",
- table->s->table_name.str,
- errstr);
- }
+ dict_stats_try_drop_table(m_user_thd,
+ ctx->new_table->name,
+ table->s->table_name);
DBUG_EXECUTE_IF("ib_ddl_crash_before_commit",
DBUG_SUICIDE(););