#include "row0upd.h"#include "dict0dict.h"#include "dict0boot.h"#include "dict0crea.h"#include "mach0data.h"#include "trx0undo.h"#include "btr0btr.h"#include "btr0cur.h"#include "que0que.h"#include "row0ins.h"#include "row0sel.h"#include "row0row.h"#include "rem0cmp.h"#include "lock0lock.h"#include "log0log.h"#include "pars0sym.h"#include "eval0eval.h"#include "buf0lru.h"Include dependency graph for row0upd.c:

Go to the source code of this file.
| static ulint row_upd | ( | upd_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 1825 of file row0upd.c.
References upd_node_struct::cmpl_info, DB_SUCCESS, dict_table_get_next_index(), err, upd_node_struct::heap, upd_node_struct::in_mysql_interface, upd_node_struct::index, upd_node_struct::is_delete, mem_heap_empty(), upd_node_struct::n_ext_vec, NULL, upd_node_struct::row, row_upd_changes_some_index_ord_field_binary(), row_upd_clust_step(), row_upd_sec_step(), upd_node_struct::state, upd_node_struct::table, UPD_NODE_INSERT_CLUSTERED, UPD_NODE_NO_ORD_CHANGE, UPD_NODE_UPDATE_CLUSTERED, upd_node_struct::update, and ut_ad.
Referenced by row_upd_step().
01827 : DB_SUCCESS if operation successfully 01828 completed, else error code or DB_LOCK_WAIT */ 01829 upd_node_t* node, /* in: row update node */ 01830 que_thr_t* thr) /* in: query thread */ 01831 { 01832 ulint err = DB_SUCCESS; 01833 01834 ut_ad(node && thr); 01835 01836 if (node->in_mysql_interface) { 01837 01838 /* We do not get the cmpl_info value from the MySQL 01839 interpreter: we must calculate it on the fly: */ 01840 01841 if (node->is_delete || 01842 row_upd_changes_some_index_ord_field_binary( 01843 node->table, node->update)) { 01844 node->cmpl_info = 0; 01845 } else { 01846 node->cmpl_info = UPD_NODE_NO_ORD_CHANGE; 01847 } 01848 } 01849 01850 if (node->state == UPD_NODE_UPDATE_CLUSTERED 01851 || node->state == UPD_NODE_INSERT_CLUSTERED) { 01852 01853 err = row_upd_clust_step(node, thr); 01854 01855 if (err != DB_SUCCESS) { 01856 01857 goto function_exit; 01858 } 01859 } 01860 01861 if (!node->is_delete && (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { 01862 01863 goto function_exit; 01864 } 01865 01866 while (node->index != NULL) { 01867 err = row_upd_sec_step(node, thr); 01868 01869 if (err != DB_SUCCESS) { 01870 01871 goto function_exit; 01872 } 01873 01874 node->index = dict_table_get_next_index(node->index); 01875 } 01876 01877 function_exit: 01878 if (err == DB_SUCCESS) { 01879 /* Do some cleanup */ 01880 01881 if (node->row != NULL) { 01882 node->row = NULL; 01883 node->n_ext_vec = 0; 01884 mem_heap_empty(node->heap); 01885 } 01886 01887 node->state = UPD_NODE_UPDATE_CLUSTERED; 01888 } 01889 01890 return(err); 01891 }
Here is the call graph for this function:

Here is the caller graph for this function:

| upd_t* row_upd_build_difference_binary | ( | dict_index_t * | index, | |
| dtuple_t * | entry, | |||
| ulint * | ext_vec, | |||
| ulint | n_ext_vec, | |||
| rec_t * | rec, | |||
| trx_t * | trx, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 780 of file row0upd.c.
References data, DATA_ROLL_PTR, DATA_TRX_ID, dfield_copy(), dfield_data_is_binary_equal(), DICT_CLUSTERED, dict_index_get_sys_col_pos(), dtuple_get_n_fields(), dtuple_get_nth_field(), upd_field_struct::extern_storage, index(), upd_field_struct::new_val, rec_get_nth_field(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_offs_nth_extern(), upd_create(), upd_ext_vec_contains(), upd_field_set_field_no(), upd_get_nth_field(), update, and ut_a.
Referenced by row_ins_clust_index_entry_by_modify().
00782 : update vector of differing 00783 fields, excluding roll ptr and trx id */ 00784 dict_index_t* index, /* in: clustered index */ 00785 dtuple_t* entry, /* in: entry to insert */ 00786 ulint* ext_vec,/* in: array containing field numbers of 00787 externally stored fields in entry, or NULL */ 00788 ulint n_ext_vec,/* in: number of fields in ext_vec */ 00789 rec_t* rec, /* in: clustered index record */ 00790 trx_t* trx, /* in: transaction */ 00791 mem_heap_t* heap) /* in: memory heap from which allocated */ 00792 { 00793 upd_field_t* upd_field; 00794 dfield_t* dfield; 00795 byte* data; 00796 ulint len; 00797 upd_t* update; 00798 ulint n_diff; 00799 ulint roll_ptr_pos; 00800 ulint trx_id_pos; 00801 ibool extern_bit; 00802 ulint i; 00803 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00804 const ulint* offsets; 00805 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00806 00807 /* This function is used only for a clustered index */ 00808 ut_a(index->type & DICT_CLUSTERED); 00809 00810 update = upd_create(dtuple_get_n_fields(entry), heap); 00811 00812 n_diff = 0; 00813 00814 roll_ptr_pos = dict_index_get_sys_col_pos(index, DATA_ROLL_PTR); 00815 trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); 00816 00817 offsets = rec_get_offsets(rec, index, offsets_, 00818 ULINT_UNDEFINED, &heap); 00819 00820 for (i = 0; i < dtuple_get_n_fields(entry); i++) { 00821 00822 data = rec_get_nth_field(rec, offsets, i, &len); 00823 00824 dfield = dtuple_get_nth_field(entry, i); 00825 00826 /* NOTE: we compare the fields as binary strings! 00827 (No collation) */ 00828 00829 if (i == trx_id_pos || i == roll_ptr_pos) { 00830 00831 goto skip_compare; 00832 } 00833 00834 extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i); 00835 00836 if (UNIV_UNLIKELY(extern_bit == 00837 (ibool)!rec_offs_nth_extern(offsets, i)) 00838 || !dfield_data_is_binary_equal(dfield, len, data)) { 00839 00840 upd_field = upd_get_nth_field(update, n_diff); 00841 00842 dfield_copy(&(upd_field->new_val), dfield); 00843 00844 upd_field_set_field_no(upd_field, i, index, trx); 00845 00846 upd_field->extern_storage = extern_bit; 00847 00848 n_diff++; 00849 } 00850 skip_compare: 00851 ; 00852 } 00853 00854 update->n_fields = n_diff; 00855 00856 return(update); 00857 }
Here is the call graph for this function:

Here is the caller graph for this function:

| upd_t* row_upd_build_sec_rec_difference_binary | ( | dict_index_t * | index, | |
| dtuple_t * | entry, | |||
| rec_t * | rec, | |||
| trx_t * | trx, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 708 of file row0upd.c.
References data, dfield_copy(), dfield_data_is_binary_equal(), DICT_CLUSTERED, dtuple_get_n_fields(), dtuple_get_nth_field(), upd_field_struct::extern_storage, FALSE, index(), upd_field_struct::new_val, rec_get_nth_field(), rec_get_offsets, REC_OFFS_SMALL_SIZE, upd_create(), upd_field_set_field_no(), upd_get_nth_field(), update, and ut_a.
Referenced by row_ins_sec_index_entry_by_modify(), and row_undo_mod_del_unmark_sec_and_undo_update().
00710 : update vector of differing 00711 fields */ 00712 dict_index_t* index, /* in: index */ 00713 dtuple_t* entry, /* in: entry to insert */ 00714 rec_t* rec, /* in: secondary index record */ 00715 trx_t* trx, /* in: transaction */ 00716 mem_heap_t* heap) /* in: memory heap from which allocated */ 00717 { 00718 upd_field_t* upd_field; 00719 dfield_t* dfield; 00720 byte* data; 00721 ulint len; 00722 upd_t* update; 00723 ulint n_diff; 00724 ulint i; 00725 ulint offsets_[REC_OFFS_SMALL_SIZE]; 00726 const ulint* offsets; 00727 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00728 00729 /* This function is used only for a secondary index */ 00730 ut_a(0 == (index->type & DICT_CLUSTERED)); 00731 00732 update = upd_create(dtuple_get_n_fields(entry), heap); 00733 00734 n_diff = 0; 00735 offsets = rec_get_offsets(rec, index, offsets_, 00736 ULINT_UNDEFINED, &heap); 00737 00738 for (i = 0; i < dtuple_get_n_fields(entry); i++) { 00739 00740 data = rec_get_nth_field(rec, offsets, i, &len); 00741 00742 dfield = dtuple_get_nth_field(entry, i); 00743 00744 /* NOTE that it may be that len != dfield_get_len(dfield) if we 00745 are updating in a character set and collation where strings of 00746 different length can be equal in an alphabetical comparison, 00747 and also in the case where we have a column prefix index 00748 and the last characters in the index field are spaces; the 00749 latter case probably caused the assertion failures reported at 00750 row0upd.c line 713 in versions 4.0.14 - 4.0.16. */ 00751 00752 /* NOTE: we compare the fields as binary strings! 00753 (No collation) */ 00754 00755 if (!dfield_data_is_binary_equal(dfield, len, data)) { 00756 00757 upd_field = upd_get_nth_field(update, n_diff); 00758 00759 dfield_copy(&(upd_field->new_val), dfield); 00760 00761 upd_field_set_field_no(upd_field, i, index, trx); 00762 00763 upd_field->extern_storage = FALSE; 00764 00765 n_diff++; 00766 } 00767 } 00768 00769 update->n_fields = n_diff; 00770 00771 return(update); 00772 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool row_upd_changes_field_size_or_external | ( | dict_index_t * | index, | |
| const ulint * | offsets, | |||
| upd_t * | update | |||
| ) |
Definition at line 361 of file row0upd.c.
References dict_index_get_nth_type(), dtype_get_sql_null_size(), upd_field_struct::extern_storage, FALSE, upd_field_struct::field_no, index(), dfield_struct::len, upd_field_struct::new_val, NULL, rec_offs_comp(), rec_offs_nth_extern(), rec_offs_nth_size(), rec_offs_nth_sql_null(), rec_offs_validate(), TRUE, upd_get_n_fields(), upd_get_nth_field(), update, and ut_ad.
Referenced by btr_cur_optimistic_update(), and trx_undo_prev_version_build().
00363 : TRUE if the update changes the size of 00364 some field in index or the field is external 00365 in rec or update */ 00366 dict_index_t* index, /* in: index */ 00367 const ulint* offsets,/* in: rec_get_offsets(rec, index) */ 00368 upd_t* update) /* in: update vector */ 00369 { 00370 upd_field_t* upd_field; 00371 dfield_t* new_val; 00372 ulint old_len; 00373 ulint new_len; 00374 ulint n_fields; 00375 ulint i; 00376 00377 ut_ad(rec_offs_validate(NULL, index, offsets)); 00378 n_fields = upd_get_n_fields(update); 00379 00380 for (i = 0; i < n_fields; i++) { 00381 upd_field = upd_get_nth_field(update, i); 00382 00383 new_val = &(upd_field->new_val); 00384 new_len = new_val->len; 00385 00386 if (new_len == UNIV_SQL_NULL && !rec_offs_comp(offsets)) { 00387 /* A bug fixed on Dec 31st, 2004: we looked at the 00388 SQL NULL size from the wrong field! We may backport 00389 this fix also to 4.0. The merge to 5.0 will be made 00390 manually immediately after we commit this to 4.1. */ 00391 00392 new_len = dtype_get_sql_null_size( 00393 dict_index_get_nth_type(index, 00394 upd_field->field_no)); 00395 } 00396 00397 old_len = rec_offs_nth_size(offsets, upd_field->field_no); 00398 00399 if (rec_offs_comp(offsets) 00400 && rec_offs_nth_sql_null(offsets, 00401 upd_field->field_no)) { 00402 /* Note that in the compact table format, for a 00403 variable length field, an SQL NULL will use zero 00404 bytes in the offset array at the start of the physical 00405 record, but a zero-length value (empty string) will 00406 use one byte! Thus, we cannot use update-in-place 00407 if we update an SQL NULL varchar to an empty string! */ 00408 00409 old_len = UNIV_SQL_NULL; 00410 } 00411 00412 if (old_len != new_len) { 00413 00414 return(TRUE); 00415 } 00416 00417 if (rec_offs_nth_extern(offsets, upd_field->field_no)) { 00418 00419 return(TRUE); 00420 } 00421 00422 if (upd_field->extern_storage) { 00423 00424 return(TRUE); 00425 } 00426 } 00427 00428 return(FALSE); 00429 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool row_upd_changes_first_fields_binary | ( | dtuple_t * | entry, | |
| dict_index_t * | index, | |||
| upd_t * | update, | |||
| ulint | n | |||
| ) | [static] |
Definition at line 1116 of file row0upd.c.
References dfield_datas_are_binary_equal(), dict_col_get_clust_pos(), dict_field_get_col(), dict_index_get_n_fields(), dict_index_get_nth_field(), dtuple_get_nth_field(), upd_field_struct::field_no, index(), upd_field_struct::new_val, dict_field_struct::prefix_len, TRUE, upd_get_n_fields(), upd_get_nth_field(), update, and ut_a.
Referenced by row_upd_check_references_constraints().
01118 : TRUE if changes */ 01119 dtuple_t* entry, /* in: index entry */ 01120 dict_index_t* index, /* in: index of entry */ 01121 upd_t* update, /* in: update vector for the row */ 01122 ulint n) /* in: how many first fields to check */ 01123 { 01124 upd_field_t* upd_field; 01125 dict_field_t* ind_field; 01126 dict_col_t* col; 01127 ulint n_upd_fields; 01128 ulint col_pos; 01129 ulint i, j; 01130 01131 ut_a(update && index); 01132 ut_a(n <= dict_index_get_n_fields(index)); 01133 01134 n_upd_fields = upd_get_n_fields(update); 01135 01136 for (i = 0; i < n; i++) { 01137 01138 ind_field = dict_index_get_nth_field(index, i); 01139 col = dict_field_get_col(ind_field); 01140 col_pos = dict_col_get_clust_pos(col); 01141 01142 ut_a(ind_field->prefix_len == 0); 01143 01144 for (j = 0; j < n_upd_fields; j++) { 01145 01146 upd_field = upd_get_nth_field(update, j); 01147 01148 if (col_pos == upd_field->field_no 01149 && !dfield_datas_are_binary_equal( 01150 dtuple_get_nth_field(entry, i), 01151 &(upd_field->new_val))) { 01152 01153 return(TRUE); 01154 } 01155 } 01156 } 01157 01158 return(FALSE); 01159 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool row_upd_changes_ord_field_binary | ( | dtuple_t * | row, | |
| dict_index_t * | index, | |||
| upd_t * | update | |||
| ) |
Definition at line 1017 of file row0upd.c.
References dfield_datas_are_binary_equal(), dict_col_get_clust_pos(), dict_col_get_no(), dict_field_get_col(), dict_index_get_n_unique(), dict_index_get_nth_field(), dtuple_get_nth_field(), upd_field_struct::field_no, index(), upd_field_struct::new_val, NULL, dict_field_struct::prefix_len, TRUE, upd_get_n_fields(), upd_get_nth_field(), update, and ut_ad.
Referenced by btr_cur_update_in_place(), row_purge_upd_exist_or_extern(), row_undo_mod_upd_exist_sec(), row_upd_clust_step(), and row_upd_sec_step().
01019 : TRUE if update vector changes 01020 an ordering field in the index record; 01021 NOTE: the fields are compared as binary 01022 strings */ 01023 dtuple_t* row, /* in: old value of row, or NULL if the 01024 row and the data values in update are not 01025 known when this function is called, e.g., at 01026 compile time */ 01027 dict_index_t* index, /* in: index of the record */ 01028 upd_t* update) /* in: update vector for the row; NOTE: the 01029 field numbers in this MUST be clustered index 01030 positions! */ 01031 { 01032 upd_field_t* upd_field; 01033 dict_field_t* ind_field; 01034 dict_col_t* col; 01035 ulint n_unique; 01036 ulint n_upd_fields; 01037 ulint col_pos; 01038 ulint col_no; 01039 ulint i, j; 01040 01041 ut_ad(update && index); 01042 01043 n_unique = dict_index_get_n_unique(index); 01044 n_upd_fields = upd_get_n_fields(update); 01045 01046 for (i = 0; i < n_unique; i++) { 01047 01048 ind_field = dict_index_get_nth_field(index, i); 01049 col = dict_field_get_col(ind_field); 01050 col_pos = dict_col_get_clust_pos(col); 01051 col_no = dict_col_get_no(col); 01052 01053 for (j = 0; j < n_upd_fields; j++) { 01054 01055 upd_field = upd_get_nth_field(update, j); 01056 01057 /* Note that if the index field is a column prefix 01058 then it may be that row does not contain an externally 01059 stored part of the column value, and we cannot compare 01060 the datas */ 01061 01062 if (col_pos == upd_field->field_no 01063 && (row == NULL 01064 || ind_field->prefix_len > 0 01065 || !dfield_datas_are_binary_equal( 01066 dtuple_get_nth_field(row, 01067 col_no), 01068 &(upd_field->new_val)))) { 01069 return(TRUE); 01070 } 01071 } 01072 } 01073 01074 return(FALSE); 01075 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool row_upd_changes_some_index_ord_field_binary | ( | dict_table_t * | table, | |
| upd_t * | update | |||
| ) |
Definition at line 1082 of file row0upd.c.
References dict_field_get_col(), dict_index_get_nth_field(), dict_table_get_first_index(), FALSE, upd_field_struct::field_no, index(), dict_col_struct::ord_part, TRUE, upd_get_n_fields(), upd_get_nth_field(), and update.
Referenced by row_upd().
01084 : TRUE if update vector may change 01085 an ordering field in an index record */ 01086 dict_table_t* table, /* in: table */ 01087 upd_t* update) /* in: update vector for the row */ 01088 { 01089 upd_field_t* upd_field; 01090 dict_index_t* index; 01091 ulint i; 01092 01093 index = dict_table_get_first_index(table); 01094 01095 for (i = 0; i < upd_get_n_fields(update); i++) { 01096 01097 upd_field = upd_get_nth_field(update, i); 01098 01099 if (dict_field_get_col(dict_index_get_nth_field(index, 01100 upd_field->field_no)) 01101 ->ord_part) { 01102 01103 return(TRUE); 01104 } 01105 } 01106 01107 return(FALSE); 01108 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_upd_check_references_constraints | ( | upd_node_t * | node, | |
| btr_pcur_t * | pcur, | |||
| dict_table_t * | table, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 148 of file row0upd.c.
References btr_pcur_get_rec(), DB_SUCCESS, trx_struct::dict_operation_lock_mode, dict_sys, dict_table_get(), err, FALSE, dict_foreign_struct::foreign_table, dict_foreign_struct::foreign_table_name, index(), upd_node_struct::is_delete, mem_heap_create, mem_heap_free, mtr_commit(), mtr_start(), dict_sys_struct::mutex, mutex_enter, mutex_exit(), dict_foreign_struct::n_fields, dict_table_struct::n_foreign_key_checks_running, NULL, dict_foreign_struct::referenced_index, dict_table_struct::referenced_list, ROW_COPY_DATA, row_ins_check_foreign_constraint(), row_mysql_freeze_data_dictionary(), row_mysql_unfreeze_data_dictionary(), row_rec_to_index_entry(), row_upd_changes_first_fields_binary(), thr_get_trx(), TRUE, upd_node_struct::update, ut_a, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by row_upd_clust_rec_by_insert(), row_upd_del_mark_clust_rec(), and row_upd_sec_index_entry().
00150 : DB_SUCCESS or an error code */ 00151 upd_node_t* node, /* in: row update node */ 00152 btr_pcur_t* pcur, /* in: cursor positioned on a record; NOTE: the 00153 cursor position is lost in this function! */ 00154 dict_table_t* table, /* in: table in question */ 00155 dict_index_t* index, /* in: index of the cursor */ 00156 que_thr_t* thr, /* in: query thread */ 00157 mtr_t* mtr) /* in: mtr */ 00158 { 00159 dict_foreign_t* foreign; 00160 mem_heap_t* heap; 00161 dtuple_t* entry; 00162 trx_t* trx; 00163 rec_t* rec; 00164 ulint err; 00165 ibool got_s_lock = FALSE; 00166 00167 if (UT_LIST_GET_FIRST(table->referenced_list) == NULL) { 00168 00169 return(DB_SUCCESS); 00170 } 00171 00172 trx = thr_get_trx(thr); 00173 00174 rec = btr_pcur_get_rec(pcur); 00175 00176 heap = mem_heap_create(500); 00177 00178 entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); 00179 00180 mtr_commit(mtr); 00181 00182 mtr_start(mtr); 00183 00184 if (trx->dict_operation_lock_mode == 0) { 00185 got_s_lock = TRUE; 00186 00187 row_mysql_freeze_data_dictionary(trx); 00188 } 00189 00190 foreign = UT_LIST_GET_FIRST(table->referenced_list); 00191 00192 while (foreign) { 00193 /* Note that we may have an update which updates the index 00194 record, but does NOT update the first fields which are 00195 referenced in a foreign key constraint. Then the update does 00196 NOT break the constraint. */ 00197 00198 if (foreign->referenced_index == index 00199 && (node->is_delete 00200 || row_upd_changes_first_fields_binary( 00201 entry, index, node->update, 00202 foreign->n_fields))) { 00203 00204 if (foreign->foreign_table == NULL) { 00205 dict_table_get(foreign->foreign_table_name); 00206 } 00207 00208 if (foreign->foreign_table) { 00209 mutex_enter(&(dict_sys->mutex)); 00210 00211 (foreign->foreign_table 00212 ->n_foreign_key_checks_running)++; 00213 00214 mutex_exit(&(dict_sys->mutex)); 00215 } 00216 00217 /* NOTE that if the thread ends up waiting for a lock 00218 we will release dict_operation_lock temporarily! 00219 But the counter on the table protects 'foreign' from 00220 being dropped while the check is running. */ 00221 00222 err = row_ins_check_foreign_constraint(FALSE, foreign, 00223 table, entry, thr); 00224 00225 if (foreign->foreign_table) { 00226 mutex_enter(&(dict_sys->mutex)); 00227 00228 ut_a(foreign->foreign_table 00229 ->n_foreign_key_checks_running > 0); 00230 00231 (foreign->foreign_table 00232 ->n_foreign_key_checks_running)--; 00233 00234 mutex_exit(&(dict_sys->mutex)); 00235 } 00236 00237 if (err != DB_SUCCESS) { 00238 if (got_s_lock) { 00239 row_mysql_unfreeze_data_dictionary( 00240 trx); 00241 } 00242 00243 mem_heap_free(heap); 00244 00245 return(err); 00246 } 00247 } 00248 00249 foreign = UT_LIST_GET_NEXT(referenced_list, foreign); 00250 } 00251 00252 if (got_s_lock) { 00253 row_mysql_unfreeze_data_dictionary(trx); 00254 } 00255 00256 mem_heap_free(heap); 00257 00258 return(DB_SUCCESS); 00259 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_upd_clust_rec | ( | upd_node_t * | node, | |
| dict_index_t * | index, | |||
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 1500 of file row0upd.c.
References btr_cur_get_rec(), btr_cur_optimistic_update(), btr_cur_pessimistic_update(), btr_cur_update_in_place(), BTR_MODIFY_TREE, BTR_NO_LOCKING_FLAG, btr_pcur_get_btr_cur(), btr_pcur_get_rec(), btr_pcur_restore_position(), btr_store_big_rec_extern_fields(), buf_LRU_buf_pool_running_out(), upd_node_struct::cmpl_info, DB_LOCK_TABLE_FULL, DB_SUCCESS, DICT_CLUSTERED, dict_table_is_comp(), dtuple_big_rec_free(), err, index(), mem_heap_free, mtr_commit(), mtr_start(), NULL, upd_node_struct::pcur, rec_get_deleted_flag(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, UPD_NODE_NO_SIZE_CHANGE, upd_node_struct::update, ut_a, and ut_ad.
Referenced by row_upd_clust_step().
01502 : DB_SUCCESS if operation successfully 01503 completed, else error code or DB_LOCK_WAIT */ 01504 upd_node_t* node, /* in: row update node */ 01505 dict_index_t* index, /* in: clustered index */ 01506 que_thr_t* thr, /* in: query thread */ 01507 mtr_t* mtr) /* in: mtr; gets committed here */ 01508 { 01509 big_rec_t* big_rec = NULL; 01510 btr_pcur_t* pcur; 01511 btr_cur_t* btr_cur; 01512 ulint err; 01513 01514 ut_ad(node); 01515 ut_ad(index->type & DICT_CLUSTERED); 01516 01517 pcur = node->pcur; 01518 btr_cur = btr_pcur_get_btr_cur(pcur); 01519 01520 ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), 01521 dict_table_is_comp(index->table))); 01522 01523 /* Try optimistic updating of the record, keeping changes within 01524 the page; we do not check locks because we assume the x-lock on the 01525 record to update */ 01526 01527 if (node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE) { 01528 err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, 01529 btr_cur, node->update, 01530 node->cmpl_info, thr, mtr); 01531 } else { 01532 err = btr_cur_optimistic_update(BTR_NO_LOCKING_FLAG, 01533 btr_cur, node->update, 01534 node->cmpl_info, thr, mtr); 01535 } 01536 01537 mtr_commit(mtr); 01538 01539 if (err == DB_SUCCESS) { 01540 01541 return(err); 01542 } 01543 01544 if (buf_LRU_buf_pool_running_out()) { 01545 01546 return(DB_LOCK_TABLE_FULL); 01547 } 01548 /* We may have to modify the tree structure: do a pessimistic descent 01549 down the index tree */ 01550 01551 mtr_start(mtr); 01552 01553 /* NOTE: this transaction has an s-lock or x-lock on the record and 01554 therefore other transactions cannot modify the record when we have no 01555 latch on the page. In addition, we assume that other query threads of 01556 the same transaction do not modify the record in the meantime. 01557 Therefore we can assert that the restoration of the cursor succeeds. */ 01558 01559 ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr)); 01560 01561 ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), 01562 dict_table_is_comp(index->table))); 01563 01564 err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur, 01565 &big_rec, node->update, 01566 node->cmpl_info, thr, mtr); 01567 mtr_commit(mtr); 01568 01569 if (err == DB_SUCCESS && big_rec) { 01570 mem_heap_t* heap = NULL; 01571 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01572 rec_t* rec; 01573 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01574 01575 mtr_start(mtr); 01576 01577 ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr)); 01578 rec = btr_cur_get_rec(btr_cur); 01579 err = btr_store_big_rec_extern_fields(index, rec, 01580 rec_get_offsets(rec, index, offsets_, 01581 ULINT_UNDEFINED, &heap), 01582 big_rec, mtr); 01583 if (UNIV_LIKELY_NULL(heap)) { 01584 mem_heap_free(heap); 01585 } 01586 mtr_commit(mtr); 01587 } 01588 01589 if (big_rec) { 01590 dtuple_big_rec_free(big_rec); 01591 } 01592 01593 return(err); 01594 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_upd_clust_rec_by_insert | ( | upd_node_t * | node, | |
| dict_index_t * | index, | |||
| que_thr_t * | thr, | |||
| ibool | check_ref, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 1398 of file row0upd.c.
References btr_cur_del_mark_set_clust_rec(), btr_cur_get_rec(), btr_cur_mark_dtuple_inherited_extern(), btr_cur_mark_extern_inherited_fields(), btr_cur_unmark_dtuple_extern_fields(), BTR_NO_LOCKING_FLAG, btr_pcur_get_btr_cur(), DATA_TRX_ID, DB_SUCCESS, DICT_CLUSTERED, dict_table_get_first_index(), err, upd_node_struct::ext_vec, trx_struct::id, index(), mem_heap_create, mem_heap_free, mtr_commit(), upd_node_struct::n_ext_vec, NULL, upd_node_struct::pcur, rec_get_offsets, REC_OFFS_NORMAL_SIZE, upd_node_struct::row, row_build_index_entry(), row_ins_index_entry(), row_upd_check_references_constraints(), row_upd_index_entry_sys_field(), row_upd_index_replace_new_col_vals(), upd_node_struct::state, upd_node_struct::table, thr_get_trx(), TRUE, UPD_NODE_INSERT_CLUSTERED, upd_node_struct::update, and ut_ad.
Referenced by row_upd_clust_step().
01400 : DB_SUCCESS if operation successfully 01401 completed, else error code or DB_LOCK_WAIT */ 01402 upd_node_t* node, /* in: row update node */ 01403 dict_index_t* index, /* in: clustered index of the record */ 01404 que_thr_t* thr, /* in: query thread */ 01405 ibool check_ref,/* in: TRUE if index may be referenced in 01406 a foreign key constraint */ 01407 mtr_t* mtr) /* in: mtr; gets committed here */ 01408 { 01409 mem_heap_t* heap = NULL; 01410 btr_pcur_t* pcur; 01411 btr_cur_t* btr_cur; 01412 trx_t* trx; 01413 dict_table_t* table; 01414 dtuple_t* entry; 01415 ulint err; 01416 01417 ut_ad(node); 01418 ut_ad(index->type & DICT_CLUSTERED); 01419 01420 trx = thr_get_trx(thr); 01421 table = node->table; 01422 pcur = node->pcur; 01423 btr_cur = btr_pcur_get_btr_cur(pcur); 01424 01425 if (node->state != UPD_NODE_INSERT_CLUSTERED) { 01426 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01427 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01428 01429 err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG, 01430 btr_cur, TRUE, thr, mtr); 01431 if (err != DB_SUCCESS) { 01432 mtr_commit(mtr); 01433 return(err); 01434 } 01435 01436 /* Mark as not-owned the externally stored fields which the new 01437 row inherits from the delete marked record: purge should not 01438 free those externally stored fields even if the delete marked 01439 record is removed from the index tree, or updated. */ 01440 01441 btr_cur_mark_extern_inherited_fields(btr_cur_get_rec(btr_cur), 01442 rec_get_offsets(btr_cur_get_rec(btr_cur), 01443 dict_table_get_first_index(table), offsets_, 01444 ULINT_UNDEFINED, &heap), node->update, mtr); 01445 if (check_ref) { 01446 /* NOTE that the following call loses 01447 the position of pcur ! */ 01448 err = row_upd_check_references_constraints(node, 01449 pcur, table, 01450 index, thr, mtr); 01451 if (err != DB_SUCCESS) { 01452 mtr_commit(mtr); 01453 if (UNIV_LIKELY_NULL(heap)) { 01454 mem_heap_free(heap); 01455 } 01456 return(err); 01457 } 01458 } 01459 01460 } 01461 01462 mtr_commit(mtr); 01463 01464 if (!heap) { 01465 heap = mem_heap_create(500); 01466 } 01467 node->state = UPD_NODE_INSERT_CLUSTERED; 01468 01469 entry = row_build_index_entry(node->row, index, heap); 01470 01471 row_upd_index_replace_new_col_vals(entry, index, node->update, NULL); 01472 01473 row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id); 01474 01475 /* If we return from a lock wait, for example, we may have 01476 extern fields marked as not-owned in entry (marked in the 01477 if-branch above). We must unmark them. */ 01478 01479 btr_cur_unmark_dtuple_extern_fields(entry, node->ext_vec, 01480 node->n_ext_vec); 01481 /* We must mark non-updated extern fields in entry as inherited, 01482 so that a possible rollback will not free them */ 01483 01484 btr_cur_mark_dtuple_inherited_extern(entry, node->ext_vec, 01485 node->n_ext_vec, 01486 node->update); 01487 01488 err = row_ins_index_entry(index, entry, node->ext_vec, 01489 node->n_ext_vec, thr); 01490 mem_heap_free(heap); 01491 01492 return(err); 01493 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_upd_clust_step | ( | upd_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 1654 of file row0upd.c.
References BTR_MODIFY_LEAF, btr_pcur_get_rec(), BTR_PCUR_ON, btr_pcur_restore_position(), upd_node_struct::cmpl_info, upd_node_struct::columns, DB_ERROR, DB_RECORD_NOT_FOUND, DB_SUCCESS, dict_drop_index_tree(), DICT_INDEXES_ID, dict_table_get_first_index(), dict_table_get_next_index(), err, upd_node_struct::has_clust_rec_x_lock, dict_table_struct::id, upd_node_struct::in_mysql_interface, upd_node_struct::index, index(), upd_node_struct::is_delete, lock_clust_rec_modify_check_and_lock(), mem_heap_free, mtr_commit(), mtr_start(), NULL, upd_node_struct::pcur, rec_get_offsets, REC_OFFS_NORMAL_SIZE, btr_pcur_struct::rel_pos, upd_node_struct::row, row_upd_changes_ord_field_binary(), row_upd_clust_rec(), row_upd_clust_rec_by_insert(), row_upd_copy_columns(), row_upd_del_mark_clust_rec(), row_upd_eval_new_vals(), row_upd_index_is_referenced(), row_upd_store_row(), upd_node_struct::state, upd_node_struct::table, thr_get_trx(), UPD_NODE_NO_ORD_CHANGE, UPD_NODE_UPDATE_ALL_SEC, UPD_NODE_UPDATE_SOME_SEC, upd_node_struct::update, ut_a, ut_dulint_cmp(), and UT_LIST_GET_FIRST.
Referenced by row_upd().
01656 : DB_SUCCESS if operation successfully 01657 completed, DB_LOCK_WAIT in case of a lock wait, 01658 else error code */ 01659 upd_node_t* node, /* in: row update node */ 01660 que_thr_t* thr) /* in: query thread */ 01661 { 01662 dict_index_t* index; 01663 btr_pcur_t* pcur; 01664 ibool success; 01665 ibool check_ref; 01666 ulint err; 01667 mtr_t* mtr; 01668 mtr_t mtr_buf; 01669 rec_t* rec; 01670 mem_heap_t* heap = NULL; 01671 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01672 const ulint* offsets; 01673 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01674 01675 index = dict_table_get_first_index(node->table); 01676 01677 check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr)); 01678 01679 pcur = node->pcur; 01680 01681 /* We have to restore the cursor to its position */ 01682 mtr = &mtr_buf; 01683 01684 mtr_start(mtr); 01685 01686 /* If the restoration does not succeed, then the same 01687 transaction has deleted the record on which the cursor was, 01688 and that is an SQL error. If the restoration succeeds, it may 01689 still be that the same transaction has successively deleted 01690 and inserted a record with the same ordering fields, but in 01691 that case we know that the transaction has at least an 01692 implicit x-lock on the record. */ 01693 01694 ut_a(pcur->rel_pos == BTR_PCUR_ON); 01695 01696 success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); 01697 01698 if (!success) { 01699 err = DB_RECORD_NOT_FOUND; 01700 01701 mtr_commit(mtr); 01702 01703 return(err); 01704 } 01705 01706 /* If this is a row in SYS_INDEXES table of the data dictionary, 01707 then we have to free the file segments of the index tree associated 01708 with the index */ 01709 01710 if (node->is_delete 01711 && ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) { 01712 01713 dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr); 01714 01715 mtr_commit(mtr); 01716 01717 mtr_start(mtr); 01718 01719 success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, 01720 mtr); 01721 if (!success) { 01722 err = DB_ERROR; 01723 01724 mtr_commit(mtr); 01725 01726 return(err); 01727 } 01728 } 01729 01730 rec = btr_pcur_get_rec(pcur); 01731 offsets = rec_get_offsets(rec, index, offsets_, 01732 ULINT_UNDEFINED, &heap); 01733 01734 if (!node->has_clust_rec_x_lock) { 01735 err = lock_clust_rec_modify_check_and_lock(0, 01736 rec, index, offsets, thr); 01737 if (err != DB_SUCCESS) { 01738 mtr_commit(mtr); 01739 goto exit_func; 01740 } 01741 } 01742 01743 /* NOTE: the following function calls will also commit mtr */ 01744 01745 if (node->is_delete) { 01746 err = row_upd_del_mark_clust_rec(node, index, thr, check_ref, 01747 mtr); 01748 if (err == DB_SUCCESS) { 01749 node->state = UPD_NODE_UPDATE_ALL_SEC; 01750 node->index = dict_table_get_next_index(index); 01751 } 01752 exit_func: 01753 if (UNIV_LIKELY_NULL(heap)) { 01754 mem_heap_free(heap); 01755 } 01756 return(err); 01757 } 01758 01759 /* If the update is made for MySQL, we already have the update vector 01760 ready, else we have to do some evaluation: */ 01761 01762 if (!node->in_mysql_interface) { 01763 /* Copy the necessary columns from clust_rec and calculate the 01764 new values to set */ 01765 row_upd_copy_columns(rec, offsets, 01766 UT_LIST_GET_FIRST(node->columns)); 01767 row_upd_eval_new_vals(node->update); 01768 } 01769 01770 if (UNIV_LIKELY_NULL(heap)) { 01771 mem_heap_free(heap); 01772 } 01773 01774 if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) { 01775 01776 err = row_upd_clust_rec(node, index, thr, mtr); 01777 return(err); 01778 } 01779 01780 row_upd_store_row(node); 01781 01782 if (row_upd_changes_ord_field_binary(node->row, index, node->update)) { 01783 01784 /* Update causes an ordering field (ordering fields within 01785 the B-tree) of the clustered index record to change: perform 01786 the update by delete marking and inserting. 01787 01788 TODO! What to do to the 'Halloween problem', where an update 01789 moves the record forward in index so that it is again 01790 updated when the cursor arrives there? Solution: the 01791 read operation must check the undo record undo number when 01792 choosing records to update. MySQL solves now the problem 01793 externally! */ 01794 01795 err = row_upd_clust_rec_by_insert(node, index, thr, check_ref, 01796 mtr); 01797 if (err != DB_SUCCESS) { 01798 01799 return(err); 01800 } 01801 01802 node->state = UPD_NODE_UPDATE_ALL_SEC; 01803 } else { 01804 err = row_upd_clust_rec(node, index, thr, mtr); 01805 01806 if (err != DB_SUCCESS) { 01807 01808 return(err); 01809 } 01810 01811 node->state = UPD_NODE_UPDATE_SOME_SEC; 01812 } 01813 01814 node->index = dict_table_get_next_index(index); 01815 01816 return(err); 01817 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void row_upd_copy_columns | ( | rec_t * | rec, | |
| const ulint * | offsets, | |||
| sym_node_t * | column | |||
| ) |
Definition at line 1165 of file row0upd.c.
References data, eval_node_copy_and_alloc_val(), sym_node_struct::field_nos, rec_get_nth_field(), SYM_CLUST_FIELD_NO, and UT_LIST_GET_NEXT.
Referenced by row_upd_clust_step(), and row_upd_in_place_in_select().
01167 : record in a clustered index */ 01168 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 01169 sym_node_t* column) /* in: first column in a column list, or 01170 NULL */ 01171 { 01172 byte* data; 01173 ulint len; 01174 01175 while (column) { 01176 data = rec_get_nth_field(rec, offsets, 01177 column->field_nos[SYM_CLUST_FIELD_NO], 01178 &len); 01179 eval_node_copy_and_alloc_val(column, data, len); 01180 01181 column = UT_LIST_GET_NEXT(col_var_list, column); 01182 } 01183 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_upd_del_mark_clust_rec | ( | upd_node_t * | node, | |
| dict_index_t * | index, | |||
| que_thr_t * | thr, | |||
| ibool | check_ref, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 1600 of file row0upd.c.
References btr_cur_del_mark_set_clust_rec(), BTR_NO_LOCKING_FLAG, btr_pcur_get_btr_cur(), DB_SUCCESS, DICT_CLUSTERED, err, index(), upd_node_struct::is_delete, mtr_commit(), upd_node_struct::pcur, row_upd_check_references_constraints(), row_upd_store_row(), TRUE, and ut_ad.
Referenced by row_upd_clust_step().
01602 : DB_SUCCESS if operation successfully 01603 completed, else error code */ 01604 upd_node_t* node, /* in: row update node */ 01605 dict_index_t* index, /* in: clustered index */ 01606 que_thr_t* thr, /* in: query thread */ 01607 ibool check_ref,/* in: TRUE if index may be referenced in 01608 a foreign key constraint */ 01609 mtr_t* mtr) /* in: mtr; gets committed here */ 01610 { 01611 btr_pcur_t* pcur; 01612 btr_cur_t* btr_cur; 01613 ulint err; 01614 01615 ut_ad(node); 01616 ut_ad(index->type & DICT_CLUSTERED); 01617 ut_ad(node->is_delete); 01618 01619 pcur = node->pcur; 01620 btr_cur = btr_pcur_get_btr_cur(pcur); 01621 01622 /* Store row because we have to build also the secondary index 01623 entries */ 01624 01625 row_upd_store_row(node); 01626 01627 /* Mark the clustered index record deleted; we do not have to check 01628 locks, because we assume that we have an x-lock on the record */ 01629 01630 err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG, 01631 btr_cur, TRUE, thr, mtr); 01632 if (err == DB_SUCCESS && check_ref) { 01633 /* NOTE that the following call loses the position of pcur ! */ 01634 01635 err = row_upd_check_references_constraints(node, 01636 pcur, index->table, 01637 index, thr, mtr); 01638 if (err != DB_SUCCESS) { 01639 mtr_commit(mtr); 01640 01641 return(err); 01642 } 01643 } 01644 01645 mtr_commit(mtr); 01646 01647 return(err); 01648 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void row_upd_eval_new_vals | ( | upd_t * | update | ) |
Definition at line 1190 of file row0upd.c.
References dfield_copy_data(), eval_exp(), upd_field_struct::exp, upd_field_struct::new_val, que_node_get_val(), upd_get_n_fields(), upd_get_nth_field(), and update.
Referenced by row_upd_clust_step(), and row_upd_in_place_in_select().
01192 : update vector */ 01193 { 01194 que_node_t* exp; 01195 upd_field_t* upd_field; 01196 ulint n_fields; 01197 ulint i; 01198 01199 n_fields = upd_get_n_fields(update); 01200 01201 for (i = 0; i < n_fields; i++) { 01202 upd_field = upd_get_nth_field(update, i); 01203 01204 exp = upd_field->exp; 01205 01206 eval_exp(exp); 01207 01208 dfield_copy_data(&(upd_field->new_val), que_node_get_val(exp)); 01209 } 01210 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_upd_in_place_in_select | ( | sel_node_t * | sel_node, | |
| que_thr_t * | thr, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 2013 of file row0upd.c.
References sel_node_struct::asc, btr_cur_update_in_place(), BTR_MODIFY_LEAF, BTR_NO_LOCKING_FLAG, btr_pcur_get_btr_cur(), btr_pcur_get_rec(), upd_node_struct::cmpl_info, upd_node_struct::columns, DB_SUCCESS, dict_table_is_comp(), err, btr_cur_struct::index, sel_node_struct::latch_mode, mem_heap_free, NULL, upd_node_struct::pcur, que_node_get_parent(), que_node_get_type(), QUE_NODE_UPDATE, rec_get_deleted_flag(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, row_upd_copy_columns(), row_upd_eval_new_vals(), upd_node_struct::select_will_do_update, sel_node_struct::select_will_do_update, dict_index_struct::table, UPD_NODE_NO_ORD_CHANGE, UPD_NODE_NO_SIZE_CHANGE, upd_node_struct::update, ut_ad, and UT_LIST_GET_FIRST.
Referenced by row_sel().
02015 : select node */ 02016 que_thr_t* thr, /* in: query thread */ 02017 mtr_t* mtr) /* in: mtr */ 02018 { 02019 upd_node_t* node; 02020 btr_pcur_t* pcur; 02021 btr_cur_t* btr_cur; 02022 ulint err; 02023 mem_heap_t* heap = NULL; 02024 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 02025 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 02026 02027 ut_ad(sel_node->select_will_do_update); 02028 ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF); 02029 ut_ad(sel_node->asc); 02030 02031 node = que_node_get_parent(sel_node); 02032 02033 ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE); 02034 02035 pcur = node->pcur; 02036 btr_cur = btr_pcur_get_btr_cur(pcur); 02037 02038 /* Copy the necessary columns from clust_rec and calculate the new 02039 values to set */ 02040 02041 row_upd_copy_columns(btr_pcur_get_rec(pcur), rec_get_offsets( 02042 btr_pcur_get_rec(pcur), btr_cur->index, offsets_, 02043 ULINT_UNDEFINED, &heap), 02044 UT_LIST_GET_FIRST(node->columns)); 02045 if (UNIV_LIKELY_NULL(heap)) { 02046 mem_heap_free(heap); 02047 } 02048 row_upd_eval_new_vals(node->update); 02049 02050 ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), 02051 dict_table_is_comp(btr_cur->index->table))); 02052 02053 ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE); 02054 ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE); 02055 ut_ad(node->select_will_do_update); 02056 02057 err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur, 02058 node->update, node->cmpl_info, 02059 thr, mtr); 02060 ut_ad(err == DB_SUCCESS); 02061 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_upd_index_entry_sys_field | ( | dtuple_t * | entry, | |
| dict_index_t * | index, | |||
| ulint | type, | |||
| dulint | val | |||
| ) |
Definition at line 327 of file row0upd.c.
References DATA_ROLL_PTR, DATA_TRX_ID, dfield_get_data(), DICT_CLUSTERED, dict_index_get_sys_col_pos(), dtuple_get_nth_field(), index(), pos(), trx_write_roll_ptr(), trx_write_trx_id(), and ut_ad.
Referenced by btr_cur_ins_lock_and_undo(), btr_cur_optimistic_update(), btr_cur_pessimistic_update(), and row_upd_clust_rec_by_insert().
00329 : index entry, where the memory buffers 00330 for sys fields are already allocated: 00331 the function just copies the new values to 00332 them */ 00333 dict_index_t* index, /* in: clustered index */ 00334 ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */ 00335 dulint val) /* in: value to write */ 00336 { 00337 dfield_t* dfield; 00338 byte* field; 00339 ulint pos; 00340 00341 ut_ad(index->type & DICT_CLUSTERED); 00342 00343 pos = dict_index_get_sys_col_pos(index, type); 00344 00345 dfield = dtuple_get_nth_field(entry, pos); 00346 field = dfield_get_data(dfield); 00347 00348 if (type == DATA_TRX_ID) { 00349 trx_write_trx_id(field, val); 00350 } else { 00351 ut_ad(type == DATA_ROLL_PTR); 00352 trx_write_roll_ptr(field, val); 00353 } 00354 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool row_upd_index_is_referenced | ( | dict_index_t * | index, | |
| trx_t * | trx | |||
| ) | [static] |
Definition at line 95 of file row0upd.c.
References trx_struct::dict_operation_lock_mode, FALSE, index(), dict_foreign_struct::referenced_index, dict_table_struct::referenced_list, row_mysql_freeze_data_dictionary(), row_mysql_unfreeze_data_dictionary(), TRUE, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by row_upd_clust_step(), and row_upd_sec_index_entry().
00097 : TRUE if referenced; NOTE that since 00098 we do not hold dict_operation_lock 00099 when leaving the function, it may be that 00100 the referencing table has been dropped when 00101 we leave this function: this function is only 00102 for heuristic use! */ 00103 dict_index_t* index, /* in: index */ 00104 trx_t* trx) /* in: transaction */ 00105 { 00106 dict_table_t* table = index->table; 00107 dict_foreign_t* foreign; 00108 ibool froze_data_dict = FALSE; 00109 00110 if (!UT_LIST_GET_FIRST(table->referenced_list)) { 00111 00112 return(FALSE); 00113 } 00114 00115 if (trx->dict_operation_lock_mode == 0) { 00116 row_mysql_freeze_data_dictionary(trx); 00117 froze_data_dict = TRUE; 00118 } 00119 00120 foreign = UT_LIST_GET_FIRST(table->referenced_list); 00121 00122 while (foreign) { 00123 if (foreign->referenced_index == index) { 00124 00125 if (froze_data_dict) { 00126 row_mysql_unfreeze_data_dictionary(trx); 00127 } 00128 00129 return(TRUE); 00130 } 00131 00132 foreign = UT_LIST_GET_NEXT(referenced_list, foreign); 00133 } 00134 00135 if (froze_data_dict) { 00136 row_mysql_unfreeze_data_dictionary(trx); 00137 } 00138 00139 return(FALSE); 00140 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* row_upd_index_parse | ( | byte * | ptr, | |
| byte * | end_ptr, | |||
| mem_heap_t * | heap, | |||
| upd_t ** | update_out | |||
| ) |
Definition at line 598 of file row0upd.c.
References buf, dfield_struct::data, upd_field_struct::field_no, dfield_struct::len, mach_parse_compressed(), mach_read_from_1(), mem_heap_alloc(), upd_field_struct::new_val, NULL, upd_create(), upd_get_nth_field(), update, and ut_memcpy().
Referenced by btr_cur_parse_update_in_place().
00600 : log data end or NULL */ 00601 byte* ptr, /* in: buffer */ 00602 byte* end_ptr,/* in: buffer end */ 00603 mem_heap_t* heap, /* in: memory heap where update vector is 00604 built */ 00605 upd_t** update_out)/* out: update vector */ 00606 { 00607 upd_t* update; 00608 upd_field_t* upd_field; 00609 dfield_t* new_val; 00610 ulint len; 00611 ulint n_fields; 00612 byte* buf; 00613 ulint info_bits; 00614 ulint i; 00615 00616 if (end_ptr < ptr + 1) { 00617 00618 return(NULL); 00619 } 00620 00621 info_bits = mach_read_from_1(ptr); 00622 ptr++; 00623 ptr = mach_parse_compressed(ptr, end_ptr, &n_fields); 00624 00625 if (ptr == NULL) { 00626 00627 return(NULL); 00628 } 00629 00630 update = upd_create(n_fields, heap); 00631 update->info_bits = info_bits; 00632 00633 for (i = 0; i < n_fields; i++) { 00634 upd_field = upd_get_nth_field(update, i); 00635 new_val = &(upd_field->new_val); 00636 00637 ptr = mach_parse_compressed(ptr, end_ptr, 00638 &(upd_field->field_no)); 00639 if (ptr == NULL) { 00640 00641 return(NULL); 00642 } 00643 00644 ptr = mach_parse_compressed(ptr, end_ptr, &len); 00645 00646 if (ptr == NULL) { 00647 00648 return(NULL); 00649 } 00650 00651 new_val->len = len; 00652 00653 if (len != UNIV_SQL_NULL) { 00654 00655 if (end_ptr < ptr + len) { 00656 00657 return(NULL); 00658 } else { 00659 buf = mem_heap_alloc(heap, len); 00660 ut_memcpy(buf, ptr, len); 00661 00662 ptr += len; 00663 00664 new_val->data = buf; 00665 } 00666 } 00667 } 00668 00669 *update_out = update; 00670 00671 return(ptr); 00672 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_upd_index_replace_new_col_vals | ( | dtuple_t * | entry, | |
| dict_index_t * | index, | |||
| upd_t * | update, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 945 of file row0upd.c.
References dict_col_struct::clust_pos, dict_field_struct::col, dfield_struct::data, dfield_set_data(), dict_col_get_type(), dict_field_get_col(), dict_index_get_n_fields(), dict_index_get_nth_field(), dtuple_get_nth_field(), dtuple_set_info_bits(), dtype_get_at_most_n_mbchars(), upd_field_struct::field_no, index(), dfield_struct::len, mem_heap_alloc(), upd_field_struct::new_val, dict_field_struct::prefix_len, upd_get_n_fields(), upd_get_nth_field(), update, ut_ad, and ut_memcpy().
Referenced by row_undo_mod_upd_exist_sec(), row_upd_clust_rec_by_insert(), row_upd_sec_index_entry(), and trx_undo_prev_version_build().
00947 : index entry where replaced */ 00948 dict_index_t* index, /* in: index; NOTE that this may also be a 00949 non-clustered index */ 00950 upd_t* update, /* in: an update vector built for the 00951 CLUSTERED index so that the field number in 00952 an upd_field is the clustered index position */ 00953 mem_heap_t* heap) /* in: memory heap to which we allocate and 00954 copy the new values, set this as NULL if you 00955 do not want allocation */ 00956 { 00957 dict_field_t* field; 00958 upd_field_t* upd_field; 00959 dfield_t* dfield; 00960 dfield_t* new_val; 00961 ulint j; 00962 ulint i; 00963 dtype_t* cur_type; 00964 00965 ut_ad(index); 00966 00967 dtuple_set_info_bits(entry, update->info_bits); 00968 00969 for (j = 0; j < dict_index_get_n_fields(index); j++) { 00970 00971 field = dict_index_get_nth_field(index, j); 00972 00973 for (i = 0; i < upd_get_n_fields(update); i++) { 00974 00975 upd_field = upd_get_nth_field(update, i); 00976 00977 if (upd_field->field_no == field->col->clust_pos) { 00978 00979 dfield = dtuple_get_nth_field(entry, j); 00980 00981 new_val = &(upd_field->new_val); 00982 00983 dfield_set_data(dfield, new_val->data, 00984 new_val->len); 00985 if (heap && new_val->len != UNIV_SQL_NULL) { 00986 dfield->data = mem_heap_alloc(heap, 00987 new_val->len); 00988 ut_memcpy(dfield->data, new_val->data, 00989 new_val->len); 00990 } 00991 00992 if (field->prefix_len > 0 00993 && new_val->len != UNIV_SQL_NULL) { 00994 00995 cur_type = dict_col_get_type( 00996 dict_field_get_col(field)); 00997 00998 dfield->len = 00999 dtype_get_at_most_n_mbchars( 01000 cur_type, 01001 field->prefix_len, 01002 new_val->len, 01003 new_val->data); 01004 } 01005 } 01006 } 01007 } 01008 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_upd_index_replace_new_col_vals_index_pos | ( | dtuple_t * | entry, | |
| dict_index_t * | index, | |||
| upd_t * | update, | |||
| ibool | order_only, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 864 of file row0upd.c.
References dfield_struct::data, dfield_set_data(), dict_col_get_type(), dict_field_get_col(), dict_index_get_n_fields(), dict_index_get_n_unique(), dict_index_get_nth_field(), dtuple_get_nth_field(), dtuple_set_info_bits(), dtype_get_at_most_n_mbchars(), upd_field_struct::field_no, index(), dfield_struct::len, mem_heap_alloc(), upd_field_struct::new_val, dict_field_struct::prefix_len, upd_get_n_fields(), upd_get_nth_field(), update, ut_ad, and ut_memcpy().
Referenced by btr_cur_optimistic_update(), and btr_cur_pessimistic_update().
00866 : index entry where replaced */ 00867 dict_index_t* index, /* in: index; NOTE that this may also be a 00868 non-clustered index */ 00869 upd_t* update, /* in: an update vector built for the index so 00870 that the field number in an upd_field is the 00871 index position */ 00872 ibool order_only, 00873 /* in: if TRUE, limit the replacement to 00874 ordering fields of index; note that this 00875 does not work for non-clustered indexes. */ 00876 mem_heap_t* heap) /* in: memory heap to which we allocate and 00877 copy the new values, set this as NULL if you 00878 do not want allocation */ 00879 { 00880 dict_field_t* field; 00881 upd_field_t* upd_field; 00882 dfield_t* dfield; 00883 dfield_t* new_val; 00884 ulint j; 00885 ulint i; 00886 ulint n_fields; 00887 dtype_t* cur_type; 00888 00889 ut_ad(index); 00890 00891 dtuple_set_info_bits(entry, update->info_bits); 00892 00893 if (order_only) { 00894 n_fields = dict_index_get_n_unique(index); 00895 } else { 00896 n_fields = dict_index_get_n_fields(index); 00897 } 00898 00899 for (j = 0; j < n_fields; j++) { 00900 00901 field = dict_index_get_nth_field(index, j); 00902 00903 for (i = 0; i < upd_get_n_fields(update); i++) { 00904 00905 upd_field = upd_get_nth_field(update, i); 00906 00907 if (upd_field->field_no == j) { 00908 00909 dfield = dtuple_get_nth_field(entry, j); 00910 00911 new_val = &(upd_field->new_val); 00912 00913 dfield_set_data(dfield, new_val->data, 00914 new_val->len); 00915 if (heap && new_val->len != UNIV_SQL_NULL) { 00916 dfield->data = mem_heap_alloc(heap, 00917 new_val->len); 00918 ut_memcpy(dfield->data, new_val->data, 00919 new_val->len); 00920 } 00921 00922 if (field->prefix_len > 0 00923 && new_val->len != UNIV_SQL_NULL) { 00924 00925 cur_type = dict_col_get_type( 00926 dict_field_get_col(field)); 00927 00928 dfield->len = 00929 dtype_get_at_most_n_mbchars( 00930 cur_type, 00931 field->prefix_len, 00932 new_val->len, 00933 new_val->data); 00934 } 00935 } 00936 } 00937 } 00938 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 530 of file row0upd.c.
References dfield_struct::data, error, upd_field_struct::field_no, dfield_struct::len, mach_write_compressed(), mach_write_to_1(), MLOG_BUF_MARGIN, mlog_catenate_string(), mlog_close(), mlog_open(), upd_field_struct::new_val, upd_get_n_fields(), upd_get_nth_field(), update, and ut_memcpy().
Referenced by btr_cur_update_in_place_log().
00532 : update vector */ 00533 byte* log_ptr,/* in: pointer to mlog buffer: must contain at least 00534 MLOG_BUF_MARGIN bytes of free space; the buffer is 00535 closed within this function */ 00536 mtr_t* mtr) /* in: mtr into whose log to write */ 00537 { 00538 upd_field_t* upd_field; 00539 dfield_t* new_val; 00540 ulint len; 00541 ulint n_fields; 00542 byte* buf_end; 00543 ulint i; 00544 00545 n_fields = upd_get_n_fields(update); 00546 00547 buf_end = log_ptr + MLOG_BUF_MARGIN; 00548 00549 mach_write_to_1(log_ptr, update->info_bits); 00550 log_ptr++; 00551 log_ptr += mach_write_compressed(log_ptr, n_fields); 00552 00553 for (i = 0; i < n_fields; i++) { 00554 00555 #if MLOG_BUF_MARGIN <= 30 00556 # error "MLOG_BUF_MARGIN <= 30" 00557 #endif 00558 00559 if (log_ptr + 30 > buf_end) { 00560 mlog_close(mtr, log_ptr); 00561 00562 log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); 00563 buf_end = log_ptr + MLOG_BUF_MARGIN; 00564 } 00565 00566 upd_field = upd_get_nth_field(update, i); 00567 00568 new_val = &(upd_field->new_val); 00569 00570 len = new_val->len; 00571 00572 log_ptr += mach_write_compressed(log_ptr, upd_field->field_no); 00573 log_ptr += mach_write_compressed(log_ptr, len); 00574 00575 if (len != UNIV_SQL_NULL) { 00576 if (log_ptr + len < buf_end) { 00577 ut_memcpy(log_ptr, new_val->data, len); 00578 00579 log_ptr += len; 00580 } else { 00581 mlog_close(mtr, log_ptr); 00582 00583 mlog_catenate_string(mtr, new_val->data, len); 00584 00585 log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); 00586 buf_end = log_ptr + MLOG_BUF_MARGIN; 00587 } 00588 } 00589 } 00590 00591 mlog_close(mtr, log_ptr); 00592 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* row_upd_parse_sys_vals | ( | byte * | ptr, | |
| byte * | end_ptr, | |||
| ulint * | pos, | |||
| dulint * | trx_id, | |||
| dulint * | roll_ptr | |||
| ) |
Definition at line 497 of file row0upd.c.
References DATA_ROLL_PTR_LEN, mach_dulint_parse_compressed(), mach_parse_compressed(), NULL, and trx_read_roll_ptr().
Referenced by btr_cur_parse_del_mark_set_clust_rec(), and btr_cur_parse_update_in_place().
00499 : log data end or NULL */ 00500 byte* ptr, /* in: buffer */ 00501 byte* end_ptr,/* in: buffer end */ 00502 ulint* pos, /* out: TRX_ID position in record */ 00503 dulint* trx_id, /* out: trx id */ 00504 dulint* roll_ptr)/* out: roll ptr */ 00505 { 00506 ptr = mach_parse_compressed(ptr, end_ptr, pos); 00507 00508 if (ptr == NULL) { 00509 00510 return(NULL); 00511 } 00512 00513 if (end_ptr < ptr + DATA_ROLL_PTR_LEN) { 00514 00515 return(NULL); 00516 } 00517 00518 *roll_ptr = trx_read_roll_ptr(ptr); 00519 ptr += DATA_ROLL_PTR_LEN; 00520 00521 ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id); 00522 00523 return(ptr); 00524 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 437 of file row0upd.c.
References dfield_get_data(), dfield_get_len(), upd_field_struct::field_no, upd_field_struct::new_val, NULL, rec_offs_comp(), rec_offs_validate(), rec_set_info_bits(), rec_set_nth_field(), upd_get_n_fields(), upd_get_nth_field(), update, and ut_ad.
Referenced by btr_cur_parse_update_in_place(), btr_cur_update_in_place(), and trx_undo_prev_version_build().
00439 : record where replaced */ 00440 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 00441 upd_t* update) /* in: update vector */ 00442 { 00443 upd_field_t* upd_field; 00444 dfield_t* new_val; 00445 ulint n_fields; 00446 ulint i; 00447 00448 ut_ad(rec_offs_validate(rec, NULL, offsets)); 00449 00450 rec_set_info_bits(rec, rec_offs_comp(offsets), update->info_bits); 00451 00452 n_fields = upd_get_n_fields(update); 00453 00454 for (i = 0; i < n_fields; i++) { 00455 upd_field = upd_get_nth_field(update, i); 00456 new_val = &(upd_field->new_val); 00457 00458 rec_set_nth_field(rec, offsets, upd_field->field_no, 00459 dfield_get_data(new_val), 00460 dfield_get_len(new_val)); 00461 } 00462 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_upd_rec_sys_fields_in_recovery | ( | rec_t * | rec, | |
| const ulint * | offsets, | |||
| ulint | pos, | |||
| dulint | trx_id, | |||
| dulint | roll_ptr | |||
| ) |
Definition at line 303 of file row0upd.c.
References DATA_ROLL_PTR_LEN, DATA_TRX_ID_LEN, rec_get_nth_field(), trx_write_roll_ptr(), trx_write_trx_id(), and ut_ad.
Referenced by btr_cur_parse_del_mark_set_clust_rec(), and btr_cur_parse_update_in_place().
00305 : record */ 00306 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 00307 ulint pos, /* in: TRX_ID position in rec */ 00308 dulint trx_id, /* in: transaction id */ 00309 dulint roll_ptr)/* in: roll ptr of the undo log record */ 00310 { 00311 byte* field; 00312 ulint len; 00313 00314 field = rec_get_nth_field(rec, offsets, pos, &len); 00315 ut_ad(len == DATA_TRX_ID_LEN); 00316 trx_write_trx_id(field, trx_id); 00317 00318 field = rec_get_nth_field(rec, offsets, pos + 1, &len); 00319 ut_ad(len == DATA_ROLL_PTR_LEN); 00320 trx_write_roll_ptr(field, roll_ptr); 00321 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint row_upd_sec_index_entry | ( | upd_node_t * | node, | |
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 1262 of file row0upd.c.
References btr_cur_del_mark_set_sec_rec(), btr_cur_get_rec(), BTR_MODIFY_LEAF, btr_pcur_close(), btr_pcur_get_btr_cur(), DB_SUCCESS, dict_index_name_print(), dict_table_is_comp(), dtuple_print(), err, upd_node_struct::index, index(), upd_node_struct::is_delete, log_free_check(), mem_heap_create, mem_heap_free, mtr_commit(), mtr_start(), NULL, rec_get_deleted_flag(), rec_print(), upd_node_struct::row, row_build_index_entry(), row_ins_index_entry(), row_search_index_entry(), row_upd_check_references_constraints(), row_upd_index_is_referenced(), row_upd_index_replace_new_col_vals(), thr_get_trx(), TRUE, trx_print(), and upd_node_struct::update.
Referenced by row_upd_sec_step().
01264 : DB_SUCCESS if operation successfully 01265 completed, else error code or DB_LOCK_WAIT */ 01266 upd_node_t* node, /* in: row update node */ 01267 que_thr_t* thr) /* in: query thread */ 01268 { 01269 ibool check_ref; 01270 ibool found; 01271 dict_index_t* index; 01272 dtuple_t* entry; 01273 btr_pcur_t pcur; 01274 btr_cur_t* btr_cur; 01275 mem_heap_t* heap; 01276 rec_t* rec; 01277 ulint err = DB_SUCCESS; 01278 mtr_t mtr; 01279 trx_t* trx = thr_get_trx(thr); 01280 01281 index = node->index; 01282 01283 check_ref = row_upd_index_is_referenced(index, trx); 01284 01285 heap = mem_heap_create(1024); 01286 01287 /* Build old index entry */ 01288 entry = row_build_index_entry(node->row, index, heap); 01289 01290 log_free_check(); 01291 mtr_start(&mtr); 01292 01293 found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur, 01294 &mtr); 01295 btr_cur = btr_pcur_get_btr_cur(&pcur); 01296 01297 rec = btr_cur_get_rec(btr_cur); 01298 01299 if (UNIV_UNLIKELY(!found)) { 01300 fputs("InnoDB: error in sec index entry update in\n" 01301 "InnoDB: ", stderr); 01302 dict_index_name_print(stderr, trx, index); 01303 fputs("\n" 01304 "InnoDB: tuple ", stderr); 01305 dtuple_print(stderr, entry); 01306 fputs("\n" 01307 "InnoDB: record ", stderr); 01308 rec_print(stderr, rec, index); 01309 putc('\n', stderr); 01310 01311 trx_print(stderr, trx, 0); 01312 01313 fputs("\n" 01314 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); 01315 } else { 01316 /* Delete mark the old index record; it can already be 01317 delete marked if we return after a lock wait in 01318 row_ins_index_entry below */ 01319 01320 if (!rec_get_deleted_flag(rec, 01321 dict_table_is_comp(index->table))) { 01322 err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE, 01323 thr, &mtr); 01324 if (err == DB_SUCCESS && check_ref) { 01325 01326 /* NOTE that the following call loses 01327 the position of pcur ! */ 01328 err = row_upd_check_references_constraints( 01329 node, 01330 &pcur, index->table, 01331 index, thr, &mtr); 01332 if (err != DB_SUCCESS) { 01333 01334 goto close_cur; 01335 } 01336 } 01337 01338 } 01339 } 01340 close_cur: 01341 btr_pcur_close(&pcur); 01342 mtr_commit(&mtr); 01343 01344 if (node->is_delete || err != DB_SUCCESS) { 01345 01346 mem_heap_free(heap); 01347 01348 return(err); 01349 } 01350 01351 /* Build a new index entry */ 01352 row_upd_index_replace_new_col_vals(entry, index, node->update, NULL); 01353 01354 /* Insert new index entry */ 01355 err = row_ins_index_entry(index, entry, NULL, 0, thr); 01356 01357 mem_heap_free(heap); 01358 01359 return(err); 01360 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ulint row_upd_sec_step | ( | upd_node_t * | node, | |
| que_thr_t * | thr | |||
| ) |
Definition at line 1367 of file row0upd.c.
References DB_SUCCESS, DICT_CLUSTERED, err, upd_node_struct::index, upd_node_struct::row, row_upd_changes_ord_field_binary(), row_upd_sec_index_entry(), upd_node_struct::state, dict_index_struct::type, UPD_NODE_UPDATE_ALL_SEC, UPD_NODE_UPDATE_SOME_SEC, upd_node_struct::update, and ut_ad.
Referenced by row_upd().
01369 : DB_SUCCESS if operation successfully 01370 completed, else error code or DB_LOCK_WAIT */ 01371 upd_node_t* node, /* in: row update node */ 01372 que_thr_t* thr) /* in: query thread */ 01373 { 01374 ulint err; 01375 01376 ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC) 01377 || (node->state == UPD_NODE_UPDATE_SOME_SEC)); 01378 ut_ad(!(node->index->type & DICT_CLUSTERED)); 01379 01380 if (node->state == UPD_NODE_UPDATE_ALL_SEC 01381 || row_upd_changes_ord_field_binary(node->row, node->index, 01382 node->update)) { 01383 err = row_upd_sec_index_entry(node, thr); 01384 01385 return(err); 01386 } 01387 01388 return(DB_SUCCESS); 01389 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1898 of file row0upd.c.
References DB_ERROR, DB_SUCCESS, err, trx_struct::error_state, upd_node_struct::has_clust_rec_x_lock, LOCK_IX, lock_table(), NULL, que_thr_struct::prev_node, que_node_get_parent(), que_node_get_type(), QUE_NODE_UPDATE, row_upd(), que_thr_struct::run_node, upd_node_struct::searched_update, SEL_NODE_FETCH, SEL_NODE_NO_MORE_ROWS, SEL_NODE_OPEN, upd_node_struct::select, sel_node_struct::state, upd_node_struct::state, upd_node_struct::table, thr_get_trx(), trx_start_if_not_started(), UPD_NODE_SET_IX_LOCK, UPD_NODE_UPDATE_CLUSTERED, ut_ad, and ut_error.
Referenced by que_thr_step(), row_update_cascade_for_mysql(), and row_update_for_mysql().
01900 : query thread to run next or NULL */ 01901 que_thr_t* thr) /* in: query thread */ 01902 { 01903 upd_node_t* node; 01904 sel_node_t* sel_node; 01905 que_node_t* parent; 01906 ulint err = DB_SUCCESS; 01907 trx_t* trx; 01908 01909 ut_ad(thr); 01910 01911 trx = thr_get_trx(thr); 01912 01913 trx_start_if_not_started(trx); 01914 01915 node = thr->run_node; 01916 01917 sel_node = node->select; 01918 01919 parent = que_node_get_parent(node); 01920 01921 ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE); 01922 01923 if (thr->prev_node == parent) { 01924 node->state = UPD_NODE_SET_IX_LOCK; 01925 } 01926 01927 if (node->state == UPD_NODE_SET_IX_LOCK) { 01928 01929 if (!node->has_clust_rec_x_lock) { 01930 /* It may be that the current session has not yet 01931 started its transaction, or it has been committed: */ 01932 01933 err = lock_table(0, node->table, LOCK_IX, thr); 01934 01935 if (err != DB_SUCCESS) { 01936 01937 goto error_handling; 01938 } 01939 } 01940 01941 node->state = UPD_NODE_UPDATE_CLUSTERED; 01942 01943 if (node->searched_update) { 01944 /* Reset the cursor */ 01945 sel_node->state = SEL_NODE_OPEN; 01946 01947 /* Fetch a row to update */ 01948 01949 thr->run_node = sel_node; 01950 01951 return(thr); 01952 } 01953 } 01954 01955 /* sel_node is NULL if we are in the MySQL interface */ 01956 01957 if (sel_node && (sel_node->state != SEL_NODE_FETCH)) { 01958 01959 if (!node->searched_update) { 01960 /* An explicit cursor should be positioned on a row 01961 to update */ 01962 01963 ut_error; 01964 01965 err = DB_ERROR; 01966 01967 goto error_handling; 01968 } 01969 01970 ut_ad(sel_node->state == SEL_NODE_NO_MORE_ROWS); 01971 01972 /* No more rows to update, or the select node performed the 01973 updates directly in-place */ 01974 01975 thr->run_node = parent; 01976 01977 return(thr); 01978 } 01979 01980 /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ 01981 01982 err = row_upd(node, thr); 01983 01984 error_handling: 01985 trx->error_state = err; 01986 01987 if (err != DB_SUCCESS) { 01988 return(NULL); 01989 } 01990 01991 /* DO THE TRIGGER ACTIONS HERE */ 01992 01993 if (node->searched_update) { 01994 /* Fetch next row to update */ 01995 01996 thr->run_node = sel_node; 01997 } else { 01998 /* It was an explicit cursor update */ 01999 02000 thr->run_node = parent; 02001 } 02002 02003 node->state = UPD_NODE_UPDATE_CLUSTERED; 02004 02005 return(thr); 02006 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void row_upd_store_row | ( | upd_node_t * | node | ) | [static] |
Definition at line 1216 of file row0upd.c.
References BTR_NO_LATCHES, btr_pcur_get_rec(), btr_push_update_extern_fields(), dict_table_get_first_index(), upd_node_struct::ext_vec, upd_node_struct::heap, upd_node_struct::is_delete, btr_pcur_struct::latch_mode, mem_heap_alloc(), mem_heap_empty(), mem_heap_free, upd_node_struct::n_ext_vec, NULL, upd_node_struct::pcur, rec_get_offsets, rec_offs_n_fields(), REC_OFFS_NORMAL_SIZE, upd_node_struct::row, row_build(), ROW_COPY_DATA, upd_node_struct::table, upd_node_struct::update, update, and ut_ad.
Referenced by row_upd_clust_step(), and row_upd_del_mark_clust_rec().
01218 : row update node */ 01219 { 01220 dict_index_t* clust_index; 01221 upd_t* update; 01222 rec_t* rec; 01223 mem_heap_t* heap = NULL; 01224 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01225 const ulint* offsets; 01226 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01227 01228 ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES); 01229 01230 if (node->row != NULL) { 01231 mem_heap_empty(node->heap); 01232 node->row = NULL; 01233 } 01234 01235 clust_index = dict_table_get_first_index(node->table); 01236 01237 rec = btr_pcur_get_rec(node->pcur); 01238 01239 offsets = rec_get_offsets(rec, clust_index, offsets_, 01240 ULINT_UNDEFINED, &heap); 01241 node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets, 01242 node->heap); 01243 node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint) 01244 * rec_offs_n_fields(offsets)); 01245 if (node->is_delete) { 01246 update = NULL; 01247 } else { 01248 update = node->update; 01249 } 01250 01251 node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec, 01252 offsets, update); 01253 if (UNIV_LIKELY_NULL(heap)) { 01254 mem_heap_free(heap); 01255 } 01256 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* row_upd_write_sys_vals_to_log | ( | dict_index_t * | index, | |
| trx_t * | trx, | |||
| dulint | roll_ptr, | |||
| byte * | log_ptr, | |||
| mtr_t *mtr | __attribute__((unused)) | |||
| ) |
Definition at line 469 of file row0upd.c.
References DATA_ROLL_PTR_LEN, DATA_TRX_ID, DICT_CLUSTERED, dict_index_get_sys_col_pos(), trx_struct::id, index(), mach_dulint_write_compressed(), mach_write_compressed(), trx_write_roll_ptr(), and ut_ad.
00471 : new pointer to mlog */ 00472 dict_index_t* index, /* in: clustered index */ 00473 trx_t* trx, /* in: transaction */ 00474 dulint roll_ptr,/* in: roll ptr of the undo log record */ 00475 byte* log_ptr,/* pointer to a buffer of size > 20 opened 00476 in mlog */ 00477 mtr_t* mtr __attribute__((unused))) /* in: mtr */ 00478 { 00479 ut_ad(index->type & DICT_CLUSTERED); 00480 ut_ad(mtr); 00481 00482 log_ptr += mach_write_compressed(log_ptr, 00483 dict_index_get_sys_col_pos(index, DATA_TRX_ID)); 00484 00485 trx_write_roll_ptr(log_ptr, roll_ptr); 00486 log_ptr += DATA_ROLL_PTR_LEN; 00487 00488 log_ptr += mach_dulint_write_compressed(log_ptr, trx->id); 00489 00490 return(log_ptr); 00491 }
Here is the call graph for this function:

