summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-03-25 10:29:25 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-03-25 10:29:48 +0200
commit71c781bfe758c1296095f99fa529276442b3a1ac (patch)
treea5ea16fd2157ff0f630f3a35e8ec2ed0b4b6dbc0
parent77e2aca3f0795884e8221b30973709b62119fade (diff)
downloadmariadb-git-71c781bfe758c1296095f99fa529276442b3a1ac.tar.gz
MDEV-18090 Assertion failures due to virtual columns after upgrading to 10.2
MariaDB before MDEV-5800 in version 10.2.2 did not support indexed virtual columns. Non-persistent virtual columns were hidden from storage engines. Only starting with MDEV-5800, InnoDB would create internal metadata on virtual columns. Similar to what was done in MDEV-18084 and MDEV-18960, we adjust two more code paths for the old tables. ha_innobase::build_template(): Do not invoke dict_index_contains_col_or_prefix() for virtual columns if InnoDB does not store the metadata. innobase_build_col_map(): Relax an assertion about the number of columns. ha_innobase::omits_virtual_cols(): Renamed from omits_virtual_cols().
-rw-r--r--storage/innobase/handler/ha_innodb.cc18
-rw-r--r--storage/innobase/handler/ha_innodb.h12
-rw-r--r--storage/innobase/handler/handler0alter.cc3
3 files changed, 19 insertions, 14 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 9366b2db30b..b448f71d6d0 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -275,12 +275,6 @@ void set_my_errno(int err)
errno = err;
}
-static uint omits_virtual_cols(const TABLE_SHARE &share)
-{
- return share.frm_version < FRM_VER_EXPRESSSIONS &&
- share.virtual_fields;
-}
-
/** Checks whether the file name belongs to a partition of a table.
@param[in] file_name file name
@return pointer to the end of the table name part of the file name, or NULL */
@@ -7475,7 +7469,8 @@ build_template_needs_field(
{
const Field* field = table->field[i];
- if (!field->stored_in_db() && omits_virtual_cols(*table->s)) {
+ if (!field->stored_in_db()
+ && ha_innobase::omits_virtual_cols(*table->s)) {
return NULL;
}
@@ -7632,7 +7627,7 @@ build_template_field(
&templ->rec_prefix_field_no);
}
} else {
- ut_ad(!omits_virtual_cols(*table->s));
+ DBUG_ASSERT(!ha_innobase::omits_virtual_cols(*table->s));
col = &dict_table_get_nth_v_col(index->table, v_no)->m_col;
templ->clust_rec_field_no = v_no;
templ->rec_prefix_field_no = ULINT_UNDEFINED;
@@ -8019,7 +8014,8 @@ no_icp:
contain = dict_index_contains_col_or_prefix(
index, i - num_v,
false);
- } else if (dict_index_is_clust(index)) {
+ } else if (skip_virtual
+ || dict_index_is_clust(index)) {
num_v++;
continue;
} else {
@@ -8521,7 +8517,7 @@ calc_row_difference(
trx_t* const trx = prebuilt->trx;
doc_id_t doc_id = FTS_NULL_DOC_ID;
ulint num_v = 0;
- const bool skip_virtual = omits_virtual_cols(*table->s);
+ const bool skip_virtual = ha_innobase::omits_virtual_cols(*table->s);
ut_ad(!srv_read_only_mode);
@@ -11063,7 +11059,7 @@ create_table_info_t::create_table_def()
/* Find out the number of virtual columns. */
ulint num_v = 0;
- const bool omit_virtual = omits_virtual_cols(*m_form->s);
+ const bool omit_virtual = ha_innobase::omits_virtual_cols(*m_form->s);
const ulint n_cols = omit_virtual
? m_form->s->stored_fields : m_form->s->fields;
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 76a9b08c4c6..9311056bde5 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -22,6 +22,8 @@ this program; if not, write to the Free Software Foundation, Inc.,
# include "../../../wsrep/wsrep_api.h"
#endif /* WITH_WSREP */
+#include "table.h"
+
/* The InnoDB handler: the interface between MySQL and InnoDB. */
/** "GEN_CLUST_INDEX" is the name reserved for InnoDB default
@@ -412,8 +414,15 @@ public:
Item* idx_cond_push(uint keyno, Item* idx_cond);
/* @} */
-protected:
+ /** Check if InnoDB is not storing virtual column metadata for a table.
+ @param s table definition (based on .frm file)
+ @return whether InnoDB will omit virtual column metadata */
+ static bool omits_virtual_cols(const TABLE_SHARE& s)
+ {
+ return s.frm_version<FRM_VER_EXPRESSSIONS && s.virtual_fields;
+ }
+protected:
/**
MySQL calls this method at the end of each statement. This method
exists for readability only, called from reset(). The name reset()
@@ -430,7 +439,6 @@ protected:
@see build_template() */
void reset_template();
-protected:
inline void update_thd(THD* thd);
void update_thd();
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 095fad367b3..3faf62479ff 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -3036,7 +3036,8 @@ innobase_build_col_map(
>= altered_table->s->fields + DATA_N_SYS_COLS);
DBUG_ASSERT(dict_table_get_n_cols(old_table)
+ dict_table_get_n_v_cols(old_table)
- >= table->s->fields + DATA_N_SYS_COLS);
+ >= table->s->fields + DATA_N_SYS_COLS
+ || ha_innobase::omits_virtual_cols(*table->s));
DBUG_ASSERT(!!add_cols == !!(ha_alter_info->handler_flags
& Alter_inplace_info::ADD_COLUMN));
DBUG_ASSERT(!add_cols || dtuple_get_n_fields(add_cols)