MySQL  8.0.19
Source Code Documentation
rec.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License, version 2.0, as published by the
7 Free Software Foundation.
8 
9 This program is also distributed with certain software (including but not
10 limited to OpenSSL) that is licensed under separate terms, as designated in a
11 particular file or component or in included license documentation. The authors
12 of MySQL hereby grant you an additional permission to link the program and
13 your derivative works with the separately licensed software that they have
14 included with MySQL.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19 for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 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
34 other files in library. The code in this file is used to make a library for
35 external 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() */
44 #define REC_OFFS_COMPACT ((ulint)1 << 31)
45 /* SQL NULL flag in offsets returned by rec_get_offsets() */
46 #define REC_OFFS_SQL_NULL ((ulint)1 << 31)
47 /* External flag in offsets returned by rec_get_offsets() */
48 #define REC_OFFS_EXTERNAL ((ulint)1 << 30)
49 /* Default value flag in offsets returned by rec_get_offsets() */
50 #define REC_OFFS_DEFAULT ((ulint)1 << 29)
51 /* Mask for offsets returned by rec_get_offsets() */
52 #define REC_OFFS_MASK (REC_OFFS_DEFAULT - 1)
53 
54 /* The offset of heap_no in a compact record */
55 #define REC_NEW_HEAP_NO 4
56 /* The shift of heap_no in a compact record.
57 The status is stored in the low-order bits. */
58 #define REC_HEAP_NO_SHIFT 3
59 
60 /* We list the byte offsets from the origin of the record, the mask,
61 and the shift needed to obtain each bit-field of the record. */
62 
63 #define REC_NEXT 2
64 #define REC_NEXT_MASK 0xFFFFUL
65 #define REC_NEXT_SHIFT 0
66 
67 #define REC_OLD_SHORT 3 /* This is single byte bit-field */
68 #define REC_OLD_SHORT_MASK 0x1UL
69 #define REC_OLD_SHORT_SHIFT 0
70 
71 #define REC_OLD_N_FIELDS 4
72 #define REC_OLD_N_FIELDS_MASK 0x7FEUL
73 #define REC_OLD_N_FIELDS_SHIFT 1
74 
75 #define REC_NEW_STATUS 3 /* This is single byte bit-field */
76 #define REC_NEW_STATUS_MASK 0x7UL
77 #define REC_NEW_STATUS_SHIFT 0
78 
79 #define REC_OLD_HEAP_NO 5
80 #define REC_HEAP_NO_MASK 0xFFF8UL
81 #if 0 /* defined in rem0rec.h for use of page0zip.cc */
82 #define REC_NEW_HEAP_NO 4
83 #define REC_HEAP_NO_SHIFT 3
84 #endif
85 
86 #define REC_OLD_N_OWNED 6 /* This is single byte bit-field */
87 #define REC_NEW_N_OWNED 5 /* This is single byte bit-field */
88 #define REC_N_OWNED_MASK 0xFUL
89 #define REC_N_OWNED_SHIFT 0
90 
91 #define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */
92 #define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */
93 #define REC_TMP_INFO_BITS 1 /* This is single byte bit-field */
94 #define REC_INFO_BITS_MASK 0xF0UL
95 #define REC_INFO_BITS_SHIFT 0
96 
97 #if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) ^ \
98  REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) ^ \
99  REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) ^ \
100  REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) ^ \
101  REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) ^ 0xFFFFFFFFUL
102 #error "sum of old-style masks != 0xFFFFFFFFUL"
103 #endif
104 #if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) ^ \
105  REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) ^ \
106  REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) ^ \
107  REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) ^ 0xFFFFFFUL
108 #error "sum of new-style masks != 0xFFFFFFUL"
109 #endif
110 
111 /* Info bit denoting the predefined minimum record: this bit is set
112 if and only if the record is the first user record on a non-leaf
113 B-tree page that is the leftmost page on its level
114 (PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */
115 #define REC_INFO_MIN_REC_FLAG 0x10UL
116 /* The deleted flag in info bits */
117 #define REC_INFO_DELETED_FLAG \
118  0x20UL /* when bit is set to 1, it means the \
119  record has been delete marked */
120 /* The 0x40UL can also be used in the future */
121 /* The instant ADD COLUMN flag. When it is set to 1, it means this record
122 was inserted/updated after an instant ADD COLUMN. */
123 #define REC_INFO_INSTANT_FLAG 0x80UL
124 
125 /* Number of extra bytes in an old-style record,
126 in addition to the data and the offsets */
127 #define REC_N_OLD_EXTRA_BYTES 6
128 /* Number of extra bytes in a new-style record,
129 in addition to the data and the offsets */
130 #define REC_N_NEW_EXTRA_BYTES 5
131 /* NUmber of extra bytes in a new-style temporary record,
132 in addition to the data and the offsets.
133 This is used only after instant ADD COLUMN. */
134 #define REC_N_TMP_EXTRA_BYTES 1
135 
136 /* Record status values */
137 #define REC_STATUS_ORDINARY 0
138 #define REC_STATUS_NODE_PTR 1
139 #define REC_STATUS_INFIMUM 2
140 #define REC_STATUS_SUPREMUM 3
141 
142 /* The following four constants are needed in page0zip.cc in order to
143 efficiently compress and decompress pages. */
144 
145 /* Length of a B-tree node pointer, in bytes */
146 #define REC_NODE_PTR_SIZE 4
147 
148 /** SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records */
149 #define REC_1BYTE_SQL_NULL_MASK 0x80UL
150 /** SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records */
151 #define REC_2BYTE_SQL_NULL_MASK 0x8000UL
152 
153 /** In a 2-byte offset of ROW_FORMAT=REDUNDANT records, the second most
154 significant bit denotes that the tail of a field is stored off-page. */
155 #define REC_2BYTE_EXTERN_MASK 0x4000UL
156 
157 #ifdef UNIV_DEBUG
158 /* Length of the rec_get_offsets() header */
159 #define REC_OFFS_HEADER_SIZE 4
160 #else /* UNIV_DEBUG */
161 /* Length of the rec_get_offsets() header */
162 #define REC_OFFS_HEADER_SIZE 2
163 #endif /* UNIV_DEBUG */
164 
165 /* Number of elements that should be initially allocated for the
166 offsets[] array, first passed to rec_get_offsets() */
167 #define REC_OFFS_NORMAL_SIZE 100
168 #define REC_OFFS_SMALL_SIZE 10
169 
170 /* Get the base address of offsets. The extra_size is stored at
171 this position, and following positions hold the end offsets of
172 the fields. */
173 #define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE)
174 
175 /** Number of fields flag which means it occupies two bytes */
176 static const uint8_t REC_N_FIELDS_TWO_BYTES_FLAG = 0x80;
177 
178 /** Max number of fields which can be stored in one byte */
179 static const uint8_t REC_N_FIELDS_ONE_BYTE_MAX = 0x7F;
180 
181 /** The following function determines the offsets to each field
182  in the record. It can reuse a previously allocated array.
183  Note that after instant ADD COLUMN, if this is a record
184  from clustered index, fields in the record may be less than
185  the fields defined in the clustered index. So the offsets
186  size is allocated according to the clustered index fields.
187  @return the new offsets */
188 ulint *rec_get_offsets_func(
189  const rec_t *rec, /*!< in: physical record */
190  const dict_index_t *index, /*!< in: record descriptor */
191  ulint *offsets, /*!< in/out: array consisting of
192  offsets[0] allocated elements,
193  or an array from rec_get_offsets(),
194  or NULL */
195  ulint n_fields, /*!< in: maximum number of
196  initialized fields
197  (ULINT_UNDEFINED if all fields) */
198 #ifdef UNIV_DEBUG
199  const char *file, /*!< in: file name where called */
200  ulint line, /*!< in: line number where called */
201 #endif /* UNIV_DEBUG */
202  mem_heap_t **heap) /*!< in/out: memory heap */
203  MY_ATTRIBUTE((warn_unused_result));
204 
205 /** The following function determines the offsets to each field
206  in the record. It can reuse a previously allocated array. */
208  const byte *extra, /*!< in: the extra bytes of a
209  compact record in reverse order,
210  excluding the fixed-size
211  REC_N_NEW_EXTRA_BYTES */
212  const dict_index_t *index, /*!< in: record descriptor */
213  ulint node_ptr, /*!< in: nonzero=node pointer,
214  0=leaf node */
215  ulint *offsets); /*!< in/out: array consisting of
216  offsets[0] allocated elements */
217 
218 /** Gets a bit field from within 1 byte. */
219 UNIV_INLINE
220 ulint rec_get_bit_field_1(
221  const rec_t *rec, /*!< in: pointer to record origin */
222  ulint offs, /*!< in: offset from the origin down */
223  ulint mask, /*!< in: mask used to filter bits */
224  ulint shift) /*!< in: shift right applied after masking */
225 {
226  ut_ad(rec);
227 
228  return ((mach_read_from_1(rec - offs) & mask) >> shift);
229 }
230 
231 /** Gets a bit field from within 2 bytes. */
232 UNIV_INLINE
233 uint16_t rec_get_bit_field_2(
234  const rec_t *rec, /*!< in: pointer to record origin */
235  ulint offs, /*!< in: offset from the origin down */
236  ulint mask, /*!< in: mask used to filter bits */
237  ulint shift) /*!< in: shift right applied after masking */
238 {
239  ut_ad(rec);
240 
241  return ((mach_read_from_2(rec - offs) & mask) >> shift);
242 }
243 
244 /** The following function retrieves the status bits of a new-style record.
245  @return status bits */
246 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ulint
247  rec_get_status(const rec_t *rec) /*!< in: physical record */
248 {
249  ulint ret;
250 
251  ut_ad(rec);
252 
255  ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
256 
257  return (ret);
258 }
259 
260 #ifdef UNIV_DEBUG
261 /** Check if the info bits are valid.
262 @param[in] bits info bits to check
263 @return true if valid */
264 inline bool rec_info_bits_valid(ulint bits) {
265  return (0 == (bits & ~(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG |
267 }
268 #endif /* UNIV_DEBUG */
269 
270 /** The following function is used to retrieve the info bits of a record.
271 @param[in] rec physical record
272 @param[in] comp nonzero=compact page format
273 @return info bits */
274 UNIV_INLINE
275 ulint rec_get_info_bits(const rec_t *rec, ulint comp) {
276  const ulint val =
280  return (val);
281 }
282 
283 /** The following function is used to retrieve the info bits of a temporary
284 record.
285 @param[in] rec physical record
286 @return info bits */
287 UNIV_INLINE
288 ulint rec_get_info_bits_temp(const rec_t *rec) {
289  const ulint val = rec_get_bit_field_1(
292  return (val);
293 }
294 
295 /** The following function is used to get the number of fields
296  in an old-style record, which is stored in the rec
297  @return number of data fields */
298 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) uint16_t
299  rec_get_n_fields_old_raw(const rec_t *rec) /*!< in: physical record */
300 {
301  uint16_t ret;
302 
303  ut_ad(rec);
304 
307  ut_ad(ret <= REC_MAX_N_FIELDS);
308  ut_ad(ret > 0);
309 
310  return (ret);
311 }
312 
313 /** The following function is used to get the number of fields
314 in an old-style record. Have to consider the case that after
315 instant ADD COLUMN, this record may have less fields than
316 current index.
317 @param[in] rec physical record
318 @param[in] index index where the record resides
319 @return number of data fields */
320 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) uint16_t
321  rec_get_n_fields_old(const rec_t *rec, const dict_index_t *index) {
322  uint16_t n = rec_get_n_fields_old_raw(rec);
323 
324  if (index->has_instant_cols()) {
326 
327  ut_ad(index->is_clustered());
329  ut_ad(n_uniq > 0);
330  /* Only when it's infimum or supremum, n is 1.
331  If n is exact n_uniq, this should be a record copied with prefix during
332  search.
333  And if it's node pointer, n is n_uniq + 1, which should be always less
334  than the number of fields in any leaf page, even if the record in
335  leaf page is before instant ADD COLUMN. This is because any record in
336  leaf page must have at least n_uniq + 2 (system columns) fields */
337  ut_ad(n == 1 || n >= n_uniq);
338  ut_ad(static_cast<uint16_t>(dict_index_get_n_fields(index)) > n_uniq + 1);
339  if (n > n_uniq + 1) {
340 #ifdef UNIV_DEBUG
341  ulint rec_diff = dict_index_get_n_fields(index) - n;
342  ulint col_diff = index->table->n_cols - index->table->n_instant_cols;
343  ut_ad(rec_diff <= col_diff);
344  if (n != dict_index_get_n_fields(index)) {
345  ut_ad(index->has_instant_cols());
346  }
347 #endif /* UNIV_DEBUG */
348  n = static_cast<uint16_t>(dict_index_get_n_fields(index));
349  }
350  }
351 
352  return (n);
353 }
354 
355 /** The following function is used to get the number of fields
356  in a record. If it's REDUNDANT record, the returned number
357  would be a logic one which considers the fact that after
358  instant ADD COLUMN, some records may have less fields than
359  index.
360  @return number of data fields */
361 UNIV_INLINE
362 ulint rec_get_n_fields(const rec_t *rec, /*!< in: physical record */
363  const dict_index_t *index) /*!< in: record descriptor */
364 {
365  ut_ad(rec);
366  ut_ad(index);
367 
368  if (!dict_table_is_comp(index->table)) {
369  return (rec_get_n_fields_old(rec, index));
370  }
371 
372  switch (rec_get_status(rec)) {
373  case REC_STATUS_ORDINARY:
374  return (dict_index_get_n_fields(index));
375  case REC_STATUS_NODE_PTR:
377  case REC_STATUS_INFIMUM:
378  case REC_STATUS_SUPREMUM:
379  return (1);
380  default:
381  ut_error;
382  }
383 }
384 
385 /** Confirms the n_fields of the entry is sane with comparing the other
386 record in the same page specified
387 @param[in] index index
388 @param[in] rec record of the same page
389 @param[in] entry index entry
390 @return true if n_fields is sane */
391 UNIV_INLINE
392 bool rec_n_fields_is_sane(dict_index_t *index, const rec_t *rec,
393  const dtuple_t *entry) {
395  /* a record for older SYS_INDEXES table
396  (missing merge_threshold column) is acceptable. */
397  || (index->table->id == DICT_INDEXES_ID &&
399 }
400 
401 /** The following function returns the number of allocated elements
402  for an array of offsets.
403  @return number of elements */
404 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ulint rec_offs_get_n_alloc(
405  const ulint *offsets) /*!< in: array for rec_get_offsets() */
406 {
407  ulint n_alloc;
408  ut_ad(offsets);
409  n_alloc = offsets[0];
410  ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
411  UNIV_MEM_ASSERT_W(offsets, n_alloc * sizeof *offsets);
412  return (n_alloc);
413 }
414 
415 /** The following function sets the number of allocated elements
416  for an array of offsets. */
417 UNIV_INLINE
418 void rec_offs_set_n_alloc(ulint *offsets, /*!< out: array for rec_get_offsets(),
419  must be allocated */
420  ulint n_alloc) /*!< in: number of elements */
421 {
422  ut_ad(offsets);
423  ut_ad(n_alloc > REC_OFFS_HEADER_SIZE);
424  UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets);
425  offsets[0] = n_alloc;
426 }
427 
428 /** The following function sets the number of fields in offsets. */
429 UNIV_INLINE
430 void rec_offs_set_n_fields(ulint *offsets, /*!< in/out: array returned by
431  rec_get_offsets() */
432  ulint n_fields) /*!< in: number of fields */
433 {
434  ut_ad(offsets);
435  ut_ad(n_fields > 0);
436  ut_ad(n_fields <= REC_MAX_N_FIELDS);
437  ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets));
438  offsets[1] = n_fields;
439 }
440 
441 /** The following function returns the number of fields in a record.
442  @return number of fields */
443 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ulint rec_offs_n_fields(
444  const ulint *offsets) /*!< in: array returned by rec_get_offsets() */
445 {
446  ulint n_fields;
447  ut_ad(offsets);
448  n_fields = offsets[1];
449  ut_ad(n_fields > 0);
450  ut_ad(n_fields <= REC_MAX_N_FIELDS);
451  ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets));
452  return (n_fields);
453 }
454 
455 /** Determine the offset of a specified field in the record, when this
456 field is a field added after an instant ADD COLUMN
457 @param[in] index Clustered index where the record resides
458 @param[in] n Nth field to get offset
459 @param[in] offs Last offset before current field
460 @return The offset of the specified field */
461 UNIV_INLINE
462 uint64_t rec_get_instant_offset(const dict_index_t *index, ulint n,
463  uint64_t offs) {
464  ut_ad(index->has_instant_cols());
465 
466  ulint length;
467  index->get_nth_default(n, &length);
468 
469  if (length == UNIV_SQL_NULL) {
470  return (offs | REC_OFFS_SQL_NULL);
471  } else {
472  return (offs | REC_OFFS_DEFAULT);
473  }
474 }
475 
476 /** The following function determines the offsets to each field in the
477  record. The offsets are written to a previously allocated array of
478  ulint, where rec_offs_n_fields(offsets) has been initialized to the
479  number of fields in the record. The rest of the array will be
480  initialized by this function. rec_offs_base(offsets)[0] will be set
481  to the extra size (if REC_OFFS_COMPACT is set, the record is in the
482  new format; if REC_OFFS_EXTERNAL is set, the record contains externally
483  stored columns), and rec_offs_base(offsets)[1..n_fields] will be set to
484  offsets past the end of fields 0..n_fields, or to the beginning of
485  fields 1..n_fields+1. When the high-order bit of the offset at [i+1]
486  is set (REC_OFFS_SQL_NULL), the field i is NULL. When the second
487  high-order bit of the offset at [i+1] is set (REC_OFFS_EXTERNAL), the
488  field i is being stored externally. */
489 void rec_init_offsets(const rec_t *rec, /*!< in: physical record */
490  const dict_index_t *index, /*!< in: record descriptor */
491  ulint *offsets); /*!< in/out: array of offsets;
492  in: n=rec_offs_n_fields(offsets) */
493 
494 #ifdef UNIV_DEBUG
495 /** Validates offsets returned by rec_get_offsets().
496  @return true if valid */
497 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ibool rec_offs_validate(
498  const rec_t *rec, /*!< in: record or NULL */
499  const dict_index_t *index, /*!< in: record descriptor or NULL */
500  const ulint *offsets) /*!< in: array returned by
501  rec_get_offsets() */
502 {
503  ulint i = rec_offs_n_fields(offsets);
504  ulint last = ULINT_MAX;
505  ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
506 
507  if (rec) {
508  ut_ad((ulint)rec == offsets[2]);
509  if (!comp && index != nullptr) {
510  ut_a(rec_get_n_fields_old(rec, index) >= i);
511  }
512  }
513  if (index) {
514  ulint max_n_fields;
515  ut_ad((ulint)index == offsets[3]);
516  ulint n_fields = dict_index_get_n_fields(index);
517  ulint n_unique_in_tree = dict_index_get_n_unique_in_tree(index) + 1;
518  max_n_fields = ut_max(n_fields, n_unique_in_tree);
519  if (!comp && rec != nullptr && rec_get_n_fields_old_raw(rec) < i) {
520  ut_a(index->has_instant_cols());
521  }
522 
523  if (comp && rec) {
524  switch (rec_get_status(rec)) {
525  case REC_STATUS_ORDINARY:
526  break;
527  case REC_STATUS_NODE_PTR:
528  max_n_fields = dict_index_get_n_unique_in_tree(index) + 1;
529  break;
530  case REC_STATUS_INFIMUM:
531  case REC_STATUS_SUPREMUM:
532  max_n_fields = 1;
533  break;
534  default:
535  ut_error;
536  }
537  }
538  /* index->n_def == 0 for dummy indexes if !comp */
539  ut_a(!comp || index->n_def);
540  ut_a(!index->n_def || i <= max_n_fields);
541  }
542  while (i--) {
543  ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
544  ut_a(curr <= last);
545  last = curr;
546  }
547  return (TRUE);
548 }
549 
550 /** Updates debug data in offsets, in order to avoid bogus
551  rec_offs_validate() failures. */
552 UNIV_INLINE
554  const rec_t *rec, /*!< in: record */
555  const dict_index_t *index, /*!< in: record descriptor */
556  ulint *offsets) /*!< in: array returned by
557  rec_get_offsets() */
558 {
559  ut_ad(rec);
560  ut_ad(index);
561  ut_ad(offsets);
562  ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets));
563  offsets[2] = (ulint)rec;
564  offsets[3] = (ulint)index;
565 }
566 
567 /** Check if the given two record offsets are identical.
568 @param[in] offsets1 field offsets of a record
569 @param[in] offsets2 field offsets of a record
570 @return true if they are identical, false otherwise. */
571 bool rec_offs_cmp(ulint *offsets1, ulint *offsets2);
572 
573 /** Print the record offsets.
574 @param[in] out the output stream to which offsets are printed.
575 @param[in] offsets the field offsets of the record.
576 @return the output stream. */
577 std::ostream &rec_offs_print(std::ostream &out, const ulint *offsets);
578 #else
579 #define rec_offs_make_valid(rec, index, offsets) ((void)0)
580 #endif /* UNIV_DEBUG */
581 
582 /** The following function tells if a new-style record is instant record or not
583 @param[in] rec new-style record
584 @return true if it's instant affected */
585 UNIV_INLINE
586 bool rec_get_instant_flag_new(const rec_t *rec) {
587  ulint info = rec_get_info_bits(rec, TRUE);
588  return ((info & REC_INFO_INSTANT_FLAG) != 0);
589 }
590 
591 /** The following function tells if a new-style temporary record is instant
592 record or not
593 @param[in] rec new-style temporary record
594 @return true if it's instant affected */
595 UNIV_INLINE
596 bool rec_get_instant_flag_new_temp(const rec_t *rec) {
597  ulint info = rec_get_info_bits_temp(rec);
598  return ((info & REC_INFO_INSTANT_FLAG) != 0);
599 }
600 
601 /** Get the number of fields for one new style leaf page record.
602 This is only needed for table after instant ADD COLUMN.
603 @param[in] rec leaf page record
604 @param[in] extra_bytes extra bytes of this record
605 @param[in,out] length length of number of fields
606 @return number of fields */
607 UNIV_INLINE
608 uint32_t rec_get_n_fields_instant(const rec_t *rec, const ulint extra_bytes,
609  uint16_t *length) {
610  uint16_t n_fields;
611  const byte *ptr;
612 
613  ptr = rec - (extra_bytes + 1);
614 
615  if ((*ptr & REC_N_FIELDS_TWO_BYTES_FLAG) == 0) {
616  *length = 1;
617  return (*ptr);
618  }
619 
620  *length = 2;
621  n_fields = ((*ptr-- & REC_N_FIELDS_ONE_BYTE_MAX) << 8);
622  n_fields |= *ptr;
623  ut_ad(n_fields < REC_MAX_N_FIELDS);
624  ut_ad(n_fields != 0);
625 
626  return (n_fields);
627 }
628 
629 /** Determines the information about null bytes and variable length bytes
630 for a new-style temporary record
631 @param[in] rec physical record
632 @param[in] index index where the record resides
633 @param[out] nulls the start of null bytes
634 @param[out] lens the start of variable length bytes
635 @param[out] n_null number of null fields
636 @return the number of fields which are inlined of the record */
637 UNIV_INLINE
638 uint16_t rec_init_null_and_len_temp(const rec_t *rec, const dict_index_t *index,
639  const byte **nulls, const byte **lens,
640  uint16_t *n_null) {
641  uint16_t non_default_fields =
642  static_cast<uint16_t>(dict_index_get_n_fields(index));
643 
644  *nulls = rec - 1;
645 
646  if (index->has_instant_cols() && dict_table_is_comp(index->table)) {
647  *nulls -= REC_N_TMP_EXTRA_BYTES;
648  }
649 
650  if (!index->has_instant_cols() || !dict_table_is_comp(index->table)) {
651  *n_null = index->n_nullable;
652  } else if (rec_get_instant_flag_new_temp(rec)) {
653  ut_ad(index->has_instant_cols());
654 
655  uint16_t length;
656  non_default_fields =
658  ut_ad(length == 1 || length == 2);
659 
660  *nulls -= length;
661  *n_null = index->get_n_nullable_before(non_default_fields);
662  } else {
663  *n_null = index->n_instant_nullable;
664  non_default_fields = index->get_instant_fields();
665  }
666 
667  *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
668 
669  return (non_default_fields);
670 }
671 
672 /** Determines the information about null bytes and variable length bytes
673 for a new style record
674 @param[in] rec physical record
675 @param[in] index index where the record resides
676 @param[out] nulls the start of null bytes
677 @param[out] lens the start of variable length bytes
678 @param[out] n_null number of null fields
679 @return the number of fields which are inlined of the record */
680 UNIV_INLINE
681 uint16_t rec_init_null_and_len_comp(const rec_t *rec, const dict_index_t *index,
682  const byte **nulls, const byte **lens,
683  uint16_t *n_null) {
684  uint16_t non_default_fields =
685  static_cast<uint16_t>(dict_index_get_n_fields(index));
686 
687  *nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
688 
689  if (!index->has_instant_cols()) {
690  *n_null = index->n_nullable;
691  } else if (rec_get_instant_flag_new(rec)) {
692  /* Row inserted after first instant ADD COLUMN */
693  uint16_t length;
694  non_default_fields =
696  ut_ad(length == 1 || length == 2);
697 
698  *nulls -= length;
699  *n_null = index->get_n_nullable_before(non_default_fields);
700  } else {
701  /* Row inserted before first instant ADD COLUMN */
702  *n_null = index->n_instant_nullable;
703  non_default_fields = index->get_instant_fields();
704  }
705 
706  *lens = *nulls - UT_BITS_IN_BYTES(*n_null);
707 
708  return (non_default_fields);
709 }
710 
711 /** Determine the offset to each field in a leaf-page record
712  in ROW_FORMAT=COMPACT. This is a special case of
713  rec_init_offsets() and rec_get_offsets_func(). */
714 UNIV_INLINE
716  const rec_t *rec, /*!< in: physical record in
717  ROW_FORMAT=COMPACT */
718  bool temp, /*!< in: whether to use the
719  format for temporary files in
720  index creation */
721  const dict_index_t *index, /*!< in: record descriptor */
722  ulint *offsets) /*!< in/out: array of offsets;
723  in: n=rec_offs_n_fields(offsets) */
724 {
725  uint16_t i = 0;
726  ulint offs = 0;
727  ulint any_ext = 0;
728  uint16_t n_null = 0;
729  const byte *nulls = nullptr;
730  const byte *lens = nullptr;
731  ulint null_mask = 1;
732  uint16_t non_default_fields = 0;
733 
734 #ifdef UNIV_DEBUG
735  /* We cannot invoke rec_offs_make_valid() here if temp=true.
736  Similarly, rec_offs_validate() will fail in that case, because
737  it invokes rec_get_status(). */
738  offsets[2] = (ulint)rec;
739  offsets[3] = (ulint)index;
740 #endif /* UNIV_DEBUG */
741 
742  if (temp) {
743  non_default_fields =
744  rec_init_null_and_len_temp(rec, index, &nulls, &lens, &n_null);
745  } else {
746  non_default_fields =
747  rec_init_null_and_len_comp(rec, index, &nulls, &lens, &n_null);
748  }
749 
750  ut_ad(temp || dict_table_is_comp(index->table));
751 
752  if (temp && dict_table_is_comp(index->table)) {
753  /* No need to do adjust fixed_len=0. We only need to
754  adjust it for ROW_FORMAT=REDUNDANT. */
755  temp = false;
756  }
757 
758  /* read the lengths of fields 0..n */
759  do {
760  const dict_field_t *field = index->get_field(i);
761  const dict_col_t *col = field->col;
762  uint64_t len;
763 
764  if (i >= non_default_fields) {
765  ut_ad(index->has_instant_cols());
766 
767  len = rec_get_instant_offset(index, i, offs);
768 
769  goto resolved;
770  }
771 
772  if (!(col->prtype & DATA_NOT_NULL)) {
773  /* nullable field => read the null flag */
774  ut_ad(n_null--);
775 
776  if (UNIV_UNLIKELY(!(byte)null_mask)) {
777  nulls--;
778  null_mask = 1;
779  }
780 
781  if (*nulls & null_mask) {
782  null_mask <<= 1;
783  /* No length is stored for NULL fields.
784  We do not advance offs, and we set
785  the length to zero and enable the
786  SQL NULL flag in offsets[]. */
787  len = offs | REC_OFFS_SQL_NULL;
788  goto resolved;
789  }
790  null_mask <<= 1;
791  }
792 
793  if (!field->fixed_len || (temp && !col->get_fixed_size(temp))) {
794  ut_ad(col->mtype != DATA_POINT);
795  /* Variable-length field: read the length */
796  len = *lens--;
797  /* If the maximum length of the field is up
798  to 255 bytes, the actual length is always
799  stored in one byte. If the maximum length is
800  more than 255 bytes, the actual length is
801  stored in one byte for 0..127. The length
802  will be encoded in two bytes when it is 128 or
803  more, or when the field is stored externally. */
804  if (DATA_BIG_COL(col)) {
805  if (len & 0x80) {
806  /* 1exxxxxxx xxxxxxxx */
807  len <<= 8;
808  len |= *lens--;
809 
810  offs += len & 0x3fff;
811  if (UNIV_UNLIKELY(len & 0x4000)) {
812  ut_ad(index->is_clustered());
813  any_ext = REC_OFFS_EXTERNAL;
814  len = offs | REC_OFFS_EXTERNAL;
815  } else {
816  len = offs;
817  }
818 
819  goto resolved;
820  }
821  }
822 
823  len = offs += len;
824  } else {
825  len = offs += field->fixed_len;
826  }
827  resolved:
828  rec_offs_base(offsets)[i + 1] = len;
829  } while (++i < rec_offs_n_fields(offsets));
830 
831  *rec_offs_base(offsets) = (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
832 }
833 
834 /** The following function is used to test whether the data offsets in the
835  record are stored in one-byte or two-byte format.
836  @return true if 1-byte form */
837 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ibool
838  rec_get_1byte_offs_flag(const rec_t *rec) /*!< in: physical record */
839 {
840 #if TRUE != 1
841 #error "TRUE != 1"
842 #endif
843 
846 }
847 
848 /** Returns the offset of nth field end if the record is stored in the 1-byte
849  offsets form. If the field is SQL null, the flag is ORed in the returned
850  value.
851  @return offset of the start of the field, SQL null flag ORed */
852 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ulint
853  rec_1_get_field_end_info(const rec_t *rec, /*!< in: record */
854  ulint n) /*!< in: field index */
855 {
858 
859  return (mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1)));
860 }
861 
862 /** Returns the offset of nth field end if the record is stored in the 2-byte
863  offsets form. If the field is SQL null, the flag is ORed in the returned
864  value.
865  @return offset of the start of the field, SQL null flag and extern
866  storage flag ORed */
867 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) ulint
868  rec_2_get_field_end_info(const rec_t *rec, /*!< in: record */
869  ulint n) /*!< in: field index */
870 {
873 
874  return (mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2)));
875 }
876 
877 #endif
dict0boot.h
REC_OFFS_EXTERNAL
#define REC_OFFS_EXTERNAL
Definition: rec.h:48
dict_col_t::get_fixed_size
ulint get_fixed_size(ulint comp) const
Returns the size of a fixed size column, 0 if not a fixed size column.
Definition: dict0mem.h:559
dtuple_t
Structure for an SQL data tuple of fields (logical record)
Definition: data0data.h:716
REC_OLD_N_FIELDS_MASK
#define REC_OLD_N_FIELDS_MASK
Definition: rec.h:72
rec_get_offsets_reverse
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:302
rec_offs_make_valid
UNIV_INLINE 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:552
rec_get_info_bits
UNIV_INLINE 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:274
rec_offs_cmp
bool rec_offs_cmp(ulint *offsets1, ulint *offsets2)
Check if the given two record offsets are identical.
Definition: rec.cc:421
REC_N_FIELDS_ONE_BYTE_MAX
static const uint8_t REC_N_FIELDS_ONE_BYTE_MAX
Max number of fields which can be stored in one byte.
Definition: rec.h:178
rec_init_null_and_len_temp
UNIV_INLINE uint16_t 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)
Determines the information about null bytes and variable length bytes for a new-style temporary recor...
Definition: rec.h:637
rec_init_offsets
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:57
REC_N_NEW_EXTRA_BYTES
#define REC_N_NEW_EXTRA_BYTES
Definition: rec.h:129
ut_a
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:53
REC_INFO_BITS_SHIFT
#define REC_INFO_BITS_SHIFT
Definition: rec.h:95
DATA_POINT
#define DATA_POINT
Definition: data0type.h:91
ut_ad
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:65
rec_offs_set_n_alloc
UNIV_INLINE 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:417
REC_STATUS_INFIMUM
#define REC_STATUS_INFIMUM
Definition: rec.h:138
dict_index_t
Data structure for an index.
Definition: dict0mem.h:869
REC_TMP_INFO_BITS
#define REC_TMP_INFO_BITS
Definition: rec.h:93
rec_get_n_fields_instant
UNIV_INLINE 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:607
rec_get_instant_offset
UNIV_INLINE 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:461
qep_row::extra
Part of traditional "extra" column or related hierarchical property.
Definition: opt_explain_format.h:261
mach_read_from_1
UNIV_INLINE uint8_t mach_read_from_1(const byte *b)
The following function is used to fetch data from one byte.
REC_MAX_N_FIELDS
#define REC_MAX_N_FIELDS
Definition: rem0types.h:42
DATA_NOT_NULL
#define DATA_NOT_NULL
Definition: data0type.h:181
REC_INFO_BITS_MASK
#define REC_INFO_BITS_MASK
Definition: rec.h:94
rec_get_offsets_func
ulint * rec_get_offsets_func(const rec_t *rec, const dict_index_t *index, ulint *offsets, ulint n_fields, const char *file, ulint line, mem_heap_t **heap)
The following function determines the offsets to each field in the record.
Definition: rec.cc:231
rec_init_null_and_len_comp
UNIV_INLINE uint16_t 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)
Determines the information about null bytes and variable length bytes for a new style record.
Definition: rec.h:680
REC_INFO_DELETED_FLAG
#define REC_INFO_DELETED_FLAG
Definition: rec.h:117
rec_get_bit_field_1
UNIV_INLINE 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:219
dict_col_t::prtype
unsigned prtype
precise type; MySQL data type, charset code, flags to indicate nullability, signedness,...
Definition: dict0mem.h:465
rec_get_status
UNIV_INLINE ulint rec_get_status(const rec_t *rec)
The following function retrieves the status bits of a new-style record.
Definition: rec.h:246
ut_error
#define ut_error
Abort execution.
Definition: ut0dbg.h:61
mach_read_from_2
UNIV_INLINE uint16_t mach_read_from_2(const byte *b)
The following function is used to fetch data from 2 consecutive bytes.
rec_offs_n_fields
UNIV_INLINE ulint rec_offs_n_fields(const ulint *offsets)
The following function returns the number of fields in a record.
Definition: rec.h:442
rec_offs_base
#define rec_offs_base(offsets)
Definition: rec.h:172
rec_t
byte rec_t
Definition: rem0types.h:39
rec_info_bits_valid
bool rec_info_bits_valid(ulint bits)
Check if the info bits are valid.
Definition: rec.h:263
mem_block_info_t
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:337
REC_OLD_N_FIELDS_SHIFT
#define REC_OLD_N_FIELDS_SHIFT
Definition: rec.h:73
rec_get_n_fields_old
UNIV_INLINE 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:320
REC_OFFS_DEFAULT
#define REC_OFFS_DEFAULT
Definition: rec.h:50
rec_1_get_field_end_info
UNIV_INLINE ulint rec_1_get_field_end_info(const rec_t *rec, ulint n)
Returns the offset of nth field end if the record is stored in the 1-byte offsets form.
Definition: rec.h:852
TRUE
#define TRUE
Definition: types.h:51
REC_N_OLD_EXTRA_BYTES
#define REC_N_OLD_EXTRA_BYTES
Definition: rec.h:126
REC_NEW_STATUS
#define REC_NEW_STATUS
Definition: rec.h:75
rec_get_instant_flag_new
UNIV_INLINE bool rec_get_instant_flag_new(const rec_t *rec)
The following function tells if a new-style record is instant record or not.
Definition: rec.h:585
REC_NEW_STATUS_MASK
#define REC_NEW_STATUS_MASK
Definition: rec.h:76
REC_OLD_SHORT_SHIFT
#define REC_OLD_SHORT_SHIFT
Definition: rec.h:69
rec_offs_print
std::ostream & rec_offs_print(std::ostream &out, const ulint *offsets)
Print the record offsets.
Definition: rec.cc:451
REC_OFFS_HEADER_SIZE
#define REC_OFFS_HEADER_SIZE
Definition: rec.h:158
REC_NEW_INFO_BITS
#define REC_NEW_INFO_BITS
Definition: rec.h:92
rec_n_fields_is_sane
UNIV_INLINE 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:391
dict_field_t
Data structure for a field in an index.
Definition: dict0mem.h:708
rec_offs_set_n_fields
UNIV_INLINE void rec_offs_set_n_fields(ulint *offsets, ulint n_fields)
The following function sets the number of fields in offsets.
Definition: rec.h:429
UT_BITS_IN_BYTES
#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:227
REC_N_TMP_EXTRA_BYTES
#define REC_N_TMP_EXTRA_BYTES
Definition: rec.h:133
REC_OFFS_MASK
#define REC_OFFS_MASK
Definition: rec.h:52
REC_STATUS_NODE_PTR
#define REC_STATUS_NODE_PTR
Definition: rec.h:137
REC_OLD_INFO_BITS
#define REC_OLD_INFO_BITS
Definition: rec.h:91
mask
static mi_bit_type mask[]
Definition: mi_packrec.cc:138
rec_get_bit_field_2
UNIV_INLINE 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:232
rec_2_get_field_end_info
UNIV_INLINE ulint rec_2_get_field_end_info(const rec_t *rec, ulint n)
Returns the offset of nth field end if the record is stored in the 2-byte offsets form.
Definition: rec.h:867
dict_index_get_n_unique_in_tree
UNIV_INLINE 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...
DICT_INDEXES_ID
#define DICT_INDEXES_ID
Definition: dict0boot.h:101
dict_index_get_n_fields
UNIV_INLINE 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...
dict_field_t::col
dict_col_t * col
pointer to the table column
Definition: dict0mem.h:711
dict_table_is_comp
UNIV_INLINE ibool dict_table_is_comp(const dict_table_t *table)
Check whether the table uses the compact page format.
rec_get_info_bits_temp
UNIV_INLINE 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:287
dtuple_get_n_fields
UNIV_INLINE ulint dtuple_get_n_fields(const dtuple_t *tuple)
Gets number of fields in a data tuple.
dict_field_t::fixed_len
unsigned fixed_len
0 or the fixed length of the column if smaller than DICT_ANTELOPE_MAX_INDEX_COL_LEN
Definition: dict0mem.h:721
_entry
Definition: completion_hash.h:34
rec_offs_validate
UNIV_INLINE ibool 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:496
REC_OFFS_SQL_NULL
#define REC_OFFS_SQL_NULL
Definition: rec.h:46
REC_INFO_MIN_REC_FLAG
#define REC_INFO_MIN_REC_FLAG
Definition: rec.h:115
REC_NEW_STATUS_SHIFT
#define REC_NEW_STATUS_SHIFT
Definition: rec.h:77
rec_get_instant_flag_new_temp
UNIV_INLINE bool rec_get_instant_flag_new_temp(const rec_t *rec)
The following function tells if a new-style temporary record is instant record or not.
Definition: rec.h:595
REC_STATUS_ORDINARY
#define REC_STATUS_ORDINARY
Definition: rec.h:136
dict_col_t::mtype
unsigned mtype
main data type
Definition: dict0mem.h:472
REC_OFFS_COMPACT
#define REC_OFFS_COMPACT
NOTE: The functions in this file should only use functions from other files in library.
Definition: rec.h:44
gis::length
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
dict_col_t
Data structure for a column in a table.
Definition: dict0mem.h:455
REC_OLD_SHORT
#define REC_OLD_SHORT
Definition: rec.h:67
rec_get_1byte_offs_flag
UNIV_INLINE ibool 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:837
REC_OLD_SHORT_MASK
#define REC_OLD_SHORT_MASK
Definition: rec.h:68
n
int n
Definition: xcom_base.c:425
rec_offs_get_n_alloc
UNIV_INLINE 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:403
REC_INFO_INSTANT_FLAG
#define REC_INFO_INSTANT_FLAG
Definition: rec.h:122
rec_get_n_fields
UNIV_INLINE 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:361
rec_init_offsets_comp_ordinary
UNIV_INLINE 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.h:714
ut_max
#define ut_max
Definition: ut0ut.h:150
dict0dict.h
info
Log info(cout, "NOTE")
REC_N_FIELDS_TWO_BYTES_FLAG
static const uint8_t REC_N_FIELDS_TWO_BYTES_FLAG
Number of fields flag which means it occupies two bytes.
Definition: rec.h:175
index
char * index(const char *, int c)
Definition: mysql.cc:2875
REC_STATUS_SUPREMUM
#define REC_STATUS_SUPREMUM
Definition: rec.h:139
dict_index_get_n_unique_in_tree_nonleaf
UNIV_INLINE 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...
DATA_BIG_COL
#define DATA_BIG_COL(col)
Definition: data0type.h:249
REC_OLD_N_FIELDS
#define REC_OLD_N_FIELDS
Definition: rec.h:71
rec_get_n_fields_old_raw
UNIV_INLINE 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:298