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/row | |
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/row')
-rw-r--r-- | storage/innobase/row/row0ins.cc | 15 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.cc | 4 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0upd.cc | 5 | ||||
-rw-r--r-- | storage/innobase/row/row0vers.cc | 2 |
5 files changed, 13 insertions, 15 deletions
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 929d3683ce6..cbe6577c02a 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -898,7 +898,6 @@ row_ins_invalidate_query_cache( innobase_invalidate_query_cache(thr_get_trx(thr), name, len); } - /** Fill virtual column information in cascade node for the child table. @param[out] cascade child update node @param[in] rec clustered rec of child table @@ -945,6 +944,11 @@ row_ins_foreign_fill_virtual( if (!record) { return DB_OUT_OF_MEMORY; } + ut_ad(!node->is_delete + || (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)); + ut_ad(foreign->type & (DICT_FOREIGN_ON_DELETE_SET_NULL + | DICT_FOREIGN_ON_UPDATE_SET_NULL + | DICT_FOREIGN_ON_UPDATE_CASCADE)); for (ulint i = 0; i < n_v_fld; i++) { @@ -960,7 +964,7 @@ row_ins_foreign_fill_virtual( dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, update->heap, NULL, thd, mysql_table, - record, NULL, NULL, NULL); + record, NULL, NULL); if (vfield == NULL) { return DB_COMPUTE_VALUE_FAILED; @@ -976,16 +980,11 @@ row_ins_foreign_fill_virtual( upd_field_set_v_field_no(upd_field, i, index); - bool set_null = - node->is_delete - ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) - : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL); - dfield_t* new_vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, update->heap, NULL, thd, mysql_table, record, NULL, - set_null ? update : node->update, foreign); + update); if (new_vfield == NULL) { return DB_COMPUTE_VALUE_FAILED; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 9e6179585b1..faa148cca24 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -600,8 +600,8 @@ error: row_field = innobase_get_computed_value( row, v_col, clust_index, v_heap, NULL, ifield, trx->mysql_thd, - my_table, vcol_storage.innobase_record, - old_table, NULL, NULL); + my_table, vcol_storage.innobase_record, + old_table, NULL); if (row_field == NULL) { *err = DB_COMPUTE_VALUE_FAILED; diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 83bf18ab9b8..87c67edff4b 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -328,7 +328,7 @@ row_sel_sec_rec_is_for_clust_rec( &heap, NULL, NULL, thr_get_trx(thr)->mysql_thd, thr->prebuilt->m_mysql_table, - record, NULL, NULL, NULL); + record, NULL, NULL); if (vfield == NULL) { innobase_report_computed_value_failed(row); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index a58c3993e90..0a79225da8c 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1149,7 +1149,7 @@ row_upd_build_difference_binary( dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, heap, NULL, thd, mysql_table, record, - NULL, NULL, NULL); + NULL, NULL); if (vfield == NULL) { *error = DB_COMPUTE_VALUE_FAILED; return(NULL); @@ -2175,8 +2175,7 @@ row_upd_store_v_row( node->row, col, index, &vc.heap, node->heap, NULL, thd, mysql_table, - record, NULL, NULL, - NULL); + record, NULL, NULL); if (vfield == NULL) { return false; } diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index b9bc8418366..bf229966525 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -491,7 +491,7 @@ row_vers_build_clust_v_col( dfield_t *vfield = innobase_get_computed_value( row, col, clust_index, &vc.heap, heap, NULL, thd, maria_table, record, NULL, - NULL, NULL); + NULL); if (vfield == NULL) { innobase_report_computed_value_failed(row); ut_ad(0); |