1/*****************************************************************************
2
3Copyright (c) 1996, 2011, 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/row0row.ic
29General row routines
30
31Created 4/20/1996 Heikki Tuuri
32*******************************************************/
33
34#include "dict0dict.h"
35#include "rem0rec.h"
36#include "trx0undo.h"
37
38/*********************************************************************//**
39Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of
40a clustered index record.
41@return	offset of DATA_TRX_ID */
42UNIV_INLINE
43ulint
44row_get_trx_id_offset(
45/*==================*/
46	const dict_index_t*	index,	/*!< in: clustered index */
47	const ulint*		offsets)/*!< in: record offsets */
48{
49	ulint	pos;
50	ulint	offset;
51	ulint	len;
52
53	ut_ad(dict_index_is_clust(index));
54	ut_ad(rec_offs_validate(NULL, index, offsets));
55
56	pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
57
58	offset = rec_get_nth_field_offs(offsets, pos, &len);
59
60	ut_ad(len == DATA_TRX_ID_LEN);
61
62	return(offset);
63}
64
65/*********************************************************************//**
66Reads the trx id field from a clustered index record.
67@return	value of the field */
68UNIV_INLINE
69trx_id_t
70row_get_rec_trx_id(
71/*===============*/
72	const rec_t*		rec,	/*!< in: record */
73	const dict_index_t*	index,	/*!< in: clustered index */
74	const ulint*		offsets)/*!< in: rec_get_offsets(rec, index) */
75{
76	ulint	offset;
77
78	ut_ad(dict_index_is_clust(index));
79	ut_ad(rec_offs_validate(rec, index, offsets));
80
81	offset = index->trx_id_offset;
82
83	if (!offset) {
84		offset = row_get_trx_id_offset(index, offsets);
85	}
86
87	return(trx_read_trx_id(rec + offset));
88}
89
90/*********************************************************************//**
91Reads the roll pointer field from a clustered index record.
92@return	value of the field */
93UNIV_INLINE
94roll_ptr_t
95row_get_rec_roll_ptr(
96/*=================*/
97	const rec_t*		rec,	/*!< in: record */
98	const dict_index_t*	index,	/*!< in: clustered index */
99	const ulint*		offsets)/*!< in: rec_get_offsets(rec, index) */
100{
101	ulint	offset;
102
103	ut_ad(dict_index_is_clust(index));
104	ut_ad(rec_offs_validate(rec, index, offsets));
105
106	offset = index->trx_id_offset;
107
108	if (!offset) {
109		offset = row_get_trx_id_offset(index, offsets);
110	}
111
112	return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
113}
114
115/*****************************************************************//**
116When an insert or purge to a table is performed, this function builds
117the entry to be inserted into or purged from an index on the table.
118@return index entry which should be inserted or purged, or NULL if the
119externally stored columns in the clustered index record are
120unavailable and ext != NULL */
121UNIV_INLINE
122dtuple_t*
123row_build_index_entry(
124/*==================*/
125	const dtuple_t*		row,	/*!< in: row which should be
126					inserted or purged */
127	const row_ext_t*	ext,	/*!< in: externally stored column
128					prefixes, or NULL */
129	dict_index_t*		index,	/*!< in: index on the table */
130	mem_heap_t*		heap)	/*!< in: memory heap from which
131					the memory for the index entry
132					is allocated */
133{
134	dtuple_t*	entry;
135
136	ut_ad(dtuple_check_typed(row));
137	entry = row_build_index_entry_low(row, ext, index, heap);
138	ut_ad(!entry || dtuple_check_typed(entry));
139	return(entry);
140}
141
142/*******************************************************************//**
143Builds from a secondary index record a row reference with which we can
144search the clustered index record. */
145UNIV_INLINE
146void
147row_build_row_ref_fast(
148/*===================*/
149	dtuple_t*	ref,	/*!< in/out: typed data tuple where the
150				reference is built */
151	const ulint*	map,	/*!< in: array of field numbers in rec
152				telling how ref should be built from
153				the fields of rec */
154	const rec_t*	rec,	/*!< in: record in the index; must be
155				preserved while ref is used, as we do
156				not copy field values to heap */
157	const ulint*	offsets)/*!< in: array returned by rec_get_offsets() */
158{
159	dfield_t*	dfield;
160	const byte*	field;
161	ulint		len;
162	ulint		ref_len;
163	ulint		field_no;
164	ulint		i;
165
166	ut_ad(rec_offs_validate(rec, NULL, offsets));
167	ut_ad(!rec_offs_any_extern(offsets));
168	ref_len = dtuple_get_n_fields(ref);
169
170	for (i = 0; i < ref_len; i++) {
171		dfield = dtuple_get_nth_field(ref, i);
172
173		field_no = *(map + i);
174
175		if (field_no != ULINT_UNDEFINED) {
176
177			field = rec_get_nth_field(rec, offsets,
178						  field_no, &len);
179			dfield_set_data(dfield, field, len);
180		}
181	}
182}
183