1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/row0upd.ic |
22 | Update of a row |
23 | |
24 | Created 12/27/1996 Heikki Tuuri |
25 | *******************************************************/ |
26 | |
27 | #include "mtr0log.h" |
28 | #include "trx0trx.h" |
29 | #include "trx0undo.h" |
30 | #include "row0row.h" |
31 | #include "lock0lock.h" |
32 | #include "page0zip.h" |
33 | |
34 | /*********************************************************************//** |
35 | Creates an update vector object. |
36 | @return own: update vector object */ |
37 | UNIV_INLINE |
38 | upd_t* |
39 | upd_create( |
40 | /*=======*/ |
41 | ulint n, /*!< in: number of fields */ |
42 | mem_heap_t* heap) /*!< in: heap from which memory allocated */ |
43 | { |
44 | upd_t* update; |
45 | |
46 | update = static_cast<upd_t*>(mem_heap_zalloc( |
47 | heap, sizeof(upd_t) + sizeof(upd_field_t) * n)); |
48 | |
49 | update->n_fields = n; |
50 | update->fields = reinterpret_cast<upd_field_t*>(&update[1]); |
51 | update->heap = heap; |
52 | |
53 | return(update); |
54 | } |
55 | |
56 | /*********************************************************************//** |
57 | Returns the number of fields in the update vector == number of columns |
58 | to be updated by an update vector. |
59 | @return number of fields */ |
60 | UNIV_INLINE |
61 | ulint |
62 | upd_get_n_fields( |
63 | /*=============*/ |
64 | const upd_t* update) /*!< in: update vector */ |
65 | { |
66 | ut_ad(update); |
67 | |
68 | return(update->n_fields); |
69 | } |
70 | |
71 | #ifdef UNIV_DEBUG |
72 | /*********************************************************************//** |
73 | Returns the nth field of an update vector. |
74 | @return update vector field */ |
75 | UNIV_INLINE |
76 | upd_field_t* |
77 | upd_get_nth_field( |
78 | /*==============*/ |
79 | const upd_t* update, /*!< in: update vector */ |
80 | ulint n) /*!< in: field position in update vector */ |
81 | { |
82 | ut_ad(update); |
83 | ut_ad(n < update->n_fields); |
84 | |
85 | return((upd_field_t*) update->fields + n); |
86 | } |
87 | #endif /* UNIV_DEBUG */ |
88 | |
89 | /*********************************************************************//** |
90 | Sets an index field number to be updated by an update vector field. */ |
91 | UNIV_INLINE |
92 | void |
93 | upd_field_set_field_no( |
94 | /*===================*/ |
95 | upd_field_t* upd_field, /*!< in: update vector field */ |
96 | ulint field_no, /*!< in: field number in a clustered |
97 | index */ |
98 | dict_index_t* index) /*!< in: index */ |
99 | { |
100 | upd_field->field_no = unsigned(field_no); |
101 | upd_field->orig_len = 0; |
102 | dict_col_copy_type(dict_index_get_nth_col(index, field_no), |
103 | dfield_get_type(&upd_field->new_val)); |
104 | } |
105 | |
106 | /** set field number to a update vector field, marks this field is updated. |
107 | @param[in,out] upd_field update vector field |
108 | @param[in] field_no virtual column sequence num |
109 | @param[in] index index */ |
110 | UNIV_INLINE |
111 | void |
112 | upd_field_set_v_field_no( |
113 | upd_field_t* upd_field, |
114 | ulint field_no, |
115 | dict_index_t* index) |
116 | { |
117 | ut_a(field_no < dict_table_get_n_v_cols(index->table)); |
118 | upd_field->field_no = unsigned(field_no); |
119 | upd_field->orig_len = 0; |
120 | |
121 | dict_col_copy_type(&dict_table_get_nth_v_col( |
122 | index->table, field_no)->m_col, |
123 | dfield_get_type(&upd_field->new_val)); |
124 | } |
125 | |
126 | /*********************************************************************//** |
127 | Returns a field of an update vector by field_no. |
128 | @return update vector field, or NULL */ |
129 | UNIV_INLINE |
130 | const upd_field_t* |
131 | upd_get_field_by_field_no( |
132 | /*======================*/ |
133 | const upd_t* update, /*!< in: update vector */ |
134 | ulint no, /*!< in: field_no */ |
135 | bool is_virtual) /*!< in: if it is virtual column */ |
136 | { |
137 | ulint i; |
138 | for (i = 0; i < upd_get_n_fields(update); i++) { |
139 | const upd_field_t* uf = upd_get_nth_field(update, i); |
140 | |
141 | /* matches only if the field matches that of is_virtual */ |
142 | if ((!is_virtual) != (!upd_fld_is_virtual_col(uf))) { |
143 | continue; |
144 | } |
145 | |
146 | if (uf->field_no == no) { |
147 | |
148 | return(uf); |
149 | } |
150 | } |
151 | |
152 | return(NULL); |
153 | } |
154 | |
155 | /*********************************************************************//** |
156 | Updates the trx id and roll ptr field in a clustered index record when |
157 | a row is updated or marked deleted. */ |
158 | UNIV_INLINE |
159 | void |
160 | row_upd_rec_sys_fields( |
161 | /*===================*/ |
162 | rec_t* rec, /*!< in/out: record */ |
163 | page_zip_des_t* page_zip,/*!< in/out: compressed page whose |
164 | uncompressed part will be updated, or NULL */ |
165 | dict_index_t* index, /*!< in: clustered index */ |
166 | const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ |
167 | const trx_t* trx, /*!< in: transaction */ |
168 | roll_ptr_t roll_ptr)/*!< in: DB_ROLL_PTR to the undo log */ |
169 | { |
170 | ut_ad(dict_index_is_clust(index)); |
171 | ut_ad(rec_offs_validate(rec, index, offsets)); |
172 | |
173 | if (page_zip) { |
174 | ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); |
175 | page_zip_write_trx_id_and_roll_ptr(page_zip, rec, offsets, |
176 | pos, trx->id, roll_ptr); |
177 | } else { |
178 | ulint offset = index->trx_id_offset; |
179 | |
180 | if (!offset) { |
181 | offset = row_get_trx_id_offset(index, offsets); |
182 | } |
183 | |
184 | compile_time_assert(DATA_TRX_ID + 1 == DATA_ROLL_PTR); |
185 | |
186 | /* During IMPORT the trx id in the record can be in the |
187 | future, if the .ibd file is being imported from another |
188 | instance. During IMPORT roll_ptr will be 0. */ |
189 | ut_ad(roll_ptr == 0 |
190 | || lock_check_trx_id_sanity( |
191 | trx_read_trx_id(rec + offset), |
192 | rec, index, offsets)); |
193 | |
194 | trx_write_trx_id(rec + offset, trx->id); |
195 | trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr); |
196 | } |
197 | } |
198 | |