1/*****************************************************************************
2
3Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file include/row0upd.ic
22Update of a row
23
24Created 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/*********************************************************************//**
35Creates an update vector object.
36@return own: update vector object */
37UNIV_INLINE
38upd_t*
39upd_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/*********************************************************************//**
57Returns the number of fields in the update vector == number of columns
58to be updated by an update vector.
59@return number of fields */
60UNIV_INLINE
61ulint
62upd_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/*********************************************************************//**
73Returns the nth field of an update vector.
74@return update vector field */
75UNIV_INLINE
76upd_field_t*
77upd_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/*********************************************************************//**
90Sets an index field number to be updated by an update vector field. */
91UNIV_INLINE
92void
93upd_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 */
110UNIV_INLINE
111void
112upd_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/*********************************************************************//**
127Returns a field of an update vector by field_no.
128@return update vector field, or NULL */
129UNIV_INLINE
130const upd_field_t*
131upd_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/*********************************************************************//**
156Updates the trx id and roll ptr field in a clustered index record when
157a row is updated or marked deleted. */
158UNIV_INLINE
159void
160row_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