#include "univ.i"#include "data0data.h"#include "btr0types.h"#include "btr0pcur.h"#include "dict0types.h"#include "trx0types.h"#include "que0types.h"#include "row0types.h"#include "pars0types.h"Include dependency graph for row0upd.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
| #define UPD_NODE_INSERT_CLUSTERED 3 |
Definition at line 410 of file row0upd.h.
Referenced by row_upd(), and row_upd_clust_rec_by_insert().
| #define UPD_NODE_MAGIC_N 1579975 |
| #define UPD_NODE_NO_ORD_CHANGE 1 |
Definition at line 422 of file row0upd.h.
Referenced by pars_update_statement(), row_purge_parse_undo_rec(), row_undo_mod_upd_exist_sec(), row_upd(), row_upd_clust_step(), row_upd_in_place_in_select(), trx_purge_get_next_rec(), and trx_undo_page_report_modify().
| #define UPD_NODE_NO_SIZE_CHANGE 2 |
Definition at line 425 of file row0upd.h.
Referenced by pars_process_assign_list(), pars_update_statement(), row_upd_clust_rec(), and row_upd_in_place_in_select().
| #define UPD_NODE_SET_IX_LOCK 1 |
| #define UPD_NODE_UPDATE_ALL_SEC 4 |
Definition at line 413 of file row0upd.h.
Referenced by row_upd_clust_step(), and row_upd_sec_step().
| #define UPD_NODE_UPDATE_CLUSTERED 2 |
Definition at line 408 of file row0upd.h.
Referenced by pars_update_statement(), row_upd(), row_upd_step(), row_update_for_mysql(), and upd_node_create().
| #define UPD_NODE_UPDATE_SOME_SEC 5 |
Definition at line 417 of file row0upd.h.
Referenced by row_upd_clust_step(), and row_upd_sec_step().
| 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:

| 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:

| 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(), sel_node_struct::select_will_do_update, upd_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:

| 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:

| UNIV_INLINE void row_upd_rec_sys_fields | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| const ulint * | offsets, | |||
| trx_t * | trx, | |||
| dulint | roll_ptr | |||
| ) |
Referenced by btr_cur_del_mark_set_clust_rec(), and btr_cur_update_in_place().
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:

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, upd_node_struct::state, sel_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:

| byte* row_upd_write_sys_vals_to_log | ( | dict_index_t * | index, | |
| trx_t * | trx, | |||
| dulint | roll_ptr, | |||
| byte * | log_ptr, | |||
| mtr_t * | mtr | |||
| ) |
Referenced by btr_cur_del_mark_set_clust_rec_log(), and btr_cur_update_in_place_log().
Here is the caller graph for this function:

| UNIV_INLINE upd_t* upd_create | ( | ulint | n, | |
| mem_heap_t * | heap | |||
| ) |
Referenced by pars_process_assign_list(), row_create_update_node_for_mysql(), row_ins_foreign_check_on_constraint(), row_upd_build_difference_binary(), row_upd_build_sec_rec_difference_binary(), row_upd_index_parse(), and trx_undo_update_rec_get_update().
Here is the caller graph for this function:

| UNIV_INLINE void upd_field_set_field_no | ( | upd_field_t * | upd_field, | |
| ulint | field_no, | |||
| dict_index_t * | index, | |||
| trx_t * | trx | |||
| ) |
Referenced by pars_process_assign_list(), row_upd_build_difference_binary(), row_upd_build_sec_rec_difference_binary(), and trx_undo_update_rec_get_update().
Here is the caller graph for this function:

Referenced by btr_cur_mark_dtuple_inherited_extern(), btr_cur_mark_extern_inherited_fields(), btr_cur_optimistic_update(), btr_push_update_extern_fields(), btr_rec_free_updated_extern_fields(), row_purge_upd_exist_or_extern(), row_undo_mod_del_unmark_sec_and_undo_update(), row_upd_changes_field_size_or_external(), row_upd_changes_first_fields_binary(), row_upd_changes_ord_field_binary(), row_upd_changes_some_index_ord_field_binary(), row_upd_eval_new_vals(), row_upd_index_replace_new_col_vals(), row_upd_index_replace_new_col_vals_index_pos(), row_upd_index_write_log(), row_upd_rec_in_place(), and trx_undo_page_report_modify().
Here is the caller graph for this function:

| UNIV_INLINE upd_field_t* upd_get_nth_field | ( | upd_t * | update, | |
| ulint | n | |||
| ) |
Referenced by btr_cur_mark_dtuple_inherited_extern(), btr_cur_mark_extern_inherited_fields(), btr_cur_optimistic_update(), btr_push_update_extern_fields(), btr_rec_free_updated_extern_fields(), pars_process_assign_list(), row_purge_upd_exist_or_extern(), row_upd_build_difference_binary(), row_upd_build_sec_rec_difference_binary(), row_upd_changes_field_size_or_external(), row_upd_changes_first_fields_binary(), row_upd_changes_ord_field_binary(), row_upd_changes_some_index_ord_field_binary(), row_upd_eval_new_vals(), row_upd_index_parse(), row_upd_index_replace_new_col_vals(), row_upd_index_replace_new_col_vals_index_pos(), row_upd_index_write_log(), row_upd_rec_in_place(), trx_undo_page_report_modify(), and trx_undo_update_rec_get_update().
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

