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.cc92
1 files changed, 71 insertions, 21 deletions
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 58e17cd3ead..873e9065515 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1023,13 +1023,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
@return whether the table will be rebuilt */
bool need_rebuild () const { return(old_table != new_table); }
- /** Clear uncommmitted added indexes after a failed operation. */
- void clear_added_indexes()
- {
- for (ulint i= 0; i < num_to_add_index; i++)
- add_index[i]->detach_columns(true);
- }
-
/** Convert table-rebuilding ALTER to instant ALTER. */
void prepare_instant()
{
@@ -1076,6 +1069,19 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
return instant_table;
}
+ /** @return whether the given column is added as a part of alter */
+ bool is_new_vcol(const dict_v_col_t &v_col) const
+ {
+ if (num_to_add_vcol == 0)
+ return false;
+ for (ulint i= 0; i < num_to_add_vcol; i++)
+ {
+ if (&add_vcol[i] == &v_col)
+ return true;
+ }
+ return false;
+ }
+
/** Create an index table where indexes are ordered as follows:
IF a new primary key is defined for the table THEN
@@ -1127,6 +1133,41 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
}
}
+ /** During rollback, InnoDB should duplicate the newly added
+ virtual column in newly added virtual index. It should be
+ present in new_vcol_info of index. */
+ void clean_new_vcol_index()
+ {
+ ut_ad(old_table == new_table);
+ const dict_index_t *index= dict_table_get_first_index(old_table);
+ while ((index = dict_table_get_next_index(index)) != NULL)
+ {
+ if (!index->has_virtual() || !index->has_new_v_col()
+ || index->is_committed())
+ continue;
+ ulint n_drop_new_vcol= 0;
+ ulint n_new_vcol= index->get_new_n_vcol();
+ index->assign_drop_v_col();
+ for (ulint i= 0; i < index->n_fields; i++)
+ {
+ dict_col_t *col= index->fields[i].col;
+ /* Skip the non-virtual and old virtual columns */
+ if (!col->is_virtual()
+ || !is_new_vcol(reinterpret_cast<dict_v_col_t&>(*col)))
+ continue;
+
+ dict_v_col_t* drop_vcol= index->add_drop_v_col(
+ reinterpret_cast<dict_v_col_t*>(col), n_drop_new_vcol);
+ drop_vcol->detach(*index);
+ /* Re-assign the index field with newly stored virtual column */
+ index->fields[i].col = reinterpret_cast<dict_col_t*>(drop_vcol);
+ n_drop_new_vcol++;
+ if (n_drop_new_vcol == n_new_vcol)
+ break;
+ }
+ }
+ }
+
private:
// Disable copying
ha_innobase_inplace_ctx(const ha_innobase_inplace_ctx&);
@@ -6812,7 +6853,7 @@ new_table_failed:
for (ulint a = 0; a < ctx->num_to_add_index; a++) {
dict_index_t* index = ctx->add_index[a];
- const bool has_new_v_col = index->has_new_v_col;
+ const ulint n_v_col = index->get_new_n_vcol();
index = create_index_dict(ctx->trx, index, add_v);
error = ctx->trx->error_state;
if (error != DB_SUCCESS) {
@@ -6842,7 +6883,10 @@ error_handling_drop_uncached_1:
goto error_handling_drop_uncached_1;
}
index->parser = index_defs[a].parser;
- index->has_new_v_col = has_new_v_col;
+ if (n_v_col) {
+ index->assign_new_v_col(n_v_col);
+ }
+
/* Note the id of the transaction that created this
index, we use it to restrict readers from accessing
this index, to ensure read consistency. */
@@ -6913,7 +6957,7 @@ error_handling_drop_uncached_1:
for (ulint a = 0; a < ctx->num_to_add_index; a++) {
dict_index_t* index = ctx->add_index[a];
- const bool has_new_v_col = index->has_new_v_col;
+ const ulint n_v_col = index->get_new_n_vcol();
DBUG_EXECUTE_IF(
"create_index_metadata_fail",
if (a + 1 == ctx->num_to_add_index) {
@@ -6945,7 +6989,9 @@ error_handling_drop_uncached:
}
index->parser = index_defs[a].parser;
- index->has_new_v_col = has_new_v_col;
+ if (n_v_col) {
+ index->assign_new_v_col(n_v_col);
+ }
/* Note the id of the transaction that created this
index, we use it to restrict readers from accessing
this index, to ensure read consistency. */
@@ -8532,7 +8578,6 @@ oom:
that we hold at most a shared lock on the table. */
m_prebuilt->trx->error_info = NULL;
ctx->trx->error_state = DB_SUCCESS;
- ctx->clear_added_indexes();
DBUG_RETURN(true);
}
@@ -8624,17 +8669,18 @@ temparary index prefix
@param table the TABLE
@param locked TRUE=table locked, FALSE=may need to do a lazy drop
@param trx the transaction
-*/
-static MY_ATTRIBUTE((nonnull))
+@param alter_trx transaction which takes S-lock on the table
+ while creating the index */
+static
void
innobase_rollback_sec_index(
-/*========================*/
- dict_table_t* user_table,
- const TABLE* table,
- ibool locked,
- trx_t* trx)
+ dict_table_t* user_table,
+ const TABLE* table,
+ ibool locked,
+ trx_t* trx,
+ const trx_t* alter_trx=NULL)
{
- row_merge_drop_indexes(trx, user_table, locked);
+ row_merge_drop_indexes(trx, user_table, locked, alter_trx);
/* Free the table->fts only if there is no FTS_DOC_ID
in the table */
@@ -8762,7 +8808,11 @@ rollback_inplace_alter_table(
}
innobase_rollback_sec_index(
- prebuilt->table, table, FALSE, ctx->trx);
+ prebuilt->table, table,
+ (ha_alter_info->alter_info->requested_lock
+ == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE),
+ ctx->trx, prebuilt->trx);
+ ctx->clean_new_vcol_index();
}
trx_commit_for_mysql(ctx->trx);