MySQL 8.3.0
Source Code Documentation
rem0lrec.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2021, 2023, 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 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL);
224}
225
226/** Mark the nth field as externally stored.
227@param[in] offsets array returned by rec_get_offsets()
228@param[in] n index of the field */
229static inline void rec_offs_make_nth_extern_low(ulint *offsets, const ulint n) {
231 rec_offs_base(offsets)[1 + n] |= REC_OFFS_EXTERNAL;
232}
233
234static inline ulint rec_offs_nth_sql_null_low(const ulint *offsets, ulint n) {
235 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL);
236}
237
238/** Returns nonzero if the default bit is set in nth field of rec.
239@param[in] offsets array returned by rec_get_offsets()
240@param[in] n index of the field
241@return nonzero if default bit is set */
242static inline ulint rec_offs_nth_default_low(const ulint *offsets, ulint n) {
243 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_DEFAULT);
244}
245
246/** Gets the physical size of a field.
247@param[in] offsets array returned by rec_get_offsets()
248@param[in] n index of the field
249@return length of field */
250static inline ulint rec_offs_nth_size_low(const ulint *offsets, ulint n) {
251 if (!n) {
252 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK);
253 }
254 return ((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n]) &
256}
257
258/** This is used to modify the value of an already existing field in a record.
259The previous value must have exactly the same size as the new value. If len
260is UNIV_SQL_NULL then the field is treated as an SQL null.
261For records in ROW_FORMAT=COMPACT (new-style records), len must not be
262UNIV_SQL_NULL unless the field already is SQL null.
263@param[in] rec record
264@param[in] offsets array returned by rec_get_offsets()
265@param[in] n index of the field
266@param[in] data pointer to the data if not SQL null
267@param[in] len length of the data or UNIV_SQL_NULL */
268static inline void rec_set_nth_field_low(rec_t *rec, const ulint *offsets,
269 ulint n, const void *data, ulint len) {
270 byte *data2;
271 ulint len2;
272
273 ut_ad(rec);
274 ut_ad(rec_offs_validate(rec, nullptr, offsets));
275
276 auto fn = [&](const ulint *offsets, ulint n) {
277 ulint n_drop = 0;
278 for (size_t i = 0; i < n; i++) {
279 ulint len = rec_offs_base(offsets)[1 + i];
280 if (len & REC_OFFS_DROP) {
281 n_drop++;
282 }
283 }
284 return n_drop;
285 };
286
287 if (len == UNIV_SQL_NULL) {
288 if (!rec_offs_nth_sql_null_low(offsets, n)) {
289 ut_a(!rec_offs_comp(offsets));
290 ulint n_drop = rec_old_is_versioned(rec) ? fn(offsets, n) : 0;
291 rec_set_nth_field_sql_null_low(rec, n - n_drop);
292 }
293
294 return;
295 }
296
297 ut_ad(!rec_offs_nth_default_low(offsets, n));
298
299 /* nullptr for index as n is physical here */
300 data2 = rec_get_nth_field(nullptr, rec, offsets, n, &len2);
301
302 if (len2 == UNIV_SQL_NULL) {
303 ut_ad(!rec_offs_comp(offsets));
304 ulint n_drop = rec_old_is_versioned(rec) ? fn(offsets, n) : 0;
305 rec_set_nth_field_null_bit_low(rec, n - n_drop, false);
306 ut_ad(len == rec_get_nth_field_size_low(rec, n - n_drop));
307 } else {
308 ut_ad(len2 == len);
309 }
310
311 ut_memcpy(data2, data, len);
312}
313
314static inline void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n) {
315 ulint offset;
316
317 offset = rec_get_field_start_offs_low(rec, n);
318
320
322}
323
324static inline void rec_set_nth_field_null_bit_low(rec_t *rec, ulint i,
325 bool val) {
326 ulint info;
327
328 if (rec_get_1byte_offs_flag(rec)) {
330
331 if (val) {
333 } else {
334 info = info & ~REC_1BYTE_SQL_NULL_MASK;
335 }
336
338
339 return;
340 }
341
343
344 if (val) {
346 } else {
347 info = info & ~REC_2BYTE_SQL_NULL_MASK;
348 }
349
351}
352
353static inline ulint rec_get_field_start_offs_low(const rec_t *rec, ulint n) {
354 ut_ad(rec);
356
357 if (n == 0) {
358 return (0);
359 }
360
361 if (rec_get_1byte_offs_flag(rec)) {
362 return (rec_1_get_field_start_offs_low(rec, n));
363 }
364
365 return (rec_2_get_field_start_offs_low(rec, n));
366}
367
371
372 if (n == 0) {
373 return (0);
374 }
375
377}
378
382
383 if (n == 0) {
384 return (0);
385 }
386
387 return (rec_2_get_prev_field_end_info(rec, n) &
389}
390
391static inline ulint rec_1_get_field_end_info_low(const rec_t *rec, ulint n) {
394
395 uint32_t version_size = 0;
396 if (rec_old_is_versioned(rec)) {
397 version_size = 1;
398 }
399
400 return (
401 mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + version_size + n + 1)));
402}
403
404static inline ulint rec_2_get_field_end_info_low(const rec_t *rec, ulint n) {
407
408 uint32_t version_size = 0;
409 if (rec_old_is_versioned(rec)) {
410 version_size = 1;
411 }
412
413 return (mach_read_from_2(rec -
414 (REC_N_OLD_EXTRA_BYTES + version_size + 2 * n + 2)));
415}
416
417static inline void rec_1_set_field_end_info_low(rec_t *rec, ulint n,
418 ulint info) {
421
422 uint32_t version_length = 0;
423 if (rec_old_is_versioned(rec)) {
424 version_length = 1;
425 }
426
427 mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + version_length + n + 1), info);
428}
429
430static inline void rec_2_set_field_end_info_low(rec_t *rec, ulint n,
431 ulint info) {
434
435 uint32_t version_length = 0;
436 if (rec_old_is_versioned(rec)) {
437 version_length = 1;
438 }
439
440 mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + version_length + 2 * n + 2),
441 info);
442}
443
444#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.
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:74
constexpr uint32_t REC_OFFS_DEFAULT
Definition: rec.h:76
constexpr uint32_t REC_N_OLD_EXTRA_BYTES
Definition: rec.h:155
constexpr uint32_t REC_OFFS_DROP
Definition: rec.h:78
constexpr uint32_t REC_OFFS_MASK
Definition: rec.h:80
constexpr uint32_t REC_1BYTE_SQL_NULL_MASK
SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:190
static bool rec_offs_validate(const rec_t *rec, const dict_index_t *index, const ulint *offsets, const bool check_status=true)
Validates offsets returned by rec_get_offsets().
Definition: rec.h:567
constexpr uint32_t REC_OFFS_SQL_NULL
Definition: rec.h:72
static ulint rec_offs_n_fields(const ulint *offsets)
The following function returns the number of fields in a record.
Definition: rec.h:509
static const ulint * rec_offs_base(const ulint *offsets)
Definition: rec.h:226
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:349
constexpr uint32_t REC_2BYTE_SQL_NULL_MASK
SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:192
static bool rec_old_is_versioned(const rec_t *rec)
The following function tells if an old-style record is versioned.
Definition: rec.h:713
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:1116
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:196
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:324
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:379
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:234
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:268
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:391
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:368
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:242
static void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n)
Set nth field value to SQL NULL.
Definition: rem0lrec.h:314
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:353
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:430
static void rec_offs_make_nth_extern_low(ulint *offsets, const ulint n)
Mark the nth field as externally stored.
Definition: rem0lrec.h:229
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:417
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:404
static ulint rec_offs_nth_size_low(const ulint *offsets, ulint n)
Gets the physical size of a field.
Definition: rem0lrec.h:250
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:641
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:622
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:80
#define UNIV_PAGE_SIZE
The universal page size of the database.
Definition: univ.i:293
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:462
constexpr auto UNIV_SQL_ADD_COL_DEFAULT
Flag to indicate a field which was added instantly.
Definition: univ.i:465
unsigned long int ulint
Definition: univ.i:405
constexpr auto UNIV_SQL_INSTANT_DROP_COL
Flag to indicate a field which was dropped instantly.
Definition: univ.i:477
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:104
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:92
static void * ut_memcpy(void *dest, const void *src, ulint n)
Wrapper for memcpy(3).
int n
Definition: xcom_base.cc:508