diff options
author | Vasil Dimov <vasil.dimov@oracle.com> | 2010-04-12 18:20:41 +0300 |
---|---|---|
committer | Vasil Dimov <vasil.dimov@oracle.com> | 2010-04-12 18:20:41 +0300 |
commit | c877ff39bceb4df96acf3e54f7c98a2bed12b8ee (patch) | |
tree | 04211a3e5734b73e9f94cff511a4a74ff87075f0 /storage/innobase/row/row0upd.c | |
parent | fe0828b3b8193e086abe740572c9b0cb2b7da671 (diff) | |
parent | 410e23a6af8b597cdda0890d6ed9008355edee7a (diff) | |
download | mariadb-git-c877ff39bceb4df96acf3e54f7c98a2bed12b8ee.tar.gz |
Import branches/innodb+ from SVN on top of storage/innobase.
Diffstat (limited to 'storage/innobase/row/row0upd.c')
-rw-r--r-- | storage/innobase/row/row0upd.c | 115 |
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); |