MySQL 8.0.32
Source Code Documentation
rec.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 1994, 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
27/** @file rem/rec.h
28 Record manager
29
30 Created 5/30/1994 Heikki Tuuri
31 *************************************************************************/
32
33/** NOTE: The functions in this file should only use functions from
34other files in library. The code in this file is used to make a library for
35external tools. */
36
37#ifndef rem_rec_h
38#define rem_rec_h
39
40#include "dict0boot.h"
41#include "dict0dict.h"
42
43/* Compact flag ORed to the extra size returned by rec_get_offsets() */
44constexpr uint32_t REC_OFFS_COMPACT = 1U << 31;
45/* SQL NULL flag in offsets returned by rec_get_offsets() */
46constexpr uint32_t REC_OFFS_SQL_NULL = 1U << 31;
47/* External flag in offsets returned by rec_get_offsets() */
48constexpr uint32_t REC_OFFS_EXTERNAL = 1 << 30;
49/* Default value flag in offsets returned by rec_get_offsets() */
50constexpr uint32_t REC_OFFS_DEFAULT = 1 << 29;
51/* An INSTANT DROP flag in offsets returned by rec_get_offsets() */
52constexpr uint32_t REC_OFFS_DROP = 1 << 28;
53/* Mask for offsets returned by rec_get_offsets() */
54constexpr uint32_t REC_OFFS_MASK = REC_OFFS_DROP - 1;
55
56/* The offset of heap_no in a compact record */
57constexpr uint32_t REC_NEW_HEAP_NO = 4;
58/* The shift of heap_no in a compact record.
59The status is stored in the low-order bits. */
60constexpr uint32_t REC_HEAP_NO_SHIFT = 3;
61
62/* We list the byte offsets from the origin of the record, the mask,
63and the shift needed to obtain each bit-field of the record. */
64
65constexpr uint32_t REC_NEXT = 2;
66constexpr uint32_t REC_NEXT_MASK = 0xFFFFUL;
67constexpr uint32_t REC_NEXT_SHIFT = 0;
68
69constexpr uint32_t REC_OLD_SHORT = 3; /* This is single byte bit-field */
70constexpr uint32_t REC_OLD_SHORT_MASK = 0x1UL;
71constexpr uint32_t REC_OLD_SHORT_SHIFT = 0;
72
73constexpr uint32_t REC_OLD_N_FIELDS = 4;
74constexpr uint32_t REC_OLD_N_FIELDS_MASK = 0x7FEUL;
75constexpr uint32_t REC_OLD_N_FIELDS_SHIFT = 1;
76
77constexpr uint32_t REC_NEW_STATUS = 3; /* This is single byte bit-field */
78constexpr uint32_t REC_NEW_STATUS_MASK = 0x7UL;
79constexpr uint32_t REC_NEW_STATUS_SHIFT = 0;
80
81constexpr uint32_t REC_OLD_HEAP_NO = 5;
82constexpr uint32_t REC_HEAP_NO_MASK = 0xFFF8UL;
83#if 0 /* defined in rem0rec.h for use of page0zip.cc */
84#define REC_NEW_HEAP_NO 4
85#define REC_HEAP_NO_SHIFT 3
86#endif
87
88constexpr uint32_t REC_OLD_N_OWNED = 6; /* This is single byte bit-field */
89constexpr uint32_t REC_NEW_N_OWNED = 5; /* This is single byte bit-field */
90constexpr uint32_t REC_N_OWNED_MASK = 0xFUL;
91constexpr uint32_t REC_N_OWNED_SHIFT = 0;
92
93constexpr uint32_t REC_OLD_INFO_BITS = 6; /* This is single byte bit-field */
94constexpr uint32_t REC_NEW_INFO_BITS = 5; /* This is single byte bit-field */
95constexpr uint32_t REC_TMP_INFO_BITS = 1; /* This is single byte bit-field */
96constexpr uint32_t REC_INFO_BITS_MASK = 0xF0UL;
97constexpr uint32_t REC_INFO_BITS_SHIFT = 0;
98
99static_assert((REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) ^
101 REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) ^
102 REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) ^
104 0xFFFFFFFFUL) == 0,
105 "sum of old-style masks != 0xFFFFFFFFUL");
106static_assert((REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) ^
107 REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) ^
108 REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) ^
110 0xFFFFFFUL) == 0,
111 "sum of new-style masks != 0xFFFFFFUL");
112
113/* Info bit denoting the predefined minimum record: this bit is set
114if and only if the record is the first user record on a non-leaf
115B-tree page that is the leftmost page on its level
116(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */
117constexpr uint32_t REC_INFO_MIN_REC_FLAG = 0x10UL;
118/** The deleted flag in info bits; when bit is set to 1, it means the record has
119 been delete marked */
120constexpr uint32_t REC_INFO_DELETED_FLAG = 0x20UL;
121/* Use this bit to indicate record has version */
122constexpr uint32_t REC_INFO_VERSION_FLAG = 0x40UL;
123/** The instant ADD COLUMN flag. When it is set to 1, it means this record
124was inserted/updated after an instant ADD COLUMN. */
125constexpr uint32_t REC_INFO_INSTANT_FLAG = 0x80UL;
126
127/* Number of extra bytes in an old-style record,
128in addition to the data and the offsets */
129constexpr uint32_t REC_N_OLD_EXTRA_BYTES = 6;
130/* Number of extra bytes in a new-style record,
131in addition to the data and the offsets */
132constexpr int32_t REC_N_NEW_EXTRA_BYTES = 5;
133/* Number of extra bytes in a new-style temporary record,
134in addition to the data and the offsets.
135This is used only after instant ADD COLUMN. */
136constexpr uint32_t REC_N_TMP_EXTRA_BYTES = 1;
137
138#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
139/** Maximum number of records in a page */
141
142/* We use decltype(A.load()) not decltype(A)::value_type, as some compilers
143don't have it implemented, even as they should have this with the C++17
144implementation. Maybe this will be available on all compilers with C++20. */
145static_assert(MAX_REC_PER_PAGE <=
146 std::numeric_limits<
147 decltype(buf_block_t::ahi_t::n_pointers.load())>::max());
148
149#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
150
151/* Record status values */
152constexpr uint32_t REC_STATUS_ORDINARY = 0;
153constexpr uint32_t REC_STATUS_NODE_PTR = 1;
154constexpr uint32_t REC_STATUS_INFIMUM = 2;
155constexpr uint32_t REC_STATUS_SUPREMUM = 3;
156
157/* The following four constants are needed in page0zip.cc in order to
158efficiently compress and decompress pages. */
159
160/* Length of a B-tree node pointer, in bytes */
161constexpr uint32_t REC_NODE_PTR_SIZE = 4;
162
163/** SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records */
164constexpr uint32_t REC_1BYTE_SQL_NULL_MASK = 0x80UL;
165/** SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records */
166constexpr uint32_t REC_2BYTE_SQL_NULL_MASK = 0x8000UL;
167
168/** In a 2-byte offset of ROW_FORMAT=REDUNDANT records, the second most
169significant bit denotes that the tail of a field is stored off-page. */
170constexpr uint32_t REC_2BYTE_EXTERN_MASK = 0x4000UL;
171
172#ifdef UNIV_DEBUG
173/* Length of the rec_get_offsets() header */
174constexpr uint32_t REC_OFFS_HEADER_SIZE = 4;
175#else /* UNIV_DEBUG */
176/* Length of the rec_get_offsets() header */
177constexpr uint32_t REC_OFFS_HEADER_SIZE = 2;
178#endif /* UNIV_DEBUG */
179
180/* Number of elements that should be initially allocated for the
181offsets[] array, first passed to rec_get_offsets() */
182constexpr uint32_t REC_OFFS_NORMAL_SIZE = 100;
183constexpr uint32_t REC_OFFS_SMALL_SIZE = 10;
184
185/* Get the base address of offsets. The extra_size is stored at
186this position, and following positions hold the end offsets of
187the fields. */
188
189static inline const ulint *rec_offs_base(const ulint *offsets) {
190 return offsets + REC_OFFS_HEADER_SIZE;
191}
192
193static inline ulint *rec_offs_base(ulint *offsets) {
194 return offsets + REC_OFFS_HEADER_SIZE;
195}
196
197/** Number of fields flag which means it occupies two bytes */
198static const uint8_t REC_N_FIELDS_TWO_BYTES_FLAG = 0x80;
199
200/** Max number of fields which can be stored in one byte */
201static const uint8_t REC_N_FIELDS_ONE_BYTE_MAX = 0x7F;
202
203/** The following function determines the offsets to each field
204 in the record. It can reuse a previously allocated array.
205 Note that after instant ADD COLUMN, if this is a record
206 from clustered index, fields in the record may be less than
207 the fields defined in the clustered index. So the offsets
208 size is allocated according to the clustered index fields.
209 @param[in] rec physical record
210 @param[in] index record descriptor
211 @param[in,out] offsets array consisting of offsets[0] allocated elements, or an
212 array from rec_get_offsets(), or NULL
213 @param[in] n_fields maximum number of initialized fields (ULINT_UNDEFINED is
214 all fields)
215 @param[in] location location where called
216 @param[in,out] heap memory heap
217 @return the new offsets */
218[[nodiscard]] ulint *rec_get_offsets(const rec_t *rec,
219 const dict_index_t *index, ulint *offsets,
220 ulint n_fields, ut::Location location,
221 mem_heap_t **heap);
222
223/** The following function determines the offsets to each field
224 in the record. It can reuse a previously allocated array. */
226 const byte *extra, /*!< in: the extra bytes of a
227 compact record in reverse order,
228 excluding the fixed-size
229 REC_N_NEW_EXTRA_BYTES */
230 const dict_index_t *index, /*!< in: record descriptor */
231 ulint node_ptr, /*!< in: nonzero=node pointer,
232 0=leaf node */
233 ulint *offsets); /*!< in/out: array consisting of
234 offsets[0] allocated elements */
235
236/** Gets a bit field from within 1 byte. */
238 const rec_t *rec, /*!< in: pointer to record origin */
239 ulint offs, /*!< in: offset from the origin down */
240 ulint mask, /*!< in: mask used to filter bits */
241 ulint shift) /*!< in: shift right applied after masking */
242{
243 ut_ad(rec);
244
245 return ((mach_read_from_1(rec - offs) & mask) >> shift);
246}
247
248/** Gets a bit field from within 2 bytes. */
249static inline uint16_t rec_get_bit_field_2(
250 const rec_t *rec, /*!< in: pointer to record origin */
251 ulint offs, /*!< in: offset from the origin down */
252 ulint mask, /*!< in: mask used to filter bits */
253 ulint shift) /*!< in: shift right applied after masking */
254{
255 ut_ad(rec);
256
257 return ((mach_read_from_2(rec - offs) & mask) >> shift);
258}
259
260/** The following function retrieves the status bits of a new-style record.
261 @return status bits */
262[[nodiscard]] static inline ulint rec_get_status(
263 const rec_t *rec) /*!< in: physical record */
264{
265 ulint ret;
266
267 ut_ad(rec);
268
271 ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
272
273 return (ret);
274}
275
276#ifdef UNIV_DEBUG
277/** Check if the info bits are valid.
278@param[in] bits info bits to check
279@return true if valid */
280inline bool rec_info_bits_valid(ulint bits) {
281 return (0 == (bits & ~(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG |
283}
284#endif /* UNIV_DEBUG */
285
286/** The following function is used to retrieve the info bits of a record.
287@param[in] rec physical record
288@param[in] comp nonzero=compact page format
289@return info bits */
290static inline ulint rec_get_info_bits(const rec_t *rec, ulint comp) {
291 const ulint val =
295 return (val);
296}
297
298/** The following function is used to retrieve the info bits of a temporary
299record.
300@param[in] rec physical record
301@return info bits */
302static inline ulint rec_get_info_bits_temp(const rec_t *rec) {
303 const ulint val = rec_get_bit_field_1(
306 return (val);
307}
308
309/** The following function is used to get the number of fields
310 in an old-style record, which is stored in the rec
311 @return number of data fields */
312[[nodiscard]] static inline uint16_t rec_get_n_fields_old_raw(
313 const rec_t *rec) /*!< in: physical record */
314{
315 uint16_t n_fields;
316
317 ut_ad(rec);
318
321
322 ut_ad(n_fields <= REC_MAX_N_FIELDS);
323 ut_ad(n_fields > 0);
324
325 return (n_fields);
326}
327
328/** The following function is used to get the number of fields
329in an old-style record. Have to consider the case that after
330instant ADD COLUMN, this record may have less fields than
331current index.
332@param[in] rec physical record
333@param[in] index index where the record resides
334@return number of data fields */
335[[nodiscard]] static inline uint16_t rec_get_n_fields_old(
336 const rec_t *rec, const dict_index_t *index) {
337 uint16_t n = rec_get_n_fields_old_raw(rec);
338
340 if (strcmp(index->name, RECOVERY_INDEX_TABLE_NAME) == 0) {
341 /* In recovery, index is not completely built. Skip validation. */
342 if (n > 1) /* For infimum/supremum, n is 1 */ {
343 n = static_cast<uint16_t>(dict_index_get_n_fields(index));
344 }
345 return n;
346 }
347
348 uint16_t n_uniq = dict_index_get_n_unique_in_tree_nonleaf(index);
349
350 ut_ad(index->is_clustered());
352 ut_ad(n_uniq > 0);
353 /* Only when it's infimum or supremum, n is 1.
354 If n is exact n_uniq, this should be a record copied with prefix during
355 search.
356 And if it's node pointer, n is n_uniq + 1, which should be always less
357 than the number of fields in any leaf page, even if the record in
358 leaf page is before instant ADD COLUMN. This is because any record in
359 leaf page must have at least n_uniq + 2 (system columns) fields */
360 ut_ad(n == 1 || n >= n_uniq);
361 ut_ad(static_cast<uint16_t>(dict_index_get_n_fields(index)) > n_uniq + 1);
362 if (n > n_uniq + 1) {
363 /* This is leaf node. If table has INSTANT columns, then it is possible
364 that record might not have all the fields in index. So get it now from
365 index. */
366#ifdef UNIV_DEBUG
367 if (index->has_instant_cols() && !index->has_row_versions()) {
369 ulint rec_diff = dict_index_get_n_fields(index) - n;
370 ulint col_diff = index->table->n_cols - index->table->n_instant_cols;
371 ut_ad(rec_diff <= col_diff);
372 }
373
374 if (n != dict_index_get_n_fields(index)) {
376 }
377#endif /* UNIV_DEBUG */
378 n = static_cast<uint16_t>(dict_index_get_n_fields(index));
379 }
380 }
381
382 return (n);
383}
384
385/** The following function is used to get the number of fields
386 in a record. If it's REDUNDANT record, the returned number
387 would be a logic one which considers the fact that after
388 instant ADD COLUMN, some records may have less fields than
389 index.
390 @return number of data fields */
392 const rec_t *rec, /*!< in: physical record */
393 const dict_index_t *index) /*!< in: record descriptor */
394{
395 ut_ad(rec);
396 ut_ad(index);
397
398 if (!dict_table_is_comp(index->table)) {
399 return (rec_get_n_fields_old(rec, index));
400 }
401
402 switch (rec_get_status(rec)) {
404 return (dict_index_get_n_fields(index));
406 return (dict_index_get_n_unique_in_tree(index) + 1);
409 return (1);
410 default:
411 ut_error;
412 }
413}
414
415/** Confirms the n_fields of the entry is sane with comparing the other
416record in the same page specified
417@param[in] index index
418@param[in] rec record of the same page
419@param[in] entry index entry
420@return true if n_fields is sane */
421static inline bool rec_n_fields_is_sane(dict_index_t *index, const rec_t *rec,
422 const dtuple_t *entry) {
423 return (rec_get_n_fields(rec, index) == dtuple_get_n_fields(entry)
424 /* a record for older SYS_INDEXES table
425 (missing merge_threshold column) is acceptable. */
426 || (index->table->id == DICT_INDEXES_ID &&
427 rec_get_n_fields(rec, index) == dtuple_get_n_fields(entry) - 1));
428}
429
430/** The following function returns the number of allocated elements
431 for an array of offsets.
432 @return number of elements */
433[[nodiscard]] static inline ulint rec_offs_get_n_alloc(
434 const ulint *offsets) /*!< in: array for rec_get_offsets() */
435{
436 ulint n_alloc;
437 ut_ad(offsets);
438 n_alloc = offsets[0];
439 ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
440 UNIV_MEM_ASSERT_W(offsets, n_alloc * sizeof *offsets);
441 return (n_alloc);
442}
443
444/** The following function sets the number of allocated elements
445 for an array of offsets. */
446static inline void rec_offs_set_n_alloc(
447 ulint *offsets, /*!< out: array for rec_get_offsets(),
448 must be allocated */
449 ulint n_alloc) /*!< in: number of elements */
450{
451 ut_ad(offsets);
452 ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
453 UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets);
454 offsets[0] = n_alloc;
455}
456
457/** The following function sets the number of fields in offsets. */
458static inline void rec_offs_set_n_fields(
459 ulint *offsets, /*!< in/out: array returned by
460 rec_get_offsets() */
461 ulint n_fields) /*!< in: number of fields */
462{
463 ut_ad(offsets);
464 ut_ad(n_fields > 0);
465 ut_ad(n_fields <= REC_MAX_N_FIELDS);
466 ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets));
467 offsets[1] = n_fields;
468}
469
470/** The following function returns the number of fields in a record.
471 @return number of fields */
472[[nodiscard]] static inline ulint rec_offs_n_fields(
473 const ulint *offsets) /*!< in: array returned by rec_get_offsets() */
474{
475 ulint n_fields;
476 ut_ad(offsets);
477 n_fields = offsets[1];
478 ut_ad(n_fields > 0);
479 ut_ad(n_fields <= REC_MAX_N_FIELDS);
480 ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets));
481 return (n_fields);
482}
483
484/** Determine the offset of a specified field in the record, when this
485field is a field added after an instant ADD COLUMN
486@param[in] index Clustered index where the record resides
487@param[in] n Nth field to get offset
488@param[in] offs Last offset before current field
489@return The offset of the specified field */
490static inline uint64_t rec_get_instant_offset(const dict_index_t *index,
491 ulint n, uint64_t offs) {
493
495 index->get_nth_default(n, &length);
496
497 if (length == UNIV_SQL_NULL) {
498 return (offs | REC_OFFS_SQL_NULL);
499 } else {
500 return (offs | REC_OFFS_DEFAULT);
501 }
502}
503
504/** The following function determines the offsets to each field in the record.
505The offsets are written to a previously allocated array of ulint, where
506rec_offs_n_fields(offsets) has been initialized to the number of fields in the
507record. The rest of the array will be initialized by this function.
508- rec_offs_base(offsets)[0] will be set to the extra size
509 (if REC_OFFS_COMPACT is set, the record is in the new format;
510 if REC_OFFS_EXTERNAL is set, the record contains externally stored columns).
511- rec_offs_base(offsets)[1..n_fields] will be set to offsets past the end of
512 fields 0..n_fields, or to the beginning of fields 1..n_fields+1.
513- If the high-order bit of the offset at [i+1] is set (REC_OFFS_SQL_NULL),
514 the field i is NULL.
515- If the second high-order bit of the offset at [i+1] is set
516(REC_OFFS_EXTERNAL), the field i is being stored externally.
517@param[in] rec physical record
518@param[in] index record descriptor
519@param[in,out] offsets array of offsets */
520void rec_init_offsets(const rec_t *rec, const dict_index_t *index,
521 ulint *offsets);
522
523#ifdef UNIV_DEBUG
524/** Validates offsets returned by rec_get_offsets().
525 @return true if valid */
526[[nodiscard]] static inline bool rec_offs_validate(
527 const rec_t *rec, /*!< in: record or NULL */
528 const dict_index_t *index, /*!< in: record descriptor or NULL */
529 const ulint *offsets) /*!< in: array returned by
530 rec_get_offsets() */
531{
532 ulint i = rec_offs_n_fields(offsets);
534 ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
535
536 if (rec) {
537 /* The offsets array might be:
538 - specific to the `rec`, in which case its address is stored in offsets[2],
539 - cached and shared by many records, in which case we've passed rec=nullptr
540 when preparing the offsets array.
541 We use caching only for the ROW_FORMAT=COMPACT format. */
542 ut_ad((ulint)rec == offsets[2] || ((ulint) nullptr == offsets[2] &&
543 offsets == index->rec_cache.offsets));
544 if (!comp && index != nullptr) {
545 ut_a(rec_get_n_fields_old(rec, index) >= i);
546 }
547 }
548
549 if (index) {
550 ulint max_n_fields;
551 ut_ad((ulint)index == offsets[3]);
552 ulint n_fields = dict_index_get_n_fields(index);
553 ulint n_unique_in_tree = dict_index_get_n_unique_in_tree(index) + 1;
554 max_n_fields = std::max(n_fields, n_unique_in_tree);
555 if (!comp && rec != nullptr && rec_get_n_fields_old_raw(rec) < i) {
557 }
558
559 if (comp && rec) {
560 switch (rec_get_status(rec)) {
562 break;
564 max_n_fields = dict_index_get_n_unique_in_tree(index) + 1;
565 break;
568 max_n_fields = 1;
569 break;
570 default:
571 ut_error;
572 }
573 }
574 /* index->n_def == 0 for dummy indexes if !comp */
575 ut_a(!comp || index->n_def);
576 ut_a(!index->n_def || i <= max_n_fields);
577 }
578 while (i--) {
579 ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
580 ut_a(curr <= last);
581 last = curr;
582 }
583 return true;
584}
585
586/** Updates debug data in offsets, in order to avoid bogus
587 rec_offs_validate() failures. */
588static inline void rec_offs_make_valid(
589 const rec_t *rec, /*!< in: record */
590 const dict_index_t *index, /*!< in: record descriptor */
591 ulint *offsets) /*!< in: array returned by
592 rec_get_offsets() */
593{
594 /* offsets are either intended for this particular rec, or to be cached */
595 ut_ad(rec || offsets == index->rec_cache.offsets);
596 ut_ad(index);
597 ut_ad(offsets);
598 ut_ad(rec == nullptr ||
599 rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets));
600 offsets[2] = (ulint)rec;
601 offsets[3] = (ulint)index;
602}
603
604/** Check if the given two record offsets are identical.
605@param[in] offsets1 field offsets of a record
606@param[in] offsets2 field offsets of a record
607@return true if they are identical, false otherwise. */
608bool rec_offs_cmp(ulint *offsets1, ulint *offsets2);
609
610/** Print the record offsets.
611@param[in] out the output stream to which offsets are printed.
612@param[in] offsets the field offsets of the record.
613@return the output stream. */
614std::ostream &rec_offs_print(std::ostream &out, const ulint *offsets);
615#else
616#define rec_offs_make_valid(rec, index, offsets) ((void)0)
617#endif /* UNIV_DEBUG */
618
619/** The following function tells if a new-style record is instant record.
620@param[in] rec new-style record
621@return true if it is instant affected */
622static inline bool rec_get_instant_flag_new(const rec_t *rec) {
623 ulint info = rec_get_info_bits(rec, true);
624 return ((info & REC_INFO_INSTANT_FLAG) != 0);
625}
626
627/** The following function tells if a new-style temp record is instant record.
628@param[in] rec new-style temp record
629@return true if it is instant affected */
630static inline bool rec_get_instant_flag_new_temp(const rec_t *rec) {
632 return ((info & REC_INFO_INSTANT_FLAG) != 0);
633}
634
635/** A simplified variant rec_init_offsets(rec, index, offsets) for the case in
636which the rec contains only fixed-length columns and non-NULL values in them,
637thus we can compute the offsets without looking at the rec. Such offsets can be
638cached and reused for many recs which don't contain NULLs.
639@see rec_init_offsets for more details
640@param[in] index The index for which we want to cache the fixed offsets
641@param[in,out] offsets The already allocated array to store the offsets.
642 It should already have been initialized with
643 rec_offs_set_n_alloc() and rec_offs_set_n_fields() before
644 the call.
645 This function will fill all the other elements. */
646inline void rec_init_fixed_offsets(const dict_index_t *index, ulint *offsets) {
648
649 rec_offs_make_valid(nullptr, index, offsets);
650 rec_offs_base(offsets)[0] =
653 const auto n_fields = rec_offs_n_fields(offsets);
654 auto field_end = rec_offs_base(offsets) + 1;
655 for (size_t i = 0; i < n_fields; i++) {
656 field_end[i] = (i ? field_end[i - 1] : 0) + index->get_field(i)->fixed_len;
657 }
658}
659
660/** The following function tells if a new-style record is versioned.
661@param[in] rec new-style (COMPACT/DYNAMIC) record
662@return true if it is versioned */
663static inline bool rec_new_is_versioned(const rec_t *rec) {
664 ulint info = rec_get_info_bits(rec, true);
665 return ((info & REC_INFO_VERSION_FLAG) != 0);
666}
667
668/** The following function tells if an old-style record is versioned.
669@param[in] rec old-style (REDUNDANT) record
670@return true if it's versioned */
671static inline bool rec_old_is_versioned(const rec_t *rec) {
672 ulint info = rec_get_info_bits(rec, false);
673 return ((info & REC_INFO_VERSION_FLAG) != 0);
674}
675
676/** The following function tells if a temporary record is versioned.
677@param[in] rec new-style temporary record
678@return true if it's instant affected */
679static inline bool rec_new_temp_is_versioned(const rec_t *rec) {
681 return ((info & REC_INFO_VERSION_FLAG) != 0);
682}
683
684/** Get the number of fields for one new style leaf page record.
685This is only needed for table after instant ADD COLUMN.
686@param[in] rec leaf page record
687@param[in] extra_bytes extra bytes of this record
688@param[in,out] length length of number of fields
689@return number of fields */
690static inline uint32_t rec_get_n_fields_instant(const rec_t *rec,
691 const ulint extra_bytes,
692 uint16_t *length) {
693 uint16_t n_fields;
694 const byte *ptr;
695
696 ptr = rec - (extra_bytes + 1);
697
698 if ((*ptr & REC_N_FIELDS_TWO_BYTES_FLAG) == 0) {
699 *length = 1;
700 return (*ptr);
701 }
702
703 *length = 2;
704 n_fields = ((*ptr-- & REC_N_FIELDS_ONE_BYTE_MAX) << 8);
705 n_fields |= *ptr;
706 ut_ad(n_fields < REC_MAX_N_FIELDS);
707 ut_ad(n_fields != 0);
708
709 return (n_fields);
710}
711
712/* For INSTANT ADD/DROP, we may have following 5 types of rec for table :
713 +----------------------------------------------------------------------------+
714 | SCENARIO | STATE |
715 |----------------------------------+------------+---------+------------------|
716 | Row property | V <= 8.0.28| Bit set | Stored on row |
717 +----------------------------------+------------+---------+------------------+
718 | INSERTED before 1st INSTANT ADD | Y | NONE | N/A |
719 |----------------------------------+------------+---------+------------------|
720 | INSERTED after 1st INSTANT ADD | Y | INSTANT | # of fields |
721 |----------------------------------+------------+---------+------------------|
722 | INSERTED before INSTANT ADD/DROP | Y | VERSION | Version = 0 |
723 |----------------------------------+------------+---------+------------------|
724 | INSERTED before INSTANT ADD/DROP | N | NONE | N/A |
725 |----------------------------------+------------+---------+------------------|
726 | INSERTED after INSTANT ADD/DROP | Y/N | VERSION | row version |
727 +----------------------------------------------------------------------------+
728*/
730 /* Record was inserted before first instant add done in the earlier
731 implementation. */
733 /* Record was inserted after first instant add done in the earlier
734 implementation. */
736 /* Record was inserted after upgrade but before first instant add done in the
737 new implementation. */
739 /* Record was inserted before first instant add/drop done in the new
740 implementation. */
742 /* Record was inserted after first instant add/drop done in the new
743 implementation. */
745 /* Record belongs to table with no verison no instant */
747 NONE
749
751 const dict_index_t *index, const rec_t *rec, bool temp) {
752 ut_ad(dict_table_is_comp(index->table) || temp);
753
754 if (!index->has_instant_cols_or_row_versions()) {
756 }
757
758 /* Position just before info-bits where version will be there if any */
759 const byte *v_ptr =
760 (byte *)rec -
762 const bool is_versioned =
764 const uint8_t version = (is_versioned) ? (uint8_t)(*v_ptr) : UINT8_UNDEFINED;
765
766 const bool is_instant = (temp) ? rec_get_instant_flag_new_temp(rec)
768
769 /* Only one of the two bits could be set */
770 DBUG_EXECUTE_IF("innodb_rec_instant_version_bit_set", {
771 ib::error() << "Record has both instant and version bit set in Table '"
772 << index->table_name << "', Index '" << index->name()
773 << "'. This indicates that the table may be corrupt. Please "
774 "run CHECK TABLE before proceeding.";
775 });
776
777 if (is_versioned && is_instant) {
778 ib::error() << "Record has both instant and version bit set in Table '"
779 << index->table_name << "', Index '" << index->name()
780 << "'. This indicates that the table may be corrupt. Please "
781 "run CHECK TABLE before proceeding.";
782 }
783 ut_ad(!is_versioned || !is_instant);
784
785 enum REC_INSERT_STATE rec_insert_state = REC_INSERT_STATE::NONE;
786 if (is_versioned) {
788 if (version == 0) {
789 ut_ad(index->has_instant_cols());
790 rec_insert_state =
792 } else {
793 ut_ad(index->has_row_versions());
795 }
796 } else if (is_instant) {
797 ut_ad(index->table->has_instant_cols());
799 } else if (index->table->has_instant_cols()) {
801 } else {
803 }
804
805 ut_ad(rec_insert_state != REC_INSERT_STATE::NONE);
806 return rec_insert_state;
807}
808
809/* Following function is to set NULLS and LENS pointers correctly for a temp
810record generated for a record from REDUNDANT FORAMT
811@param[in] index record descriptor
812@param[in,out] rec temp record
813@param[out] n_null number of nullable columns in record
814@param[out] nulls pointer to nullbit map in temp record
815@param[out] lens pointer to lens in temp record
816@returns the row version stored in record or nondefault fields in record */
818 const dict_index_t *index, const rec_t *rec, uint16_t *n_null,
819 const byte **nulls, const byte **lens, uint16_t &non_default_fields,
820 uint8_t &row_version) {
822
823 non_default_fields = static_cast<uint16_t>(dict_index_get_n_fields(index));
824
825 row_version = UINT8_UNDEFINED;
826
827 /* Set nulls just before the record */
828 *nulls = rec - 1;
829
830 enum REC_INSERT_STATE rec_insert_state =
831 get_rec_insert_state(index, rec, true);
832
833 if (rec_insert_state == INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION) {
834 *n_null = index->n_nullable;
835 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
836 return rec_insert_state;
837 }
838
839 /* info-bits must be present. Shift nulls before that. */
840 *nulls -= REC_N_TMP_EXTRA_BYTES;
841
842 switch (rec_insert_state) {
846 *n_null = index->get_nullable_in_version(0);
847 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
848 } break;
849
852 /* Read the version information */
853 row_version = (uint8_t)(**nulls);
854 ut_a(is_valid_row_version(row_version));
855
856 /* Shift nulls before the record version */
857 *nulls -= 1;
858 *n_null = index->get_nullable_in_version(row_version);
859 } break;
860
862 default:
863 ut_a(0);
864 }
865
866 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
867 return rec_insert_state;
868}
869
870/** Determines the information about null bytes and variable length bytes
871for a new-style temporary record
872@param[in] rec physical record
873@param[in] index index where the record resides
874@param[out] nulls the start of null bytes
875@param[out] lens the start of variable length bytes
876@param[out] n_null number of null fields
877@param[out] non_default_fields non default fields from record
878@param[out] row_version row version of the record
879@return the row inserted state */
881 const rec_t *rec, const dict_index_t *index, const byte **nulls,
882 const byte **lens, uint16_t *n_null, uint16_t &non_default_fields,
883 uint8_t &row_version) {
884 /* Following is the format for TEMP record.
885 +----+----+-------------------+--------------------+
886 | OP | ES |<-- Extra info --> | F1 | F2 | ... | Fn|
887 +----+----+-------------------+--------------------+
888 |
889 v
890 +--------------------+-------+---------+-----------+
891 | LN | ... | L2 | L1 | nulls | version | info-bits |
892 +--------------------+-------+---------+-----------+
893 <------ LENS ------>
894
895 where
896 info-bits => Present iff table has INSTANT/VERSION
897 version => version number iff version bit is set.
898 */
899
900 /* Redundant format */
901 if (!dict_table_is_comp(index->table)) {
902 return init_nulls_lens_for_temp_redundant(index, rec, n_null, nulls, lens,
903 non_default_fields, row_version);
904 }
905
906 non_default_fields = static_cast<uint16_t>(dict_index_get_n_fields(index));
907
908 row_version = UINT8_UNDEFINED;
909
910 /* Set nulls just before the record */
911 *nulls = rec - 1;
912
913 const enum REC_INSERT_STATE rec_insert_state =
914 get_rec_insert_state(index, rec, true);
915
916 if (rec_insert_state == INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION) {
917 *n_null = index->n_nullable;
918 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
919 return rec_insert_state;
920 }
921
922 /* info-bits must be present. Shift nulls before that. */
923 *nulls -= REC_N_TMP_EXTRA_BYTES;
924
925 switch (rec_insert_state) {
928 /* Read the version information */
929 row_version = (uint8_t)(**nulls);
930 ut_a(is_valid_row_version(row_version));
931
932 /* Shift nulls before the record version */
933 *nulls -= 1;
934
935 *n_null = index->get_nullable_in_version(row_version);
936 } break;
937
939 /* Row inserted after first instant ADD COLUMN V1 */
940 ut_ad(index->table->has_instant_cols());
941 uint16_t length;
942 non_default_fields =
944 ut_ad(length == 1 || length == 2);
945
946 /* Shift nulls before "number of fields" */
947 *nulls -= length;
948 *n_null = index->get_n_nullable_before(non_default_fields);
949 } break;
950
952 *n_null = index->get_nullable_before_instant_add_drop();
953 non_default_fields = index->get_instant_fields();
954 } break;
955
957 /* Row inserted before first INSTANT ADD/DROP in V2 */
958 *n_null = index->get_nullable_before_instant_add_drop();
959 } break;
960
962 default:
963 ut_a(0);
964 }
965
966 /* Position lens */
967 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
968
969 return (rec_insert_state);
970}
971
972/** Determines the information about null bytes and variable length bytes
973for a new style record
974@param[in] rec physical record
975@param[in] index index where the record resides
976@param[out] nulls the start of null bytes
977@param[out] lens the start of variable length bytes
978@param[out] n_null number of null fields
979@param[out] non_default_fields non default fields from record
980@param[out] row_version row version of the record
981@return number of fields with no default or the row version of record */
983 const rec_t *rec, const dict_index_t *index, const byte **nulls,
984 const byte **lens, uint16_t *n_null, uint16_t &non_default_fields,
985 uint8_t &row_version) {
986 non_default_fields = static_cast<uint16_t>(dict_index_get_n_fields(index));
987
988 row_version = UINT8_UNDEFINED;
989
990 /* Position nulls */
991 *nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
992
993 const enum REC_INSERT_STATE rec_insert_state =
994 get_rec_insert_state(index, rec, false);
995
996 switch (rec_insert_state) {
1000
1001 *n_null = index->n_nullable;
1002 } break;
1003
1006 /* Read the row version from record */
1007 row_version = (uint8_t)(**nulls);
1008 ut_ad(is_valid_row_version(row_version));
1009
1010#ifdef UNIV_DEBUG
1011 if (strcmp(index->name, RECOVERY_INDEX_TABLE_NAME) != 0) {
1012 if (row_version > 0) {
1013 /* Row inserted after first instant ADD/DROP COLUMN V2 */
1014 ut_ad(index->table->has_row_versions());
1015 } else {
1016 /* Upgraded table. Row inserted before V2 INSTANT ADD/DROP */
1017 ut_ad(index->table->is_upgraded_instant());
1018 }
1019 }
1020#endif
1021
1022 /* Reposition nulls to skip version */
1023 *nulls -= 1;
1024 *n_null = index->get_nullable_in_version(row_version);
1025 } break;
1026
1028 /* Row inserted after first instant ADD COLUMN V1 */
1029 uint16_t length;
1030 non_default_fields =
1032 ut_ad(length == 1 || length == 2);
1033
1034 /* Reposition nulls to skip number of fields */
1035 *nulls -= length;
1036 *n_null = index->calculate_n_instant_nullable(non_default_fields);
1037 } break;
1038
1040 *n_null = index->get_nullable_before_instant_add_drop();
1041 non_default_fields = index->get_instant_fields();
1042 } break;
1043
1045 /* Row inserted before first INSTANT ADD/DROP in V2 */
1046 *n_null = index->get_nullable_before_instant_add_drop();
1047 } break;
1048
1049 default:
1050 ut_ad(false);
1051 }
1052
1053 /* Position lens */
1054 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
1055
1056 /* Return record version or non_default_field stored */
1057 return (rec_insert_state);
1058}
1059
1060/** Determine the offset to each field in a leaf-page record in
1061ROW_FORMAT=COMPACT. This is a special case of rec_init_offsets() and
1062rec_get_offsets().
1063@param[in] rec physical record in ROW_FORMAT=COMPACT
1064@param[in] temp whether to use the format for temporary files in index
1065 creation
1066@param[in] index record descriptor
1067@param[in,out] offsets array of offsets */
1068void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp,
1069 const dict_index_t *index, ulint *offsets);
1070
1071/** The following function is used to test whether the data offsets in the
1072 record are stored in one-byte or two-byte format.
1073 @return true if 1-byte form */
1074[[nodiscard]] static inline bool rec_get_1byte_offs_flag(
1075 const rec_t *rec) /*!< in: physical record */
1076{
1079}
1080
1081#endif
The class error is used to emit error messages.
Definition: ut0log.h:229
static ulint dtuple_get_n_fields(const dtuple_t *tuple)
Gets number of fields in a data tuple.
Data dictionary creation and booting.
constexpr uint32_t DICT_INDEXES_ID
Definition: dict0boot.h:96
Data dictionary system.
static uint16_t dict_index_get_n_unique_in_tree_nonleaf(const dict_index_t *index)
Gets the number of fields on nonleaf page level in the internal representation of an index which uniq...
static bool dict_table_is_comp(const dict_table_t *table)
Check whether the table uses the compact page format.
static ulint dict_index_get_n_unique_in_tree(const dict_index_t *index)
Gets the number of fields in the internal representation of an index which uniquely determine the pos...
static ulint dict_index_get_n_fields(const dict_index_t *index)
Gets the number of fields in the internal representation of an index, including fields added by the d...
static bool is_valid_row_version(const uint8_t version)
Definition: dict0mem.h:426
constexpr char RECOVERY_INDEX_TABLE_NAME[]
index/table name used while applying REDO logs during recovery
Definition: dict0mem.h:88
static bool is_instant(const Alter_inplace_info *ha_alter_info)
Determine if this is an instant ALTER TABLE.
Definition: handler0alter.cc:912
static uint16_t mach_read_from_2(const byte *b)
The following function is used to fetch data from 2 consecutive bytes.
static uint8_t mach_read_from_1(const byte *b)
The following function is used to fetch data from one byte.
static mi_bit_type mask[]
Definition: mi_packrec.cc:140
#define DBUG_EXECUTE_IF(keyword, a1)
Definition: my_dbug.h:170
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
bool rec_info_bits_valid(ulint bits)
Check if the info bits are valid.
Definition: rec.h:280
constexpr uint32_t REC_INFO_INSTANT_FLAG
The instant ADD COLUMN flag.
Definition: rec.h:125
static const uint8_t REC_N_FIELDS_TWO_BYTES_FLAG
Number of fields flag which means it occupies two bytes.
Definition: rec.h:198
static uint16_t rec_get_bit_field_2(const rec_t *rec, ulint offs, ulint mask, ulint shift)
Gets a bit field from within 2 bytes.
Definition: rec.h:249
constexpr uint32_t REC_N_OWNED_MASK
Definition: rec.h:90
static enum REC_INSERT_STATE rec_init_null_and_len_temp(const rec_t *rec, const dict_index_t *index, const byte **nulls, const byte **lens, uint16_t *n_null, uint16_t &non_default_fields, uint8_t &row_version)
Determines the information about null bytes and variable length bytes for a new-style temporary recor...
Definition: rec.h:880
constexpr uint32_t REC_OFFS_EXTERNAL
Definition: rec.h:48
constexpr uint32_t REC_OFFS_HEADER_SIZE
Definition: rec.h:174
static enum REC_INSERT_STATE init_nulls_lens_for_temp_redundant(const dict_index_t *index, const rec_t *rec, uint16_t *n_null, const byte **nulls, const byte **lens, uint16_t &non_default_fields, uint8_t &row_version)
Definition: rec.h:817
constexpr uint32_t REC_OFFS_DEFAULT
Definition: rec.h:50
constexpr uint32_t REC_NEW_HEAP_NO
Definition: rec.h:57
void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp, const dict_index_t *index, ulint *offsets)
Determine the offset to each field in a leaf-page record in ROW_FORMAT=COMPACT.
Definition: rec.cc:529
void rec_init_fixed_offsets(const dict_index_t *index, ulint *offsets)
A simplified variant rec_init_offsets(rec, index, offsets) for the case in which the rec contains onl...
Definition: rec.h:646
static enum REC_INSERT_STATE rec_init_null_and_len_comp(const rec_t *rec, const dict_index_t *index, const byte **nulls, const byte **lens, uint16_t *n_null, uint16_t &non_default_fields, uint8_t &row_version)
Determines the information about null bytes and variable length bytes for a new style record.
Definition: rec.h:982
static bool rec_get_instant_flag_new_temp(const rec_t *rec)
The following function tells if a new-style temp record is instant record.
Definition: rec.h:630
constexpr uint32_t REC_NEXT
Definition: rec.h:65
constexpr uint32_t REC_N_OLD_EXTRA_BYTES
Definition: rec.h:129
constexpr uint32_t REC_STATUS_SUPREMUM
Definition: rec.h:155
constexpr uint32_t REC_NODE_PTR_SIZE
Definition: rec.h:161
constexpr uint32_t REC_INFO_BITS_SHIFT
Definition: rec.h:97
constexpr uint32_t REC_OFFS_DROP
Definition: rec.h:52
constexpr uint32_t REC_INFO_MIN_REC_FLAG
Definition: rec.h:117
static ulint rec_get_info_bits(const rec_t *rec, ulint comp)
The following function is used to retrieve the info bits of a record.
Definition: rec.h:290
void rec_init_offsets(const rec_t *rec, const dict_index_t *index, ulint *offsets)
The following function determines the offsets to each field in the record.
Definition: rec.cc:347
constexpr uint32_t REC_NEW_INFO_BITS
Definition: rec.h:94
constexpr uint32_t REC_OLD_INFO_BITS
Definition: rec.h:93
constexpr uint32_t REC_OFFS_MASK
Definition: rec.h:54
constexpr uint32_t REC_OLD_SHORT_MASK
Definition: rec.h:70
constexpr uint32_t REC_OLD_SHORT_SHIFT
Definition: rec.h:71
constexpr uint32_t REC_INFO_BITS_MASK
Definition: rec.h:96
static ulint rec_get_info_bits_temp(const rec_t *rec)
The following function is used to retrieve the info bits of a temporary record.
Definition: rec.h:302
static uint64_t rec_get_instant_offset(const dict_index_t *index, ulint n, uint64_t offs)
Determine the offset of a specified field in the record, when this field is a field added after an in...
Definition: rec.h:490
static const uint8_t REC_N_FIELDS_ONE_BYTE_MAX
Max number of fields which can be stored in one byte.
Definition: rec.h:201
constexpr uint32_t REC_HEAP_NO_MASK
Definition: rec.h:82
REC_INSERT_STATE
Definition: rec.h:729
@ INSERTED_AFTER_UPGRADE_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION
Definition: rec.h:738
@ INSERTED_AFTER_INSTANT_ADD_OLD_IMPLEMENTATION
Definition: rec.h:735
@ INSERTED_AFTER_INSTANT_ADD_NEW_IMPLEMENTATION
Definition: rec.h:744
@ INSERTED_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION
Definition: rec.h:741
@ INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION
Definition: rec.h:746
@ NONE
Definition: rec.h:747
@ INSERTED_BEFORE_INSTANT_ADD_OLD_IMPLEMENTATION
Definition: rec.h:732
constexpr uint32_t REC_TMP_INFO_BITS
Definition: rec.h:95
constexpr uint32_t REC_HEAP_NO_SHIFT
Definition: rec.h:60
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:526
constexpr uint32_t REC_STATUS_ORDINARY
Definition: rec.h:152
static enum REC_INSERT_STATE get_rec_insert_state(const dict_index_t *index, const rec_t *rec, bool temp)
Definition: rec.h:750
static ulint rec_offs_get_n_alloc(const ulint *offsets)
The following function returns the number of allocated elements for an array of offsets.
Definition: rec.h:433
constexpr uint32_t REC_STATUS_INFIMUM
Definition: rec.h:154
constexpr uint32_t REC_NEW_STATUS
Definition: rec.h:77
static void rec_offs_make_valid(const rec_t *rec, const dict_index_t *index, ulint *offsets)
Updates debug data in offsets, in order to avoid bogus rec_offs_validate() failures.
Definition: rec.h:588
static bool rec_new_is_versioned(const rec_t *rec)
The following function tells if a new-style record is versioned.
Definition: rec.h:663
constexpr uint32_t REC_INFO_DELETED_FLAG
The deleted flag in info bits; when bit is set to 1, it means the record has been delete marked.
Definition: rec.h:120
static uint16_t rec_get_n_fields_old(const rec_t *rec, const dict_index_t *index)
The following function is used to get the number of fields in an old-style record.
Definition: rec.h:335
constexpr uint32_t REC_1BYTE_SQL_NULL_MASK
SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:164
constexpr uint32_t REC_OLD_N_FIELDS
Definition: rec.h:73
constexpr auto MAX_REC_PER_PAGE
Maximum number of records in a page.
Definition: rec.h:140
constexpr uint32_t REC_OFFS_COMPACT
NOTE: The functions in this file should only use functions from other files in library.
Definition: rec.h:44
static void rec_offs_set_n_alloc(ulint *offsets, ulint n_alloc)
The following function sets the number of allocated elements for an array of offsets.
Definition: rec.h:446
static bool rec_new_temp_is_versioned(const rec_t *rec)
The following function tells if a temporary record is versioned.
Definition: rec.h:679
constexpr uint32_t REC_NEW_STATUS_MASK
Definition: rec.h:78
constexpr uint32_t REC_OFFS_SQL_NULL
Definition: rec.h:46
constexpr uint32_t REC_N_TMP_EXTRA_BYTES
Definition: rec.h:136
constexpr uint32_t REC_OLD_N_OWNED
Definition: rec.h:88
static ulint rec_offs_n_fields(const ulint *offsets)
The following function returns the number of fields in a record.
Definition: rec.h:472
static const ulint * rec_offs_base(const ulint *offsets)
Definition: rec.h:189
constexpr int32_t REC_N_NEW_EXTRA_BYTES
Definition: rec.h:132
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:312
constexpr uint32_t REC_NEXT_MASK
Definition: rec.h:66
constexpr uint32_t REC_2BYTE_SQL_NULL_MASK
SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records.
Definition: rec.h:166
ulint * rec_get_offsets(const rec_t *rec, const dict_index_t *index, ulint *offsets, ulint n_fields, ut::Location location, mem_heap_t **heap)
The following function determines the offsets to each field in the record.
Definition: rec.cc:358
constexpr uint32_t REC_INFO_VERSION_FLAG
Definition: rec.h:122
constexpr uint32_t REC_NEW_N_OWNED
Definition: rec.h:89
constexpr uint32_t REC_OLD_N_FIELDS_SHIFT
Definition: rec.h:75
constexpr uint32_t REC_OLD_HEAP_NO
Definition: rec.h:81
static bool rec_old_is_versioned(const rec_t *rec)
The following function tells if an old-style record is versioned.
Definition: rec.h:671
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:1074
void rec_get_offsets_reverse(const byte *extra, const dict_index_t *index, ulint node_ptr, ulint *offsets)
The following function determines the offsets to each field in the record.
Definition: rec.cc:415
constexpr uint32_t REC_N_OWNED_SHIFT
Definition: rec.h:91
static uint32_t rec_get_n_fields_instant(const rec_t *rec, const ulint extra_bytes, uint16_t *length)
Get the number of fields for one new style leaf page record.
Definition: rec.h:690
constexpr uint32_t REC_STATUS_NODE_PTR
Definition: rec.h:153
static bool rec_n_fields_is_sane(dict_index_t *index, const rec_t *rec, const dtuple_t *entry)
Confirms the n_fields of the entry is sane with comparing the other record in the same page specified...
Definition: rec.h:421
constexpr uint32_t REC_OLD_SHORT
Definition: rec.h:69
constexpr uint32_t REC_NEXT_SHIFT
Definition: rec.h:67
static void rec_offs_set_n_fields(ulint *offsets, ulint n_fields)
The following function sets the number of fields in offsets.
Definition: rec.h:458
constexpr uint32_t REC_OFFS_NORMAL_SIZE
Definition: rec.h:182
static ulint rec_get_bit_field_1(const rec_t *rec, ulint offs, ulint mask, ulint shift)
Gets a bit field from within 1 byte.
Definition: rec.h:237
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:170
constexpr uint32_t REC_NEW_STATUS_SHIFT
Definition: rec.h:79
bool rec_offs_cmp(ulint *offsets1, ulint *offsets2)
Check if the given two record offsets are identical.
Definition: rec.cc:714
static ulint rec_get_n_fields(const rec_t *rec, const dict_index_t *index)
The following function is used to get the number of fields in a record.
Definition: rec.h:391
std::ostream & rec_offs_print(std::ostream &out, const ulint *offsets)
Print the record offsets.
Definition: rec.cc:746
static ulint rec_get_status(const rec_t *rec)
The following function retrieves the status bits of a new-style record.
Definition: rec.h:262
static bool rec_get_instant_flag_new(const rec_t *rec)
The following function tells if a new-style record is instant record.
Definition: rec.h:622
constexpr uint32_t REC_OLD_N_FIELDS_MASK
Definition: rec.h:74
constexpr uint32_t REC_OFFS_SMALL_SIZE
Definition: rec.h:183
byte rec_t
Definition: rem0types.h:40
constexpr uint32_t REC_MAX_N_FIELDS
Definition: rem0types.h:43
required uint64 version
Definition: replication_group_member_actions.proto:40
Definition: completion_hash.h:34
std::atomic< uint16_t > n_pointers
Used in debugging.
Definition: buf0buf.h:1763
unsigned fixed_len
0 or the fixed length of the column if smaller than DICT_ANTELOPE_MAX_INDEX_COL_LEN
Definition: dict0mem.h:907
Data structure for an index.
Definition: dict0mem.h:1045
uint32_t get_n_nullable_before(uint32_t nth) const
Returns the number of nullable fields before specified nth field.
Definition: dict0mem.h:1367
const char * table_name
table name
Definition: dict0mem.h:1056
id_name_t name
index name
Definition: dict0mem.h:1053
const byte * get_nth_default(ulint nth, ulint *length) const
Get the default value of nth field and its length if exists.
Definition: dict0mem.h:1574
bool has_instant_cols_or_row_versions() const
check if either instant or versioned.
Definition: dict0mem.h:1351
uint32_t get_instant_fields() const
Returns the number of fields before first instant ADD COLUMN.
Definition: dict0mem.ic:91
dict_field_t * get_field(ulint pos) const
Gets the nth field of an index.
Definition: dict0mem.h:1501
uint16_t get_nullable_before_instant_add_drop() const
Get the nullable fields before any INSTANT ADD/DROP.
Definition: dict0mem.h:1255
size_t calculate_n_instant_nullable(size_t _n_fields) const
Definition: dict0mem.h:1394
unsigned n_def
number of fields defined so far
Definition: dict0mem.h:1102
unsigned n_nullable
number of nullable fields
Definition: dict0mem.h:1111
rec_cache_t rec_cache
cache the field that needs to be re-computed on each insert.
Definition: dict0mem.h:1224
bool has_row_versions() const
Check whether index belongs to a table having row versions.
Definition: dict0mem.h:1347
bool is_clustered() const
Definition: dict0mem.h:1310
bool has_instant_cols() const
Check whether index has any instantly added columns.
Definition: dict0mem.h:1343
dict_table_t * table
back pointer to table
Definition: dict0mem.h:1059
uint32_t get_nullable_in_version(uint8_t version) const
Return nullable in a specific row version.
Definition: dict0mem.h:1435
bool has_instant_cols() const
Definition: dict0mem.h:2487
bool has_row_versions() const
Definition: dict0mem.h:2472
unsigned n_cols
Number of non-virtual columns.
Definition: dict0mem.h:2044
unsigned n_instant_cols
Number of non-virtual columns before first instant ADD COLUMN, including the system columns like n_co...
Definition: dict0mem.h:2049
table_id_t id
Id of the table.
Definition: dict0mem.h:1963
bool is_upgraded_instant() const
Checks if table is upgraded table with INSTANT ADD columns in V1.
Definition: dict0mem.h:2544
Structure for an SQL data tuple of fields (logical record)
Definition: data0data.h:681
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:301
Part of traditional "extra" column or related hierarchical property.
Definition: opt_explain_format.h:264
const ulint * offsets
Holds reference to cached offsets for record.
Definition: dict0mem.h:981
Definition: ut0core.h:32
#define UNIV_MEM_ASSERT_W(addr, size)
Definition: univ.i:619
constexpr uint8_t UINT8_UNDEFINED
The 'undefined' value for a 8-bit unsigned integer.
Definition: univ.i:435
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
#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size)
Definition: univ.i:631
constexpr ulint ULINT_MAX
Maximum value for a ulint.
Definition: univ.i:441
unsigned long int ulint
Definition: univ.i:407
constexpr size_t UNIV_PAGE_SIZE_MAX
Maximum page size InnoDB currently supports.
Definition: univ.i:324
#define ut_error
Abort execution.
Definition: ut0dbg.h:64
#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
#define UT_BITS_IN_BYTES(b)
Determine how many bytes (groups of 8 bits) are needed to store the given number of bits.
Definition: ut0ut.h:191
int n
Definition: xcom_base.cc:508