#include "row0umod.h"#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"Include dependency graph for row0umod.c:

Go to the source code of this file.
| ulint row_undo_mod | ( | undo_node_t * | node, | |
| que_thr_t * | thr | |||
| ) |
Definition at line 711 of file row0umod.c.
References DB_SUCCESS, dict_table_get_first_index(), dict_table_get_next_index(), err, FALSE, undo_node_struct::index, NULL, undo_node_struct::rec_type, row_undo_mod_clust(), row_undo_mod_del_mark_sec(), row_undo_mod_parse_undo_rec(), row_undo_mod_upd_del_sec(), row_undo_mod_upd_exist_sec(), row_undo_search_clust_to_pcur(), undo_node_struct::state, undo_node_struct::table, undo_node_struct::trx, TRX_UNDO_DEL_MARK_REC, trx_undo_rec_release(), TRX_UNDO_UPD_DEL_REC, TRX_UNDO_UPD_EXIST_REC, undo_node_struct::undo_no, UNDO_NODE_FETCH_NEXT, UNDO_NODE_MODIFY, and ut_ad.
Referenced by row_undo().
00713 : DB_SUCCESS or error code */ 00714 undo_node_t* node, /* in: row undo node */ 00715 que_thr_t* thr) /* in: query thread */ 00716 { 00717 ibool found; 00718 ulint err; 00719 00720 ut_ad(node && thr); 00721 ut_ad(node->state == UNDO_NODE_MODIFY); 00722 00723 row_undo_mod_parse_undo_rec(node, thr); 00724 00725 if (node->table == NULL) { 00726 found = FALSE; 00727 } else { 00728 found = row_undo_search_clust_to_pcur(node); 00729 } 00730 00731 if (!found) { 00732 /* It is already undone, or will be undone by another query 00733 thread, or table was dropped */ 00734 00735 trx_undo_rec_release(node->trx, node->undo_no); 00736 node->state = UNDO_NODE_FETCH_NEXT; 00737 00738 return(DB_SUCCESS); 00739 } 00740 00741 node->index = dict_table_get_next_index( 00742 dict_table_get_first_index(node->table)); 00743 00744 if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { 00745 00746 err = row_undo_mod_upd_exist_sec(node, thr); 00747 00748 } else if (node->rec_type == TRX_UNDO_DEL_MARK_REC) { 00749 00750 err = row_undo_mod_del_mark_sec(node, thr); 00751 } else { 00752 ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); 00753 err = row_undo_mod_upd_del_sec(node, thr); 00754 } 00755 00756 if (err != DB_SUCCESS) { 00757 00758 return(err); 00759 } 00760 00761 err = row_undo_mod_clust(node, thr); 00762 00763 return(err); 00764 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_clust | ( | undo_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 189 of file row0umod.c.
References BTR_MODIFY_LEAF, BTR_MODIFY_TREE, btr_pcur_commit_specify_mtr(), DB_SUCCESS, err, mtr_start(), undo_node_struct::pcur, undo_node_struct::rec_type, row_undo_mod_clust_low(), row_undo_mod_remove_clust_low(), row_undo_mod_undo_also_prev_vers(), undo_node_struct::state, undo_node_struct::trx, trx_undo_rec_release(), trx_undo_rec_reserve(), TRX_UNDO_UPD_DEL_REC, undo_node_struct::undo_no, UNDO_NODE_FETCH_NEXT, UNDO_NODE_PREV_VERS, and ut_ad.
Referenced by row_undo_mod().
00191 : DB_SUCCESS or error code: we may run 00192 out of file space */ 00193 undo_node_t* node, /* in: row undo node */ 00194 que_thr_t* thr) /* in: query thread */ 00195 { 00196 btr_pcur_t* pcur; 00197 mtr_t mtr; 00198 ulint err; 00199 ibool success; 00200 ibool more_vers; 00201 dulint new_undo_no; 00202 00203 ut_ad(node && thr); 00204 00205 /* Check if also the previous version of the clustered index record 00206 should be undone in this same rollback operation */ 00207 00208 more_vers = row_undo_mod_undo_also_prev_vers(node, &new_undo_no); 00209 00210 pcur = &(node->pcur); 00211 00212 mtr_start(&mtr); 00213 00214 /* Try optimistic processing of the record, keeping changes within 00215 the index page */ 00216 00217 err = row_undo_mod_clust_low(node, thr, &mtr, BTR_MODIFY_LEAF); 00218 00219 if (err != DB_SUCCESS) { 00220 btr_pcur_commit_specify_mtr(pcur, &mtr); 00221 00222 /* We may have to modify tree structure: do a pessimistic 00223 descent down the index tree */ 00224 00225 mtr_start(&mtr); 00226 00227 err = row_undo_mod_clust_low(node, thr, &mtr, BTR_MODIFY_TREE); 00228 } 00229 00230 btr_pcur_commit_specify_mtr(pcur, &mtr); 00231 00232 if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_UPD_DEL_REC) { 00233 00234 mtr_start(&mtr); 00235 00236 err = row_undo_mod_remove_clust_low(node, thr, &mtr, 00237 BTR_MODIFY_LEAF); 00238 if (err != DB_SUCCESS) { 00239 btr_pcur_commit_specify_mtr(pcur, &mtr); 00240 00241 /* We may have to modify tree structure: do a 00242 pessimistic descent down the index tree */ 00243 00244 mtr_start(&mtr); 00245 00246 err = row_undo_mod_remove_clust_low(node, thr, &mtr, 00247 BTR_MODIFY_TREE); 00248 } 00249 00250 btr_pcur_commit_specify_mtr(pcur, &mtr); 00251 } 00252 00253 node->state = UNDO_NODE_FETCH_NEXT; 00254 00255 trx_undo_rec_release(node->trx, node->undo_no); 00256 00257 if (more_vers && err == DB_SUCCESS) { 00258 00259 /* Reserve the undo log record to the prior version after 00260 committing &mtr: this is necessary to comply with the latching 00261 order, as &mtr may contain the fsp latch which is lower in 00262 the latch hierarchy than trx->undo_mutex. */ 00263 00264 success = trx_undo_rec_reserve(node->trx, new_undo_no); 00265 00266 if (success) { 00267 node->state = UNDO_NODE_PREV_VERS; 00268 } 00269 } 00270 00271 return(err); 00272 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_clust_low | ( | undo_node_t * | node, | |
| que_thr_t * | thr, | |||
| mtr_t * | mtr, | |||
| ulint | mode | |||
| ) | [static] |
Definition at line 79 of file row0umod.c.
References btr_cur_optimistic_update(), btr_cur_pessimistic_update(), BTR_KEEP_SYS_FLAG, BTR_MODIFY_LEAF, BTR_MODIFY_TREE, BTR_NO_LOCKING_FLAG, BTR_NO_UNDO_LOG_FLAG, btr_pcur_get_btr_cur(), btr_pcur_restore_position(), undo_node_struct::cmpl_info, err, undo_node_struct::pcur, undo_node_struct::update, and ut_ad.
Referenced by row_undo_mod_clust().
00081 : DB_SUCCESS, DB_FAIL, or error code: 00082 we may run out of file space */ 00083 undo_node_t* node, /* in: row undo node */ 00084 que_thr_t* thr, /* in: query thread */ 00085 mtr_t* mtr, /* in: mtr */ 00086 ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ 00087 { 00088 big_rec_t* dummy_big_rec; 00089 btr_pcur_t* pcur; 00090 btr_cur_t* btr_cur; 00091 ulint err; 00092 ibool success; 00093 00094 pcur = &(node->pcur); 00095 btr_cur = btr_pcur_get_btr_cur(pcur); 00096 00097 success = btr_pcur_restore_position(mode, pcur, mtr); 00098 00099 ut_ad(success); 00100 00101 if (mode == BTR_MODIFY_LEAF) { 00102 00103 err = btr_cur_optimistic_update(BTR_NO_LOCKING_FLAG 00104 | BTR_NO_UNDO_LOG_FLAG 00105 | BTR_KEEP_SYS_FLAG, 00106 btr_cur, node->update, 00107 node->cmpl_info, thr, mtr); 00108 } else { 00109 ut_ad(mode == BTR_MODIFY_TREE); 00110 00111 err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG 00112 | BTR_NO_UNDO_LOG_FLAG 00113 | BTR_KEEP_SYS_FLAG, 00114 btr_cur, &dummy_big_rec, node->update, 00115 node->cmpl_info, thr, mtr); 00116 } 00117 00118 return(err); 00119 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_del_mark_or_remove_sec | ( | undo_node_t * | node, | |
| que_thr_t * | thr, | |||
| dict_index_t * | index, | |||
| dtuple_t * | entry | |||
| ) | [static] |
Definition at line 370 of file row0umod.c.
References BTR_MODIFY_LEAF, BTR_MODIFY_TREE, DB_SUCCESS, err, index(), and row_undo_mod_del_mark_or_remove_sec_low().
Referenced by row_undo_mod_upd_del_sec(), and row_undo_mod_upd_exist_sec().
00372 : DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ 00373 undo_node_t* node, /* in: row undo node */ 00374 que_thr_t* thr, /* in: query thread */ 00375 dict_index_t* index, /* in: index */ 00376 dtuple_t* entry) /* in: index entry */ 00377 { 00378 ulint err; 00379 00380 err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index, 00381 entry, BTR_MODIFY_LEAF); 00382 if (err == DB_SUCCESS) { 00383 00384 return(err); 00385 } 00386 00387 err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index, 00388 entry, BTR_MODIFY_TREE); 00389 return(err); 00390 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_del_mark_or_remove_sec_low | ( | undo_node_t * | node, | |
| que_thr_t * | thr, | |||
| dict_index_t * | index, | |||
| dtuple_t * | entry, | |||
| ulint | mode | |||
| ) | [static] |
Definition at line 278 of file row0umod.c.
References btr_cur_del_mark_set_sec_rec(), btr_cur_optimistic_delete(), btr_cur_pessimistic_delete(), BTR_MODIFY_LEAF, BTR_MODIFY_TREE, BTR_NO_LOCKING_FLAG, btr_pcur_close(), btr_pcur_commit_specify_mtr(), btr_pcur_get_btr_cur(), btr_pcur_get_rec(), btr_pcur_restore_position(), BTR_SEARCH_LEAF, DB_FAIL, DB_SUCCESS, err, FALSE, index(), log_free_check(), mtr_commit(), mtr_start(), undo_node_struct::pcur, row_search_index_entry(), row_vers_old_has_index_entry(), TRUE, ut_a, and ut_ad.
Referenced by row_undo_mod_del_mark_or_remove_sec().
00280 : DB_SUCCESS, DB_FAIL, or 00281 DB_OUT_OF_FILE_SPACE */ 00282 undo_node_t* node, /* in: row undo node */ 00283 que_thr_t* thr, /* in: query thread */ 00284 dict_index_t* index, /* in: index */ 00285 dtuple_t* entry, /* in: index entry */ 00286 ulint mode) /* in: latch mode BTR_MODIFY_LEAF or 00287 BTR_MODIFY_TREE */ 00288 { 00289 ibool found; 00290 btr_pcur_t pcur; 00291 btr_cur_t* btr_cur; 00292 ibool success; 00293 ibool old_has; 00294 ulint err; 00295 mtr_t mtr; 00296 mtr_t mtr_vers; 00297 00298 log_free_check(); 00299 mtr_start(&mtr); 00300 00301 found = row_search_index_entry(index, entry, mode, &pcur, &mtr); 00302 00303 btr_cur = btr_pcur_get_btr_cur(&pcur); 00304 00305 if (!found) { 00306 /* Not found */ 00307 00308 btr_pcur_close(&pcur); 00309 mtr_commit(&mtr); 00310 00311 return(DB_SUCCESS); 00312 } 00313 00314 /* We should remove the index record if no prior version of the row, 00315 which cannot be purged yet, requires its existence. If some requires, 00316 we should delete mark the record. */ 00317 00318 mtr_start(&mtr_vers); 00319 00320 success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur), 00321 &mtr_vers); 00322 ut_a(success); 00323 00324 old_has = row_vers_old_has_index_entry(FALSE, 00325 btr_pcur_get_rec(&(node->pcur)), 00326 &mtr_vers, index, entry); 00327 if (old_has) { 00328 err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, 00329 btr_cur, TRUE, thr, &mtr); 00330 ut_ad(err == DB_SUCCESS); 00331 } else { 00332 /* Remove the index record */ 00333 00334 if (mode == BTR_MODIFY_LEAF) { 00335 success = btr_cur_optimistic_delete(btr_cur, &mtr); 00336 if (success) { 00337 err = DB_SUCCESS; 00338 } else { 00339 err = DB_FAIL; 00340 } 00341 } else { 00342 ut_ad(mode == BTR_MODIFY_TREE); 00343 00344 btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 00345 TRUE, &mtr); 00346 00347 /* The delete operation may fail if we have little 00348 file space left: TODO: easiest to crash the database 00349 and restart with more file space */ 00350 } 00351 } 00352 00353 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr_vers); 00354 btr_pcur_close(&pcur); 00355 mtr_commit(&mtr); 00356 00357 return(err); 00358 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_del_mark_sec | ( | undo_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 521 of file row0umod.c.
References BTR_MODIFY_LEAF, BTR_MODIFY_TREE, DB_FAIL, DB_SUCCESS, dict_table_get_next_index(), err, undo_node_struct::index, index(), mem_heap_create, mem_heap_free, NULL, undo_node_struct::row, row_build_index_entry(), and row_undo_mod_del_unmark_sec_and_undo_update().
Referenced by row_undo_mod().
00523 : DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ 00524 undo_node_t* node, /* in: row undo node */ 00525 que_thr_t* thr) /* in: query thread */ 00526 { 00527 mem_heap_t* heap; 00528 dtuple_t* entry; 00529 dict_index_t* index; 00530 ulint err; 00531 00532 heap = mem_heap_create(1024); 00533 00534 while (node->index != NULL) { 00535 index = node->index; 00536 00537 entry = row_build_index_entry(node->row, index, heap); 00538 00539 err = row_undo_mod_del_unmark_sec_and_undo_update( 00540 BTR_MODIFY_LEAF, 00541 thr, index, entry); 00542 if (err == DB_FAIL) { 00543 err = row_undo_mod_del_unmark_sec_and_undo_update( 00544 BTR_MODIFY_TREE, 00545 thr, index, entry); 00546 } 00547 00548 if (err != DB_SUCCESS) { 00549 00550 mem_heap_free(heap); 00551 00552 return(err); 00553 } 00554 00555 node->index = dict_table_get_next_index(node->index); 00556 } 00557 00558 mem_heap_free(heap); 00559 00560 return(DB_SUCCESS); 00561 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_del_unmark_sec_and_undo_update | ( | ulint | mode, | |
| que_thr_t * | thr, | |||
| dict_index_t * | index, | |||
| dtuple_t * | entry | |||
| ) | [static] |
Definition at line 399 of file row0umod.c.
References btr_cur_del_mark_set_sec_rec(), btr_cur_get_rec(), btr_cur_optimistic_update(), btr_cur_pessimistic_update(), BTR_KEEP_SYS_FLAG, BTR_MODIFY_LEAF, BTR_MODIFY_TREE, BTR_NO_LOCKING_FLAG, btr_pcur_close(), btr_pcur_get_btr_cur(), btr_pcur_get_rec(), DB_FAIL, DB_OVERFLOW, DB_SUCCESS, DB_UNDERFLOW, dict_index_name_print(), dtuple_print(), err, FALSE, index(), log_free_check(), mem_heap_create, mem_heap_free, mtr_commit(), mtr_start(), rec_print(), row_search_index_entry(), row_upd_build_sec_rec_difference_binary(), thr_get_trx(), trx_print(), upd_get_n_fields(), update, and ut_a.
Referenced by row_undo_mod_del_mark_sec(), and row_undo_mod_upd_exist_sec().
00401 : DB_FAIL or DB_SUCCESS or 00402 DB_OUT_OF_FILE_SPACE */ 00403 ulint mode, /* in: search mode: BTR_MODIFY_LEAF or 00404 BTR_MODIFY_TREE */ 00405 que_thr_t* thr, /* in: query thread */ 00406 dict_index_t* index, /* in: index */ 00407 dtuple_t* entry) /* in: index entry */ 00408 { 00409 mem_heap_t* heap; 00410 btr_pcur_t pcur; 00411 upd_t* update; 00412 ulint err = DB_SUCCESS; 00413 ibool found; 00414 big_rec_t* dummy_big_rec; 00415 mtr_t mtr; 00416 trx_t* trx = thr_get_trx(thr); 00417 00418 log_free_check(); 00419 mtr_start(&mtr); 00420 00421 found = row_search_index_entry(index, entry, mode, &pcur, &mtr); 00422 00423 if (!found) { 00424 fputs("InnoDB: error in sec index entry del undo in\n" 00425 "InnoDB: ", stderr); 00426 dict_index_name_print(stderr, trx, index); 00427 fputs("\n" 00428 "InnoDB: tuple ", stderr); 00429 dtuple_print(stderr, entry); 00430 fputs("\n" 00431 "InnoDB: record ", stderr); 00432 rec_print(stderr, btr_pcur_get_rec(&pcur), index); 00433 putc('\n', stderr); 00434 trx_print(stderr, trx, 0); 00435 fputs("\n" 00436 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); 00437 } else { 00438 btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur); 00439 00440 err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, 00441 btr_cur, FALSE, thr, &mtr); 00442 ut_a(err == DB_SUCCESS); 00443 heap = mem_heap_create(100); 00444 00445 update = row_upd_build_sec_rec_difference_binary(index, entry, 00446 btr_cur_get_rec(btr_cur), trx, heap); 00447 if (upd_get_n_fields(update) == 0) { 00448 00449 /* Do nothing */ 00450 00451 } else if (mode == BTR_MODIFY_LEAF) { 00452 /* Try an optimistic updating of the record, keeping 00453 changes within the page */ 00454 00455 err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG 00456 | BTR_NO_LOCKING_FLAG, 00457 btr_cur, update, 0, thr, &mtr); 00458 if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { 00459 err = DB_FAIL; 00460 } 00461 } else { 00462 ut_a(mode == BTR_MODIFY_TREE); 00463 err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG 00464 | BTR_NO_LOCKING_FLAG, 00465 btr_cur, &dummy_big_rec, 00466 update, 0, thr, &mtr); 00467 } 00468 00469 mem_heap_free(heap); 00470 } 00471 00472 btr_pcur_close(&pcur); 00473 mtr_commit(&mtr); 00474 00475 return(err); 00476 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void row_undo_mod_parse_undo_rec | ( | undo_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 651 of file row0umod.c.
References undo_node_struct::cmpl_info, dict_table_get_first_index(), dict_table_get_on_id(), undo_node_struct::heap, dict_table_struct::ibd_file_missing, undo_node_struct::new_roll_ptr, undo_node_struct::new_trx_id, NULL, undo_node_struct::rec_type, undo_node_struct::ref, undo_node_struct::table, thr_get_trx(), trx_undo_rec_get_pars(), trx_undo_rec_get_row_ref(), trx_undo_update_rec_get_sys_cols(), trx_undo_update_rec_get_update(), undo_node_struct::undo_rec, undo_node_struct::update, and ut_ad.
Referenced by row_undo_mod().
00653 : row undo node */ 00654 que_thr_t* thr) /* in: query thread */ 00655 { 00656 dict_index_t* clust_index; 00657 byte* ptr; 00658 dulint undo_no; 00659 dulint table_id; 00660 dulint trx_id; 00661 dulint roll_ptr; 00662 ulint info_bits; 00663 ulint type; 00664 ulint cmpl_info; 00665 ibool dummy_extern; 00666 trx_t* trx; 00667 00668 ut_ad(node && thr); 00669 trx = thr_get_trx(thr); 00670 ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, 00671 &dummy_extern, &undo_no, &table_id); 00672 node->rec_type = type; 00673 00674 node->table = dict_table_get_on_id(table_id, trx); 00675 00676 /* TODO: other fixes associated with DROP TABLE + rollback in the 00677 same table by another user */ 00678 00679 if (node->table == NULL) { 00680 /* Table was dropped */ 00681 return; 00682 } 00683 00684 if (node->table->ibd_file_missing) { 00685 /* We skip undo operations to missing .ibd files */ 00686 node->table = NULL; 00687 00688 return; 00689 } 00690 00691 clust_index = dict_table_get_first_index(node->table); 00692 00693 ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, 00694 &info_bits); 00695 00696 ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), 00697 node->heap); 00698 00699 trx_undo_update_rec_get_update(ptr, clust_index, type, trx_id, 00700 roll_ptr, info_bits, trx, 00701 node->heap, &(node->update)); 00702 node->new_roll_ptr = roll_ptr; 00703 node->new_trx_id = trx_id; 00704 node->cmpl_info = cmpl_info; 00705 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_remove_clust_low | ( | undo_node_t * | node, | |
| que_thr_t *thr | __attribute__((unused)), | |||
| mtr_t * | mtr, | |||
| ulint | mode | |||
| ) | [static] |
Definition at line 125 of file row0umod.c.
References btr_cur_optimistic_delete(), btr_cur_pessimistic_delete(), BTR_MODIFY_LEAF, BTR_MODIFY_TREE, btr_pcur_get_btr_cur(), btr_pcur_restore_position(), DB_FAIL, DB_SUCCESS, err, FALSE, undo_node_struct::new_trx_id, undo_node_struct::pcur, undo_node_struct::rec_type, row_vers_must_preserve_del_marked(), TRX_UNDO_UPD_DEL_REC, and ut_ad.
Referenced by row_undo_mod_clust().
00127 : DB_SUCCESS, DB_FAIL, or error code: 00128 we may run out of file space */ 00129 undo_node_t* node, /* in: row undo node */ 00130 que_thr_t* thr __attribute__((unused)), /* in: query thread */ 00131 mtr_t* mtr, /* in: mtr */ 00132 ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ 00133 { 00134 btr_pcur_t* pcur; 00135 btr_cur_t* btr_cur; 00136 ulint err; 00137 ibool success; 00138 00139 pcur = &(node->pcur); 00140 btr_cur = btr_pcur_get_btr_cur(pcur); 00141 00142 success = btr_pcur_restore_position(mode, pcur, mtr); 00143 00144 if (!success) { 00145 00146 return(DB_SUCCESS); 00147 } 00148 00149 /* Find out if we can remove the whole clustered index record */ 00150 00151 if (node->rec_type == TRX_UNDO_UPD_DEL_REC 00152 && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { 00153 00154 /* Ok, we can remove */ 00155 } else { 00156 return(DB_SUCCESS); 00157 } 00158 00159 if (mode == BTR_MODIFY_LEAF) { 00160 success = btr_cur_optimistic_delete(btr_cur, mtr); 00161 00162 if (success) { 00163 err = DB_SUCCESS; 00164 } else { 00165 err = DB_FAIL; 00166 } 00167 } else { 00168 ut_ad(mode == BTR_MODIFY_TREE); 00169 00170 /* Note that since this operation is analogous to purge, 00171 we can free also inherited externally stored fields: 00172 hence the last FALSE in the call below */ 00173 00174 btr_cur_pessimistic_delete(&err, FALSE, btr_cur, FALSE, mtr); 00175 00176 /* The delete operation may fail if we have little 00177 file space left: TODO: easiest to crash the database 00178 and restart with more file space */ 00179 } 00180 00181 return(err); 00182 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool row_undo_mod_undo_also_prev_vers | ( | undo_node_t * | node, | |
| dulint * | undo_no | |||
| ) |
Definition at line 50 of file row0umod.c.
References FALSE, undo_node_struct::heap, trx_struct::id, undo_node_struct::new_roll_ptr, undo_node_struct::new_trx_id, trx_struct::roll_limit, undo_node_struct::trx, trx_undo_get_undo_rec_low(), trx_undo_rec_get_undo_no(), ut_dulint_cmp(), and ut_dulint_zero.
Referenced by row_undo_mod_clust().
00052 : TRUE if also previous modify or 00053 insert of this row should be undone */ 00054 undo_node_t* node, /* in: row undo node */ 00055 dulint* undo_no)/* out: the undo number */ 00056 { 00057 trx_undo_rec_t* undo_rec; 00058 trx_t* trx; 00059 00060 trx = node->trx; 00061 00062 if (0 != ut_dulint_cmp(node->new_trx_id, trx->id)) { 00063 00064 *undo_no = ut_dulint_zero; 00065 return(FALSE); 00066 } 00067 00068 undo_rec = trx_undo_get_undo_rec_low(node->new_roll_ptr, node->heap); 00069 00070 *undo_no = trx_undo_rec_get_undo_no(undo_rec); 00071 00072 return(ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0); 00073 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_upd_del_sec | ( | undo_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 482 of file row0umod.c.
References DB_SUCCESS, dict_table_get_next_index(), err, undo_node_struct::index, index(), mem_heap_create, mem_heap_free, NULL, undo_node_struct::row, row_build_index_entry(), and row_undo_mod_del_mark_or_remove_sec().
Referenced by row_undo_mod().
00484 : DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ 00485 undo_node_t* node, /* in: row undo node */ 00486 que_thr_t* thr) /* in: query thread */ 00487 { 00488 mem_heap_t* heap; 00489 dtuple_t* entry; 00490 dict_index_t* index; 00491 ulint err; 00492 00493 heap = mem_heap_create(1024); 00494 00495 while (node->index != NULL) { 00496 index = node->index; 00497 00498 entry = row_build_index_entry(node->row, index, heap); 00499 00500 err = row_undo_mod_del_mark_or_remove_sec(node, thr, index, 00501 entry); 00502 if (err != DB_SUCCESS) { 00503 00504 mem_heap_free(heap); 00505 00506 return(err); 00507 } 00508 00509 node->index = dict_table_get_next_index(node->index); 00510 } 00511 00512 mem_heap_free(heap); 00513 00514 return(DB_SUCCESS); 00515 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_undo_mod_upd_exist_sec | ( | undo_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 567 of file row0umod.c.
References BTR_MODIFY_LEAF, BTR_MODIFY_TREE, undo_node_struct::cmpl_info, DB_FAIL, DB_SUCCESS, dict_table_get_next_index(), err, undo_node_struct::index, index(), mem_heap_create, mem_heap_free, NULL, undo_node_struct::row, row_build_index_entry(), row_undo_mod_del_mark_or_remove_sec(), row_undo_mod_del_unmark_sec_and_undo_update(), row_upd_changes_ord_field_binary(), row_upd_index_replace_new_col_vals(), UPD_NODE_NO_ORD_CHANGE, and undo_node_struct::update.
Referenced by row_undo_mod().
00569 : DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ 00570 undo_node_t* node, /* in: row undo node */ 00571 que_thr_t* thr) /* in: query thread */ 00572 { 00573 mem_heap_t* heap; 00574 dtuple_t* entry; 00575 dict_index_t* index; 00576 ulint err; 00577 00578 if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) { 00579 /* No change in secondary indexes */ 00580 00581 return(DB_SUCCESS); 00582 } 00583 00584 heap = mem_heap_create(1024); 00585 00586 while (node->index != NULL) { 00587 index = node->index; 00588 00589 if (row_upd_changes_ord_field_binary(node->row, node->index, 00590 node->update)) { 00591 00592 /* Build the newest version of the index entry */ 00593 entry = row_build_index_entry(node->row, index, heap); 00594 00595 /* NOTE that if we updated the fields of a 00596 delete-marked secondary index record so that 00597 alphabetically they stayed the same, e.g., 00598 'abc' -> 'aBc', we cannot return to the original 00599 values because we do not know them. But this should 00600 not cause problems because in row0sel.c, in queries 00601 we always retrieve the clustered index record or an 00602 earlier version of it, if the secondary index record 00603 through which we do the search is delete-marked. */ 00604 00605 err = row_undo_mod_del_mark_or_remove_sec(node, thr, 00606 index, entry); 00607 if (err != DB_SUCCESS) { 00608 mem_heap_free(heap); 00609 00610 return(err); 00611 } 00612 00613 /* We may have to update the delete mark in the 00614 secondary index record of the previous version of 00615 the row. We also need to update the fields of 00616 the secondary index record if we updated its fields 00617 but alphabetically they stayed the same, e.g., 00618 'abc' -> 'aBc'. */ 00619 00620 row_upd_index_replace_new_col_vals(entry, index, 00621 node->update, NULL); 00622 err = row_undo_mod_del_unmark_sec_and_undo_update( 00623 BTR_MODIFY_LEAF, 00624 thr, index, entry); 00625 if (err == DB_FAIL) { 00626 err = 00627 row_undo_mod_del_unmark_sec_and_undo_update( 00628 BTR_MODIFY_TREE, 00629 thr, index, entry); 00630 } 00631 00632 if (err != DB_SUCCESS) { 00633 mem_heap_free(heap); 00634 00635 return(err); 00636 } 00637 } 00638 00639 node->index = dict_table_get_next_index(node->index); 00640 } 00641 00642 mem_heap_free(heap); 00643 00644 return(DB_SUCCESS); 00645 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