Definition at line 678 of file row0upd.c.
References FALSE, NULL, and TRUE.
Referenced by row_upd_build_difference_binary().
00680 : TRUE if i is in ext_vec */ 00681 ulint* ext_vec, /* in: array of indexes or NULL */ 00682 ulint n_ext_vec, /* in: number of numbers in ext_vec */ 00683 ulint i) /* in: a number */ 00684 { 00685 ulint j; 00686 00687 if (ext_vec == NULL) { 00688 00689 return(FALSE); 00690 } 00691 00692 for (j = 0; j < n_ext_vec; j++) { 00693 if (ext_vec[j] == i) { 00694 00695 return(TRUE); 00696 } 00697 } 00698 00699 return(FALSE); 00700 }
Here is the caller graph for this function:

| upd_node_t* upd_node_create | ( | mem_heap_t * | heap | ) |
Definition at line 265 of file row0upd.c.
References upd_node_struct::cascade_heap, upd_node_struct::cascade_node, upd_node_struct::cmpl_info, upd_node_struct::common, upd_node_struct::ext_vec, FALSE, upd_node_struct::foreign, upd_node_struct::heap, upd_node_struct::in_mysql_interface, upd_node_struct::index, upd_node_struct::magic_n, mem_heap_alloc(), mem_heap_create, NULL, QUE_NODE_UPDATE, upd_node_struct::row, upd_node_struct::select, upd_node_struct::select_will_do_update, upd_node_struct::state, que_common_struct::type, UPD_NODE_MAGIC_N, UPD_NODE_UPDATE_CLUSTERED, and upd_node_struct::update.
Referenced by pars_update_statement_start(), and row_create_update_node_for_mysql().
00267 : update node */ 00268 mem_heap_t* heap) /* in: mem heap where created */ 00269 { 00270 upd_node_t* node; 00271 00272 node = mem_heap_alloc(heap, sizeof(upd_node_t)); 00273 node->common.type = QUE_NODE_UPDATE; 00274 00275 node->state = UPD_NODE_UPDATE_CLUSTERED; 00276 node->select_will_do_update = FALSE; 00277 node->in_mysql_interface = FALSE; 00278 00279 node->row = NULL; 00280 node->ext_vec = NULL; 00281 node->index = NULL; 00282 node->update = NULL; 00283 00284 node->foreign = NULL; 00285 node->cascade_heap = NULL; 00286 node->cascade_node = NULL; 00287 00288 node->select = NULL; 00289 00290 node->heap = mem_heap_create(128); 00291 node->magic_n = UPD_NODE_MAGIC_N; 00292 00293 node->cmpl_info = 0; 00294 00295 return(node); 00296 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

