MySQL 8.0.31
Source Code Documentation
rem0lrec.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2021, 2022, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for 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 St, Fifth Floor, Boston, MA 02110-1301 USA
24*****************************************************************************/
25
26/** @file include/rem0lrec.h
27 Record manager.
28 This file contains low level functions which deals with physical index of
29 fields in a physical record.
30
31 After INSTANT ADD/DROP feature, fields index on logical record might not be
32 same as field index on physical record. So a wrapper (rem0wrec.h) is
33 implemented which translates logical index to physical index. And then
34 functions of this file are called with physical index of the field.
35
36 Created 13/08/2021 Mayank Prasad
37*****************************************************************************/
38
39#ifndef rem0lrec_h
40#define rem0lrec_h
41
42#include "rem0rec.h"
43
44/** Set nth field value to SQL NULL.
45@param[in,out] rec record
46@param[in] n index of the field. */
47static inline void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n);
48
49/** Returns nonzero if the SQL NULL bit is set in nth field of rec.
50@param[in] offsets array returned by rec_get_offsets()
51@param[in] n index of the field.
52@return nonzero if SQL NULL */
53static inline ulint rec_offs_nth_sql_null_low(const ulint *offsets, ulint n);
54
55/** Read the offset of the start of a data field in the record. The start of an
56SQL null field is the end offset of the previous non-null field, or 0, if none
57exists. If n is the number of the last field + 1, then the end offset of the
58last field is returned.
59@param[in] rec record
60@param[in] n index of the field
61@return offset of the start of the field */
62static inline ulint rec_get_field_start_offs_low(const rec_t *rec, ulint n);
63
64/** Returns the offset of nth field start if the record is stored in the 1-byte
65offsets form.
66@param[in] rec record
67@param[in] n index of the field
68@return offset of the start of the field */
69static inline ulint rec_1_get_field_start_offs_low(const rec_t *rec, ulint n);
70
71/** Returns the offset of nth field end if the record is stored in the 1-byte
72offsets form. If the field is SQL null, the flag is ORed in the returned value.
73@param[in] rec record
74@param[in] n index of the field
75@return offset of the start of the field, SQL null flag ORed */
76static inline ulint rec_1_get_field_end_info_low(const rec_t *rec, ulint n);
77
78/** Sets the field end info for the nth field if the record is stored in the
791-byte format.
80@param[in,out] rec record
81@param[in] n index of the field
82@param[in] info value to set */
83static inline void rec_1_set_field_end_info_low(rec_t *rec, ulint n,
84 ulint info);
85/** Returns the offset of nth field start if the record is stored in the 2-byte
86offsets form.
87@param[in] rec record
88@param[in] n index of the field
89@return offset of the start of the field */
90static inline ulint rec_2_get_field_start_offs_low(const rec_t *rec, ulint n);
91
92/** Returns the offset of nth field end if the record is stored in the 2-byte
93offsets form. If the field is SQL null, the flag is ORed in the returned value.
94@param[in] rec record
95@param[in] n index of the field
96@return offset of the start of the field, SQL null flag and extern storage flag
97ORed */
98static inline ulint rec_2_get_field_end_info_low(const rec_t *rec, ulint n);
99
100/** Sets the field end info for the nth field if the record is stored in the
1012-byte format.
102@param[in] rec record
103@param[in] n index of the field
104@param[out] info end info */
105static inline void rec_2_set_field_end_info_low(rec_t *rec, ulint n,
106 ulint info);
107
108/** Sets the value of the ith field SQL null bit of an old-style record.
109@param[in] rec record
110@param[in] i index of the field
111@param[in] val value to set */
112static inline void rec_set_nth_field_null_bit_low(rec_t *rec, ulint i,
113 bool val);
114
115/** Gets the physical size of an old-style field.
116Also an SQL null may have a field of size > 0, if the data type is of a fixed
117size.
118@param[in] rec record
119@param[in] n index of the field
120@return field size in bytes */
121static inline ulint rec_get_nth_field_size_low(const rec_t *rec, ulint n) {
122 ulint os;
123 ulint next_os;
124
126 next_os = rec_get_field_start_offs_low(rec, n + 1);
127
128 ut_ad(next_os - os < UNIV_PAGE_SIZE);
129
130 return (next_os - os);
131}
132
133/** Get an offset to the nth data field in a record.
134@param[in] offsets array returned by rec_get_offsets()
135@param[in] n index of the field
136@param[out] len length of the field; UNIV_SQL_NULL if SQL null;
137 UNIV_SQL_ADD_COL_DEFAULT if it's default value and no
138 value inlined
139@return offset from the origin of rec */
140static inline ulint rec_get_nth_field_offs_low(const ulint *offsets, ulint n,
141 ulint *len) {
142 ulint offs;
144 ut_ad(n < rec_offs_n_fields(offsets));
145 ut_ad(len);
146
147 if (n == 0) {
148 offs = 0;
149 } else {
150 offs = rec_offs_base(offsets)[n] & REC_OFFS_MASK;
151 }
152
153 length = rec_offs_base(offsets)[1 + n];
154
157 } else if (length & REC_OFFS_DEFAULT) {
159 } else if (length & REC_OFFS_DROP) {
161 } else {
163 length -= offs;
164 }
165
166 *len = length;
167 return (offs);
168}
169
170/** The following function is used to get the offset to the nth
171data field in an old-style record.
172@param[in] rec record
173@param[in] n index of the field
174@param[out] len length of the field; UNIV_SQL_NULL if SQL null;
175@return offset to the field */
177 ulint *len) {
178 ulint os;
179 ulint next_os;
180
181 ut_ad(len);
182 ut_a(rec);
184
185 if (rec_get_1byte_offs_flag(rec)) {
187
188 next_os = rec_1_get_field_end_info_low(rec, n);
189
190 if (next_os & REC_1BYTE_SQL_NULL_MASK) {
191 *len = UNIV_SQL_NULL;
192
193 return (os);
194 }
195
196 next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK;
197 } else {
199
200 next_os = rec_2_get_field_end_info_low(rec, n);
201
202 if (next_os & REC_2BYTE_SQL_NULL_MASK) {
203 *len = UNIV_SQL_NULL;
204
205 return (os);
206 }
207
208 next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK);
209 }
210
211 *len = next_os - os;
212
213 ut_ad(*len < UNIV_PAGE_SIZE);
214
215 return (os);
216}
217
218/** Returns nonzero if the extern bit is set in nth field of rec.
219@param[in] offsets array returned by rec_get_offsets()
220@param[in] n index of the field
221@return nonzero if externally stored */
222static inline ulint rec_offs_nth_extern_low(const ulint *offsets, ulint n) {
223 ut_ad(rec_offs_validate(nullptr, nullptr, offsets));
224 ut_ad(n < rec_offs_n_fields(offsets));
225 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL);
226}
227
228/** Mark the nth field as externally stored.
229@param[in] offsets array returned by rec_get_offsets()
230@param[in] n index of the field */
231static inline void rec_offs_make_nth_extern_low(ulint *offsets, const ulint n) {
233 rec_offs_base(offsets)[1 + n] |= REC_OFFS_EXTERNAL;
234}
235
236static inline ulint rec_offs_nth_sql_null_low(const ulint *offsets, ulint n) {
237 ut_ad(rec_offs_validate(nullptr, nullptr, offsets));
238 ut_ad(n < rec_offs_n_fields(offsets));
239 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL);
240}
241
242/** Returns nonzero if the default bit is set in nth field of rec.
243@param[in] offsets array returned by rec_get_offsets()
244@param[in] n index of the field
245@return nonzero if default bit is set */
246static inline ulint rec_offs_nth_default_low(const ulint *offsets, ulint n) {
247 ut_ad(rec_offs_validate(nullptr, nullptr, offsets));
248 ut_ad(n < rec_offs_n_fields(offsets));
249 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_DEFAULT);
250}
251
252/** Gets the physical size of a field.
253@param[in] offsets array returned by rec_get_offsets()
254@param[in] n index of the field
255@return length of field */
256static inline ulint rec_offs_nth_size_low(const ulint *offsets, ulint n) {
257 ut_ad(rec_offs_validate(nullptr, nullptr, offsets));
258 ut_ad(n < rec_offs_n_fields(offsets));
259 if (!n) {
260 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK);
261 }
262 return ((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n]) &
264}
265
266/** This is used to modify the value of an already existing field in a record.
267The previous value must have exactly the same size as the new value. If len
268is UNIV_SQL_NULL then the field is treated as an SQL null.
269For records in ROW_FORMAT=COMPACT (new-style records), len must not be
270UNIV_SQL_NULL unless the field already is SQL null.
271@param[in] rec record
272@param[in] offsets array returned by rec_get_offsets()
273@param[in] n index of the field
274@param[in] data pointer to the data if not SQL null
275@param[in] len length of the data or UNIV_SQL_NULL */
276static inline void rec_set_nth_field_low(rec_t *rec, const ulint *offsets,
277 ulint n, const void *data, ulint len) {
278 byte *data2;
279 ulint len2;
280
281 ut_ad(rec);
282 ut_ad(rec_offs_validate(rec, nullptr, offsets));
283
284 auto fn = [&](const ulint *offsets, ulint n) {
285 ulint n_drop = 0;
286 for (size_t i = 0; i < n; i++) {
287 ulint len = rec_offs_base(offsets)[1 + i];
288 if (len & REC_OFFS_DROP) {
289 n_drop++;
290 }
291 }
292 return n_drop;
293 };
294
295 if (len == UNIV_SQL_NULL) {
296 if (!rec_offs_nth_sql_null_low(offsets, n)) {
297 ut_a(!rec_offs_comp(offsets));
298 ulint n_drop = rec_old_is_versioned(rec) ? fn(offsets, n) : 0;
299 rec_set_nth_field_sql_null_low(rec, n - n_drop);
300 }
301
302 return;
303 }
304
305 ut_ad(!rec_offs_nth_default_low(offsets, n));
306
307 /* nullptr for index as n is physical here */
308 data2 = rec_get_nth_field(nullptr, rec, offsets, n, &len2);
309
310 if (len2 == UNIV_SQL_NULL) {
311 ut_ad(!rec_offs_comp(offsets));
312 ulint n_drop = rec_old_is_versioned(rec) ? fn(offsets, n) : 0;
313 rec_set_nth_field_null_bit_low(rec, n - n_drop, false);
314 ut_ad(len == rec_get_nth_field_size_low(rec, n - n_drop));
315 } else {
316 ut_ad(len2 == len);
317 }
318
319 ut_memcpy(data2, data, len);
320}
321
322static inline void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n) {
323 ulint offset;
324
325 offset = rec_get_field_start_offs_low(rec, n);
326
328
330}
331
332static inline void rec_set_nth_field_null_bit_low(rec_t *rec, ulint i,
333 bool val) {
334 ulint info;
335
336 if (rec_get_1byte_offs_flag(rec)) {
338
339 if (val) {
341 } else {
342 info = info & ~REC_1BYTE_SQL_NULL_MASK;
343 }
344
346
347 return;
348 }
349
351
352 if (val) {
354 } else {
355 info = info & ~REC_2BYTE_SQL_NULL_MASK;
356 }
357
359}
360
361static inline ulint rec_get_field_start_offs_low(const rec_t *rec, ulint n) {
362 ut_ad(rec);
364
365 if (n == 0) {
366 return (0);
367 }
368
369 if (rec_get_1byte_offs_flag(rec)) {
370 return (rec_1_get_field_start_offs_low(rec, n));
371 }
372
373 return (rec_2_get_field_start_offs_low(rec, n));
374}
375
379
380 if (n == 0) {
381 return (0);
382 }
383
385}
386
390
391 if (n == 0) {
392 return (0);
393 }
394
395 return (rec_2_get_prev_field_end_info(rec, n) &
397}
398
399static inline ulint rec_1_get_field_end_info_low(const rec_t *rec, ulint n) {
402
403 uint32_t version_size = 0;
404 if (rec_old_is_versioned(rec)) {
405 version_size = 1;
406 }
407
408 return (
409 mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + version_size + n + 1)));
410}
411
412static inline ulint rec_2_get_field_end_info_low(const rec_t *rec, ulint n) {
415
416 uint32_t version_size = 0;
417 if (rec_old_is_versioned(rec)) {
418 version_size = 1;
419 }
420
421 return (mach_read_from_2(rec -
422 (REC_N_OLD_EXTRA_BYTES + version_size + 2 * n + 2)));
423}
424
425static inline void rec_1_set_field_end_info_low(rec_t *rec, ulint n,
426 ulint info) {
429
430 uint32_t version_length = 0;
431 if (rec_old_is_versioned(rec)) {
432 version_length = 1;
433 }
434
435 mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + version_length + n + 1), info);
436}
437
438static inline void rec_2_set_field_end_info_low(rec_t *rec, ulint n,
439 ulint info) {
442
443 uint32_t version_length = 0;
444 if (rec_old_is_versioned(rec)) {
445 version_length = 1;
446 }
447
448 mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + version_length + 2 * n + 2),
449 info);
450}
451
452#endif
static void data_write_sql_null(byte *data, ulint len)
Writes an SQL null field full of zeros.
static uint16_t mach_read_from_2(const byte *b)
The following function is used to fetch data from 2 consecutive bytes.
static void mach_write_to_2(byte *b, ulint n)
The following function is used to store data in two consecutive bytes.
static void mach_write_to_1(byte *b, ulint n)
The following function is used to store data in one byte.
static uint8_t mach_read_from_1(const byte *b)
The following function is used to fetch data from one byte.
Log info(cout, "NOTE")
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:75
constexpr uint32_t REC_OFFS_EXTERNAL
Definition: rec.h:48
constexpr uint32_t REC_OFFS_DEFAULT
Definition: rec.h:50
constexpr uint32_t REC_N_OLD_EXTRA_BYTES
Definition: rec.h:129
constexpr uint32_t REC_OFFS_DROP
Definition: rec.h:52
constexpr uint32_t REC_OFFS_MASK
Definition: rec.h:54
static bool rec_offs_validate(const rec_t *rec, const dict_index_t *index, const ulint *offsets)
Validates offsets returned by rec_get_offsets().
Definition: rec.h:513
constexpr uint32_t REC_1BYTE_SQL_NULL_MASK
SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:151
constexpr uint32_t REC_OFFS_SQL_NULL
Definition: rec.h:46
static ulint rec_offs_n_fields(const ulint *offsets)
The following function returns the number of fields in a record.
Definition: rec.h:459
static const ulint * rec_offs_base(const ulint *offsets)
Definition: rec.h:176
static uint16_t rec_get_n_fields_old_raw(const rec_t *rec)
The following function is used to get the number of fields in an old-style record,...
Definition: rec.h:299
constexpr uint32_t REC_2BYTE_SQL_NULL_MASK
SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:153
static bool rec_old_is_versioned(const rec_t *rec)
The following function tells if an old-style record is versioned.
Definition: rec.h:658
static bool rec_get_1byte_offs_flag(const rec_t *rec)
The following function is used to test whether the data offsets in the record are stored in one-byte ...
Definition: rec.h:910
constexpr uint32_t REC_2BYTE_EXTERN_MASK
In a 2-byte offset of ROW_FORMAT=REDUNDANT records, the second most significant bit denotes that the ...
Definition: rec.h:157
static void rec_set_nth_field_null_bit_low(rec_t *rec, ulint i, bool val)
Sets the value of the ith field SQL null bit of an old-style record.
Definition: rem0lrec.h:332
static ulint rec_get_nth_field_offs_old_low(const rec_t *rec, ulint n, ulint *len)
The following function is used to get the offset to the nth data field in an old-style record.
Definition: rem0lrec.h:176
static ulint rec_offs_nth_extern_low(const ulint *offsets, ulint n)
Returns nonzero if the extern bit is set in nth field of rec.
Definition: rem0lrec.h:222
static ulint rec_2_get_field_start_offs_low(const rec_t *rec, ulint n)
Returns the offset of nth field start if the record is stored in the 2-byte offsets form.
Definition: rem0lrec.h:387
static ulint rec_offs_nth_sql_null_low(const ulint *offsets, ulint n)
Returns nonzero if the SQL NULL bit is set in nth field of rec.
Definition: rem0lrec.h:236
static void rec_set_nth_field_low(rec_t *rec, const ulint *offsets, ulint n, const void *data, ulint len)
This is used to modify the value of an already existing field in a record.
Definition: rem0lrec.h:276
static ulint rec_1_get_field_end_info_low(const rec_t *rec, ulint n)
Returns the offset of nth field end if the record is stored in the 1-byte offsets form.
Definition: rem0lrec.h:399
static ulint rec_1_get_field_start_offs_low(const rec_t *rec, ulint n)
Returns the offset of nth field start if the record is stored in the 1-byte offsets form.
Definition: rem0lrec.h:376
static ulint rec_get_nth_field_offs_low(const ulint *offsets, ulint n, ulint *len)
Get an offset to the nth data field in a record.
Definition: rem0lrec.h:140
static ulint rec_offs_nth_default_low(const ulint *offsets, ulint n)
Returns nonzero if the default bit is set in nth field of rec.
Definition: rem0lrec.h:246
static void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n)
Set nth field value to SQL NULL.
Definition: rem0lrec.h:322
static ulint rec_get_field_start_offs_low(const rec_t *rec, ulint n)
Read the offset of the start of a data field in the record.
Definition: rem0lrec.h:361
static void rec_2_set_field_end_info_low(rec_t *rec, ulint n, ulint info)
Sets the field end info for the nth field if the record is stored in the 2-byte format.
Definition: rem0lrec.h:438
static void rec_offs_make_nth_extern_low(ulint *offsets, const ulint n)
Mark the nth field as externally stored.
Definition: rem0lrec.h:231
static void rec_1_set_field_end_info_low(rec_t *rec, ulint n, ulint info)
Sets the field end info for the nth field if the record is stored in the 1-byte format.
Definition: rem0lrec.h:425
static ulint rec_get_nth_field_size_low(const rec_t *rec, ulint n)
Gets the physical size of an old-style field.
Definition: rem0lrec.h:121
static ulint rec_2_get_field_end_info_low(const rec_t *rec, ulint n)
Returns the offset of nth field end if the record is stored in the 2-byte offsets form.
Definition: rem0lrec.h:412
static ulint rec_offs_nth_size_low(const ulint *offsets, ulint n)
Gets the physical size of a field.
Definition: rem0lrec.h:256
Record manager.
static bool rec_offs_comp(const ulint *offsets)
Determine if the offsets are for a record in the new compact format.
static ulint rec_2_get_prev_field_end_info(const rec_t *rec, ulint n)
Returns the offset of n - 1th field end if the record is stored in the 2-byte offsets form.
Definition: rem0rec.ic:626
static ulint rec_1_get_prev_field_end_info(const rec_t *rec, ulint n)
Returns the offset of n - 1th field end if the record is stored in the 1-byte offsets form.
Definition: rem0rec.ic:607
byte rec_t
Definition: rem0types.h:40
byte * rec_get_nth_field(const dict_index_t *index, const rec_t *rec, const ulint *offsets, ulint n, ulint *len)
Gets the value of the specified field in the record.
Definition: rem0wrec.cc:35
#define UNIV_PAGE_SIZE
The universal page size of the database.
Definition: univ.i:295
constexpr uint32_t UNIV_SQL_NULL
The following number as the length of a logical field means that the field has the SQL NULL as its va...
Definition: univ.i:464
constexpr auto UNIV_SQL_ADD_COL_DEFAULT
Flag to indicate a field which was added instantly.
Definition: univ.i:467
unsigned long int ulint
Definition: univ.i:407
constexpr auto UNIV_SQL_INSTANT_DROP_COL
Flag to indicate a field which was dropped instantly.
Definition: univ.i:479
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:68
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:56
static void * ut_memcpy(void *dest, const void *src, ulint n)
Wrapper for memcpy(3).
int n
Definition: xcom_base.cc:505