From ffecaa0c77e93573b2c2205c66710cc3a359993b Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sat, 6 Jun 2020 10:44:32 +0300 Subject: MDEV-20661 Virtual fields are not recalculated on system fields value assignment --- sql/sql_insert.cc | 4 ++++ sql/table.cc | 28 +++++++++++++--------------- storage/innobase/include/row0upd.h | 22 ++++++++++++++++++++++ storage/innobase/row/row0mysql.cc | 23 +++++++++++++++++++++++ storage/innobase/row/row0upd.cc | 16 +++++++++++++++- 5 files changed, 77 insertions(+), 16 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 807dd94c6f0..8d0e08d8c8c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1682,6 +1682,10 @@ int vers_insert_history_row(TABLE *table) if (row_start->cmp(row_start->ptr, row_end->ptr) >= 0) return 0; + if (table->vfield && + table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_READ)) + return HA_ERR_GENERIC; + return table->file->ha_write_row(table->record[0]); } diff --git a/sql/table.cc b/sql/table.cc index a4de5d9c930..a6dfa409975 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8547,29 +8547,27 @@ void TABLE::vers_update_fields() bitmap_set_bit(write_set, vers_start_field()->field_index); bitmap_set_bit(write_set, vers_end_field()->field_index); - if (versioned(VERS_TIMESTAMP)) + if (!vers_write) { - if (!vers_write) - { - file->column_bitmaps_signal(); - return; - } - if (vers_start_field()->store_timestamp(in_use->query_start(), - in_use->query_start_sec_part())) - DBUG_ASSERT(0); + file->column_bitmaps_signal(); + return; } - else + + if (versioned(VERS_TIMESTAMP) && + vers_start_field()->store_timestamp(in_use->query_start(), + in_use->query_start_sec_part())) { - if (!vers_write) - { - file->column_bitmaps_signal(); - return; - } + DBUG_ASSERT(0); } vers_end_field()->set_max(); bitmap_set_bit(read_set, vers_end_field()->field_index); file->column_bitmaps_signal(); + if (vfield && + update_virtual_fields(file, VCOL_UPDATE_FOR_READ)) + { + DBUG_ASSERT(0); + } } diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 677af76c561..a367ae7d3eb 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -429,6 +429,28 @@ struct upd_t{ fields[n_fields++] = field; } + void remove_element(ulint i) + { + ut_ad(n_fields > 0); + ut_ad(i < n_fields); + while (i < n_fields - 1) { + fields[i] = fields[i + 1]; + i++; + } + n_fields--; + } + + bool remove(const ulint field_no) + { + for (ulint i = 0; i < n_fields; ++i) { + if (field_no == fields[i].field_no) { + remove_element(i); + return true; + } + } + return false; + } + /** Determine if the given field_no is modified. @return true if modified, false otherwise. */ bool is_modified(const ulint field_no) const diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 4a273cd635e..914641aecfd 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -69,6 +69,8 @@ Created 9/17/2000 Heikki Tuuri #include #include #include +// FIXME: remove +#include #ifdef WITH_WSREP #include "mysql/service_wsrep.h" @@ -1441,6 +1443,27 @@ row_insert_for_mysql( set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf); } + dict_index_t* clust_index = dict_table_get_first_index(table); + THD *thd= trx->mysql_thd; + TABLE *mysql_table = prebuilt->m_mysql_table; + mem_heap_t* local_heap = NULL; + for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(table); + col_no++) { + + const dict_v_col_t* v_col + = dict_table_get_nth_v_col(table, col_no); + for (ulint i = 0; i < unsigned{v_col->num_base}; i++) { + dict_col_t* base_col = v_col->base_col[i]; + if (base_col->ind == table->vers_end) { + innobase_get_computed_value( + node->row, v_col, clust_index, &local_heap, table->heap, NULL, thd, + mysql_table, mysql_table->record[0], NULL, NULL, NULL); + } + } + } + if (local_heap) { + mem_heap_free(local_heap); + } } savept = trx_savept_take(trx); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index b7d396bd5cb..41372c324b4 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -3503,5 +3503,19 @@ void upd_node_t::make_versioned_helper(const trx_t* trx, ulint idx) } dfield_set_data(&ufield->new_val, update->vers_sys_value, col->len); -} + for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(table); + col_no++) { + const dict_v_col_t* v_col + = dict_table_get_nth_v_col(table, col_no); + for (ulint i = 0; i < unsigned{v_col->num_base}; i++) { + dict_col_t* base_col = v_col->base_col[i]; + if (base_col->ind == col->ind) { + /* Virtual column depends on system field value which we updated above. + Remove it from update vector, so it is recalculated in row_upd_store_v_row() (see !update branch). */ + update->remove(v_col->v_pos); + break; + } + } + } +} -- cgit v1.2.1