MySQL 9.0.0
Source Code Documentation
rem0lrec.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2021, 2024, 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 designed to work 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 either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25*****************************************************************************/
26
27/** @file include/rem0lrec.h
28 Record manager.
29 This file contains low level functions which deals with physical index of
30 fields in a physical record.
31
32 After INSTANT ADD/DROP feature, fields index on logical record might not be
33 same as field index on physical record. So a wrapper (rem0wrec.h) is
34 implemented which translates logical index to physical index. And then
35 functions of this file are called with physical index of the field.
36
37 Created 13/08/2021 Mayank Prasad
38*****************************************************************************/
39
40#ifndef rem0lrec_h
41#define rem0lrec_h
42
43#include "rem0rec.h"
44
45/** Set nth field value to SQL NULL.
46@param[in,out] rec record
47@param[in] n index of the field. */
48static inline void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n);
49
50/** Returns nonzero if the SQL NULL bit is set in nth field of rec.
51@param[in] offsets array returned by rec_get_offsets()
52@param[in] n index of the field.
53@return nonzero if SQL NULL */
54static inline ulint rec_offs_nth_sql_null_low(const ulint *offsets, ulint n);
55
56/** Read the offset of the start of a data field in the record. The start of an
57SQL null field is the end offset of the previous non-null field, or 0, if none
58exists. If n is the number of the last field + 1, then the end offset of the
59last field is returned.
60@param[in] rec record
61@param[in] n index of the field
62@return offset of the start of the field */
63static inline ulint rec_get_field_start_offs_low(const rec_t *rec, ulint n);
64
65/** Returns the offset of nth field start if the record is stored in the 1-byte
66offsets form.
67@param[in] rec record
68@param[in] n index of the field
69@return offset of the start of the field */
70static inline ulint rec_1_get_field_start_offs_low(const rec_t *rec, ulint n);
71
72/** Returns the offset of nth field end if the record is stored in the 1-byte
73offsets form. If the field is SQL null, the flag is ORed in the returned value.
74@param[in] rec record
75@param[in] n index of the field
76@return offset of the start of the field, SQL null flag ORed */
77static inline ulint rec_1_get_field_end_info_low(const rec_t *rec, ulint n);
78
79/** Sets the field end info for the nth field if the record is stored in the
801-byte format.
81@param[in,out] rec record
82@param[in] n index of the field
83@param[in] info value to set */
84static inline void rec_1_set_field_end_info_low(rec_t *rec, ulint n,
85 ulint info);
86/** Returns the offset of nth field start if the record is stored in the 2-byte
87offsets form.
88@param[in] rec record
89@param[in] n index of the field
90@return offset of the start of the field */
91static inline ulint rec_2_get_field_start_offs_low(const rec_t *rec, ulint n);
92
93/** Returns the offset of nth field end if the record is stored in the 2-byte
94offsets form. If the field is SQL null, the flag is ORed in the returned value.
95@param[in] rec record
96@param[in] n index of the field
97@return offset of the start of the field, SQL null flag and extern storage flag
98ORed */
99static inline ulint rec_2_get_field_end_info_low(const rec_t *rec, ulint n);
100
101/** Sets the field end info for the nth field if the record is stored in the
1022-byte format.
103@param[in] rec record
104@param[in] n index of the field
105@param[out] info end info */
106static inline void rec_2_set_field_end_info_low(rec_t *rec, ulint n,
107 ulint info);
108
109/** Sets the value of the ith field SQL null bit of an old-style record.
110@param[in] rec record
111@param[in] i index of the field
112@param[in] val value to set */
113static inline void rec_set_nth_field_null_bit_low(rec_t *rec, ulint i,
114 bool val);
115
116/** Gets the physical size of an old-style field.
117Also an SQL null may have a field of size > 0, if the data type is of a fixed
118size.
119@param[in] rec record
120@param[in] n index of the field
121@return field size in bytes */
122static inline ulint rec_get_nth_field_size_low(const rec_t *rec, ulint n) {
123 ulint os;
124 ulint next_os;
125
127 next_os = rec_get_field_start_offs_low(rec, n + 1);
128
129 ut_ad(next_os - os < UNIV_PAGE_SIZE);
130
131 return (next_os - os);
132}
133
134/** Get an offset to the nth data field in a record.
135@param[in] offsets array returned by rec_get_offsets()
136@param[in] n index of the field
137@param[out] len length of the field; UNIV_SQL_NULL if SQL null;
138 UNIV_SQL_ADD_COL_DEFAULT if it's default value and no
139 value inlined
140@return offset from the origin of rec */
141static inline ulint rec_get_nth_field_offs_low(const ulint *offsets, ulint n,
142 ulint *len) {
143 ulint offs;
145 ut_ad(n < rec_offs_n_fields(offsets));
146 ut_ad(len);
147
148 if (n == 0) {
149 offs = 0;
150 } else {
151 offs = rec_offs_base(offsets)[n] & REC_OFFS_MASK;
152 }
153
154 length = rec_offs_base(offsets)[1 + n];
155
158 } else if (length & REC_OFFS_DEFAULT) {
160 } else if (length & REC_OFFS_DROP) {
162 } else {
164 length -= offs;
165 }
166
167 *len = length;
168 return (offs);
169}
170
171/** The following function is used to get the offset to the nth
172data field in an old-style record.
173@param[in] rec record
174@param[in] n index of the field
175@param[out] len length of the field; UNIV_SQL_NULL if SQL null;
176@return offset to the field */
178 ulint *len) {
179 ulint os;
180 ulint next_os;
181
182 ut_ad(len);
183 ut_a(rec);
185
186 if (rec_get_1byte_offs_flag(rec)) {
188
189 next_os = rec_1_get_field_end_info_low(rec, n);
190
191 if (next_os & REC_1BYTE_SQL_NULL_MASK) {
192 *len = UNIV_SQL_NULL;
193
194 return (os);
195 }
196
197 next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK;
198 } else {
200
201 next_os = rec_2_get_field_end_info_low(rec, n);
202
203 if (next_os & REC_2BYTE_SQL_NULL_MASK) {
204 *len = UNIV_SQL_NULL;
205
206 return (os);
207 }
208
209 next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK);
210 }
211
212 *len = next_os - os;
213
214 ut_ad(*len < UNIV_PAGE_SIZE);
215
216 return (os);
217}
218
219/** Returns nonzero if the extern bit is set in nth field of rec.
220@param[in] offsets array returned by rec_get_offsets()
221@param[in] n index of the field
222@return nonzero if externally stored */
223static inline ulint rec_offs_nth_extern_low(const ulint *offsets, ulint n) {
224 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL);
225}
226
227/** Mark the nth field as externally stored.
228@param[in] offsets array returned by rec_get_offsets()
229@param[in] n index of the field */
230static inline void rec_offs_make_nth_extern_low(ulint *offsets, const ulint n) {
232 rec_offs_base(offsets)[1 + n] |= REC_OFFS_EXTERNAL;
233}
234
235static inline ulint rec_offs_nth_sql_null_low(const ulint *offsets, ulint n) {
236 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL);
237}
238
239/** Returns nonzero if the default bit is set in nth field of rec.
240@param[in] offsets array returned by rec_get_offsets()
241@param[in] n index of the field
242@return nonzero if default bit is set */
243static inline ulint rec_offs_nth_default_low(const ulint *offsets, ulint n) {
244 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_DEFAULT);
245}
246
247/** Gets the physical size of a field.
248@param[in] offsets array returned by rec_get_offsets()
249@param[in] n index of the field
250@return length of field */
251static inline ulint rec_offs_nth_size_low(const ulint *offsets, ulint n) {
252 if (!n) {
253 return (rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK);
254 }
255 return ((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n]) &
257}
258
259/** This is used to modify the value of an already existing field in a record.
260The previous value must have exactly the same size as the new value. If len
261is UNIV_SQL_NULL then the field is treated as an SQL null.
262For records in ROW_FORMAT=COMPACT (new-style records), len must not be
263UNIV_SQL_NULL unless the field already is SQL null.
264@param[in] rec record
265@param[in] offsets array returned by rec_get_offsets()
266@param[in] n index of the field
267@param[in] data pointer to the data if not SQL null
268@param[in] len length of the data or UNIV_SQL_NULL */
269static inline void rec_set_nth_field_low(rec_t *rec, const ulint *offsets,
270 ulint n, const void *data, ulint len) {
271 byte *data2;
272 ulint len2;
273
274 ut_ad(rec);
275 ut_ad(rec_offs_validate(rec, nullptr, offsets));
276
277 auto fn = [&](const ulint *offsets, ulint n) {
278 ulint n_drop = 0;
279 for (size_t i = 0; i < n; i++) {
280 ulint len = rec_offs_base(offsets)[1 + i];
281 if (len & REC_OFFS_DROP) {
282 n_drop++;
283 }
284 }
285 return n_drop;
286 };
287
288 if (len == UNIV_SQL_NULL) {
289 if (!rec_offs_nth_sql_null_low(offsets, n)) {
290 ut_a(!rec_offs_comp(offsets));
291 ulint n_drop = rec_old_is_versioned(rec) ? fn(offsets, n) : 0;
292 rec_set_nth_field_sql_null_low(rec, n - n_drop);
293 }
294
295 return;
296 }
297
298 ut_ad(!rec_offs_nth_default_low(offsets, n));
299
300 /* nullptr for index as n is physical here */
301 data2 = rec_get_nth_field(nullptr, rec, offsets, n, &len2);
302
303 if (len2 == UNIV_SQL_NULL) {
304 ut_ad(!rec_offs_comp(offsets));
305 ulint n_drop = rec_old_is_versioned(rec) ? fn(offsets, n) : 0;
306 rec_set_nth_field_null_bit_low(rec, n - n_drop, false);
307 ut_ad(len == rec_get_nth_field_size_low(rec, n - n_drop));
308 } else {
309 ut_ad(len2 == len);
310 }
311
312 ut_memcpy(data2, data, len);
313}
314
315static inline void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n) {
316 ulint offset;
317
318 offset = rec_get_field_start_offs_low(rec, n);
319
321
323}
324
325static inline void rec_set_nth_field_null_bit_low(rec_t *rec, ulint i,
326 bool val) {
327 ulint info;
328
329 if (rec_get_1byte_offs_flag(rec)) {
330 info = rec_1_get_field_end_info_low(rec, i);
331
332 if (val) {
333 info = info | REC_1BYTE_SQL_NULL_MASK;
334 } else {
335 info = info & ~REC_1BYTE_SQL_NULL_MASK;
336 }
337
338 rec_1_set_field_end_info_low(rec, i, info);
339
340 return;
341 }
342
343 info = rec_2_get_field_end_info_low(rec, i);
344
345 if (val) {
346 info = info | REC_2BYTE_SQL_NULL_MASK;
347 } else {
348 info = info & ~REC_2BYTE_SQL_NULL_MASK;
349 }
350
351 rec_2_set_field_end_info_low(rec, i, info);
352}
353
354static inline ulint rec_get_field_start_offs_low(const rec_t *rec, ulint n) {
355 ut_ad(rec);
357
358 if (n == 0) {
359 return (0);
360 }
361
362 if (rec_get_1byte_offs_flag(rec)) {
363 return (rec_1_get_field_start_offs_low(rec, n));
364 }
365
366 return (rec_2_get_field_start_offs_low(rec, n));
367}
368
372
373 if (n == 0) {
374 return (0);
375 }
376
378}
379
383
384 if (n == 0) {
385 return (0);
386 }
387
388 return (rec_2_get_prev_field_end_info(rec, n) &
390}
391
392static inline ulint rec_1_get_field_end_info_low(const rec_t *rec, ulint n) {
395
396 uint32_t version_size = 0;
397 if (rec_old_is_versioned(rec)) {
398 version_size = 1;
399 }
400
401 return (
402 mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + version_size + n + 1)));
403}
404
405static inline ulint rec_2_get_field_end_info_low(const rec_t *rec, ulint n) {
408
409 uint32_t version_size = 0;
410 if (rec_old_is_versioned(rec)) {
411 version_size = 1;
412 }
413
414 return (mach_read_from_2(rec -
415 (REC_N_OLD_EXTRA_BYTES + version_size + 2 * n + 2)));
416}
417
418static inline void rec_1_set_field_end_info_low(rec_t *rec, ulint n,
419 ulint info) {
422
423 uint32_t version_length = 0;
424 if (rec_old_is_versioned(rec)) {
425 version_length = 1;
426 }
427
428 mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + version_length + n + 1), info);
429}
430
431static inline void rec_2_set_field_end_info_low(rec_t *rec, ulint n,
432 ulint info) {
435
436 uint32_t version_length = 0;
437 if (rec_old_is_versioned(rec)) {
438 version_length = 1;
439 }
440
441 mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + version_length + 2 * n + 2),
442 info);
443}
444
445#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:76
constexpr uint32_t REC_OFFS_EXTERNAL
Definition: rec.h:75
constexpr uint32_t REC_OFFS_DEFAULT
Definition: rec.h:77
constexpr uint32_t REC_N_OLD_EXTRA_BYTES
Definition: rec.h:156
constexpr uint32_t REC_OFFS_DROP
Definition: rec.h:79
constexpr uint32_t REC_OFFS_MASK
Definition: rec.h:81
constexpr uint32_t REC_1BYTE_SQL_NULL_MASK
SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:191
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:568
constexpr uint32_t REC_OFFS_SQL_NULL
Definition: rec.h:73
static ulint rec_offs_n_fields(const ulint *offsets)
The following function returns the number of fields in a record.
Definition: rec.h:510
static const ulint * rec_offs_base(const ulint *offsets)
Definition: rec.h:227
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:350
constexpr uint32_t REC_2BYTE_SQL_NULL_MASK
SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:193
static bool rec_old_is_versioned(const rec_t *rec)
The following function tells if an old-style record is versioned.
Definition: rec.h:714
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:1117
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:197
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:325
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:177
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:223
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:380
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:235
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:269
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:392
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:369
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:141
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:243
static void rec_set_nth_field_sql_null_low(rec_t *rec, ulint n)
Set nth field value to SQL NULL.
Definition: rem0lrec.h:315
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:354
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:431
static void rec_offs_make_nth_extern_low(ulint *offsets, const ulint n)
Mark the nth field as externally stored.
Definition: rem0lrec.h:230
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:418
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:122
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:405
static ulint rec_offs_nth_size_low(const ulint *offsets, ulint n)
Gets the physical size of a field.
Definition: rem0lrec.h:251
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:642
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:623
byte rec_t
Definition: rem0types.h:41
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:81
#define UNIV_PAGE_SIZE
The universal page size of the database.
Definition: univ.i:294
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:463
constexpr auto UNIV_SQL_ADD_COL_DEFAULT
Flag to indicate a field which was added instantly.
Definition: univ.i:466
unsigned long int ulint
Definition: univ.i:406
constexpr auto UNIV_SQL_INSTANT_DROP_COL
Flag to indicate a field which was dropped instantly.
Definition: univ.i:478
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:105
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:93
static void * ut_memcpy(void *dest, const void *src, ulint n)
Wrapper for memcpy(3).
int n
Definition: xcom_base.cc:509