MySQL 8.0.33
Source Code Documentation
rec.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 1994, 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
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/** Instant state of a record. Determined by instant and version bit in info
186 * bits. */
188 /* Record is neither instant nor versioned: Instant: 0, Version: 0 */
190 /* Record is versioned but not instant: Instant: 0, Version: 1 */
192 /* Record is instant but not versioned: Instant: 1, Version: 0 */
194};
195
196/* Get the base address of offsets. The extra_size is stored at
197this position, and following positions hold the end offsets of
198the fields. */
199
200static inline const ulint *rec_offs_base(const ulint *offsets) {
201 return offsets + REC_OFFS_HEADER_SIZE;
202}
203
204static inline ulint *rec_offs_base(ulint *offsets) {
205 return offsets + REC_OFFS_HEADER_SIZE;
206}
207
208/** Number of fields flag which means it occupies two bytes */
209static const uint8_t REC_N_FIELDS_TWO_BYTES_FLAG = 0x80;
210
211/** Max number of fields which can be stored in one byte */
212static const uint8_t REC_N_FIELDS_ONE_BYTE_MAX = 0x7F;
213
214/** The following function determines the offsets to each field
215 in the record. It can reuse a previously allocated array.
216 Note that after instant ADD COLUMN, if this is a record
217 from clustered index, fields in the record may be less than
218 the fields defined in the clustered index. So the offsets
219 size is allocated according to the clustered index fields.
220 @param[in] rec physical record
221 @param[in] index record descriptor
222 @param[in,out] offsets array consisting of offsets[0] allocated elements, or an
223 array from rec_get_offsets(), or NULL
224 @param[in] n_fields maximum number of initialized fields (ULINT_UNDEFINED is
225 all fields)
226 @param[in] location location where called
227 @param[in,out] heap memory heap
228 @return the new offsets */
229[[nodiscard]] ulint *rec_get_offsets(const rec_t *rec,
230 const dict_index_t *index, ulint *offsets,
231 ulint n_fields, ut::Location location,
232 mem_heap_t **heap);
233
234/** The following function determines the offsets to each field
235 in the record. It can reuse a previously allocated array. */
237 const byte *extra, /*!< in: the extra bytes of a
238 compact record in reverse order,
239 excluding the fixed-size
240 REC_N_NEW_EXTRA_BYTES */
241 const dict_index_t *index, /*!< in: record descriptor */
242 ulint node_ptr, /*!< in: nonzero=node pointer,
243 0=leaf node */
244 ulint *offsets); /*!< in/out: array consisting of
245 offsets[0] allocated elements */
246
247/** Gets a bit field from within 1 byte. */
249 const rec_t *rec, /*!< in: pointer to record origin */
250 ulint offs, /*!< in: offset from the origin down */
251 ulint mask, /*!< in: mask used to filter bits */
252 ulint shift) /*!< in: shift right applied after masking */
253{
254 ut_ad(rec);
255
256 return ((mach_read_from_1(rec - offs) & mask) >> shift);
257}
258
259/** Gets a bit field from within 2 bytes. */
260static inline uint16_t rec_get_bit_field_2(
261 const rec_t *rec, /*!< in: pointer to record origin */
262 ulint offs, /*!< in: offset from the origin down */
263 ulint mask, /*!< in: mask used to filter bits */
264 ulint shift) /*!< in: shift right applied after masking */
265{
266 ut_ad(rec);
267
268 return ((mach_read_from_2(rec - offs) & mask) >> shift);
269}
270
271/** The following function retrieves the status bits of a new-style record.
272 @return status bits */
273[[nodiscard]] static inline ulint rec_get_status(
274 const rec_t *rec) /*!< in: physical record */
275{
276 ulint ret;
277
278 ut_ad(rec);
279
282 ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
283
284 return (ret);
285}
286
287#ifdef UNIV_DEBUG
288/** Check if the info bits are valid.
289@param[in] bits info bits to check
290@return true if valid */
291inline bool rec_info_bits_valid(ulint bits) {
292 return (0 == (bits & ~(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG |
294}
295#endif /* UNIV_DEBUG */
296
297/** The following function is used to retrieve the info bits of a record.
298@param[in] rec physical record
299@param[in] comp nonzero=compact page format
300@return info bits */
301static inline ulint rec_get_info_bits(const rec_t *rec, ulint comp) {
302 const ulint val =
306 return (val);
307}
308
309/** The following function is used to retrieve the info bits of a temporary
310record.
311@param[in] rec physical record
312@return info bits */
313static inline ulint rec_get_info_bits_temp(const rec_t *rec) {
314 const ulint val = rec_get_bit_field_1(
317 return (val);
318}
319
320/** The following function is used to get the number of fields
321 in an old-style record, which is stored in the rec
322 @return number of data fields */
323[[nodiscard]] static inline uint16_t rec_get_n_fields_old_raw(
324 const rec_t *rec) /*!< in: physical record */
325{
326 uint16_t n_fields;
327
328 ut_ad(rec);
329
332
333 ut_ad(n_fields <= REC_MAX_N_FIELDS);
334 ut_ad(n_fields > 0);
335
336 return (n_fields);
337}
338
339/** The following function is used to get the number of fields
340in an old-style record. Have to consider the case that after
341instant ADD COLUMN, this record may have less fields than
342current index.
343@param[in] rec physical record
344@param[in] index index where the record resides
345@return number of data fields */
346[[nodiscard]] static inline uint16_t rec_get_n_fields_old(
347 const rec_t *rec, const dict_index_t *index) {
348 uint16_t n = rec_get_n_fields_old_raw(rec);
349
351 if (strcmp(index->name, RECOVERY_INDEX_TABLE_NAME) == 0) {
352 /* In recovery, index is not completely built. Skip validation. */
353 if (n > 1) /* For infimum/supremum, n is 1 */ {
354 n = static_cast<uint16_t>(dict_index_get_n_fields(index));
355 }
356 return n;
357 }
358
359 uint16_t n_uniq = dict_index_get_n_unique_in_tree_nonleaf(index);
360
361 ut_ad(index->is_clustered());
363 ut_ad(n_uniq > 0);
364 /* Only when it's infimum or supremum, n is 1.
365 If n is exact n_uniq, this should be a record copied with prefix during
366 search.
367 And if it's node pointer, n is n_uniq + 1, which should be always less
368 than the number of fields in any leaf page, even if the record in
369 leaf page is before instant ADD COLUMN. This is because any record in
370 leaf page must have at least n_uniq + 2 (system columns) fields */
371 ut_ad(n == 1 || n >= n_uniq);
372 ut_ad(static_cast<uint16_t>(dict_index_get_n_fields(index)) > n_uniq + 1);
373 if (n > n_uniq + 1) {
374 /* This is leaf node. If table has INSTANT columns, then it is possible
375 that record might not have all the fields in index. So get it now from
376 index. */
377#ifdef UNIV_DEBUG
378 if (index->has_instant_cols() && !index->has_row_versions()) {
380 ulint rec_diff = dict_index_get_n_fields(index) - n;
381 ulint col_diff = index->table->n_cols - index->table->n_instant_cols;
382 ut_ad(rec_diff <= col_diff);
383 }
384
385 if (n != dict_index_get_n_fields(index)) {
387 }
388#endif /* UNIV_DEBUG */
389 n = static_cast<uint16_t>(dict_index_get_n_fields(index));
390 }
391 }
392
393 return (n);
394}
395
396/** The following function is used to get the number of fields
397 in a record. If it's REDUNDANT record, the returned number
398 would be a logic one which considers the fact that after
399 instant ADD COLUMN, some records may have less fields than
400 index.
401 @return number of data fields */
403 const rec_t *rec, /*!< in: physical record */
404 const dict_index_t *index) /*!< in: record descriptor */
405{
406 ut_ad(rec);
407 ut_ad(index);
408
409 if (!dict_table_is_comp(index->table)) {
410 return (rec_get_n_fields_old(rec, index));
411 }
412
413 switch (rec_get_status(rec)) {
415 return (dict_index_get_n_fields(index));
417 return (dict_index_get_n_unique_in_tree(index) + 1);
420 return (1);
421 default:
422 ut_error;
423 }
424}
425
426/** Confirms the n_fields of the entry is sane with comparing the other
427record in the same page specified
428@param[in] index index
429@param[in] rec record of the same page
430@param[in] entry index entry
431@return true if n_fields is sane */
432static inline bool rec_n_fields_is_sane(dict_index_t *index, const rec_t *rec,
433 const dtuple_t *entry) {
434 return (rec_get_n_fields(rec, index) == dtuple_get_n_fields(entry)
435 /* a record for older SYS_INDEXES table
436 (missing merge_threshold column) is acceptable. */
437 || (index->table->id == DICT_INDEXES_ID &&
438 rec_get_n_fields(rec, index) == dtuple_get_n_fields(entry) - 1));
439}
440
441/** The following function returns the number of allocated elements
442 for an array of offsets.
443 @return number of elements */
444[[nodiscard]] static inline ulint rec_offs_get_n_alloc(
445 const ulint *offsets) /*!< in: array for rec_get_offsets() */
446{
447 ulint n_alloc;
448 ut_ad(offsets);
449 n_alloc = offsets[0];
450 ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
451 UNIV_MEM_ASSERT_W(offsets, n_alloc * sizeof *offsets);
452 return (n_alloc);
453}
454
455/** The following function sets the number of allocated elements
456 for an array of offsets. */
457static inline void rec_offs_set_n_alloc(
458 ulint *offsets, /*!< out: array for rec_get_offsets(),
459 must be allocated */
460 ulint n_alloc) /*!< in: number of elements */
461{
462 ut_ad(offsets);
463 ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
464 UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets);
465 offsets[0] = n_alloc;
466}
467
468/** The following function sets the number of fields in offsets. */
469static inline void rec_offs_set_n_fields(
470 ulint *offsets, /*!< in/out: array returned by
471 rec_get_offsets() */
472 ulint n_fields) /*!< in: number of fields */
473{
474 ut_ad(offsets);
475 ut_ad(n_fields > 0);
476 ut_ad(n_fields <= REC_MAX_N_FIELDS);
477 ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets));
478 offsets[1] = n_fields;
479}
480
481/** The following function returns the number of fields in a record.
482 @return number of fields */
483[[nodiscard]] static inline ulint rec_offs_n_fields(
484 const ulint *offsets) /*!< in: array returned by rec_get_offsets() */
485{
486 ulint n_fields;
487 ut_ad(offsets);
488 n_fields = offsets[1];
489 ut_ad(n_fields > 0);
490 ut_ad(n_fields <= REC_MAX_N_FIELDS);
491 ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets));
492 return (n_fields);
493}
494
495/** Determine the offset of a specified field in the record, when this
496field is a field added after an instant ADD COLUMN
497@param[in] index Clustered index where the record resides
498@param[in] n Nth field to get offset
499@param[in] offs Last offset before current field
500@return The offset of the specified field */
501static inline uint64_t rec_get_instant_offset(const dict_index_t *index,
502 ulint n, uint64_t offs) {
504
506 index->get_nth_default(n, &length);
507
508 if (length == UNIV_SQL_NULL) {
509 return (offs | REC_OFFS_SQL_NULL);
510 } else {
511 return (offs | REC_OFFS_DEFAULT);
512 }
513}
514
515/** The following function determines the offsets to each field in the record.
516The offsets are written to a previously allocated array of ulint, where
517rec_offs_n_fields(offsets) has been initialized to the number of fields in the
518record. The rest of the array will be initialized by this function.
519- rec_offs_base(offsets)[0] will be set to the extra size
520 (if REC_OFFS_COMPACT is set, the record is in the new format;
521 if REC_OFFS_EXTERNAL is set, the record contains externally stored columns).
522- rec_offs_base(offsets)[1..n_fields] will be set to offsets past the end of
523 fields 0..n_fields, or to the beginning of fields 1..n_fields+1.
524- If the high-order bit of the offset at [i+1] is set (REC_OFFS_SQL_NULL),
525 the field i is NULL.
526- If the second high-order bit of the offset at [i+1] is set
527(REC_OFFS_EXTERNAL), the field i is being stored externally.
528@param[in] rec physical record
529@param[in] index record descriptor
530@param[in,out] offsets array of offsets */
531void rec_init_offsets(const rec_t *rec, const dict_index_t *index,
532 ulint *offsets);
533
534#ifdef UNIV_DEBUG
535/** Validates offsets returned by rec_get_offsets().
536 @return true if valid */
537[[nodiscard]] static inline bool rec_offs_validate(
538 const rec_t *rec, /*!< in: record or NULL */
539 const dict_index_t *index, /*!< in: record descriptor or NULL */
540 const ulint *offsets) /*!< in: array returned by
541 rec_get_offsets() */
542{
543 ulint i = rec_offs_n_fields(offsets);
545 ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
546
547 if (rec) {
548 /* The offsets array might be:
549 - specific to the `rec`, in which case its address is stored in offsets[2],
550 - cached and shared by many records, in which case we've passed rec=nullptr
551 when preparing the offsets array.
552 We use caching only for the ROW_FORMAT=COMPACT format. */
553 ut_ad((ulint)rec == offsets[2] || ((ulint) nullptr == offsets[2] &&
554 offsets == index->rec_cache.offsets));
555 if (!comp && index != nullptr) {
556 ut_a(rec_get_n_fields_old(rec, index) >= i);
557 }
558 }
559
560 if (index) {
561 ulint max_n_fields;
562 ut_ad((ulint)index == offsets[3]);
563 ulint n_fields = dict_index_get_n_fields(index);
564 ulint n_unique_in_tree = dict_index_get_n_unique_in_tree(index) + 1;
565 max_n_fields = std::max(n_fields, n_unique_in_tree);
566 if (!comp && rec != nullptr && rec_get_n_fields_old_raw(rec) < i) {
568 }
569
570 if (comp && rec) {
571 switch (rec_get_status(rec)) {
573 break;
575 max_n_fields = dict_index_get_n_unique_in_tree(index) + 1;
576 break;
579 max_n_fields = 1;
580 break;
581 default:
582 ut_error;
583 }
584 }
585 /* index->n_def == 0 for dummy indexes if !comp */
586 ut_a(!comp || index->n_def);
587 ut_a(!index->n_def || i <= max_n_fields);
588 }
589 while (i--) {
590 ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
591 ut_a(curr <= last);
592 last = curr;
593 }
594 return true;
595}
596
597/** Updates debug data in offsets, in order to avoid bogus
598 rec_offs_validate() failures. */
599static inline void rec_offs_make_valid(
600 const rec_t *rec, /*!< in: record */
601 const dict_index_t *index, /*!< in: record descriptor */
602 ulint *offsets) /*!< in: array returned by
603 rec_get_offsets() */
604{
605 /* offsets are either intended for this particular rec, or to be cached */
606 ut_ad(rec || offsets == index->rec_cache.offsets);
607 ut_ad(index);
608 ut_ad(offsets);
609 ut_ad(rec == nullptr ||
610 rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets));
611 offsets[2] = (ulint)rec;
612 offsets[3] = (ulint)index;
613}
614
615/** Check if the given two record offsets are identical.
616@param[in] offsets1 field offsets of a record
617@param[in] offsets2 field offsets of a record
618@return true if they are identical, false otherwise. */
619bool rec_offs_cmp(ulint *offsets1, ulint *offsets2);
620
621/** Print the record offsets.
622@param[in] out the output stream to which offsets are printed.
623@param[in] offsets the field offsets of the record.
624@return the output stream. */
625std::ostream &rec_offs_print(std::ostream &out, const ulint *offsets);
626#else
627#define rec_offs_make_valid(rec, index, offsets) ((void)0)
628#endif /* UNIV_DEBUG */
629
630/** The following function tells if a new-style record is instant record.
631@param[in] rec new-style record
632@return true if it is instant affected */
633static inline bool rec_get_instant_flag_new(const rec_t *rec) {
634 ulint info = rec_get_info_bits(rec, true);
635 return ((info & REC_INFO_INSTANT_FLAG) != 0);
636}
637
638/** The following function tells if a new-style temp record is instant record.
639@param[in] rec new-style temp record
640@return true if it is instant affected */
641static inline bool rec_get_instant_flag_new_temp(const rec_t *rec) {
643 return ((info & REC_INFO_INSTANT_FLAG) != 0);
644}
645
646/** A simplified variant rec_init_offsets(rec, index, offsets) for the case in
647which the rec contains only fixed-length columns and non-NULL values in them,
648thus we can compute the offsets without looking at the rec. Such offsets can be
649cached and reused for many recs which don't contain NULLs.
650@see rec_init_offsets for more details
651@param[in] index The index for which we want to cache the fixed offsets
652@param[in,out] offsets The already allocated array to store the offsets.
653 It should already have been initialized with
654 rec_offs_set_n_alloc() and rec_offs_set_n_fields() before
655 the call.
656 This function will fill all the other elements. */
657inline void rec_init_fixed_offsets(const dict_index_t *index, ulint *offsets) {
659
660 rec_offs_make_valid(nullptr, index, offsets);
661 rec_offs_base(offsets)[0] =
664 const auto n_fields = rec_offs_n_fields(offsets);
665 auto field_end = rec_offs_base(offsets) + 1;
666 for (size_t i = 0; i < n_fields; i++) {
667 field_end[i] = (i ? field_end[i - 1] : 0) + index->get_field(i)->fixed_len;
668 }
669}
670
671/** The following function tells if a new-style record is versioned.
672@param[in] rec new-style (COMPACT/DYNAMIC) record
673@return true if it is versioned */
674static inline bool rec_new_is_versioned(const rec_t *rec) {
675 ulint info = rec_get_info_bits(rec, true);
676 return ((info & REC_INFO_VERSION_FLAG) != 0);
677}
678
679/** The following function tells if an old-style record is versioned.
680@param[in] rec old-style (REDUNDANT) record
681@return true if it's versioned */
682static inline bool rec_old_is_versioned(const rec_t *rec) {
683 ulint info = rec_get_info_bits(rec, false);
684 return ((info & REC_INFO_VERSION_FLAG) != 0);
685}
686
687/** The following function tells if a temporary record is versioned.
688@param[in] rec new-style temporary record
689@return true if it's instant affected */
690static inline bool rec_new_temp_is_versioned(const rec_t *rec) {
692 return ((info & REC_INFO_VERSION_FLAG) != 0);
693}
694
695/** Get the number of fields for one new style leaf page record.
696This is only needed for table after instant ADD COLUMN.
697@param[in] rec leaf page record
698@param[in] extra_bytes extra bytes of this record
699@param[in,out] length length of number of fields
700@return number of fields */
701static inline uint32_t rec_get_n_fields_instant(const rec_t *rec,
702 const ulint extra_bytes,
703 uint16_t *length) {
704 uint16_t n_fields;
705 const byte *ptr;
706
707 ptr = rec - (extra_bytes + 1);
708
709 if ((*ptr & REC_N_FIELDS_TWO_BYTES_FLAG) == 0) {
710 *length = 1;
711 return (*ptr);
712 }
713
714 *length = 2;
715 n_fields = ((*ptr-- & REC_N_FIELDS_ONE_BYTE_MAX) << 8);
716 n_fields |= *ptr;
717 ut_ad(n_fields < REC_MAX_N_FIELDS);
718 ut_ad(n_fields != 0);
719
720 return (n_fields);
721}
722
723/* For INSTANT ADD/DROP, we may have following 5 types of rec for table :
724 +----------------------------------------------------------------------------+
725 | SCENARIO | STATE |
726 |----------------------------------+------------+---------+------------------|
727 | Row property | V <= 8.0.28| Bit set | Stored on row |
728 +----------------------------------+------------+---------+------------------+
729 | INSERTED before 1st INSTANT ADD | Y | NONE | N/A |
730 |----------------------------------+------------+---------+------------------|
731 | INSERTED after 1st INSTANT ADD | Y | INSTANT | # of fields |
732 |----------------------------------+------------+---------+------------------|
733 | INSERTED before INSTANT ADD/DROP | Y | VERSION | Version = 0 |
734 |----------------------------------+------------+---------+------------------|
735 | INSERTED before INSTANT ADD/DROP | N | NONE | N/A |
736 |----------------------------------+------------+---------+------------------|
737 | INSERTED after INSTANT ADD/DROP | Y/N | VERSION | row version |
738 +----------------------------------------------------------------------------+
739*/
741 /* Record was inserted before first instant add done in the earlier
742 implementation. */
744 /* Record was inserted after first instant add done in the earlier
745 implementation. */
747 /* Record was inserted after upgrade but before first instant add done in the
748 new implementation. */
750 /* Record was inserted before first instant add/drop done in the new
751 implementation. */
753 /* Record was inserted after first instant add/drop done in the new
754 implementation. */
756 /* Record belongs to table with no verison no instant */
758 NONE
760
762 const dict_index_t *index, const rec_t *rec, bool temp) {
763 ut_ad(dict_table_is_comp(index->table) || temp);
764
765 if (!index->has_instant_cols_or_row_versions()) {
767 }
768
769 /* Position just before info-bits where version will be there if any */
770 const byte *v_ptr =
771 (byte *)rec -
773 const bool is_versioned =
775 const uint8_t version = (is_versioned) ? (uint8_t)(*v_ptr) : UINT8_UNDEFINED;
776
777 const bool is_instant = (temp) ? rec_get_instant_flag_new_temp(rec)
779
780 /* Only one of the two bits could be set */
781 DBUG_EXECUTE_IF("innodb_rec_instant_version_bit_set", {
782 ib::error() << "Record has both instant and version bit set in Table '"
783 << index->table_name << "', Index '" << index->name()
784 << "'. This indicates that the table may be corrupt. Please "
785 "run CHECK TABLE before proceeding.";
786 });
787
788 if (is_versioned && is_instant) {
789 ib::error() << "Record has both instant and version bit set in Table '"
790 << index->table_name << "', Index '" << index->name()
791 << "'. This indicates that the table may be corrupt. Please "
792 "run CHECK TABLE before proceeding.";
793 }
794 ut_ad(!is_versioned || !is_instant);
795
796 enum REC_INSERT_STATE rec_insert_state = REC_INSERT_STATE::NONE;
797 if (is_versioned) {
799 if (version == 0) {
800 ut_ad(index->has_instant_cols());
801 rec_insert_state =
803 } else {
804 ut_ad(index->has_row_versions());
806 }
807 } else if (is_instant) {
808 ut_ad(index->table->has_instant_cols());
810 } else if (index->table->has_instant_cols()) {
812 } else {
814 }
815
816 ut_ad(rec_insert_state != REC_INSERT_STATE::NONE);
817 return rec_insert_state;
818}
819
820/* Following function is to set NULLS and LENS pointers correctly for a temp
821record generated for a record from REDUNDANT FORAMT
822@param[in] index record descriptor
823@param[in,out] rec temp record
824@param[out] n_null number of nullable columns in record
825@param[out] nulls pointer to nullbit map in temp record
826@param[out] lens pointer to lens in temp record
827@returns the row version stored in record or nondefault fields in record */
829 const dict_index_t *index, const rec_t *rec, uint16_t *n_null,
830 const byte **nulls, const byte **lens, uint16_t &non_default_fields,
831 uint8_t &row_version) {
833
834 non_default_fields = static_cast<uint16_t>(dict_index_get_n_fields(index));
835
836 row_version = UINT8_UNDEFINED;
837
838 /* Set nulls just before the record */
839 *nulls = rec - 1;
840
841 enum REC_INSERT_STATE rec_insert_state =
842 get_rec_insert_state(index, rec, true);
843
844 if (rec_insert_state == INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION) {
845 *n_null = index->n_nullable;
846 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
847 return rec_insert_state;
848 }
849
850 /* info-bits must be present. Shift nulls before that. */
851 *nulls -= REC_N_TMP_EXTRA_BYTES;
852
853 switch (rec_insert_state) {
857 *n_null = index->get_nullable_in_version(0);
858 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
859 } break;
860
863 /* Read the version information */
864 row_version = (uint8_t)(**nulls);
865 ut_a(is_valid_row_version(row_version));
866
867 /* Shift nulls before the record version */
868 *nulls -= 1;
869 *n_null = index->get_nullable_in_version(row_version);
870 } break;
871
873 default:
874 ut_a(0);
875 }
876
877 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
878 return rec_insert_state;
879}
880
881/** Determines the information about null bytes and variable length bytes
882for a new-style temporary record
883@param[in] rec physical record
884@param[in] index index where the record resides
885@param[out] nulls the start of null bytes
886@param[out] lens the start of variable length bytes
887@param[out] n_null number of null fields
888@param[out] non_default_fields non default fields from record
889@param[out] row_version row version of the record
890@return the row inserted state */
892 const rec_t *rec, const dict_index_t *index, const byte **nulls,
893 const byte **lens, uint16_t *n_null, uint16_t &non_default_fields,
894 uint8_t &row_version) {
895 /* Following is the format for TEMP record.
896 +----+----+-------------------+--------------------+
897 | OP | ES |<-- Extra info --> | F1 | F2 | ... | Fn|
898 +----+----+-------------------+--------------------+
899 |
900 v
901 +--------------------+-------+---------+-----------+
902 | LN | ... | L2 | L1 | nulls | version | info-bits |
903 +--------------------+-------+---------+-----------+
904 <------ LENS ------>
905
906 where
907 info-bits => Present iff table has INSTANT/VERSION
908 version => version number iff version bit is set.
909 */
910
911 /* Redundant format */
912 if (!dict_table_is_comp(index->table)) {
913 return init_nulls_lens_for_temp_redundant(index, rec, n_null, nulls, lens,
914 non_default_fields, row_version);
915 }
916
917 non_default_fields = static_cast<uint16_t>(dict_index_get_n_fields(index));
918
919 row_version = UINT8_UNDEFINED;
920
921 /* Set nulls just before the record */
922 *nulls = rec - 1;
923
924 const enum REC_INSERT_STATE rec_insert_state =
925 get_rec_insert_state(index, rec, true);
926
927 if (rec_insert_state == INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION) {
928 *n_null = index->n_nullable;
929 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
930 return rec_insert_state;
931 }
932
933 /* info-bits must be present. Shift nulls before that. */
934 *nulls -= REC_N_TMP_EXTRA_BYTES;
935
936 switch (rec_insert_state) {
939 /* Read the version information */
940 row_version = (uint8_t)(**nulls);
941 ut_a(is_valid_row_version(row_version));
942
943 /* Shift nulls before the record version */
944 *nulls -= 1;
945
946 *n_null = index->get_nullable_in_version(row_version);
947 } break;
948
950 /* Row inserted after first instant ADD COLUMN V1 */
951 ut_ad(index->table->has_instant_cols());
952 uint16_t length;
953 non_default_fields =
955 ut_ad(length == 1 || length == 2);
956
957 /* Shift nulls before "number of fields" */
958 *nulls -= length;
959 *n_null = index->get_n_nullable_before(non_default_fields);
960 } break;
961
963 *n_null = index->get_nullable_before_instant_add_drop();
964 non_default_fields = index->get_instant_fields();
965 } break;
966
968 /* Row inserted before first INSTANT ADD/DROP in V2 */
969 *n_null = index->get_nullable_before_instant_add_drop();
970 } break;
971
973 default:
974 ut_a(0);
975 }
976
977 /* Position lens */
978 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
979
980 return (rec_insert_state);
981}
982
983/** Determines the information about null bytes and variable length bytes
984for a new style record
985@param[in] rec physical record
986@param[in] index index where the record resides
987@param[out] nulls the start of null bytes
988@param[out] lens the start of variable length bytes
989@param[out] n_null number of null fields
990@param[out] non_default_fields non default fields from record
991@param[out] row_version row version of the record
992@return number of fields with no default or the row version of record */
994 const rec_t *rec, const dict_index_t *index, const byte **nulls,
995 const byte **lens, uint16_t *n_null, uint16_t &non_default_fields,
996 uint8_t &row_version) {
997 non_default_fields = static_cast<uint16_t>(dict_index_get_n_fields(index));
998
999 row_version = UINT8_UNDEFINED;
1000
1001 /* Position nulls */
1002 *nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
1003
1004 const enum REC_INSERT_STATE rec_insert_state =
1005 get_rec_insert_state(index, rec, false);
1006
1007 switch (rec_insert_state) {
1011
1012 *n_null = index->n_nullable;
1013 } break;
1014
1017 /* Read the row version from record */
1018 row_version = (uint8_t)(**nulls);
1019 ut_ad(is_valid_row_version(row_version));
1020
1021#ifdef UNIV_DEBUG
1022 if (strcmp(index->name, RECOVERY_INDEX_TABLE_NAME) != 0) {
1023 if (row_version > 0) {
1024 /* Row inserted after first instant ADD/DROP COLUMN V2 */
1025 ut_ad(index->table->has_row_versions());
1026 } else {
1027 /* Upgraded table. Row inserted before V2 INSTANT ADD/DROP */
1028 ut_ad(index->table->is_upgraded_instant());
1029 }
1030 }
1031#endif
1032
1033 /* Reposition nulls to skip version */
1034 *nulls -= 1;
1035 *n_null = index->get_nullable_in_version(row_version);
1036 } break;
1037
1039 /* Row inserted after first instant ADD COLUMN V1 */
1040 uint16_t length;
1041 non_default_fields =
1043 ut_ad(length == 1 || length == 2);
1044
1045 /* Reposition nulls to skip number of fields */
1046 *nulls -= length;
1047 *n_null = index->calculate_n_instant_nullable(non_default_fields);
1048 } break;
1049
1051 *n_null = index->get_nullable_before_instant_add_drop();
1052 non_default_fields = index->get_instant_fields();
1053 } break;
1054
1056 /* Row inserted before first INSTANT ADD/DROP in V2 */
1057 *n_null = index->get_nullable_before_instant_add_drop();
1058 } break;
1059
1060 default:
1061 ut_ad(false);
1062 }
1063
1064 /* Position lens */
1065 *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
1066
1067 /* Return record version or non_default_field stored */
1068 return (rec_insert_state);
1069}
1070
1071/** Determine the offset to each field in a leaf-page record in
1072ROW_FORMAT=COMPACT. This is a special case of rec_init_offsets() and
1073rec_get_offsets().
1074@param[in] rec physical record in ROW_FORMAT=COMPACT
1075@param[in] temp whether to use the format for temporary files in index
1076 creation
1077@param[in] index record descriptor
1078@param[in,out] offsets array of offsets */
1079void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp,
1080 const dict_index_t *index, ulint *offsets);
1081
1082/** The following function is used to test whether the data offsets in the
1083 record are stored in one-byte or two-byte format.
1084 @return true if 1-byte form */
1085[[nodiscard]] static inline bool rec_get_1byte_offs_flag(
1086 const rec_t *rec) /*!< in: physical record */
1087{
1090}
1091
1092#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:291
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:209
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:260
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:891
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:828
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:657
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:993
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:641
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:301
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
Rec_instant_state
Instant state of a record.
Definition: rec.h:187
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:313
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:501
static const uint8_t REC_N_FIELDS_ONE_BYTE_MAX
Max number of fields which can be stored in one byte.
Definition: rec.h:212
constexpr uint32_t REC_HEAP_NO_MASK
Definition: rec.h:82
REC_INSERT_STATE
Definition: rec.h:740
@ INSERTED_AFTER_UPGRADE_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION
Definition: rec.h:749
@ INSERTED_AFTER_INSTANT_ADD_OLD_IMPLEMENTATION
Definition: rec.h:746
@ INSERTED_AFTER_INSTANT_ADD_NEW_IMPLEMENTATION
Definition: rec.h:755
@ INSERTED_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION
Definition: rec.h:752
@ INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION
Definition: rec.h:757
@ NONE
Definition: rec.h:758
@ INSERTED_BEFORE_INSTANT_ADD_OLD_IMPLEMENTATION
Definition: rec.h:743
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:537
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:761
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:444
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:599
static bool rec_new_is_versioned(const rec_t *rec)
The following function tells if a new-style record is versioned.
Definition: rec.h:674
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:346
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:457
static bool rec_new_temp_is_versioned(const rec_t *rec)
The following function tells if a temporary record is versioned.
Definition: rec.h:690
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:483
static const ulint * rec_offs_base(const ulint *offsets)
Definition: rec.h:200
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:323
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:682
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:1085
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:701
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:432
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:469
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:248
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:402
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:273
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:633
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:1761
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:2481
bool has_row_versions() const
Definition: dict0mem.h:2466
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:2538
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:617
constexpr uint8_t UINT8_UNDEFINED
The 'undefined' value for a 8-bit unsigned integer.
Definition: univ.i:433
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
#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size)
Definition: univ.i:629
constexpr ulint ULINT_MAX
Maximum value for a ulint.
Definition: univ.i:439
unsigned long int ulint
Definition: univ.i:405
constexpr size_t UNIV_PAGE_SIZE_MAX
Maximum page size InnoDB currently supports.
Definition: univ.i:322
#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