Commit cb437417 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-19114 gcol.innodb_virtual_debug: Assertion n_fields>0 failed

This is a regression due to MDEV-16376
commit 8dc70c86.
To make dict_index_t::detach_columns() idempotent,
we cleared dict_index_t::n_fields. But, this could
cause trouble with purge after a secondary index
creation failed (not even involving virtual columns).

A better way is to clear the dict_field_t::col pointers
that point to virtual columns that are being freed
due to aborting index creation on an index that depends
on a virtual column.

Note: the v_cols[] of an existing dict_table_t object will
never be modified. If any virtual columns are added or removed,
ha_innobase::commit_inplace_alter_table() would invoke
dict_table_remove_from_cache() and reload the table to dict_sys.
Index creation is a special case where the dict_index_t points
to virtual columns that do not yet exist in dict_table_t.
parent f9144a42
...@@ -2200,7 +2200,7 @@ dict_index_remove_from_v_col_list(dict_index_t* index) { ...@@ -2200,7 +2200,7 @@ dict_index_remove_from_v_col_list(dict_index_t* index) {
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) { for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
col = dict_index_get_nth_col(index, i); col = dict_index_get_nth_col(index, i);
if (dict_col_is_virtual(col)) { if (col && col->is_virtual()) {
vcol = reinterpret_cast<const dict_v_col_t*>( vcol = reinterpret_cast<const dict_v_col_t*>(
col); col);
/* This could be NULL, when we do add /* This could be NULL, when we do add
......
...@@ -248,16 +248,12 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx ...@@ -248,16 +248,12 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
@return whether the table will be rebuilt */ @return whether the table will be rebuilt */
bool need_rebuild () const { return(old_table != new_table); } bool need_rebuild () const { return(old_table != new_table); }
/** Clear uncommmitted added indexes after a failed operation. */ /** Clear uncommmitted added indexes after a failed operation. */
void clear_added_indexes() void clear_added_indexes()
{ {
for (ulint i = 0; i < num_to_add_index; i++) { for (ulint i= 0; i < num_to_add_index; i++)
if (!add_index[i]->is_committed()) { add_index[i]->detach_columns(true);
add_index[i]->detach_columns(); }
add_index[i]->n_fields = 0;
}
}
}
/** Share context between partitions. /** Share context between partitions.
@param[in] ctx context from another partition of the table */ @param[in] ctx context from another partition of the table */
......
...@@ -634,12 +634,12 @@ struct dict_col_t{ ...@@ -634,12 +634,12 @@ struct dict_col_t{
this column. Our current max limit is this column. Our current max limit is
3072 for Barracuda table */ 3072 for Barracuda table */
/** @return whether this is a virtual column */ /** @return whether this is a virtual column */
bool is_virtual() const { return prtype & DATA_VIRTUAL; } bool is_virtual() const { return prtype & DATA_VIRTUAL; }
/** Detach the column from an index. /** Detach a virtual column from an index.
@param[in] index index to be detached from */ @param index being-freed index */
inline void detach(const dict_index_t& index); inline void detach(const dict_index_t &index);
}; };
/** Index information put in a list of virtual column structure. Index /** Index information put in a list of virtual column structure. Index
...@@ -1017,15 +1017,22 @@ struct dict_index_t{ ...@@ -1017,15 +1017,22 @@ struct dict_index_t{
/** @return whether the index is corrupted */ /** @return whether the index is corrupted */
inline bool is_corrupted() const; inline bool is_corrupted() const;
/** Detach the columns from the index that is to be freed. */ /** Detach the virtual columns from the index that is to be removed.
void detach_columns() @param whether to reset fields[].col */
{ void detach_columns(bool clear= false)
if (has_virtual()) { {
for (unsigned i = 0; i < n_fields; i++) { if (!has_virtual())
fields[i].col->detach(*this); return;
} for (unsigned i= 0; i < n_fields; i++)
} {
} dict_col_t* col= fields[i].col;
if (!col || !col->is_virtual())
continue;
col->detach(*this);
if (clear)
fields[i].col= NULL;
}
}
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
/** @return a clone of this */ /** @return a clone of this */
...@@ -1102,24 +1109,24 @@ struct dict_index_t{ ...@@ -1102,24 +1109,24 @@ struct dict_index_t{
inline record_size_info_t record_size_info() const; inline record_size_info_t record_size_info() const;
}; };
/** Detach a column from an index. /** Detach a virtual column from an index.
@param[in] index index to be detached from */ @param index being-freed index */
inline void dict_col_t::detach(const dict_index_t& index) inline void dict_col_t::detach(const dict_index_t &index)
{ {
if (!is_virtual()) { ut_ad(is_virtual());
return;
} if (dict_v_idx_list *v_indexes= reinterpret_cast<const dict_v_col_t*>(this)
->v_indexes)
if (dict_v_idx_list* v_indexes = reinterpret_cast<const dict_v_col_t*> {
(this)->v_indexes) { for (dict_v_idx_list::iterator i= v_indexes->begin();
for (dict_v_idx_list::iterator i = v_indexes->begin(); i != v_indexes->end(); i++)
i != v_indexes->end(); i++) { {
if (i->index == &index) { if (i->index == &index) {
v_indexes->erase(i); v_indexes->erase(i);
return; return;
} }
} }
} }
} }
/** The status of online index creation */ /** The status of online index creation */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment