From 1f5ca66e53b165c29ea733acd0fab79975a43eda Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Wed, 27 Oct 2021 18:37:33 +0300 Subject: =?UTF-8?q?MDEV-26866=20FOREIGN=20KEY=E2=80=A6SET=20NULL=20corrupt?= =?UTF-8?q?s=20an=20index=20on=20a=20virtual=20column?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- storage/innobase/handler/ha_innodb.cc | 64 +++++++---------------------------- 1 file changed, 13 insertions(+), 51 deletions(-) (limited to 'storage/innobase/handler') 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); } -- cgit v1.2.1