MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rem0rec.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2013, 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 as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /********************************************************************/
26 #include "rem0rec.h"
27 
28 #ifdef UNIV_NONINL
29 #include "rem0rec.ic"
30 #endif
31 
32 #include "page0page.h"
33 #include "mtr0mtr.h"
34 #include "mtr0log.h"
35 #include "fts0fts.h"
36 
37 /* PHYSICAL RECORD (OLD STYLE)
38  ===========================
39 
40 The physical record, which is the data type of all the records
41 found in index pages of the database, has the following format
42 (lower addresses and more significant bits inside a byte are below
43 represented on a higher text line):
44 
45 | offset of the end of the last field of data, the most significant
46  bit is set to 1 if and only if the field is SQL-null,
47  if the offset is 2-byte, then the second most significant
48  bit is set to 1 if the field is stored on another page:
49  mostly this will occur in the case of big BLOB fields |
50 ...
51 | offset of the end of the first field of data + the SQL-null bit |
52 | 4 bits used to delete mark a record, and mark a predefined
53  minimum record in alphabetical order |
54 | 4 bits giving the number of records owned by this record
55  (this term is explained in page0page.h) |
56 | 13 bits giving the order number of this record in the
57  heap of the index page |
58 | 10 bits giving the number of fields in this record |
59 | 1 bit which is set to 1 if the offsets above are given in
60  one byte format, 0 if in two byte format |
61 | two bytes giving an absolute pointer to the next record in the page |
62 ORIGIN of the record
63 | first field of data |
64 ...
65 | last field of data |
66 
67 The origin of the record is the start address of the first field
68 of data. The offsets are given relative to the origin.
69 The offsets of the data fields are stored in an inverted
70 order because then the offset of the first fields are near the
71 origin, giving maybe a better processor cache hit rate in searches.
72 
73 The offsets of the data fields are given as one-byte
74 (if there are less than 127 bytes of data in the record)
75 or two-byte unsigned integers. The most significant bit
76 is not part of the offset, instead it indicates the SQL-null
77 if the bit is set to 1. */
78 
79 /* PHYSICAL RECORD (NEW STYLE)
80  ===========================
81 
82 The physical record, which is the data type of all the records
83 found in index pages of the database, has the following format
84 (lower addresses and more significant bits inside a byte are below
85 represented on a higher text line):
86 
87 | length of the last non-null variable-length field of data:
88  if the maximum length is 255, one byte; otherwise,
89  0xxxxxxx (one byte, length=0..127), or 1exxxxxxxxxxxxxx (two bytes,
90  length=128..16383, extern storage flag) |
91 ...
92 | length of first variable-length field of data |
93 | SQL-null flags (1 bit per nullable field), padded to full bytes |
94 | 4 bits used to delete mark a record, and mark a predefined
95  minimum record in alphabetical order |
96 | 4 bits giving the number of records owned by this record
97  (this term is explained in page0page.h) |
98 | 13 bits giving the order number of this record in the
99  heap of the index page |
100 | 3 bits record type: 000=conventional, 001=node pointer (inside B-tree),
101  010=infimum, 011=supremum, 1xx=reserved |
102 | two bytes giving a relative pointer to the next record in the page |
103 ORIGIN of the record
104 | first field of data |
105 ...
106 | last field of data |
107 
108 The origin of the record is the start address of the first field
109 of data. The offsets are given relative to the origin.
110 The offsets of the data fields are stored in an inverted
111 order because then the offset of the first fields are near the
112 origin, giving maybe a better processor cache hit rate in searches.
113 
114 The offsets of the data fields are given as one-byte
115 (if there are less than 127 bytes of data in the record)
116 or two-byte unsigned integers. The most significant bit
117 is not part of the offset, instead it indicates the SQL-null
118 if the bit is set to 1. */
119 
120 /* CANONICAL COORDINATES. A record can be seen as a single
121 string of 'characters' in the following way: catenate the bytes
122 in each field, in the order of fields. An SQL-null field
123 is taken to be an empty sequence of bytes. Then after
124 the position of each field insert in the string
125 the 'character' <FIELD-END>, except that after an SQL-null field
126 insert <NULL-FIELD-END>. Now the ordinal position of each
127 byte in this canonical string is its canonical coordinate.
128 So, for the record ("AA", SQL-NULL, "BB", ""), the canonical
129 string is "AA<FIELD_END><NULL-FIELD-END>BB<FIELD-END><FIELD-END>".
130 We identify prefixes (= initial segments) of a record
131 with prefixes of the canonical string. The canonical
132 length of the prefix is the length of the corresponding
133 prefix of the canonical string. The canonical length of
134 a record is the length of its canonical string.
135 
136 For example, the maximal common prefix of records
137 ("AA", SQL-NULL, "BB", "C") and ("AA", SQL-NULL, "B", "C")
138 is "AA<FIELD-END><NULL-FIELD-END>B", and its canonical
139 length is 5.
140 
141 A complete-field prefix of a record is a prefix which ends at the
142 end of some field (containing also <FIELD-END>).
143 A record is a complete-field prefix of another record, if
144 the corresponding canonical strings have the same property. */
145 
146 /* this is used to fool compiler in rec_validate */
147 UNIV_INTERN ulint rec_dummy;
148 
149 /***************************************************************/
152 static
153 ibool
154 rec_validate_old(
155 /*=============*/
156  const rec_t* rec);
158 /******************************************************/
162 UNIV_INTERN
163 ulint
165 /*=================*/
166  const rec_t* rec,
167  const dict_index_t* index,
168  ulint n)
169 {
170  const byte* nulls;
171  const byte* lens;
172  ulint null_mask;
173  ulint n_extern;
174  ulint i;
175 
176  ut_ad(dict_table_is_comp(index->table));
177  ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
178  ut_ad(n == ULINT_UNDEFINED || n <= dict_index_get_n_fields(index));
179 
180  if (n == ULINT_UNDEFINED) {
181  n = dict_index_get_n_fields(index);
182  }
183 
184  nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
185  lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
186  null_mask = 1;
187  n_extern = 0;
188  i = 0;
189 
190  /* read the lengths of fields 0..n */
191  do {
192  const dict_field_t* field
193  = dict_index_get_nth_field(index, i);
194  const dict_col_t* col
195  = dict_field_get_col(field);
196  ulint len;
197 
198  if (!(col->prtype & DATA_NOT_NULL)) {
199  /* nullable field => read the null flag */
200 
201  if (UNIV_UNLIKELY(!(byte) null_mask)) {
202  nulls--;
203  null_mask = 1;
204  }
205 
206  if (*nulls & null_mask) {
207  null_mask <<= 1;
208  /* No length is stored for NULL fields. */
209  continue;
210  }
211  null_mask <<= 1;
212  }
213 
214  if (UNIV_UNLIKELY(!field->fixed_len)) {
215  /* Variable-length field: read the length */
216  len = *lens--;
217  /* If the maximum length of the field is up
218  to 255 bytes, the actual length is always
219  stored in one byte. If the maximum length is
220  more than 255 bytes, the actual length is
221  stored in one byte for 0..127. The length
222  will be encoded in two bytes when it is 128 or
223  more, or when the field is stored externally. */
224  if (UNIV_UNLIKELY(col->len > 255)
225  || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) {
226  if (len & 0x80) {
227  /* 1exxxxxxx xxxxxxxx */
228  if (len & 0x40) {
229  n_extern++;
230  }
231  lens--;
232  }
233  }
234  }
235  } while (++i < n);
236 
237  return(n_extern);
238 }
239 
240 /******************************************************/
244 UNIV_INLINE __attribute__((nonnull))
245 void
246 rec_init_offsets_comp_ordinary(
247 /*===========================*/
248  const rec_t* rec,
250  bool temp,
253  const dict_index_t* index,
254  ulint* offsets)
256 {
257  ulint i = 0;
258  ulint offs = 0;
259  ulint any_ext = 0;
260  ulint n_null = index->n_nullable;
261  const byte* nulls = temp
262  ? rec - 1
263  : rec - (1 + REC_N_NEW_EXTRA_BYTES);
264  const byte* lens = nulls - UT_BITS_IN_BYTES(n_null);
265  ulint null_mask = 1;
266 
267 #ifdef UNIV_DEBUG
268  /* We cannot invoke rec_offs_make_valid() here if temp=true.
269  Similarly, rec_offs_validate() will fail in that case, because
270  it invokes rec_get_status(). */
271  offsets[2] = (ulint) rec;
272  offsets[3] = (ulint) index;
273 #endif /* UNIV_DEBUG */
274 
275  ut_ad(temp || dict_table_is_comp(index->table));
276 
277  if (temp && dict_table_is_comp(index->table)) {
278  /* No need to do adjust fixed_len=0. We only need to
279  adjust it for ROW_FORMAT=REDUNDANT. */
280  temp = false;
281  }
282 
283  /* read the lengths of fields 0..n */
284  do {
285  const dict_field_t* field
286  = dict_index_get_nth_field(index, i);
287  const dict_col_t* col
288  = dict_field_get_col(field);
289  ulint len;
290 
291  if (!(col->prtype & DATA_NOT_NULL)) {
292  /* nullable field => read the null flag */
293  ut_ad(n_null--);
294 
295  if (UNIV_UNLIKELY(!(byte) null_mask)) {
296  nulls--;
297  null_mask = 1;
298  }
299 
300  if (*nulls & null_mask) {
301  null_mask <<= 1;
302  /* No length is stored for NULL fields.
303  We do not advance offs, and we set
304  the length to zero and enable the
305  SQL NULL flag in offsets[]. */
306  len = offs | REC_OFFS_SQL_NULL;
307  goto resolved;
308  }
309  null_mask <<= 1;
310  }
311 
312  if (!field->fixed_len
313  || (temp && !dict_col_get_fixed_size(col, temp))) {
314  /* Variable-length field: read the length */
315  len = *lens--;
316  /* If the maximum length of the field is up
317  to 255 bytes, the actual length is always
318  stored in one byte. If the maximum length is
319  more than 255 bytes, the actual length is
320  stored in one byte for 0..127. The length
321  will be encoded in two bytes when it is 128 or
322  more, or when the field is stored externally. */
323  if (UNIV_UNLIKELY(col->len > 255)
324  || UNIV_UNLIKELY(col->mtype
325  == DATA_BLOB)) {
326  if (len & 0x80) {
327  /* 1exxxxxxx xxxxxxxx */
328  len <<= 8;
329  len |= *lens--;
330 
331  offs += len & 0x3fff;
332  if (UNIV_UNLIKELY(len
333  & 0x4000)) {
335  (index));
336  any_ext = REC_OFFS_EXTERNAL;
337  len = offs
338  | REC_OFFS_EXTERNAL;
339  } else {
340  len = offs;
341  }
342 
343  goto resolved;
344  }
345  }
346 
347  len = offs += len;
348  } else {
349  len = offs += field->fixed_len;
350  }
351 resolved:
352  rec_offs_base(offsets)[i + 1] = len;
353  } while (++i < rec_offs_n_fields(offsets));
354 
355  *rec_offs_base(offsets)
356  = (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
357 }
358 
359 /******************************************************/
373 static
374 void
375 rec_init_offsets(
376 /*=============*/
377  const rec_t* rec,
378  const dict_index_t* index,
379  ulint* offsets)
381 {
382  ulint i = 0;
383  ulint offs;
384 
385  rec_offs_make_valid(rec, index, offsets);
386 
387  if (dict_table_is_comp(index->table)) {
388  const byte* nulls;
389  const byte* lens;
390  dict_field_t* field;
391  ulint null_mask;
392  ulint status = rec_get_status(rec);
393  ulint n_node_ptr_field = ULINT_UNDEFINED;
394 
395  switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
396  case REC_STATUS_INFIMUM:
397  case REC_STATUS_SUPREMUM:
398  /* the field is 8 bytes long */
399  rec_offs_base(offsets)[0]
400  = REC_N_NEW_EXTRA_BYTES | REC_OFFS_COMPACT;
401  rec_offs_base(offsets)[1] = 8;
402  return;
403  case REC_STATUS_NODE_PTR:
404  n_node_ptr_field
406  break;
407  case REC_STATUS_ORDINARY:
408  rec_init_offsets_comp_ordinary(
409  rec, false, index, offsets);
410  return;
411  }
412 
413  nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
414  lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
415  offs = 0;
416  null_mask = 1;
417 
418  /* read the lengths of fields 0..n */
419  do {
420  ulint len;
421  if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
422  len = offs += REC_NODE_PTR_SIZE;
423  goto resolved;
424  }
425 
426  field = dict_index_get_nth_field(index, i);
427  if (!(dict_field_get_col(field)->prtype
428  & DATA_NOT_NULL)) {
429  /* nullable field => read the null flag */
430 
431  if (UNIV_UNLIKELY(!(byte) null_mask)) {
432  nulls--;
433  null_mask = 1;
434  }
435 
436  if (*nulls & null_mask) {
437  null_mask <<= 1;
438  /* No length is stored for NULL fields.
439  We do not advance offs, and we set
440  the length to zero and enable the
441  SQL NULL flag in offsets[]. */
442  len = offs | REC_OFFS_SQL_NULL;
443  goto resolved;
444  }
445  null_mask <<= 1;
446  }
447 
448  if (UNIV_UNLIKELY(!field->fixed_len)) {
449  /* Variable-length field: read the length */
450  const dict_col_t* col
451  = dict_field_get_col(field);
452  len = *lens--;
453  /* If the maximum length of the field
454  is up to 255 bytes, the actual length
455  is always stored in one byte. If the
456  maximum length is more than 255 bytes,
457  the actual length is stored in one
458  byte for 0..127. The length will be
459  encoded in two bytes when it is 128 or
460  more, or when the field is stored
461  externally. */
462  if (UNIV_UNLIKELY(col->len > 255)
463  || UNIV_UNLIKELY(col->mtype
464  == DATA_BLOB)) {
465  if (len & 0x80) {
466  /* 1exxxxxxx xxxxxxxx */
467 
468  len <<= 8;
469  len |= *lens--;
470 
471  /* B-tree node pointers
472  must not contain externally
473  stored columns. Thus
474  the "e" flag must be 0. */
475  ut_a(!(len & 0x4000));
476  offs += len & 0x3fff;
477  len = offs;
478 
479  goto resolved;
480  }
481  }
482 
483  len = offs += len;
484  } else {
485  len = offs += field->fixed_len;
486  }
487 resolved:
488  rec_offs_base(offsets)[i + 1] = len;
489  } while (++i < rec_offs_n_fields(offsets));
490 
491  *rec_offs_base(offsets)
492  = (rec - (lens + 1)) | REC_OFFS_COMPACT;
493  } else {
494  /* Old-style record: determine extra size and end offsets */
495  offs = REC_N_OLD_EXTRA_BYTES;
496  if (rec_get_1byte_offs_flag(rec)) {
497  offs += rec_offs_n_fields(offsets);
498  *rec_offs_base(offsets) = offs;
499  /* Determine offsets to fields */
500  do {
501  offs = rec_1_get_field_end_info(rec, i);
502  if (offs & REC_1BYTE_SQL_NULL_MASK) {
503  offs &= ~REC_1BYTE_SQL_NULL_MASK;
504  offs |= REC_OFFS_SQL_NULL;
505  }
506  rec_offs_base(offsets)[1 + i] = offs;
507  } while (++i < rec_offs_n_fields(offsets));
508  } else {
509  offs += 2 * rec_offs_n_fields(offsets);
510  *rec_offs_base(offsets) = offs;
511  /* Determine offsets to fields */
512  do {
513  offs = rec_2_get_field_end_info(rec, i);
514  if (offs & REC_2BYTE_SQL_NULL_MASK) {
515  offs &= ~REC_2BYTE_SQL_NULL_MASK;
516  offs |= REC_OFFS_SQL_NULL;
517  }
518  if (offs & REC_2BYTE_EXTERN_MASK) {
519  offs &= ~REC_2BYTE_EXTERN_MASK;
520  offs |= REC_OFFS_EXTERNAL;
521  *rec_offs_base(offsets) |= REC_OFFS_EXTERNAL;
522  }
523  rec_offs_base(offsets)[1 + i] = offs;
524  } while (++i < rec_offs_n_fields(offsets));
525  }
526  }
527 }
528 
529 /******************************************************/
533 UNIV_INTERN
534 ulint*
536 /*=================*/
537  const rec_t* rec,
538  const dict_index_t* index,
539  ulint* offsets,
543  ulint n_fields,
546  mem_heap_t** heap,
547  const char* file,
548  ulint line)
549 {
550  ulint n;
551  ulint size;
552 
553  ut_ad(rec);
554  ut_ad(index);
555  ut_ad(heap);
556 
557  if (dict_table_is_comp(index->table)) {
558  switch (UNIV_EXPECT(rec_get_status(rec),
559  REC_STATUS_ORDINARY)) {
560  case REC_STATUS_ORDINARY:
561  n = dict_index_get_n_fields(index);
562  break;
563  case REC_STATUS_NODE_PTR:
564  /* Node pointer records consist of the
565  uniquely identifying fields of the record
566  followed by a child page number field. */
567  n = dict_index_get_n_unique_in_tree(index) + 1;
568  break;
569  case REC_STATUS_INFIMUM:
570  case REC_STATUS_SUPREMUM:
571  /* infimum or supremum record */
572  n = 1;
573  break;
574  default:
575  ut_error;
576  return(NULL);
577  }
578  } else {
579  n = rec_get_n_fields_old(rec);
580  }
581 
582  if (UNIV_UNLIKELY(n_fields < n)) {
583  n = n_fields;
584  }
585 
586  /* The offsets header consists of the allocation size at
587  offsets[0] and the REC_OFFS_HEADER_SIZE bytes. */
588  size = n + (1 + REC_OFFS_HEADER_SIZE);
589 
590  if (UNIV_UNLIKELY(!offsets)
591  || UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) {
592  if (UNIV_UNLIKELY(!*heap)) {
593  *heap = mem_heap_create_func(size * sizeof(ulint),
594  MEM_HEAP_DYNAMIC,
595  file, line);
596  }
597  offsets = static_cast<ulint*>(
598  mem_heap_alloc(*heap, size * sizeof(ulint)));
599 
600  rec_offs_set_n_alloc(offsets, size);
601  }
602 
603  rec_offs_set_n_fields(offsets, n);
604  rec_init_offsets(rec, index, offsets);
605  return(offsets);
606 }
607 
608 /******************************************************/
611 UNIV_INTERN
612 void
614 /*====================*/
615  const byte* extra,
619  const dict_index_t* index,
620  ulint node_ptr,
622  ulint* offsets)
624 {
625  ulint n;
626  ulint i;
627  ulint offs;
628  ulint any_ext;
629  const byte* nulls;
630  const byte* lens;
631  dict_field_t* field;
632  ulint null_mask;
633  ulint n_node_ptr_field;
634 
635  ut_ad(extra);
636  ut_ad(index);
637  ut_ad(offsets);
638  ut_ad(dict_table_is_comp(index->table));
639 
640  if (UNIV_UNLIKELY(node_ptr)) {
641  n_node_ptr_field = dict_index_get_n_unique_in_tree(index);
642  n = n_node_ptr_field + 1;
643  } else {
644  n_node_ptr_field = ULINT_UNDEFINED;
645  n = dict_index_get_n_fields(index);
646  }
647 
648  ut_a(rec_offs_get_n_alloc(offsets) >= n + (1 + REC_OFFS_HEADER_SIZE));
649  rec_offs_set_n_fields(offsets, n);
650 
651  nulls = extra;
652  lens = nulls + UT_BITS_IN_BYTES(index->n_nullable);
653  i = offs = 0;
654  null_mask = 1;
655  any_ext = 0;
656 
657  /* read the lengths of fields 0..n */
658  do {
659  ulint len;
660  if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
661  len = offs += REC_NODE_PTR_SIZE;
662  goto resolved;
663  }
664 
665  field = dict_index_get_nth_field(index, i);
666  if (!(dict_field_get_col(field)->prtype & DATA_NOT_NULL)) {
667  /* nullable field => read the null flag */
668 
669  if (UNIV_UNLIKELY(!(byte) null_mask)) {
670  nulls++;
671  null_mask = 1;
672  }
673 
674  if (*nulls & null_mask) {
675  null_mask <<= 1;
676  /* No length is stored for NULL fields.
677  We do not advance offs, and we set
678  the length to zero and enable the
679  SQL NULL flag in offsets[]. */
680  len = offs | REC_OFFS_SQL_NULL;
681  goto resolved;
682  }
683  null_mask <<= 1;
684  }
685 
686  if (UNIV_UNLIKELY(!field->fixed_len)) {
687  /* Variable-length field: read the length */
688  const dict_col_t* col
689  = dict_field_get_col(field);
690  len = *lens++;
691  /* If the maximum length of the field is up
692  to 255 bytes, the actual length is always
693  stored in one byte. If the maximum length is
694  more than 255 bytes, the actual length is
695  stored in one byte for 0..127. The length
696  will be encoded in two bytes when it is 128 or
697  more, or when the field is stored externally. */
698  if (UNIV_UNLIKELY(col->len > 255)
699  || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) {
700  if (len & 0x80) {
701  /* 1exxxxxxx xxxxxxxx */
702  len <<= 8;
703  len |= *lens++;
704 
705  offs += len & 0x3fff;
706  if (UNIV_UNLIKELY(len & 0x4000)) {
707  any_ext = REC_OFFS_EXTERNAL;
708  len = offs | REC_OFFS_EXTERNAL;
709  } else {
710  len = offs;
711  }
712 
713  goto resolved;
714  }
715  }
716 
717  len = offs += len;
718  } else {
719  len = offs += field->fixed_len;
720  }
721 resolved:
722  rec_offs_base(offsets)[i + 1] = len;
723  } while (++i < rec_offs_n_fields(offsets));
724 
725  ut_ad(lens >= extra);
726  *rec_offs_base(offsets) = (lens - extra + REC_N_NEW_EXTRA_BYTES)
727  | REC_OFFS_COMPACT | any_ext;
728 }
729 
730 /************************************************************/
734 UNIV_INTERN
735 ulint
737 /*=======================*/
738  const rec_t* rec,
739  ulint n,
740  ulint* len)
742 {
743  ulint os;
744  ulint next_os;
745 
746  ut_ad(len);
747  ut_a(rec);
748  ut_a(n < rec_get_n_fields_old(rec));
749 
750  if (rec_get_1byte_offs_flag(rec)) {
751  os = rec_1_get_field_start_offs(rec, n);
752 
753  next_os = rec_1_get_field_end_info(rec, n);
754 
755  if (next_os & REC_1BYTE_SQL_NULL_MASK) {
756  *len = UNIV_SQL_NULL;
757 
758  return(os);
759  }
760 
761  next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK;
762  } else {
763  os = rec_2_get_field_start_offs(rec, n);
764 
765  next_os = rec_2_get_field_end_info(rec, n);
766 
767  if (next_os & REC_2BYTE_SQL_NULL_MASK) {
768  *len = UNIV_SQL_NULL;
769 
770  return(os);
771  }
772 
773  next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK
775  }
776 
777  *len = next_os - os;
778 
779  ut_ad(*len < UNIV_PAGE_SIZE);
780 
781  return(os);
782 }
783 
784 /**********************************************************/
787 UNIV_INLINE __attribute__((warn_unused_result, nonnull(1,2)))
788 ulint
789 rec_get_converted_size_comp_prefix_low(
790 /*===================================*/
791  const dict_index_t* index,
795  const dfield_t* fields,
796  ulint n_fields,
797  ulint* extra,
798  bool temp)
800 {
801  ulint extra_size;
802  ulint data_size;
803  ulint i;
804  ulint n_null = index->n_nullable;
805  ut_ad(n_fields > 0);
806  ut_ad(n_fields <= dict_index_get_n_fields(index));
807  ut_ad(!temp || extra);
808 
809  extra_size = temp
810  ? UT_BITS_IN_BYTES(n_null)
811  : REC_N_NEW_EXTRA_BYTES
812  + UT_BITS_IN_BYTES(n_null);
813  data_size = 0;
814 
815  if (temp && dict_table_is_comp(index->table)) {
816  /* No need to do adjust fixed_len=0. We only need to
817  adjust it for ROW_FORMAT=REDUNDANT. */
818  temp = false;
819  }
820 
821  /* read the lengths of fields 0..n */
822  for (i = 0; i < n_fields; i++) {
823  const dict_field_t* field;
824  ulint len;
825  ulint fixed_len;
826  const dict_col_t* col;
827 
828  field = dict_index_get_nth_field(index, i);
829  len = dfield_get_len(&fields[i]);
830  col = dict_field_get_col(field);
831 
832  ut_ad(dict_col_type_assert_equal(col,
833  dfield_get_type(&fields[i])));
834  /* All NULLable fields must be included in the n_null count. */
835  ut_ad((col->prtype & DATA_NOT_NULL) || n_null--);
836 
837  if (dfield_is_null(&fields[i])) {
838  /* No length is stored for NULL fields. */
839  ut_ad(!(col->prtype & DATA_NOT_NULL));
840  continue;
841  }
842 
843  ut_ad(len <= col->len || col->mtype == DATA_BLOB
844  || (col->len == 0 && col->mtype == DATA_VARCHAR));
845 
846  fixed_len = field->fixed_len;
847  if (temp && fixed_len
848  && !dict_col_get_fixed_size(col, temp)) {
849  fixed_len = 0;
850  }
851  /* If the maximum length of a variable-length field
852  is up to 255 bytes, the actual length is always stored
853  in one byte. If the maximum length is more than 255
854  bytes, the actual length is stored in one byte for
855  0..127. The length will be encoded in two bytes when
856  it is 128 or more, or when the field is stored externally. */
857 
858  if (fixed_len) {
859 #ifdef UNIV_DEBUG
860  ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen);
861  ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen);
862 
863  ut_ad(len <= fixed_len);
864 
865  ut_ad(!mbmaxlen || len >= mbminlen
866  * (fixed_len / mbmaxlen));
867 
868  /* dict_index_add_col() should guarantee this */
869  ut_ad(!field->prefix_len
870  || fixed_len == field->prefix_len);
871 #endif /* UNIV_DEBUG */
872  } else if (dfield_is_ext(&fields[i])) {
873  ut_ad(col->len >= 256 || col->mtype == DATA_BLOB);
874  extra_size += 2;
875  } else if (len < 128
876  || (col->len < 256 && col->mtype != DATA_BLOB)) {
877  extra_size++;
878  } else {
879  /* For variable-length columns, we look up the
880  maximum length from the column itself. If this
881  is a prefix index column shorter than 256 bytes,
882  this will waste one byte. */
883  extra_size += 2;
884  }
885  data_size += len;
886  }
887 
888  if (extra) {
889  *extra = extra_size;
890  }
891 
892  return(extra_size + data_size);
893 }
894 
895 /**********************************************************/
898 UNIV_INTERN
899 ulint
901 /*===============================*/
902  const dict_index_t* index,
903  const dfield_t* fields,
904  ulint n_fields,
905  ulint* extra)
906 {
907  ut_ad(dict_table_is_comp(index->table));
908  return(rec_get_converted_size_comp_prefix_low(
909  index, fields, n_fields, extra, false));
910 }
911 
912 /**********************************************************/
915 UNIV_INTERN
916 ulint
918 /*========================*/
919  const dict_index_t* index,
923  ulint status,
924  const dfield_t* fields,
925  ulint n_fields,
926  ulint* extra)
927 {
928  ulint size;
929  ut_ad(n_fields > 0);
930 
931  switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
932  case REC_STATUS_ORDINARY:
933  ut_ad(n_fields == dict_index_get_n_fields(index));
934  size = 0;
935  break;
936  case REC_STATUS_NODE_PTR:
937  n_fields--;
938  ut_ad(n_fields == dict_index_get_n_unique_in_tree(index));
939  ut_ad(dfield_get_len(&fields[n_fields]) == REC_NODE_PTR_SIZE);
940  size = REC_NODE_PTR_SIZE; /* child page number */
941  break;
942  case REC_STATUS_INFIMUM:
943  case REC_STATUS_SUPREMUM:
944  /* infimum or supremum record, 8 data bytes */
945  if (UNIV_LIKELY_NULL(extra)) {
946  *extra = REC_N_NEW_EXTRA_BYTES;
947  }
948  return(REC_N_NEW_EXTRA_BYTES + 8);
949  default:
950  ut_error;
951  return(ULINT_UNDEFINED);
952  }
953 
954  return(size + rec_get_converted_size_comp_prefix_low(
955  index, fields, n_fields, extra, false));
956 }
957 
958 /***********************************************************/
960 UNIV_INTERN
961 void
962 rec_set_nth_field_null_bit(
963 /*=======================*/
964  rec_t* rec,
965  ulint i,
966  ibool val)
967 {
968  ulint info;
969 
970  if (rec_get_1byte_offs_flag(rec)) {
971 
972  info = rec_1_get_field_end_info(rec, i);
973 
974  if (val) {
975  info = info | REC_1BYTE_SQL_NULL_MASK;
976  } else {
977  info = info & ~REC_1BYTE_SQL_NULL_MASK;
978  }
979 
980  rec_1_set_field_end_info(rec, i, info);
981 
982  return;
983  }
984 
985  info = rec_2_get_field_end_info(rec, i);
986 
987  if (val) {
988  info = info | REC_2BYTE_SQL_NULL_MASK;
989  } else {
990  info = info & ~REC_2BYTE_SQL_NULL_MASK;
991  }
992 
993  rec_2_set_field_end_info(rec, i, info);
994 }
995 
996 /***********************************************************/
999 UNIV_INTERN
1000 void
1001 rec_set_nth_field_sql_null(
1002 /*=======================*/
1003  rec_t* rec,
1004  ulint n)
1005 {
1006  ulint offset;
1007 
1008  offset = rec_get_field_start_offs(rec, n);
1009 
1010  data_write_sql_null(rec + offset, rec_get_nth_field_size(rec, n));
1011 
1012  rec_set_nth_field_null_bit(rec, n, TRUE);
1013 }
1014 
1015 /*********************************************************/
1019 static
1020 rec_t*
1021 rec_convert_dtuple_to_rec_old(
1022 /*==========================*/
1023  byte* buf,
1024  const dtuple_t* dtuple,
1025  ulint n_ext)
1026 {
1027  const dfield_t* field;
1028  ulint n_fields;
1029  ulint data_size;
1030  rec_t* rec;
1031  ulint end_offset;
1032  ulint ored_offset;
1033  ulint len;
1034  ulint i;
1035 
1036  ut_ad(buf && dtuple);
1037  ut_ad(dtuple_validate(dtuple));
1038  ut_ad(dtuple_check_typed(dtuple));
1039 
1040  n_fields = dtuple_get_n_fields(dtuple);
1041  data_size = dtuple_get_data_size(dtuple, 0);
1042 
1043  ut_ad(n_fields > 0);
1044 
1045  /* Calculate the offset of the origin in the physical record */
1046 
1047  rec = buf + rec_get_converted_extra_size(data_size, n_fields, n_ext);
1048 #ifdef UNIV_DEBUG
1049  /* Suppress Valgrind warnings of ut_ad()
1050  in mach_write_to_1(), mach_write_to_2() et al. */
1051  memset(buf, 0xff, rec - buf + data_size);
1052 #endif /* UNIV_DEBUG */
1053  /* Store the number of fields */
1054  rec_set_n_fields_old(rec, n_fields);
1055 
1056  /* Set the info bits of the record */
1058  & REC_INFO_BITS_MASK);
1059 
1060  /* Store the data and the offsets */
1061 
1062  end_offset = 0;
1063 
1064  if (!n_ext && data_size <= REC_1BYTE_OFFS_LIMIT) {
1065 
1066  rec_set_1byte_offs_flag(rec, TRUE);
1067 
1068  for (i = 0; i < n_fields; i++) {
1069 
1070  field = dtuple_get_nth_field(dtuple, i);
1071 
1072  if (dfield_is_null(field)) {
1074  dfield_get_type(field), 0);
1075  data_write_sql_null(rec + end_offset, len);
1076 
1077  end_offset += len;
1078  ored_offset = end_offset
1080  } else {
1081  /* If the data is not SQL null, store it */
1082  len = dfield_get_len(field);
1083 
1084  memcpy(rec + end_offset,
1085  dfield_get_data(field), len);
1086 
1087  end_offset += len;
1088  ored_offset = end_offset;
1089  }
1090 
1091  rec_1_set_field_end_info(rec, i, ored_offset);
1092  }
1093  } else {
1094  rec_set_1byte_offs_flag(rec, FALSE);
1095 
1096  for (i = 0; i < n_fields; i++) {
1097 
1098  field = dtuple_get_nth_field(dtuple, i);
1099 
1100  if (dfield_is_null(field)) {
1102  dfield_get_type(field), 0);
1103  data_write_sql_null(rec + end_offset, len);
1104 
1105  end_offset += len;
1106  ored_offset = end_offset
1108  } else {
1109  /* If the data is not SQL null, store it */
1110  len = dfield_get_len(field);
1111 
1112  memcpy(rec + end_offset,
1113  dfield_get_data(field), len);
1114 
1115  end_offset += len;
1116  ored_offset = end_offset;
1117 
1118  if (dfield_is_ext(field)) {
1119  ored_offset |= REC_2BYTE_EXTERN_MASK;
1120  }
1121  }
1122 
1123  rec_2_set_field_end_info(rec, i, ored_offset);
1124  }
1125  }
1126 
1127  return(rec);
1128 }
1129 
1130 /*********************************************************/
1132 UNIV_INLINE __attribute__((nonnull))
1133 void
1134 rec_convert_dtuple_to_rec_comp(
1135 /*===========================*/
1136  rec_t* rec,
1137  const dict_index_t* index,
1138  const dfield_t* fields,
1139  ulint n_fields,
1140  ulint status,
1141  bool temp)
1144 {
1145  const dfield_t* field;
1146  const dtype_t* type;
1147  byte* end;
1148  byte* nulls;
1149  byte* lens;
1150  ulint len;
1151  ulint i;
1152  ulint n_node_ptr_field;
1153  ulint fixed_len;
1154  ulint null_mask = 1;
1155  ulint n_null;
1156 
1157  ut_ad(temp || dict_table_is_comp(index->table));
1158  ut_ad(n_fields > 0);
1159 
1160  if (temp) {
1161  ut_ad(status == REC_STATUS_ORDINARY);
1162  ut_ad(n_fields <= dict_index_get_n_fields(index));
1163  n_node_ptr_field = ULINT_UNDEFINED;
1164  nulls = rec - 1;
1165  if (dict_table_is_comp(index->table)) {
1166  /* No need to do adjust fixed_len=0. We only
1167  need to adjust it for ROW_FORMAT=REDUNDANT. */
1168  temp = false;
1169  }
1170  } else {
1171  nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
1172 
1173  switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
1174  case REC_STATUS_ORDINARY:
1175  ut_ad(n_fields <= dict_index_get_n_fields(index));
1176  n_node_ptr_field = ULINT_UNDEFINED;
1177  break;
1178  case REC_STATUS_NODE_PTR:
1179  ut_ad(n_fields
1180  == dict_index_get_n_unique_in_tree(index) + 1);
1181  n_node_ptr_field = n_fields - 1;
1182  break;
1183  case REC_STATUS_INFIMUM:
1184  case REC_STATUS_SUPREMUM:
1185  ut_ad(n_fields == 1);
1186  n_node_ptr_field = ULINT_UNDEFINED;
1187  break;
1188  default:
1189  ut_error;
1190  return;
1191  }
1192  }
1193 
1194  end = rec;
1195  n_null = index->n_nullable;
1196  lens = nulls - UT_BITS_IN_BYTES(n_null);
1197  /* clear the SQL-null flags */
1198  memset(lens + 1, 0, nulls - lens);
1199 
1200  /* Store the data and the offsets */
1201 
1202  for (i = 0, field = fields; i < n_fields; i++, field++) {
1203  const dict_field_t* ifield;
1204 
1205  type = dfield_get_type(field);
1206  len = dfield_get_len(field);
1207 
1208  if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
1209  ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
1210  ut_ad(len == REC_NODE_PTR_SIZE);
1211  memcpy(end, dfield_get_data(field), len);
1212  end += REC_NODE_PTR_SIZE;
1213  break;
1214  }
1215 
1216  if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
1217  /* nullable field */
1218  ut_ad(n_null--);
1219 
1220  if (UNIV_UNLIKELY(!(byte) null_mask)) {
1221  nulls--;
1222  null_mask = 1;
1223  }
1224 
1225  ut_ad(*nulls < null_mask);
1226 
1227  /* set the null flag if necessary */
1228  if (dfield_is_null(field)) {
1229  *nulls |= null_mask;
1230  null_mask <<= 1;
1231  continue;
1232  }
1233 
1234  null_mask <<= 1;
1235  }
1236  /* only nullable fields can be null */
1237  ut_ad(!dfield_is_null(field));
1238 
1239  ifield = dict_index_get_nth_field(index, i);
1240  fixed_len = ifield->fixed_len;
1241  if (temp && fixed_len
1242  && !dict_col_get_fixed_size(ifield->col, temp)) {
1243  fixed_len = 0;
1244  }
1245  /* If the maximum length of a variable-length field
1246  is up to 255 bytes, the actual length is always stored
1247  in one byte. If the maximum length is more than 255
1248  bytes, the actual length is stored in one byte for
1249  0..127. The length will be encoded in two bytes when
1250  it is 128 or more, or when the field is stored externally. */
1251  if (fixed_len) {
1252 #ifdef UNIV_DEBUG
1253  ulint mbminlen = DATA_MBMINLEN(
1254  ifield->col->mbminmaxlen);
1255  ulint mbmaxlen = DATA_MBMAXLEN(
1256  ifield->col->mbminmaxlen);
1257 
1258  ut_ad(len <= fixed_len);
1259  ut_ad(!mbmaxlen || len >= mbminlen
1260  * (fixed_len / mbmaxlen));
1261  ut_ad(!dfield_is_ext(field));
1262 #endif /* UNIV_DEBUG */
1263  } else if (dfield_is_ext(field)) {
1264  ut_ad(ifield->col->len >= 256
1265  || ifield->col->mtype == DATA_BLOB);
1266  ut_ad(len <= REC_ANTELOPE_MAX_INDEX_COL_LEN
1268  *lens-- = (byte) (len >> 8) | 0xc0;
1269  *lens-- = (byte) len;
1270  } else {
1271  ut_ad(len <= dtype_get_len(type)
1272  || dtype_get_mtype(type) == DATA_BLOB
1273  || !strcmp(index->name,
1274  FTS_INDEX_TABLE_IND_NAME));
1275  if (len < 128
1276  || (dtype_get_len(type) < 256
1277  && dtype_get_mtype(type) != DATA_BLOB)) {
1278 
1279  *lens-- = (byte) len;
1280  } else {
1281  ut_ad(len < 16384);
1282  *lens-- = (byte) (len >> 8) | 0x80;
1283  *lens-- = (byte) len;
1284  }
1285  }
1286 
1287  memcpy(end, dfield_get_data(field), len);
1288  end += len;
1289  }
1290 }
1291 
1292 /*********************************************************/
1296 static
1297 rec_t*
1298 rec_convert_dtuple_to_rec_new(
1299 /*==========================*/
1300  byte* buf,
1302  const dict_index_t* index,
1303  const dtuple_t* dtuple)
1304 {
1305  ulint extra_size;
1306  ulint status;
1307  rec_t* rec;
1308 
1309  status = dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK;
1311  index, status, dtuple->fields, dtuple->n_fields, &extra_size);
1312  rec = buf + extra_size;
1313 
1314  rec_convert_dtuple_to_rec_comp(
1315  rec, index, dtuple->fields, dtuple->n_fields, status, false);
1316 
1317  /* Set the info bits of the record */
1319 
1320  return(rec);
1321 }
1322 
1323 /*********************************************************/
1327 UNIV_INTERN
1328 rec_t*
1330 /*======================*/
1331  byte* buf,
1333  const dict_index_t* index,
1334  const dtuple_t* dtuple,
1335  ulint n_ext)
1337 {
1338  rec_t* rec;
1339 
1340  ut_ad(buf && index && dtuple);
1341  ut_ad(dtuple_validate(dtuple));
1342  ut_ad(dtuple_check_typed(dtuple));
1343 
1344  if (dict_table_is_comp(index->table)) {
1345  rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
1346  } else {
1347  rec = rec_convert_dtuple_to_rec_old(buf, dtuple, n_ext);
1348  }
1349 
1350 #ifdef UNIV_DEBUG
1351  {
1352  mem_heap_t* heap = NULL;
1353  ulint offsets_[REC_OFFS_NORMAL_SIZE];
1354  const ulint* offsets;
1355  ulint i;
1356  rec_offs_init(offsets_);
1357 
1358  offsets = rec_get_offsets(rec, index,
1359  offsets_, ULINT_UNDEFINED, &heap);
1360  ut_ad(rec_validate(rec, offsets));
1361  ut_ad(dtuple_get_n_fields(dtuple)
1362  == rec_offs_n_fields(offsets));
1363 
1364  for (i = 0; i < rec_offs_n_fields(offsets); i++) {
1365  ut_ad(!dfield_is_ext(dtuple_get_nth_field(dtuple, i))
1366  == !rec_offs_nth_extern(offsets, i));
1367  }
1368 
1369  if (UNIV_LIKELY_NULL(heap)) {
1370  mem_heap_free(heap);
1371  }
1372  }
1373 #endif /* UNIV_DEBUG */
1374  return(rec);
1375 }
1376 
1377 #ifndef UNIV_HOTBACKUP
1378 /**********************************************************/
1381 UNIV_INTERN
1382 ulint
1384 /*========================*/
1385  const dict_index_t* index,
1386  const dfield_t* fields,
1387  ulint n_fields,
1388  ulint* extra)
1389 {
1390  return(rec_get_converted_size_comp_prefix_low(
1391  index, fields, n_fields, extra, true));
1392 }
1393 
1394 /******************************************************/
1397 UNIV_INTERN
1398 void
1400 /*==================*/
1401  const rec_t* rec,
1402  const dict_index_t* index,
1403  ulint* offsets)
1405 {
1406  rec_init_offsets_comp_ordinary(rec, true, index, offsets);
1407 }
1408 
1409 /*********************************************************/
1412 UNIV_INTERN
1413 void
1415 /*=======================*/
1416  rec_t* rec,
1417  const dict_index_t* index,
1418  const dfield_t* fields,
1419  ulint n_fields)
1420 {
1421  rec_convert_dtuple_to_rec_comp(rec, index, fields, n_fields,
1422  REC_STATUS_ORDINARY, true);
1423 }
1424 
1425 /**************************************************************/
1428 UNIV_INTERN
1429 void
1431 /*======================*/
1432  dtuple_t* tuple,
1433  const rec_t* rec,
1434  const dict_index_t* index,
1435  ulint n_fields,
1437  mem_heap_t* heap)
1438 {
1439  ulint i;
1440  ulint offsets_[REC_OFFS_NORMAL_SIZE];
1441  ulint* offsets = offsets_;
1442  rec_offs_init(offsets_);
1443 
1444  offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap);
1445 
1446  ut_ad(rec_validate(rec, offsets));
1447  ut_ad(dtuple_check_typed(tuple));
1448 
1450  rec, dict_table_is_comp(index->table)));
1451 
1452  for (i = 0; i < n_fields; i++) {
1453  dfield_t* field;
1454  const byte* data;
1455  ulint len;
1456 
1457  field = dtuple_get_nth_field(tuple, i);
1458  data = rec_get_nth_field(rec, offsets, i, &len);
1459 
1460  if (len != UNIV_SQL_NULL) {
1461  dfield_set_data(field,
1462  mem_heap_dup(heap, data, len), len);
1463  ut_ad(!rec_offs_nth_extern(offsets, i));
1464  } else {
1465  dfield_set_null(field);
1466  }
1467  }
1468 }
1469 
1470 /**************************************************************/
1474 static
1475 rec_t*
1476 rec_copy_prefix_to_buf_old(
1477 /*=======================*/
1478  const rec_t* rec,
1479  ulint n_fields,
1480  ulint area_end,
1481  byte** buf,
1483  ulint* buf_size)
1484 {
1485  rec_t* copy_rec;
1486  ulint area_start;
1487  ulint prefix_len;
1488 
1489  if (rec_get_1byte_offs_flag(rec)) {
1490  area_start = REC_N_OLD_EXTRA_BYTES + n_fields;
1491  } else {
1492  area_start = REC_N_OLD_EXTRA_BYTES + 2 * n_fields;
1493  }
1494 
1495  prefix_len = area_start + area_end;
1496 
1497  if ((*buf == NULL) || (*buf_size < prefix_len)) {
1498  if (*buf != NULL) {
1499  mem_free(*buf);
1500  }
1501 
1502  *buf = static_cast<byte*>(mem_alloc2(prefix_len, buf_size));
1503  }
1504 
1505  ut_memcpy(*buf, rec - area_start, prefix_len);
1506 
1507  copy_rec = *buf + area_start;
1508 
1509  rec_set_n_fields_old(copy_rec, n_fields);
1510 
1511  return(copy_rec);
1512 }
1513 
1514 /**************************************************************/
1518 UNIV_INTERN
1519 rec_t*
1521 /*===================*/
1522  const rec_t* rec,
1523  const dict_index_t* index,
1524  ulint n_fields,
1526  byte** buf,
1529  ulint* buf_size)
1530 {
1531  const byte* nulls;
1532  const byte* lens;
1533  ulint i;
1534  ulint prefix_len;
1535  ulint null_mask;
1536  ulint status;
1537 
1538  UNIV_PREFETCH_RW(*buf);
1539 
1540  if (!dict_table_is_comp(index->table)) {
1541  ut_ad(rec_validate_old(rec));
1542  return(rec_copy_prefix_to_buf_old(
1543  rec, n_fields,
1544  rec_get_field_start_offs(rec, n_fields),
1545  buf, buf_size));
1546  }
1547 
1548  status = rec_get_status(rec);
1549 
1550  switch (status) {
1551  case REC_STATUS_ORDINARY:
1552  ut_ad(n_fields <= dict_index_get_n_fields(index));
1553  break;
1554  case REC_STATUS_NODE_PTR:
1555  /* it doesn't make sense to copy the child page number field */
1556  ut_ad(n_fields <= dict_index_get_n_unique_in_tree(index));
1557  break;
1558  case REC_STATUS_INFIMUM:
1559  case REC_STATUS_SUPREMUM:
1560  /* infimum or supremum record: no sense to copy anything */
1561  default:
1562  ut_error;
1563  return(NULL);
1564  }
1565 
1566  nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
1567  lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
1568  UNIV_PREFETCH_R(lens);
1569  prefix_len = 0;
1570  null_mask = 1;
1571 
1572  /* read the lengths of fields 0..n */
1573  for (i = 0; i < n_fields; i++) {
1574  const dict_field_t* field;
1575  const dict_col_t* col;
1576 
1577  field = dict_index_get_nth_field(index, i);
1578  col = dict_field_get_col(field);
1579 
1580  if (!(col->prtype & DATA_NOT_NULL)) {
1581  /* nullable field => read the null flag */
1582  if (UNIV_UNLIKELY(!(byte) null_mask)) {
1583  nulls--;
1584  null_mask = 1;
1585  }
1586 
1587  if (*nulls & null_mask) {
1588  null_mask <<= 1;
1589  continue;
1590  }
1591 
1592  null_mask <<= 1;
1593  }
1594 
1595  if (field->fixed_len) {
1596  prefix_len += field->fixed_len;
1597  } else {
1598  ulint len = *lens--;
1599  /* If the maximum length of the column is up
1600  to 255 bytes, the actual length is always
1601  stored in one byte. If the maximum length is
1602  more than 255 bytes, the actual length is
1603  stored in one byte for 0..127. The length
1604  will be encoded in two bytes when it is 128 or
1605  more, or when the column is stored externally. */
1606  if (col->len > 255 || col->mtype == DATA_BLOB) {
1607  if (len & 0x80) {
1608  /* 1exxxxxx */
1609  len &= 0x3f;
1610  len <<= 8;
1611  len |= *lens--;
1612  UNIV_PREFETCH_R(lens);
1613  }
1614  }
1615  prefix_len += len;
1616  }
1617  }
1618 
1619  UNIV_PREFETCH_R(rec + prefix_len);
1620 
1621  prefix_len += rec - (lens + 1);
1622 
1623  if ((*buf == NULL) || (*buf_size < prefix_len)) {
1624  if (*buf != NULL) {
1625  mem_free(*buf);
1626  }
1627 
1628  *buf = static_cast<byte*>(mem_alloc2(prefix_len, buf_size));
1629  }
1630 
1631  memcpy(*buf, lens + 1, prefix_len);
1632 
1633  return(*buf + (rec - (lens + 1)));
1634 }
1635 #endif /* UNIV_HOTBACKUP */
1636 
1637 /***************************************************************/
1640 static
1641 ibool
1642 rec_validate_old(
1643 /*=============*/
1644  const rec_t* rec)
1645 {
1646  const byte* data;
1647  ulint len;
1648  ulint n_fields;
1649  ulint len_sum = 0;
1650  ulint sum = 0;
1651  ulint i;
1652 
1653  ut_a(rec);
1654  n_fields = rec_get_n_fields_old(rec);
1655 
1656  if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
1657  fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
1658  (ulong) n_fields);
1659  return(FALSE);
1660  }
1661 
1662  for (i = 0; i < n_fields; i++) {
1663  data = rec_get_nth_field_old(rec, i, &len);
1664 
1665  if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
1666  fprintf(stderr,
1667  "InnoDB: Error: record field %lu len %lu\n",
1668  (ulong) i,
1669  (ulong) len);
1670  return(FALSE);
1671  }
1672 
1673  if (len != UNIV_SQL_NULL) {
1674  len_sum += len;
1675  sum += *(data + len -1); /* dereference the
1676  end of the field to
1677  cause a memory trap
1678  if possible */
1679  } else {
1680  len_sum += rec_get_nth_field_size(rec, i);
1681  }
1682  }
1683 
1684  if (len_sum != rec_get_data_size_old(rec)) {
1685  fprintf(stderr,
1686  "InnoDB: Error: record len should be %lu, len %lu\n",
1687  (ulong) len_sum,
1688  rec_get_data_size_old(rec));
1689  return(FALSE);
1690  }
1691 
1692  rec_dummy = sum; /* This is here only to fool the compiler */
1693 
1694  return(TRUE);
1695 }
1696 
1697 /***************************************************************/
1700 UNIV_INTERN
1701 ibool
1702 rec_validate(
1703 /*=========*/
1704  const rec_t* rec,
1705  const ulint* offsets)
1706 {
1707  const byte* data;
1708  ulint len;
1709  ulint n_fields;
1710  ulint len_sum = 0;
1711  ulint sum = 0;
1712  ulint i;
1713 
1714  ut_a(rec);
1715  n_fields = rec_offs_n_fields(offsets);
1716 
1717  if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
1718  fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
1719  (ulong) n_fields);
1720  return(FALSE);
1721  }
1722 
1723  ut_a(rec_offs_comp(offsets) || n_fields <= rec_get_n_fields_old(rec));
1724 
1725  for (i = 0; i < n_fields; i++) {
1726  data = rec_get_nth_field(rec, offsets, i, &len);
1727 
1728  if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
1729  fprintf(stderr,
1730  "InnoDB: Error: record field %lu len %lu\n",
1731  (ulong) i,
1732  (ulong) len);
1733  return(FALSE);
1734  }
1735 
1736  if (len != UNIV_SQL_NULL) {
1737  len_sum += len;
1738  sum += *(data + len -1); /* dereference the
1739  end of the field to
1740  cause a memory trap
1741  if possible */
1742  } else if (!rec_offs_comp(offsets)) {
1743  len_sum += rec_get_nth_field_size(rec, i);
1744  }
1745  }
1746 
1747  if (len_sum != rec_offs_data_size(offsets)) {
1748  fprintf(stderr,
1749  "InnoDB: Error: record len should be %lu, len %lu\n",
1750  (ulong) len_sum,
1751  (ulong) rec_offs_data_size(offsets));
1752  return(FALSE);
1753  }
1754 
1755  rec_dummy = sum; /* This is here only to fool the compiler */
1756 
1757  if (!rec_offs_comp(offsets)) {
1758  ut_a(rec_validate_old(rec));
1759  }
1760 
1761  return(TRUE);
1762 }
1763 
1764 /***************************************************************/
1766 UNIV_INTERN
1767 void
1769 /*==========*/
1770  FILE* file,
1771  const rec_t* rec)
1772 {
1773  const byte* data;
1774  ulint len;
1775  ulint n;
1776  ulint i;
1777 
1778  ut_ad(rec);
1779 
1780  n = rec_get_n_fields_old(rec);
1781 
1782  fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
1783  " %u-byte offsets; info bits %lu\n",
1784  (ulong) n,
1785  rec_get_1byte_offs_flag(rec) ? 1 : 2,
1786  (ulong) rec_get_info_bits(rec, FALSE));
1787 
1788  for (i = 0; i < n; i++) {
1789 
1790  data = rec_get_nth_field_old(rec, i, &len);
1791 
1792  fprintf(file, " %lu:", (ulong) i);
1793 
1794  if (len != UNIV_SQL_NULL) {
1795  if (len <= 30) {
1796 
1797  ut_print_buf(file, data, len);
1798  } else {
1799  ut_print_buf(file, data, 30);
1800 
1801  fprintf(file, " (total %lu bytes)",
1802  (ulong) len);
1803  }
1804  } else {
1805  fprintf(file, " SQL NULL, size %lu ",
1806  rec_get_nth_field_size(rec, i));
1807  }
1808 
1809  putc(';', file);
1810  putc('\n', file);
1811  }
1812 
1813  rec_validate_old(rec);
1814 }
1815 
1816 #ifndef UNIV_HOTBACKUP
1817 /***************************************************************/
1820 UNIV_INTERN
1821 void
1823 /*===========*/
1824  FILE* file,
1825  const rec_t* rec,
1826  const ulint* offsets)
1827 {
1828  ulint i;
1829 
1830  for (i = 0; i < rec_offs_n_fields(offsets); i++) {
1831  const byte* data;
1832  ulint len;
1833 
1834  data = rec_get_nth_field(rec, offsets, i, &len);
1835 
1836  fprintf(file, " %lu:", (ulong) i);
1837 
1838  if (len != UNIV_SQL_NULL) {
1839  if (len <= 30) {
1840 
1841  ut_print_buf(file, data, len);
1842  } else if (rec_offs_nth_extern(offsets, i)) {
1843  ut_print_buf(file, data, 30);
1844  fprintf(file, " (total %lu bytes, external)",
1845  (ulong) len);
1846  ut_print_buf(file, data + len
1849  } else {
1850  ut_print_buf(file, data, 30);
1851 
1852  fprintf(file, " (total %lu bytes)",
1853  (ulong) len);
1854  }
1855  } else {
1856  fputs(" SQL NULL", file);
1857  }
1858  putc(';', file);
1859  putc('\n', file);
1860  }
1861 }
1862 
1863 /***************************************************************/
1865 UNIV_INTERN
1866 void
1868 /*==========*/
1869  FILE* file,
1870  const rec_t* rec,
1871  const ulint* offsets)
1872 {
1873  ut_ad(rec);
1874  ut_ad(offsets);
1875  ut_ad(rec_offs_validate(rec, NULL, offsets));
1876 
1877  if (!rec_offs_comp(offsets)) {
1878  rec_print_old(file, rec);
1879  return;
1880  }
1881 
1882  fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
1883  " compact format; info bits %lu\n",
1884  (ulong) rec_offs_n_fields(offsets),
1885  (ulong) rec_get_info_bits(rec, TRUE));
1886 
1887  rec_print_comp(file, rec, offsets);
1888  rec_validate(rec, offsets);
1889 }
1890 
1891 /***************************************************************/
1893 UNIV_INTERN
1894 void
1895 rec_print(
1896 /*======*/
1897  FILE* file,
1898  const rec_t* rec,
1899  const dict_index_t* index)
1900 {
1901  ut_ad(index);
1902 
1903  if (!dict_table_is_comp(index->table)) {
1904  rec_print_old(file, rec);
1905  return;
1906  } else {
1907  mem_heap_t* heap = NULL;
1908  ulint offsets_[REC_OFFS_NORMAL_SIZE];
1909  rec_offs_init(offsets_);
1910 
1911  rec_print_new(file, rec,
1912  rec_get_offsets(rec, index, offsets_,
1913  ULINT_UNDEFINED, &heap));
1914  if (UNIV_LIKELY_NULL(heap)) {
1915  mem_heap_free(heap);
1916  }
1917  }
1918 }
1919 
1920 # ifdef UNIV_DEBUG
1921 /************************************************************/
1924 UNIV_INTERN
1925 trx_id_t
1926 rec_get_trx_id(
1927 /*===========*/
1928  const rec_t* rec,
1929  const dict_index_t* index)
1930 {
1931  const page_t* page
1932  = page_align(rec);
1933  ulint trx_id_col
1934  = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
1935  const byte* trx_id;
1936  ulint len;
1937  mem_heap_t* heap = NULL;
1938  ulint offsets_[REC_OFFS_NORMAL_SIZE];
1939  ulint* offsets = offsets_;
1940  rec_offs_init(offsets_);
1941 
1943  ut_ad(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)
1944  == index->id);
1945  ut_ad(dict_index_is_clust(index));
1946  ut_ad(trx_id_col > 0);
1947  ut_ad(trx_id_col != ULINT_UNDEFINED);
1948 
1949  offsets = rec_get_offsets(rec, index, offsets, trx_id_col + 1, &heap);
1950 
1951  trx_id = rec_get_nth_field(rec, offsets, trx_id_col, &len);
1952 
1953  ut_ad(len == DATA_TRX_ID_LEN);
1954 
1955  if (heap) {
1956  mem_heap_free(heap);
1957  }
1958 
1959  return(trx_read_trx_id(trx_id));
1960 }
1961 # endif /* UNIV_DEBUG */
1962 #endif /* !UNIV_HOTBACKUP */