diff options
Diffstat (limited to 'storage/innobase/handler/handler0alter.cc')
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 92 |
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); |