From aa8a31dadd21ada93bc3c739de866c78614e746a Mon Sep 17 00:00:00 2001 From: Aditya A Date: Wed, 10 Oct 2018 18:05:02 +0530 Subject: [PATCH] Bug #22990029 GCOLS: INCORRECT BEHAVIOR AFTER DATA INSERTED WITH IGNORE KEYWORD PROBLEM ------- 1. We are inserting a base column entry which causes an invalid value by the function provided to generate virtual column,but we go ahead and insert this due to ignore keyword. 2. We then delete this record, making this record delete marked in innodb. If we try to insert another record with the same pk as the deleted record and if the rec is not purged ,then we try to undelete mark this record and try to build a update vector with previous and updated value and while calculating the value of virtual column we get error from server that we cannot calculate this from base column. Innodb assumes that innobase_get_computed_value() Should always return a valid value for the base column present in the row. The failure of this call was not handled ,so we were crashing. FIX --- storage/innobase/include/row0upd.h | 8 +++++--- storage/innobase/row/row0ins.cc | 8 ++++++-- storage/innobase/row/row0log.cc | 5 ++++- storage/innobase/row/row0upd.cc | 10 ++++++++-- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 9686f8d6896..5e75eea00df 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -219,6 +219,7 @@ the equal ordering fields. NOTE: we compare the fields as binary strings! @param[in] heap memory heap from which allocated @param[in,out] mysql_table NULL, or mysql table object when user thread invokes dml +@param[out] error error number in case of failure @return own: update vector of differing fields, excluding roll ptr and trx id */ upd_t* @@ -230,8 +231,9 @@ row_upd_build_difference_binary( bool no_sys, trx_t* trx, mem_heap_t* heap, - TABLE* mysql_table) - MY_ATTRIBUTE((nonnull(1,2,3,7), warn_unused_result)); + TABLE* mysql_table, + dberr_t* error) + MY_ATTRIBUTE((nonnull(1,2,3,7,9), warn_unused_result)); /***********************************************************//** Replaces the new column values stored in the update vector to the index entry given. */ diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 2db545973a3..e60e350b9f6 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -326,7 +326,7 @@ row_ins_clust_index_entry_by_modify( { const rec_t* rec; upd_t* update; - dberr_t err; + dberr_t err = DB_SUCCESS; btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur); TABLE* mysql_table = NULL; ut_ad(dict_index_is_clust(cursor->index)); @@ -349,7 +349,11 @@ row_ins_clust_index_entry_by_modify( update = row_upd_build_difference_binary( cursor->index, entry, rec, NULL, true, - thr_get_trx(thr), heap, mysql_table); + thr_get_trx(thr), heap, mysql_table, &err); + if (err != DB_SUCCESS) { + return(err); + } + if (mode != BTR_MODIFY_TREE) { ut_ad((mode & ~BTR_ALREADY_S_LATCHED) == BTR_MODIFY_LEAF); diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 16a71fbe896..d5581f4f48d 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -2042,7 +2042,10 @@ func_exit_committed: row, NULL, index, heap, ROW_BUILD_NORMAL); upd_t* update = row_upd_build_difference_binary( index, entry, btr_pcur_get_rec(&pcur), cur_offsets, - false, NULL, heap, dup->table); + false, NULL, heap, dup->table, &error); + if (error != DB_SUCCESS) { + goto func_exit; + } if (!update->n_fields) { /* Nothing to do. */ diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index ccb18cb843b..1a27ab80b35 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1036,8 +1036,9 @@ the equal ordering fields. NOTE: we compare the fields as binary strings! @param[in] heap memory heap from which allocated @param[in] mysql_table NULL, or mysql table object when user thread invokes dml +@param[out] error error number in case of failure @return own: update vector of differing fields, excluding roll ptr and -trx id */ +trx id,if error is not equal to DB_SUCCESS, return NULL */ upd_t* row_upd_build_difference_binary( dict_index_t* index, @@ -1047,7 +1048,8 @@ row_upd_build_difference_binary( bool no_sys, trx_t* trx, mem_heap_t* heap, - TABLE* mysql_table) + TABLE* mysql_table, + dberr_t* error) { upd_field_t* upd_field; dfield_t* dfield; @@ -1159,6 +1161,10 @@ row_upd_build_difference_binary( update->old_vrow, col, index, &v_heap, heap, NULL, thd, mysql_table, record, NULL, NULL, NULL); + if (vfield == NULL) { + *error = DB_COMPUTE_VALUE_FAILED; + return(NULL); + } if (!dfield_data_is_binary_equal( dfield, vfield->len,