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