summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin/row/row0umod.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innodb_plugin/row/row0umod.c')
-rw-r--r--storage/innodb_plugin/row/row0umod.c815
1 files changed, 0 insertions, 815 deletions
diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c
deleted file mode 100644
index 6be475d8c78..00000000000
--- a/storage/innodb_plugin/row/row0umod.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file row/row0umod.c
-Undo modify of a row
-
-Created 2/27/1997 Heikki Tuuri
-*******************************************************/
-
-#include "row0umod.h"
-
-#ifdef UNIV_NONINL
-#include "row0umod.ic"
-#endif
-
-#include "dict0dict.h"
-#include "dict0boot.h"
-#include "trx0undo.h"
-#include "trx0roll.h"
-#include "btr0btr.h"
-#include "mach0data.h"
-#include "row0undo.h"
-#include "row0vers.h"
-#include "trx0trx.h"
-#include "trx0rec.h"
-#include "row0row.h"
-#include "row0upd.h"
-#include "que0que.h"
-#include "log0log.h"
-
-/* Considerations on undoing a modify operation.
-(1) Undoing a delete marking: all index records should be found. Some of
-them may have delete mark already FALSE, if the delete mark operation was
-stopped underway, or if the undo operation ended prematurely because of a
-system crash.
-(2) Undoing an update of a delete unmarked record: the newer version of
-an updated secondary index entry should be removed if no prior version
-of the clustered index record requires its existence. Otherwise, it should
-be delete marked.
-(3) Undoing an update of a delete marked record. In this kind of update a
-delete marked clustered index record was delete unmarked and possibly also
-some of its fields were changed. Now, it is possible that the delete marked
-version has become obsolete at the time the undo is started. */
-
-/***********************************************************//**
-Checks if also the previous version of the clustered index record was
-modified or inserted by the same transaction, and its undo number is such
-that it should be undone in the same rollback.
-@return TRUE if also previous modify or insert of this row should be undone */
-UNIV_INLINE
-ibool
-row_undo_mod_undo_also_prev_vers(
-/*=============================*/
- undo_node_t* node, /*!< in: row undo node */
- undo_no_t* undo_no)/*!< out: the undo number */
-{
- trx_undo_rec_t* undo_rec;
- trx_t* trx;
-
- trx = node->trx;
-
- if (0 != ut_dulint_cmp(node->new_trx_id, trx->id)) {
-
- *undo_no = ut_dulint_zero;
- return(FALSE);
- }
-
- undo_rec = trx_undo_get_undo_rec_low(node->new_roll_ptr, node->heap);
-
- *undo_no = trx_undo_rec_get_undo_no(undo_rec);
-
- return(ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0);
-}
-
-/***********************************************************//**
-Undoes a modify in a clustered index record.
-@return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */
-static
-ulint
-row_undo_mod_clust_low(
-/*===================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr, /*!< in: mtr; must be committed before
- latching any further pages */
- ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
-{
- btr_pcur_t* pcur;
- btr_cur_t* btr_cur;
- ulint err;
- ibool success;
-
- pcur = &(node->pcur);
- btr_cur = btr_pcur_get_btr_cur(pcur);
-
- success = btr_pcur_restore_position(mode, pcur, mtr);
-
- ut_ad(success);
-
- if (mode == BTR_MODIFY_LEAF) {
-
- err = btr_cur_optimistic_update(BTR_NO_LOCKING_FLAG
- | BTR_NO_UNDO_LOG_FLAG
- | BTR_KEEP_SYS_FLAG,
- btr_cur, node->update,
- node->cmpl_info, thr, mtr);
- } else {
- mem_heap_t* heap = NULL;
- big_rec_t* dummy_big_rec;
-
- ut_ad(mode == BTR_MODIFY_TREE);
-
- err = btr_cur_pessimistic_update(
- BTR_NO_LOCKING_FLAG
- | BTR_NO_UNDO_LOG_FLAG
- | BTR_KEEP_SYS_FLAG,
- btr_cur, &heap, &dummy_big_rec, node->update,
- node->cmpl_info, thr, mtr);
-
- ut_a(!dummy_big_rec);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- }
-
- return(err);
-}
-
-/***********************************************************//**
-Removes a clustered index record after undo if possible.
-@return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */
-static
-ulint
-row_undo_mod_remove_clust_low(
-/*==========================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr __attribute__((unused)), /*!< in: query thread */
- mtr_t* mtr, /*!< in: mtr */
- ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
-{
- btr_pcur_t* pcur;
- btr_cur_t* btr_cur;
- ulint err;
- ibool success;
-
- pcur = &(node->pcur);
- btr_cur = btr_pcur_get_btr_cur(pcur);
-
- success = btr_pcur_restore_position(mode, pcur, mtr);
-
- if (!success) {
-
- return(DB_SUCCESS);
- }
-
- /* Find out if we can remove the whole clustered index record */
-
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC
- && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
-
- /* Ok, we can remove */
- } else {
- return(DB_SUCCESS);
- }
-
- if (mode == BTR_MODIFY_LEAF) {
- success = btr_cur_optimistic_delete(btr_cur, mtr);
-
- if (success) {
- err = DB_SUCCESS;
- } else {
- err = DB_FAIL;
- }
- } else {
- ut_ad(mode == BTR_MODIFY_TREE);
-
- /* Note that since this operation is analogous to purge,
- we can free also inherited externally stored fields:
- hence the RB_NONE in the call below */
-
- btr_cur_pessimistic_delete(&err, FALSE, btr_cur, RB_NONE, mtr);
-
- /* The delete operation may fail if we have little
- file space left: TODO: easiest to crash the database
- and restart with more file space */
- }
-
- return(err);
-}
-
-/***********************************************************//**
-Undoes a modify in a clustered index record. Sets also the node state for the
-next round of undo.
-@return DB_SUCCESS or error code: we may run out of file space */
-static
-ulint
-row_undo_mod_clust(
-/*===============*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr) /*!< in: query thread */
-{
- btr_pcur_t* pcur;
- mtr_t mtr;
- ulint err;
- ibool success;
- ibool more_vers;
- undo_no_t new_undo_no;
-
- ut_ad(node && thr);
-
- /* Check if also the previous version of the clustered index record
- should be undone in this same rollback operation */
-
- more_vers = row_undo_mod_undo_also_prev_vers(node, &new_undo_no);
-
- pcur = &(node->pcur);
-
- mtr_start(&mtr);
-
- /* Try optimistic processing of the record, keeping changes within
- the index page */
-
- err = row_undo_mod_clust_low(node, thr, &mtr, BTR_MODIFY_LEAF);
-
- if (err != DB_SUCCESS) {
- btr_pcur_commit_specify_mtr(pcur, &mtr);
-
- /* We may have to modify tree structure: do a pessimistic
- descent down the index tree */
-
- mtr_start(&mtr);
-
- err = row_undo_mod_clust_low(node, thr, &mtr, BTR_MODIFY_TREE);
- }
-
- btr_pcur_commit_specify_mtr(pcur, &mtr);
-
- if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_UPD_DEL_REC) {
-
- mtr_start(&mtr);
-
- err = row_undo_mod_remove_clust_low(node, thr, &mtr,
- BTR_MODIFY_LEAF);
- if (err != DB_SUCCESS) {
- btr_pcur_commit_specify_mtr(pcur, &mtr);
-
- /* We may have to modify tree structure: do a
- pessimistic descent down the index tree */
-
- mtr_start(&mtr);
-
- err = row_undo_mod_remove_clust_low(node, thr, &mtr,
- BTR_MODIFY_TREE);
- }
-
- btr_pcur_commit_specify_mtr(pcur, &mtr);
- }
-
- node->state = UNDO_NODE_FETCH_NEXT;
-
- trx_undo_rec_release(node->trx, node->undo_no);
-
- if (more_vers && err == DB_SUCCESS) {
-
- /* Reserve the undo log record to the prior version after
- committing &mtr: this is necessary to comply with the latching
- order, as &mtr may contain the fsp latch which is lower in
- the latch hierarchy than trx->undo_mutex. */
-
- success = trx_undo_rec_reserve(node->trx, new_undo_no);
-
- if (success) {
- node->state = UNDO_NODE_PREV_VERS;
- }
- }
-
- return(err);
-}
-
-/***********************************************************//**
-Delete marks or removes a secondary index entry if found.
-@return DB_SUCCESS, DB_FAIL, or DB_OUT_OF_FILE_SPACE */
-static
-ulint
-row_undo_mod_del_mark_or_remove_sec_low(
-/*====================================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr, /*!< in: query thread */
- dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry */
- ulint mode) /*!< in: latch mode BTR_MODIFY_LEAF or
- BTR_MODIFY_TREE */
-{
- ibool found;
- btr_pcur_t pcur;
- btr_cur_t* btr_cur;
- ibool success;
- ibool old_has;
- ulint err;
- mtr_t mtr;
- mtr_t mtr_vers;
-
- log_free_check();
- mtr_start(&mtr);
-
- found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
-
- btr_cur = btr_pcur_get_btr_cur(&pcur);
-
- if (!found) {
- /* In crash recovery, the secondary index record may
- be missing if the UPDATE did not have time to insert
- the secondary index records before the crash. When we
- are undoing that UPDATE in crash recovery, the record
- may be missing.
-
- In normal processing, if an update ends in a deadlock
- before it has inserted all updated secondary index
- records, then the undo will not find those records. */
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(DB_SUCCESS);
- }
-
- /* We should remove the index record if no prior version of the row,
- which cannot be purged yet, requires its existence. If some requires,
- we should delete mark the record. */
-
- mtr_start(&mtr_vers);
-
- success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur),
- &mtr_vers);
- ut_a(success);
-
- old_has = row_vers_old_has_index_entry(FALSE,
- btr_pcur_get_rec(&(node->pcur)),
- &mtr_vers, index, entry);
- if (old_has) {
- err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, TRUE, thr, &mtr);
- ut_ad(err == DB_SUCCESS);
- } else {
- /* Remove the index record */
-
- if (mode == BTR_MODIFY_LEAF) {
- success = btr_cur_optimistic_delete(btr_cur, &mtr);
- if (success) {
- err = DB_SUCCESS;
- } else {
- err = DB_FAIL;
- }
- } else {
- ut_ad(mode == BTR_MODIFY_TREE);
-
- /* No need to distinguish RB_RECOVERY here, because we
- are deleting a secondary index record: the distinction
- between RB_NORMAL and RB_RECOVERY only matters when
- deleting a record that contains externally stored
- columns. */
- ut_ad(!dict_index_is_clust(index));
- btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
- RB_NORMAL, &mtr);
-
- /* The delete operation may fail if we have little
- file space left: TODO: easiest to crash the database
- and restart with more file space */
- }
- }
-
- btr_pcur_commit_specify_mtr(&(node->pcur), &mtr_vers);
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(err);
-}
-
-/***********************************************************//**
-Delete marks or removes a secondary index entry if found.
-NOTE that if we updated the fields of a delete-marked secondary index record
-so that alphabetically they stayed the same, e.g., 'abc' -> 'aBc', we cannot
-return to the original values because we do not know them. But this should
-not cause problems because in row0sel.c, in queries we always retrieve the
-clustered index record or an earlier version of it, if the secondary index
-record through which we do the search is delete-marked.
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-static
-ulint
-row_undo_mod_del_mark_or_remove_sec(
-/*================================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr, /*!< in: query thread */
- dict_index_t* index, /*!< in: index */
- dtuple_t* entry) /*!< in: index entry */
-{
- ulint err;
-
- err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
- entry, BTR_MODIFY_LEAF);
- if (err == DB_SUCCESS) {
-
- return(err);
- }
-
- err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
- entry, BTR_MODIFY_TREE);
- return(err);
-}
-
-/***********************************************************//**
-Delete unmarks a secondary index entry which must be found. It might not be
-delete-marked at the moment, but it does not harm to unmark it anyway. We also
-need to update the fields of the secondary index record if we updated its
-fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'.
-@return DB_FAIL or DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-static
-ulint
-row_undo_mod_del_unmark_sec_and_undo_update(
-/*========================================*/
- ulint mode, /*!< in: search mode: BTR_MODIFY_LEAF or
- BTR_MODIFY_TREE */
- que_thr_t* thr, /*!< in: query thread */
- dict_index_t* index, /*!< in: index */
- dtuple_t* entry) /*!< in: index entry */
-{
- mem_heap_t* heap;
- btr_pcur_t pcur;
- upd_t* update;
- ulint err = DB_SUCCESS;
- big_rec_t* dummy_big_rec;
- mtr_t mtr;
- trx_t* trx = thr_get_trx(thr);
-
- /* Ignore indexes that are being created. */
- if (UNIV_UNLIKELY(*index->name == TEMP_INDEX_PREFIX)) {
-
- return(DB_SUCCESS);
- }
-
- log_free_check();
- mtr_start(&mtr);
-
- if (UNIV_UNLIKELY(!row_search_index_entry(index, entry,
- mode, &pcur, &mtr))) {
- fputs("InnoDB: error in sec index entry del undo in\n"
- "InnoDB: ", stderr);
- dict_index_name_print(stderr, trx, index);
- fputs("\n"
- "InnoDB: tuple ", stderr);
- dtuple_print(stderr, entry);
- fputs("\n"
- "InnoDB: record ", stderr);
- rec_print(stderr, btr_pcur_get_rec(&pcur), index);
- putc('\n', stderr);
- trx_print(stderr, trx, 0);
- fputs("\n"
- "InnoDB: Submit a detailed bug report"
- " to http://bugs.mysql.com\n", stderr);
- } else {
- btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);
-
- err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, FALSE, thr, &mtr);
- ut_a(err == DB_SUCCESS);
- heap = mem_heap_create(100);
-
- update = row_upd_build_sec_rec_difference_binary(
- index, entry, btr_cur_get_rec(btr_cur), trx, heap);
- if (upd_get_n_fields(update) == 0) {
-
- /* Do nothing */
-
- } else if (mode == BTR_MODIFY_LEAF) {
- /* Try an optimistic updating of the record, keeping
- changes within the page */
-
- err = btr_cur_optimistic_update(
- BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG,
- btr_cur, update, 0, thr, &mtr);
- switch (err) {
- case DB_OVERFLOW:
- case DB_UNDERFLOW:
- case DB_ZIP_OVERFLOW:
- err = DB_FAIL;
- }
- } else {
- ut_a(mode == BTR_MODIFY_TREE);
- err = btr_cur_pessimistic_update(
- BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG,
- btr_cur, &heap, &dummy_big_rec,
- update, 0, thr, &mtr);
- ut_a(!dummy_big_rec);
- }
-
- mem_heap_free(heap);
- }
-
- btr_pcur_close(&pcur);
- mtr_commit(&mtr);
-
- return(err);
-}
-
-/***********************************************************//**
-Undoes a modify in secondary indexes when undo record type is UPD_DEL.
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-static
-ulint
-row_undo_mod_upd_del_sec(
-/*=====================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr) /*!< in: query thread */
-{
- mem_heap_t* heap;
- dtuple_t* entry;
- dict_index_t* index;
- ulint err = DB_SUCCESS;
-
- heap = mem_heap_create(1024);
-
- while (node->index != NULL) {
- index = node->index;
-
- entry = row_build_index_entry(node->row, node->ext,
- index, heap);
- if (UNIV_UNLIKELY(!entry)) {
- /* The database must have crashed after
- inserting a clustered index record but before
- writing all the externally stored columns of
- that record. Because secondary index entries
- are inserted after the clustered index record,
- we may assume that the secondary index record
- does not exist. However, this situation may
- only occur during the rollback of incomplete
- transactions. */
- ut_a(trx_is_recv(thr_get_trx(thr)));
- } else {
- err = row_undo_mod_del_mark_or_remove_sec(
- node, thr, index, entry);
-
- if (err != DB_SUCCESS) {
-
- break;
- }
- }
-
- mem_heap_empty(heap);
-
- node->index = dict_table_get_next_index(node->index);
- }
-
- mem_heap_free(heap);
-
- return(err);
-}
-
-/***********************************************************//**
-Undoes a modify in secondary indexes when undo record type is DEL_MARK.
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-static
-ulint
-row_undo_mod_del_mark_sec(
-/*======================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr) /*!< in: query thread */
-{
- mem_heap_t* heap;
- dtuple_t* entry;
- dict_index_t* index;
- ulint err;
-
- heap = mem_heap_create(1024);
-
- while (node->index != NULL) {
- index = node->index;
-
- entry = row_build_index_entry(node->row, node->ext,
- index, heap);
- ut_a(entry);
- err = row_undo_mod_del_unmark_sec_and_undo_update(
- BTR_MODIFY_LEAF, thr, index, entry);
- if (err == DB_FAIL) {
- err = row_undo_mod_del_unmark_sec_and_undo_update(
- BTR_MODIFY_TREE, thr, index, entry);
- }
-
- if (err != DB_SUCCESS) {
-
- mem_heap_free(heap);
-
- return(err);
- }
-
- node->index = dict_table_get_next_index(node->index);
- }
-
- mem_heap_free(heap);
-
- return(DB_SUCCESS);
-}
-
-/***********************************************************//**
-Undoes a modify in secondary indexes when undo record type is UPD_EXIST.
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-static
-ulint
-row_undo_mod_upd_exist_sec(
-/*=======================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr) /*!< in: query thread */
-{
- mem_heap_t* heap;
- dtuple_t* entry;
- dict_index_t* index;
- ulint err;
-
- if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) {
- /* No change in secondary indexes */
-
- return(DB_SUCCESS);
- }
-
- heap = mem_heap_create(1024);
-
- while (node->index != NULL) {
- index = node->index;
-
- if (row_upd_changes_ord_field_binary(node->row, node->index,
- node->update)) {
-
- /* Build the newest version of the index entry */
- entry = row_build_index_entry(node->row, node->ext,
- index, heap);
- ut_a(entry);
- /* NOTE that if we updated the fields of a
- delete-marked secondary index record so that
- alphabetically they stayed the same, e.g.,
- 'abc' -> 'aBc', we cannot return to the original
- values because we do not know them. But this should
- not cause problems because in row0sel.c, in queries
- we always retrieve the clustered index record or an
- earlier version of it, if the secondary index record
- through which we do the search is delete-marked. */
-
- err = row_undo_mod_del_mark_or_remove_sec(node, thr,
- index,
- entry);
- if (err != DB_SUCCESS) {
- mem_heap_free(heap);
-
- return(err);
- }
-
- /* We may have to update the delete mark in the
- secondary index record of the previous version of
- the row. We also need to update the fields of
- the secondary index record if we updated its fields
- but alphabetically they stayed the same, e.g.,
- 'abc' -> 'aBc'. */
- mem_heap_empty(heap);
- entry = row_build_index_entry(node->undo_row,
- node->undo_ext,
- index, heap);
- ut_a(entry);
-
- err = row_undo_mod_del_unmark_sec_and_undo_update(
- BTR_MODIFY_LEAF, thr, index, entry);
- if (err == DB_FAIL) {
- err = row_undo_mod_del_unmark_sec_and_undo_update(
- BTR_MODIFY_TREE, thr, index, entry);
- }
-
- if (err != DB_SUCCESS) {
- mem_heap_free(heap);
-
- return(err);
- }
- }
-
- node->index = dict_table_get_next_index(node->index);
- }
-
- mem_heap_free(heap);
-
- return(DB_SUCCESS);
-}
-
-/***********************************************************//**
-Parses the row reference and other info in a modify undo log record. */
-static
-void
-row_undo_mod_parse_undo_rec(
-/*========================*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr) /*!< in: query thread */
-{
- dict_index_t* clust_index;
- byte* ptr;
- undo_no_t undo_no;
- dulint table_id;
- trx_id_t trx_id;
- roll_ptr_t roll_ptr;
- ulint info_bits;
- ulint type;
- ulint cmpl_info;
- ibool dummy_extern;
- trx_t* trx;
-
- ut_ad(node && thr);
- trx = thr_get_trx(thr);
- ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
- &dummy_extern, &undo_no, &table_id);
- node->rec_type = type;
-
- node->table = dict_table_get_on_id(table_id, trx);
-
- /* TODO: other fixes associated with DROP TABLE + rollback in the
- same table by another user */
-
- if (node->table == NULL) {
- /* Table was dropped */
- return;
- }
-
- if (node->table->ibd_file_missing) {
- /* We skip undo operations to missing .ibd files */
- node->table = NULL;
-
- return;
- }
-
- clust_index = dict_table_get_first_index(node->table);
-
- ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr,
- &info_bits);
-
- ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
- node->heap);
-
- trx_undo_update_rec_get_update(ptr, clust_index, type, trx_id,
- roll_ptr, info_bits, trx,
- node->heap, &(node->update));
- node->new_roll_ptr = roll_ptr;
- node->new_trx_id = trx_id;
- node->cmpl_info = cmpl_info;
-}
-
-/***********************************************************//**
-Undoes a modify operation on a row of a table.
-@return DB_SUCCESS or error code */
-UNIV_INTERN
-ulint
-row_undo_mod(
-/*=========*/
- undo_node_t* node, /*!< in: row undo node */
- que_thr_t* thr) /*!< in: query thread */
-{
- ulint err;
-
- ut_ad(node && thr);
- ut_ad(node->state == UNDO_NODE_MODIFY);
-
- row_undo_mod_parse_undo_rec(node, thr);
-
- if (!node->table || !row_undo_search_clust_to_pcur(node)) {
- /* It is already undone, or will be undone by another query
- thread, or table was dropped */
-
- trx_undo_rec_release(node->trx, node->undo_no);
- node->state = UNDO_NODE_FETCH_NEXT;
-
- return(DB_SUCCESS);
- }
-
- node->index = dict_table_get_next_index(
- dict_table_get_first_index(node->table));
-
- if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
-
- err = row_undo_mod_upd_exist_sec(node, thr);
-
- } else if (node->rec_type == TRX_UNDO_DEL_MARK_REC) {
-
- err = row_undo_mod_del_mark_sec(node, thr);
- } else {
- ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
- err = row_undo_mod_upd_del_sec(node, thr);
- }
-
- if (err != DB_SUCCESS) {
-
- return(err);
- }
-
- err = row_undo_mod_clust(node, thr);
-
- return(err);
-}