1/*****************************************************************************
2
3Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 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/row0row.ic
22General row routines
23
24Created 4/20/1996 Heikki Tuuri
25*******************************************************/
26
27#include "dict0dict.h"
28#include "rem0rec.h"
29#include "trx0undo.h"
30
31/*********************************************************************//**
32Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of
33a clustered index record.
34@return offset of DATA_TRX_ID */
35UNIV_INLINE
36ulint
37row_get_trx_id_offset(
38/*==================*/
39 const dict_index_t* index, /*!< in: clustered index */
40 const ulint* offsets)/*!< in: record offsets */
41{
42 ulint pos;
43 ulint offset;
44 ulint len;
45
46 ut_ad(dict_index_is_clust(index));
47 ut_ad(rec_offs_validate(NULL, index, offsets));
48
49 pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
50
51 offset = rec_get_nth_field_offs(offsets, pos, &len);
52
53 ut_ad(len == DATA_TRX_ID_LEN);
54
55 return(offset);
56}
57
58/*********************************************************************//**
59Reads the trx id field from a clustered index record.
60@return value of the field */
61UNIV_INLINE
62trx_id_t
63row_get_rec_trx_id(
64/*===============*/
65 const rec_t* rec, /*!< in: record */
66 const dict_index_t* index, /*!< in: clustered index */
67 const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
68{
69 ulint offset;
70
71 ut_ad(dict_index_is_clust(index));
72 ut_ad(rec_offs_validate(rec, index, offsets));
73
74 offset = index->trx_id_offset;
75
76 if (!offset) {
77 offset = row_get_trx_id_offset(index, offsets);
78 }
79
80 return(trx_read_trx_id(rec + offset));
81}
82
83/*********************************************************************//**
84Reads the roll pointer field from a clustered index record.
85@return value of the field */
86UNIV_INLINE
87roll_ptr_t
88row_get_rec_roll_ptr(
89/*=================*/
90 const rec_t* rec, /*!< in: record */
91 const dict_index_t* index, /*!< in: clustered index */
92 const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
93{
94 ulint offset;
95
96 ut_ad(dict_index_is_clust(index));
97 ut_ad(rec_offs_validate(rec, index, offsets));
98
99 offset = index->trx_id_offset;
100
101 if (!offset) {
102 offset = row_get_trx_id_offset(index, offsets);
103 }
104
105 return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
106}
107
108/*****************************************************************//**
109When an insert or purge to a table is performed, this function builds
110the entry to be inserted into or purged from an index on the table.
111@return index entry which should be inserted or purged, or NULL if the
112externally stored columns in the clustered index record are
113unavailable and ext != NULL */
114UNIV_INLINE
115dtuple_t*
116row_build_index_entry(
117/*==================*/
118 const dtuple_t* row, /*!< in: row which should be
119 inserted or purged */
120 const row_ext_t* ext, /*!< in: externally stored column
121 prefixes, or NULL */
122 dict_index_t* index, /*!< in: index on the table */
123 mem_heap_t* heap) /*!< in: memory heap from which
124 the memory for the index entry
125 is allocated */
126{
127 dtuple_t* entry;
128
129 ut_ad(dtuple_check_typed(row));
130 entry = row_build_index_entry_low(row, ext, index, heap,
131 ROW_BUILD_NORMAL);
132 ut_ad(!entry || dtuple_check_typed(entry));
133 return(entry);
134}
135
136/*******************************************************************//**
137Builds from a secondary index record a row reference with which we can
138search the clustered index record. */
139UNIV_INLINE
140void
141row_build_row_ref_fast(
142/*===================*/
143 dtuple_t* ref, /*!< in/out: typed data tuple where the
144 reference is built */
145 const ulint* map, /*!< in: array of field numbers in rec
146 telling how ref should be built from
147 the fields of rec */
148 const rec_t* rec, /*!< in: secondary index record;
149 must be preserved while ref is used, as we do
150 not copy field values to heap */
151 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
152{
153 dfield_t* dfield;
154 const byte* field;
155 ulint len;
156 ulint ref_len;
157 ulint field_no;
158 ulint i;
159
160 ut_ad(rec_offs_validate(rec, NULL, offsets));
161 ut_ad(!rec_offs_any_extern(offsets));
162 ref_len = dtuple_get_n_fields(ref);
163
164 for (i = 0; i < ref_len; i++) {
165 dfield = dtuple_get_nth_field(ref, i);
166
167 field_no = *(map + i);
168
169 if (field_no != ULINT_UNDEFINED) {
170
171 field = rec_get_nth_field(rec, offsets,
172 field_no, &len);
173 dfield_set_data(dfield, field, len);
174 }
175 }
176}
177
178/** Parse the integer data from specified data, which could be
179DATA_INT, DATA_FLOAT or DATA_DOUBLE. If the value is less than 0
180and the type is not unsigned then we reset the value to 0
181@param[in] data data to read
182@param[in] len length of data
183@param[in] mtype mtype of data
184@param[in] unsigned_type if the data is unsigned
185@return the integer value from the data */
186ib_uint64_t
187row_parse_int(
188 const byte* data,
189 ulint len,
190 ulint mtype,
191 bool unsigned_type)
192{
193 ib_uint64_t value = 0;
194
195 switch (mtype) {
196 case DATA_INT:
197
198 ut_a(len <= sizeof value);
199 value = mach_read_int_type(data, len, unsigned_type);
200 break;
201
202 case DATA_FLOAT:
203
204 ut_a(len == sizeof(float));
205 value = static_cast<ib_uint64_t>(mach_float_read(data));
206 break;
207
208 case DATA_DOUBLE:
209
210 ut_a(len == sizeof(double));
211 value = static_cast<ib_uint64_t>(mach_double_read(data));
212 break;
213
214 default:
215 ut_error;
216
217 }
218
219 if (!unsigned_type && static_cast<int64_t>(value) < 0) {
220 value = 0;
221 }
222
223 return(value);
224}
225
226