summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0upd.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row/row0upd.c')
-rw-r--r--storage/innobase/row/row0upd.c115
1 files changed, 73 insertions, 42 deletions
diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c
index 58dfd43ead9..f1a90a3bf1c 100644
--- a/storage/innobase/row/row0upd.c
+++ b/storage/innobase/row/row0upd.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2010, 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
@@ -1344,9 +1344,6 @@ row_upd_copy_columns(
data = rec_get_nth_field(rec, offsets,
column->field_nos[SYM_CLUST_FIELD_NO],
&len);
- if (len == UNIV_SQL_NULL) {
- len = UNIV_SQL_NULL;
- }
eval_node_copy_and_alloc_val(column, data, len);
column = UT_LIST_GET_NEXT(col_var_list, column);
@@ -1434,21 +1431,22 @@ row_upd_sec_index_entry(
upd_node_t* node, /*!< in: row update node */
que_thr_t* thr) /*!< in: query thread */
{
- ibool check_ref;
- ibool found;
- dict_index_t* index;
- dtuple_t* entry;
- btr_pcur_t pcur;
- btr_cur_t* btr_cur;
- mem_heap_t* heap;
- rec_t* rec;
- ulint err = DB_SUCCESS;
- mtr_t mtr;
- trx_t* trx = thr_get_trx(thr);
+ mtr_t mtr;
+ const rec_t* rec;
+ btr_pcur_t pcur;
+ mem_heap_t* heap;
+ dtuple_t* entry;
+ dict_index_t* index;
+ btr_cur_t* btr_cur;
+ ibool referenced;
+ ulint err = DB_SUCCESS;
+ trx_t* trx = thr_get_trx(thr);
+ ulint mode = BTR_MODIFY_LEAF;
+ enum row_search_result search_result;
index = node->index;
- check_ref = row_upd_index_is_referenced(index, trx);
+ referenced = row_upd_index_is_referenced(index, trx);
heap = mem_heap_create(1024);
@@ -1459,13 +1457,33 @@ row_upd_sec_index_entry(
log_free_check();
mtr_start(&mtr);
- found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
- &mtr);
+ /* Set the query thread, so that ibuf_insert_low() will be
+ able to invoke thd_get_trx(). */
+ btr_pcur_get_btr_cur(&pcur)->thr = thr;
+
+ /* We can only try to use the insert/delete buffer to buffer
+ delete-mark operations if the index we're modifying has no foreign
+ key constraints referring to it. */
+ if (!referenced) {
+ mode |= BTR_DELETE_MARK;
+ }
+
+ search_result = row_search_index_entry(index, entry, mode,
+ &pcur, &mtr);
+
btr_cur = btr_pcur_get_btr_cur(&pcur);
rec = btr_cur_get_rec(btr_cur);
- if (UNIV_UNLIKELY(!found)) {
+ switch (search_result) {
+ case ROW_NOT_DELETED_REF: /* should only occur for BTR_DELETE */
+ ut_error;
+ break;
+ case ROW_BUFFERED:
+ /* Entry was delete marked already. */
+ break;
+
+ case ROW_NOT_FOUND:
fputs("InnoDB: error in sec index entry update in\n"
"InnoDB: ", stderr);
dict_index_name_print(stderr, trx, index);
@@ -1482,20 +1500,26 @@ row_upd_sec_index_entry(
fputs("\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
- } else {
+ break;
+ case ROW_FOUND:
/* Delete mark the old index record; it can already be
delete marked if we return after a lock wait in
row_ins_index_entry below */
- if (!rec_get_deleted_flag(rec,
- dict_table_is_comp(index->table))) {
- err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
- thr, &mtr);
- if (err == DB_SUCCESS && check_ref) {
+ if (!rec_get_deleted_flag(
+ rec, dict_table_is_comp(index->table))) {
+
+ err = btr_cur_del_mark_set_sec_rec(
+ 0, btr_cur, TRUE, thr, &mtr);
+
+ if (err == DB_SUCCESS && referenced) {
+
+ ulint* offsets;
+
+ offsets = rec_get_offsets(
+ rec, index, NULL, ULINT_UNDEFINED,
+ &heap);
- ulint* offsets = rec_get_offsets(
- rec, index, NULL,
- ULINT_UNDEFINED, &heap);
/* NOTE that the following call loses
the position of pcur ! */
err = row_upd_check_references_constraints(
@@ -1503,6 +1527,7 @@ row_upd_sec_index_entry(
index, offsets, thr, &mtr);
}
}
+ break;
}
btr_pcur_close(&pcur);
@@ -1566,7 +1591,7 @@ row_upd_clust_rec_by_insert(
upd_node_t* node, /*!< in: row update node */
dict_index_t* index, /*!< in: clustered index of the record */
que_thr_t* thr, /*!< in: query thread */
- ibool check_ref,/*!< in: TRUE if index may be referenced in
+ ibool referenced,/*!< in: TRUE if index may be referenced in
a foreign key constraint */
mtr_t* mtr) /*!< in: mtr; gets committed here */
{
@@ -1612,16 +1637,21 @@ row_upd_clust_rec_by_insert(
btr_cur_mark_extern_inherited_fields(
btr_cur_get_page_zip(btr_cur),
rec, index, offsets, node->update, mtr);
- if (check_ref) {
+ if (referenced) {
/* NOTE that the following call loses
the position of pcur ! */
+
err = row_upd_check_references_constraints(
node, pcur, table, index, offsets, thr, mtr);
+
if (err != DB_SUCCESS) {
+
mtr_commit(mtr);
+
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
return(err);
}
}
@@ -1776,7 +1806,8 @@ row_upd_del_mark_clust_rec(
ulint* offsets,/*!< in/out: rec_get_offsets() for the
record under the cursor */
que_thr_t* thr, /*!< in: query thread */
- ibool check_ref,/*!< in: TRUE if index may be referenced in
+ ibool referenced,
+ /*!< in: TRUE if index may be referenced in
a foreign key constraint */
mtr_t* mtr) /*!< in: mtr; gets committed here */
{
@@ -1801,13 +1832,11 @@ row_upd_del_mark_clust_rec(
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
btr_cur, TRUE, thr, mtr);
- if (err == DB_SUCCESS && check_ref) {
+ if (err == DB_SUCCESS && referenced) {
/* NOTE that the following call loses the position of pcur ! */
- err = row_upd_check_references_constraints(node,
- pcur, index->table,
- index, offsets,
- thr, mtr);
+ err = row_upd_check_references_constraints(
+ node, pcur, index->table, index, offsets, thr, mtr);
}
mtr_commit(mtr);
@@ -1829,7 +1858,6 @@ row_upd_clust_step(
dict_index_t* index;
btr_pcur_t* pcur;
ibool success;
- ibool check_ref;
ulint err;
mtr_t* mtr;
mtr_t mtr_buf;
@@ -1837,11 +1865,12 @@ row_upd_clust_step(
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets;
+ ibool referenced;
rec_offs_init(offsets_);
index = dict_table_get_first_index(node->table);
- check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
+ referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
pcur = node->pcur;
@@ -1911,8 +1940,9 @@ row_upd_clust_step(
/* NOTE: the following function calls will also commit mtr */
if (node->is_delete) {
- err = row_upd_del_mark_clust_rec(node, index, offsets,
- thr, check_ref, mtr);
+ err = row_upd_del_mark_clust_rec(
+ node, index, offsets, thr, referenced, mtr);
+
if (err == DB_SUCCESS) {
node->state = UPD_NODE_UPDATE_ALL_SEC;
node->index = dict_table_get_next_index(index);
@@ -1960,8 +1990,9 @@ exit_func:
choosing records to update. MySQL solves now the problem
externally! */
- err = row_upd_clust_rec_by_insert(node, index, thr, check_ref,
- mtr);
+ err = row_upd_clust_rec_by_insert(
+ node, index, thr, referenced, mtr);
+
if (err != DB_SUCCESS) {
return(err);