diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-10-27 18:37:33 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-10-28 07:32:27 +0300 |
commit | 1f5ca66e53b165c29ea733acd0fab79975a43eda (patch) | |
tree | 2552b55cb6a1e16cfa2a8648520adba9160c525a /storage/innobase/handler | |
parent | 3a9967d7579a31e5a43606d563584335348caaa5 (diff) | |
download | mariadb-git-1f5ca66e53b165c29ea733acd0fab79975a43eda.tar.gz |
MDEV-26866 FOREIGN KEY…SET NULL corrupts an index on a virtual column
The initial test case for MySQL Bug #33053297 is based on
mysql/mysql-server@27130e25078864b010d81266f9613d389d4a229b.
innobase_get_field_from_update_vector is not a suitable function to fetch
updated row info, as well as parent table's update vector is not always
suitable. For instance, in case of DELETE it contains undefined data.
castade->update vector seems to be good enough to fetch all base columns
update data, and besides faster, and less error-prone.
Diffstat (limited to 'storage/innobase/handler')
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 64 |
1 files changed, 13 insertions, 51 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 91d245ad0e2..37748cb497a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -21795,48 +21795,6 @@ innobase_rename_vc_templ( table->vc_templ->tb_name = t_tbname; } -/** Get the updated parent field value from the update vector for the -given col_no. -@param[in] foreign foreign key information -@param[in] update updated parent vector. -@param[in] col_no base column position of the child table to check -@return updated field from the parent update vector, else NULL */ -static -dfield_t* -innobase_get_field_from_update_vector( - dict_foreign_t* foreign, - upd_t* update, - ulint col_no) -{ - dict_table_t* parent_table = foreign->referenced_table; - dict_index_t* parent_index = foreign->referenced_index; - ulint parent_field_no; - ulint parent_col_no; - ulint prefix_col_no; - - for (ulint i = 0; i < foreign->n_fields; i++) { - if (dict_index_get_nth_col_no(foreign->foreign_index, i) - != col_no) { - continue; - } - - parent_col_no = dict_index_get_nth_col_no(parent_index, i); - parent_field_no = dict_table_get_nth_col_pos( - parent_table, parent_col_no, &prefix_col_no); - - for (ulint j = 0; j < update->n_fields; j++) { - upd_field_t* parent_ufield - = &update->fields[j]; - - if (parent_ufield->field_no == parent_field_no) { - return(&parent_ufield->new_val); - } - } - } - - return (NULL); -} - /** Allocate a heap and record for calculating virtual fields @@ -21919,9 +21877,10 @@ void innobase_report_computed_value_failed(dtuple_t *row) @param[in] ifield index field @param[in] thd MySQL thread handle @param[in,out] mysql_table mysql table object +@param[in,out] mysql_rec MariaDB record buffer @param[in] old_table during ALTER TABLE, this is the old table or NULL. -@param[in] parent_update update vector for the parent row +@param[in] update update vector for the row, if any @param[in] foreign foreign key information @return the field filled with computed value, or NULL if just want to store the value in passed in "my_rec" */ @@ -21937,8 +21896,7 @@ innobase_get_computed_value( TABLE* mysql_table, byte* mysql_rec, const dict_table_t* old_table, - upd_t* parent_update, - dict_foreign_t* foreign) + const upd_t* update) { byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN]; byte* buf; @@ -21951,6 +21909,8 @@ innobase_get_computed_value( ulint ret = 0; + dict_index_t *clust_index= dict_table_get_first_index(index->table); + ut_ad(index->table->vc_templ); ut_ad(thd != NULL); ut_ad(mysql_table); @@ -21980,14 +21940,16 @@ innobase_get_computed_value( = index->table->vc_templ->vtempl[col_no]; const byte* data; - if (parent_update != NULL) { - /** Get the updated field from update vector - of the parent table. */ - row_field = innobase_get_field_from_update_vector( - foreign, parent_update, col_no); + if (update) { + ulint clust_no = dict_col_get_clust_pos(base_col, + clust_index); + if (const upd_field_t *uf = upd_get_field_by_field_no( + update, clust_no, false)) { + row_field = &uf->new_val; + } } - if (row_field == NULL) { + if (!row_field) { row_field = dtuple_get_nth_field(row, col_no); } |