1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/row0row.h
29 General row routines
30 
31 Created 4/20/1996 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef row0row_h
35 #define row0row_h
36 
37 #include "univ.i"
38 #include "data0data.h"
39 #include "dict0types.h"
40 #include "trx0types.h"
41 #include "que0types.h"
42 #include "mtr0mtr.h"
43 #include "rem0types.h"
44 #include "read0types.h"
45 #include "row0types.h"
46 #include "btr0types.h"
47 
48 /*********************************************************************//**
49 Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of
50 a clustered index record.
51 @return	offset of DATA_TRX_ID */
52 UNIV_INLINE
53 ulint
54 row_get_trx_id_offset(
55 /*==================*/
56 	const dict_index_t*	index,	/*!< in: clustered index */
57 	const ulint*		offsets)/*!< in: record offsets */
58 	MY_ATTRIBUTE((nonnull, warn_unused_result));
59 /*********************************************************************//**
60 Reads the trx id field from a clustered index record.
61 @return	value of the field */
62 UNIV_INLINE
63 trx_id_t
64 row_get_rec_trx_id(
65 /*===============*/
66 	const rec_t*		rec,	/*!< in: record */
67 	const dict_index_t*	index,	/*!< in: clustered index */
68 	const ulint*		offsets)/*!< in: rec_get_offsets(rec, index) */
69 	MY_ATTRIBUTE((nonnull, warn_unused_result));
70 /*********************************************************************//**
71 Reads the roll pointer field from a clustered index record.
72 @return	value of the field */
73 UNIV_INLINE
74 roll_ptr_t
75 row_get_rec_roll_ptr(
76 /*=================*/
77 	const rec_t*		rec,	/*!< in: record */
78 	const dict_index_t*	index,	/*!< in: clustered index */
79 	const ulint*		offsets)/*!< in: rec_get_offsets(rec, index) */
80 	MY_ATTRIBUTE((nonnull, warn_unused_result));
81 /*****************************************************************//**
82 When an insert or purge to a table is performed, this function builds
83 the entry to be inserted into or purged from an index on the table.
84 @return index entry which should be inserted or purged
85 @retval NULL if the externally stored columns in the clustered index record
86 are unavailable and ext != NULL, or row is missing some needed columns. */
87 UNIV_INTERN
88 dtuple_t*
89 row_build_index_entry_low(
90 /*======================*/
91 	const dtuple_t*		row,	/*!< in: row which should be
92 					inserted or purged */
93 	const row_ext_t*	ext,	/*!< in: externally stored column
94 					prefixes, or NULL */
95 	dict_index_t*		index,	/*!< in: index on the table */
96 	mem_heap_t*		heap)	/*!< in: memory heap from which
97 					the memory for the index entry
98 					is allocated */
99 	MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4)));
100 /*****************************************************************//**
101 When an insert or purge to a table is performed, this function builds
102 the entry to be inserted into or purged from an index on the table.
103 @return index entry which should be inserted or purged, or NULL if the
104 externally stored columns in the clustered index record are
105 unavailable and ext != NULL */
106 UNIV_INLINE
107 dtuple_t*
108 row_build_index_entry(
109 /*==================*/
110 	const dtuple_t*		row,	/*!< in: row which should be
111 					inserted or purged */
112 	const row_ext_t*	ext,	/*!< in: externally stored column
113 					prefixes, or NULL */
114 	dict_index_t*		index,	/*!< in: index on the table */
115 	mem_heap_t*		heap)	/*!< in: memory heap from which
116 					the memory for the index entry
117 					is allocated */
118 	MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4)));
119 /*******************************************************************//**
120 An inverse function to row_build_index_entry. Builds a row from a
121 record in a clustered index.
122 @return	own: row built; see the NOTE below! */
123 UNIV_INTERN
124 dtuple_t*
125 row_build(
126 /*======*/
127 	ulint			type,	/*!< in: ROW_COPY_POINTERS or
128 					ROW_COPY_DATA; the latter
129 					copies also the data fields to
130 					heap while the first only
131 					places pointers to data fields
132 					on the index page, and thus is
133 					more efficient */
134 	const dict_index_t*	index,	/*!< in: clustered index */
135 	const rec_t*		rec,	/*!< in: record in the clustered
136 					index; NOTE: in the case
137 					ROW_COPY_POINTERS the data
138 					fields in the row will point
139 					directly into this record,
140 					therefore, the buffer page of
141 					this record must be at least
142 					s-latched and the latch held
143 					as long as the row dtuple is used! */
144 	const ulint*		offsets,/*!< in: rec_get_offsets(rec,index)
145 					or NULL, in which case this function
146 					will invoke rec_get_offsets() */
147 	const dict_table_t*	col_table,
148 					/*!< in: table, to check which
149 					externally stored columns
150 					occur in the ordering columns
151 					of an index, or NULL if
152 					index->table should be
153 					consulted instead; the user
154 					columns in this table should be
155 					the same columns as in index->table */
156 	const dtuple_t*		add_cols,
157 					/*!< in: default values of
158 					added columns, or NULL */
159 	const ulint*		col_map,/*!< in: mapping of old column
160 					numbers to new ones, or NULL */
161 	row_ext_t**		ext,	/*!< out, own: cache of
162 					externally stored column
163 					prefixes, or NULL */
164 	mem_heap_t*		heap)	/*!< in: memory heap from which
165 					the memory needed is allocated */
166 	MY_ATTRIBUTE((nonnull(2,3,9)));
167 /*******************************************************************//**
168 Converts an index record to a typed data tuple.
169 @return index entry built; does not set info_bits, and the data fields
170 in the entry will point directly to rec */
171 UNIV_INTERN
172 dtuple_t*
173 row_rec_to_index_entry_low(
174 /*=======================*/
175 	const rec_t*		rec,	/*!< in: record in the index */
176 	const dict_index_t*	index,	/*!< in: index */
177 	const ulint*		offsets,/*!< in: rec_get_offsets(rec, index) */
178 	ulint*			n_ext,	/*!< out: number of externally
179 					stored columns */
180 	mem_heap_t*		heap)	/*!< in: memory heap from which
181 					the memory needed is allocated */
182 	MY_ATTRIBUTE((nonnull, warn_unused_result));
183 /*******************************************************************//**
184 Converts an index record to a typed data tuple. NOTE that externally
185 stored (often big) fields are NOT copied to heap.
186 @return	own: index entry built */
187 UNIV_INTERN
188 dtuple_t*
189 row_rec_to_index_entry(
190 /*===================*/
191 	const rec_t*		rec,	/*!< in: record in the index */
192 	const dict_index_t*	index,	/*!< in: index */
193 	const ulint*		offsets,/*!< in/out: rec_get_offsets(rec) */
194 	ulint*			n_ext,	/*!< out: number of externally
195 					stored columns */
196 	mem_heap_t*		heap)	/*!< in: memory heap from which
197 					the memory needed is allocated */
198 	MY_ATTRIBUTE((nonnull, warn_unused_result));
199 /*******************************************************************//**
200 Builds from a secondary index record a row reference with which we can
201 search the clustered index record.
202 @return	own: row reference built; see the NOTE below! */
203 UNIV_INTERN
204 dtuple_t*
205 row_build_row_ref(
206 /*==============*/
207 	ulint		type,	/*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
208 				the former copies also the data fields to
209 				heap, whereas the latter only places pointers
210 				to data fields on the index page */
211 	dict_index_t*	index,	/*!< in: secondary index */
212 	const rec_t*	rec,	/*!< in: record in the index;
213 				NOTE: in the case ROW_COPY_POINTERS
214 				the data fields in the row will point
215 				directly into this record, therefore,
216 				the buffer page of this record must be
217 				at least s-latched and the latch held
218 				as long as the row reference is used! */
219 	mem_heap_t*	heap)	/*!< in: memory heap from which the memory
220 				needed is allocated */
221 	MY_ATTRIBUTE((nonnull, warn_unused_result));
222 /*******************************************************************//**
223 Builds from a secondary index record a row reference with which we can
224 search the clustered index record. */
225 UNIV_INTERN
226 void
227 row_build_row_ref_in_tuple(
228 /*=======================*/
229 	dtuple_t*		ref,	/*!< in/out: row reference built;
230 					see the NOTE below! */
231 	const rec_t*		rec,	/*!< in: record in the index;
232 					NOTE: the data fields in ref
233 					will point directly into this
234 					record, therefore, the buffer
235 					page of this record must be at
236 					least s-latched and the latch
237 					held as long as the row
238 					reference is used! */
239 	const dict_index_t*	index,	/*!< in: secondary index */
240 	ulint*			offsets,/*!< in: rec_get_offsets(rec, index)
241 					or NULL */
242 	trx_t*			trx)	/*!< in: transaction or NULL */
243 	MY_ATTRIBUTE((nonnull(1,2,3)));
244 /*******************************************************************//**
245 Builds from a secondary index record a row reference with which we can
246 search the clustered index record. */
247 UNIV_INLINE
248 void
249 row_build_row_ref_fast(
250 /*===================*/
251 	dtuple_t*	ref,	/*!< in/out: typed data tuple where the
252 				reference is built */
253 	const ulint*	map,	/*!< in: array of field numbers in rec
254 				telling how ref should be built from
255 				the fields of rec */
256 	const rec_t*	rec,	/*!< in: record in the index; must be
257 				preserved while ref is used, as we do
258 				not copy field values to heap */
259 	const ulint*	offsets);/*!< in: array returned by rec_get_offsets() */
260 /***************************************************************//**
261 Searches the clustered index record for a row, if we have the row
262 reference.
263 @return	TRUE if found */
264 UNIV_INTERN
265 ibool
266 row_search_on_row_ref(
267 /*==================*/
268 	btr_pcur_t*		pcur,	/*!< out: persistent cursor, which must
269 					be closed by the caller */
270 	ulint			mode,	/*!< in: BTR_MODIFY_LEAF, ... */
271 	const dict_table_t*	table,	/*!< in: table */
272 	const dtuple_t*		ref,	/*!< in: row reference */
273 	mtr_t*			mtr)	/*!< in/out: mtr */
274 	MY_ATTRIBUTE((nonnull, warn_unused_result));
275 /*********************************************************************//**
276 Fetches the clustered index record for a secondary index record. The latches
277 on the secondary index record are preserved.
278 @return	record or NULL, if no record found */
279 UNIV_INTERN
280 rec_t*
281 row_get_clust_rec(
282 /*==============*/
283 	ulint		mode,	/*!< in: BTR_MODIFY_LEAF, ... */
284 	const rec_t*	rec,	/*!< in: record in a secondary index */
285 	dict_index_t*	index,	/*!< in: secondary index */
286 	dict_index_t**	clust_index,/*!< out: clustered index */
287 	mtr_t*		mtr)	/*!< in: mtr */
288 	MY_ATTRIBUTE((nonnull, warn_unused_result));
289 
290 /** Result of row_search_index_entry */
291 enum row_search_result {
292 	ROW_FOUND = 0,		/*!< the record was found */
293 	ROW_NOT_FOUND,		/*!< record not found */
294 	ROW_BUFFERED,		/*!< one of BTR_INSERT, BTR_DELETE, or
295 				BTR_DELETE_MARK was specified, the
296 				secondary index leaf page was not in
297 				the buffer pool, and the operation was
298 				enqueued in the insert/delete buffer */
299 	ROW_NOT_DELETED_REF	/*!< BTR_DELETE was specified, and
300 				row_purge_poss_sec() failed */
301 };
302 
303 /***************************************************************//**
304 Searches an index record.
305 @return	whether the record was found or buffered */
306 UNIV_INTERN
307 enum row_search_result
308 row_search_index_entry(
309 /*===================*/
310 	dict_index_t*	index,	/*!< in: index */
311 	const dtuple_t*	entry,	/*!< in: index entry */
312 	ulint		mode,	/*!< in: BTR_MODIFY_LEAF, ... */
313 	btr_pcur_t*	pcur,	/*!< in/out: persistent cursor, which must
314 				be closed by the caller */
315 	mtr_t*		mtr)	/*!< in: mtr */
316 	MY_ATTRIBUTE((nonnull, warn_unused_result));
317 
318 #define ROW_COPY_DATA		1
319 #define ROW_COPY_POINTERS	2
320 
321 /* The allowed latching order of index records is the following:
322 (1) a secondary index record ->
323 (2) the clustered index record ->
324 (3) rollback segment data for the clustered index record. */
325 
326 /*******************************************************************//**
327 Formats the raw data in "data" (in InnoDB on-disk format) using
328 "dict_field" and writes the result to "buf".
329 Not more than "buf_size" bytes are written to "buf".
330 The result is always NUL-terminated (provided buf_size is positive) and the
331 number of bytes that were written to "buf" is returned (including the
332 terminating NUL).
333 @return	number of bytes that were written */
334 UNIV_INTERN
335 ulint
336 row_raw_format(
337 /*===========*/
338 	const char*		data,		/*!< in: raw data */
339 	ulint			data_len,	/*!< in: raw data length
340 						in bytes */
341 	const dict_field_t*	dict_field,	/*!< in: index field */
342 	char*			buf,		/*!< out: output buffer */
343 	ulint			buf_size)	/*!< in: output buffer size
344 						in bytes */
345 	MY_ATTRIBUTE((nonnull, warn_unused_result));
346 
347 #ifndef UNIV_NONINL
348 #include "row0row.ic"
349 #endif
350 
351 #endif
352