1/*****************************************************************************
2
3Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/********************************************************************//**
21@file data/data0data.cc
22SQL data field and tuple
23
24Created 5/30/1994 Heikki Tuuri
25*************************************************************************/
26
27#include "ha_prototypes.h"
28
29#include "data0data.h"
30#include "rem0rec.h"
31#include "rem0cmp.h"
32#include "page0page.h"
33#include "page0zip.h"
34#include "dict0dict.h"
35#include "btr0cur.h"
36#include "row0upd.h"
37
38#ifdef UNIV_DEBUG
39/** Dummy variable to catch access to uninitialized fields. In the
40debug version, dtuple_create() will make all fields of dtuple_t point
41to data_error. */
42byte data_error;
43#endif /* UNIV_DEBUG */
44
45/** Trim the tail of an index tuple before insert or update.
46After instant ADD COLUMN, if the last fields of a clustered index tuple
47match the 'default row', there will be no need to store them.
48NOTE: A page latch in the index must be held, so that the index
49may not lose 'instantness' before the trimmed tuple has been
50inserted or updated.
51@param[in] index index possibly with instantly added columns */
52void dtuple_t::trim(const dict_index_t& index)
53{
54 ut_ad(n_fields >= index.n_core_fields);
55 ut_ad(n_fields <= index.n_fields);
56 ut_ad(index.is_instant());
57
58 ulint i = n_fields;
59 for (; i > index.n_core_fields; i--) {
60 const dfield_t* dfield = dtuple_get_nth_field(this, i - 1);
61 const dict_col_t* col = dict_index_get_nth_col(&index, i - 1);
62 ut_ad(col->is_instant());
63 ulint len = dfield_get_len(dfield);
64 if (len != col->def_val.len) {
65 break;
66 }
67
68 if (len != 0 && len != UNIV_SQL_NULL
69 && dfield->data != col->def_val.data
70 && memcmp(dfield->data, col->def_val.data, len)) {
71 break;
72 }
73 }
74
75 n_fields = i;
76}
77
78/** Compare two data tuples.
79@param[in] tuple1 first data tuple
80@param[in] tuple2 second data tuple
81@return positive, 0, negative if tuple1 is greater, equal, less, than tuple2,
82respectively */
83int
84dtuple_coll_cmp(
85 const dtuple_t* tuple1,
86 const dtuple_t* tuple2)
87{
88 ulint n_fields;
89 ulint i;
90 int cmp;
91
92 ut_ad(tuple1 != NULL);
93 ut_ad(tuple2 != NULL);
94 ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
95 ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
96 ut_ad(dtuple_check_typed(tuple1));
97 ut_ad(dtuple_check_typed(tuple2));
98
99 n_fields = dtuple_get_n_fields(tuple1);
100
101 cmp = (int) n_fields - (int) dtuple_get_n_fields(tuple2);
102
103 for (i = 0; cmp == 0 && i < n_fields; i++) {
104 const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
105 const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
106 cmp = cmp_dfield_dfield(field1, field2);
107 }
108
109 return(cmp);
110}
111
112/*********************************************************************//**
113Sets number of fields used in a tuple. Normally this is set in
114dtuple_create, but if you want later to set it smaller, you can use this. */
115void
116dtuple_set_n_fields(
117/*================*/
118 dtuple_t* tuple, /*!< in: tuple */
119 ulint n_fields) /*!< in: number of fields */
120{
121 ut_ad(tuple);
122
123 tuple->n_fields = n_fields;
124 tuple->n_fields_cmp = n_fields;
125}
126
127/**********************************************************//**
128Checks that a data field is typed.
129@return TRUE if ok */
130static
131ibool
132dfield_check_typed_no_assert(
133/*=========================*/
134 const dfield_t* field) /*!< in: data field */
135{
136 if (dfield_get_type(field)->mtype > DATA_MTYPE_CURRENT_MAX
137 || dfield_get_type(field)->mtype < DATA_MTYPE_CURRENT_MIN) {
138
139 ib::error() << "Data field type "
140 << dfield_get_type(field)->mtype
141 << ", len " << dfield_get_len(field);
142
143 return(FALSE);
144 }
145
146 return(TRUE);
147}
148
149/**********************************************************//**
150Checks that a data tuple is typed.
151@return TRUE if ok */
152static
153ibool
154dtuple_check_typed_no_assert(
155/*=========================*/
156 const dtuple_t* tuple) /*!< in: tuple */
157{
158 const dfield_t* field;
159 ulint i;
160
161 if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
162 ib::error() << "Index entry has "
163 << dtuple_get_n_fields(tuple) << " fields";
164dump:
165 fputs("InnoDB: Tuple contents: ", stderr);
166 dtuple_print(stderr, tuple);
167 putc('\n', stderr);
168
169 return(FALSE);
170 }
171
172 for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
173
174 field = dtuple_get_nth_field(tuple, i);
175
176 if (!dfield_check_typed_no_assert(field)) {
177 goto dump;
178 }
179 }
180
181 return(TRUE);
182}
183
184#ifdef UNIV_DEBUG
185/**********************************************************//**
186Checks that a data field is typed. Asserts an error if not.
187@return TRUE if ok */
188ibool
189dfield_check_typed(
190/*===============*/
191 const dfield_t* field) /*!< in: data field */
192{
193 if (dfield_get_type(field)->mtype > DATA_MTYPE_CURRENT_MAX
194 || dfield_get_type(field)->mtype < DATA_MTYPE_CURRENT_MIN) {
195
196 ib::fatal() << "Data field type "
197 << dfield_get_type(field)->mtype
198 << ", len " << dfield_get_len(field);
199 }
200
201 return(TRUE);
202}
203
204/**********************************************************//**
205Checks that a data tuple is typed. Asserts an error if not.
206@return TRUE if ok */
207ibool
208dtuple_check_typed(
209/*===============*/
210 const dtuple_t* tuple) /*!< in: tuple */
211{
212 const dfield_t* field;
213 ulint i;
214
215 for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
216
217 field = dtuple_get_nth_field(tuple, i);
218
219 ut_a(dfield_check_typed(field));
220 }
221
222 return(TRUE);
223}
224
225/**********************************************************//**
226Validates the consistency of a tuple which must be complete, i.e,
227all fields must have been set.
228@return TRUE if ok */
229ibool
230dtuple_validate(
231/*============*/
232 const dtuple_t* tuple) /*!< in: tuple */
233{
234 const dfield_t* field;
235 ulint n_fields;
236 ulint len;
237 ulint i;
238
239 ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
240
241 n_fields = dtuple_get_n_fields(tuple);
242
243 /* We dereference all the data of each field to test
244 for memory traps */
245
246 for (i = 0; i < n_fields; i++) {
247
248 field = dtuple_get_nth_field(tuple, i);
249 len = dfield_get_len(field);
250
251 if (!dfield_is_null(field)) {
252
253 const byte* data;
254
255 data = static_cast<const byte*>(dfield_get_data(field));
256#ifndef UNIV_DEBUG_VALGRIND
257 ulint j;
258
259 for (j = 0; j < len; j++) {
260 data++;
261 }
262#endif /* !UNIV_DEBUG_VALGRIND */
263
264 UNIV_MEM_ASSERT_RW(data, len);
265 }
266 }
267
268 ut_a(dtuple_check_typed(tuple));
269
270 return(TRUE);
271}
272#endif /* UNIV_DEBUG */
273
274/*************************************************************//**
275Pretty prints a dfield value according to its data type. */
276void
277dfield_print(
278/*=========*/
279 const dfield_t* dfield) /*!< in: dfield */
280{
281 const byte* data;
282 ulint len;
283 ulint i;
284
285 len = dfield_get_len(dfield);
286 data = static_cast<const byte*>(dfield_get_data(dfield));
287
288 if (dfield_is_null(dfield)) {
289 fputs("NULL", stderr);
290
291 return;
292 }
293
294 switch (dtype_get_mtype(dfield_get_type(dfield))) {
295 case DATA_CHAR:
296 case DATA_VARCHAR:
297 for (i = 0; i < len; i++) {
298 int c = *data++;
299 putc(isprint(c) ? c : ' ', stderr);
300 }
301
302 if (dfield_is_ext(dfield)) {
303 fputs("(external)", stderr);
304 }
305 break;
306 case DATA_INT:
307 ut_a(len == 4); /* only works for 32-bit integers */
308 fprintf(stderr, "%d", (int) mach_read_from_4(data));
309 break;
310 default:
311 ut_error;
312 }
313}
314
315/*************************************************************//**
316Pretty prints a dfield value according to its data type. Also the hex string
317is printed if a string contains non-printable characters. */
318void
319dfield_print_also_hex(
320/*==================*/
321 const dfield_t* dfield) /*!< in: dfield */
322{
323 const byte* data;
324 ulint len;
325 ulint prtype;
326 ulint i;
327 ibool print_also_hex;
328
329 len = dfield_get_len(dfield);
330 data = static_cast<const byte*>(dfield_get_data(dfield));
331
332 if (dfield_is_null(dfield)) {
333 fputs("NULL", stderr);
334
335 return;
336 }
337
338 prtype = dtype_get_prtype(dfield_get_type(dfield));
339
340 switch (dtype_get_mtype(dfield_get_type(dfield))) {
341 ib_id_t id;
342 case DATA_INT:
343 switch (len) {
344 ulint val;
345 case 1:
346 val = mach_read_from_1(data);
347
348 if (!(prtype & DATA_UNSIGNED)) {
349 val &= ~0x80U;
350 fprintf(stderr, "%ld", (long) val);
351 } else {
352 fprintf(stderr, "%lu", (ulong) val);
353 }
354 break;
355
356 case 2:
357 val = mach_read_from_2(data);
358
359 if (!(prtype & DATA_UNSIGNED)) {
360 val &= ~0x8000U;
361 fprintf(stderr, "%ld", (long) val);
362 } else {
363 fprintf(stderr, "%lu", (ulong) val);
364 }
365 break;
366
367 case 3:
368 val = mach_read_from_3(data);
369
370 if (!(prtype & DATA_UNSIGNED)) {
371 val &= ~0x800000U;
372 fprintf(stderr, "%ld", (long) val);
373 } else {
374 fprintf(stderr, "%lu", (ulong) val);
375 }
376 break;
377
378 case 4:
379 val = mach_read_from_4(data);
380
381 if (!(prtype & DATA_UNSIGNED)) {
382 val &= ~0x80000000;
383 fprintf(stderr, "%ld", (long) val);
384 } else {
385 fprintf(stderr, "%lu", (ulong) val);
386 }
387 break;
388
389 case 6:
390 id = mach_read_from_6(data);
391 fprintf(stderr, IB_ID_FMT, id);
392 break;
393
394 case 7:
395 id = mach_read_from_7(data);
396 fprintf(stderr, IB_ID_FMT, id);
397 break;
398 case 8:
399 id = mach_read_from_8(data);
400 fprintf(stderr, IB_ID_FMT, id);
401 break;
402 default:
403 goto print_hex;
404 }
405 break;
406
407 case DATA_SYS:
408 switch (prtype & DATA_SYS_PRTYPE_MASK) {
409 case DATA_TRX_ID:
410 id = mach_read_from_6(data);
411
412 fprintf(stderr, "trx_id " TRX_ID_FMT, id);
413 break;
414
415 case DATA_ROLL_PTR:
416 id = mach_read_from_7(data);
417
418 fprintf(stderr, "roll_ptr " TRX_ID_FMT, id);
419 break;
420
421 case DATA_ROW_ID:
422 id = mach_read_from_6(data);
423
424 fprintf(stderr, "row_id " TRX_ID_FMT, id);
425 break;
426
427 default:
428 goto print_hex;
429 }
430 break;
431
432 case DATA_CHAR:
433 case DATA_VARCHAR:
434 print_also_hex = FALSE;
435
436 for (i = 0; i < len; i++) {
437 int c = *data++;
438
439 if (!isprint(c)) {
440 print_also_hex = TRUE;
441
442 fprintf(stderr, "\\x%02x", (unsigned char) c);
443 } else {
444 putc(c, stderr);
445 }
446 }
447
448 if (dfield_is_ext(dfield)) {
449 fputs("(external)", stderr);
450 }
451
452 if (!print_also_hex) {
453 break;
454 }
455
456 data = static_cast<byte*>(dfield_get_data(dfield));
457 /* fall through */
458
459 case DATA_BINARY:
460 default:
461print_hex:
462 fputs(" Hex: ",stderr);
463
464 for (i = 0; i < len; i++) {
465 fprintf(stderr, "%02x", *data++);
466 }
467
468 if (dfield_is_ext(dfield)) {
469 fputs("(external)", stderr);
470 }
471 }
472}
473
474/*************************************************************//**
475Print a dfield value using ut_print_buf. */
476static
477void
478dfield_print_raw(
479/*=============*/
480 FILE* f, /*!< in: output stream */
481 const dfield_t* dfield) /*!< in: dfield */
482{
483 ulint len = dfield_get_len(dfield);
484 if (!dfield_is_null(dfield)) {
485 ulint print_len = ut_min(len, static_cast<ulint>(1000));
486 ut_print_buf(f, dfield_get_data(dfield), print_len);
487 if (len != print_len) {
488 fprintf(f, "(total %lu bytes%s)",
489 (ulong) len,
490 dfield_is_ext(dfield) ? ", external" : "");
491 }
492 } else {
493 fputs(" SQL NULL", f);
494 }
495}
496
497/**********************************************************//**
498The following function prints the contents of a tuple. */
499void
500dtuple_print(
501/*=========*/
502 FILE* f, /*!< in: output stream */
503 const dtuple_t* tuple) /*!< in: tuple */
504{
505 ulint n_fields;
506 ulint i;
507
508 n_fields = dtuple_get_n_fields(tuple);
509
510 fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
511
512 for (i = 0; i < n_fields; i++) {
513 fprintf(f, " %lu:", (ulong) i);
514
515 dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
516
517 putc(';', f);
518 putc('\n', f);
519 }
520
521 ut_ad(dtuple_validate(tuple));
522}
523
524/** Print the contents of a tuple.
525@param[out] o output stream
526@param[in] field array of data fields
527@param[in] n number of data fields */
528void
529dfield_print(
530 std::ostream& o,
531 const dfield_t* field,
532 ulint n)
533{
534 for (ulint i = 0; i < n; i++, field++) {
535 const void* data = dfield_get_data(field);
536 const ulint len = dfield_get_len(field);
537
538 if (i) {
539 o << ',';
540 }
541
542 if (dfield_is_null(field)) {
543 o << "NULL";
544 } else if (dfield_is_ext(field)) {
545 ulint local_len = len - BTR_EXTERN_FIELD_REF_SIZE;
546 ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
547
548 o << '['
549 << local_len
550 << '+' << BTR_EXTERN_FIELD_REF_SIZE << ']';
551 ut_print_buf(o, data, local_len);
552 ut_print_buf_hex(o, static_cast<const byte*>(data)
553 + local_len,
554 BTR_EXTERN_FIELD_REF_SIZE);
555 } else {
556 o << '[' << len << ']';
557 ut_print_buf(o, data, len);
558 }
559 }
560}
561
562/** Print the contents of a tuple.
563@param[out] o output stream
564@param[in] tuple data tuple */
565void
566dtuple_print(
567 std::ostream& o,
568 const dtuple_t* tuple)
569{
570 const ulint n = dtuple_get_n_fields(tuple);
571
572 o << "TUPLE (info_bits=" << dtuple_get_info_bits(tuple)
573 << ", " << n << " fields): {";
574
575 dfield_print(o, tuple->fields, n);
576
577 o << "}";
578}
579
580/**************************************************************//**
581Moves parts of long fields in entry to the big record vector so that
582the size of tuple drops below the maximum record size allowed in the
583database. Moves data only from those fields which are not necessary
584to determine uniquely the insertion place of the tuple in the index.
585@return own: created big record vector, NULL if we are not able to
586shorten the entry enough, i.e., if there are too many fixed-length or
587short fields in entry or the index is clustered */
588big_rec_t*
589dtuple_convert_big_rec(
590/*===================*/
591 dict_index_t* index, /*!< in: index */
592 upd_t* upd, /*!< in/out: update vector */
593 dtuple_t* entry, /*!< in/out: index entry */
594 ulint* n_ext) /*!< in/out: number of
595 externally stored columns */
596{
597 mem_heap_t* heap;
598 big_rec_t* vector;
599 dfield_t* dfield;
600 dict_field_t* ifield;
601 ulint size;
602 ulint n_fields;
603 ulint local_len;
604 ulint local_prefix_len;
605
606 if (!dict_index_is_clust(index)) {
607 return(NULL);
608 }
609
610 if (!dict_table_has_atomic_blobs(index->table)) {
611 /* up to MySQL 5.1: store a 768-byte prefix locally */
612 local_len = BTR_EXTERN_FIELD_REF_SIZE
613 + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
614 } else {
615 /* new-format table: do not store any BLOB prefix locally */
616 local_len = BTR_EXTERN_FIELD_REF_SIZE;
617 }
618
619 ut_a(dtuple_check_typed_no_assert(entry));
620
621 size = rec_get_converted_size(index, entry, *n_ext);
622
623 if (UNIV_UNLIKELY(size > 1000000000)) {
624 ib::warn() << "Tuple size is very big: " << size;
625 fputs("InnoDB: Tuple contents: ", stderr);
626 dtuple_print(stderr, entry);
627 putc('\n', stderr);
628 }
629
630 heap = mem_heap_create(size + dtuple_get_n_fields(entry)
631 * sizeof(big_rec_field_t) + 1000);
632
633 vector = big_rec_t::alloc(heap, dtuple_get_n_fields(entry));
634
635 /* Decide which fields to shorten: the algorithm is to look for
636 a variable-length field that yields the biggest savings when
637 stored externally */
638
639 n_fields = 0;
640
641 while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
642 *n_ext),
643 dict_table_is_comp(index->table),
644 dict_index_get_n_fields(index),
645 dict_table_page_size(index->table))) {
646
647 ulint i;
648 ulint longest = 0;
649 ulint longest_i = ULINT_MAX;
650 byte* data;
651
652 for (i = dict_index_get_n_unique_in_tree(index);
653 i < dtuple_get_n_fields(entry); i++) {
654 ulint savings;
655
656 dfield = dtuple_get_nth_field(entry, i);
657 ifield = dict_index_get_nth_field(index, i);
658
659 /* Skip fixed-length, NULL, externally stored,
660 or short columns */
661
662 if (ifield->fixed_len
663 || dfield_is_null(dfield)
664 || dfield_is_ext(dfield)
665 || dfield_get_len(dfield) <= local_len
666 || dfield_get_len(dfield)
667 <= BTR_EXTERN_LOCAL_STORED_MAX_SIZE) {
668 goto skip_field;
669 }
670
671 savings = dfield_get_len(dfield) - local_len;
672
673 /* Check that there would be savings */
674 if (longest >= savings) {
675 goto skip_field;
676 }
677
678 /* In DYNAMIC and COMPRESSED format, store
679 locally any non-BLOB columns whose maximum
680 length does not exceed 256 bytes. This is
681 because there is no room for the "external
682 storage" flag when the maximum length is 255
683 bytes or less. This restriction trivially
684 holds in REDUNDANT and COMPACT format, because
685 there we always store locally columns whose
686 length is up to local_len == 788 bytes.
687 @see rec_init_offsets_comp_ordinary */
688 if (!DATA_BIG_COL(ifield->col)) {
689 goto skip_field;
690 }
691
692 longest_i = i;
693 longest = savings;
694
695skip_field:
696 continue;
697 }
698
699 if (!longest) {
700 /* Cannot shorten more */
701
702 mem_heap_free(heap);
703
704 return(NULL);
705 }
706
707 /* Move data from field longest_i to big rec vector.
708
709 We store the first bytes locally to the record. Then
710 we can calculate all ordering fields in all indexes
711 from locally stored data. */
712
713 dfield = dtuple_get_nth_field(entry, longest_i);
714 ifield = dict_index_get_nth_field(index, longest_i);
715 local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
716
717 vector->append(
718 big_rec_field_t(
719 longest_i,
720 dfield_get_len(dfield) - local_prefix_len,
721 static_cast<char*>(dfield_get_data(dfield))
722 + local_prefix_len));
723
724 /* Allocate the locally stored part of the column. */
725 data = static_cast<byte*>(mem_heap_alloc(heap, local_len));
726
727 /* Copy the local prefix. */
728 memcpy(data, dfield_get_data(dfield), local_prefix_len);
729 /* Clear the extern field reference (BLOB pointer). */
730 memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
731#if 0
732 /* The following would fail the Valgrind checks in
733 page_cur_insert_rec_low() and page_cur_insert_rec_zip().
734 The BLOB pointers in the record will be initialized after
735 the record and the BLOBs have been written. */
736 UNIV_MEM_ALLOC(data + local_prefix_len,
737 BTR_EXTERN_FIELD_REF_SIZE);
738#endif
739
740 dfield_set_data(dfield, data, local_len);
741 dfield_set_ext(dfield);
742
743 n_fields++;
744 (*n_ext)++;
745 ut_ad(n_fields < dtuple_get_n_fields(entry));
746
747 if (upd && !upd->is_modified(longest_i)) {
748
749 DEBUG_SYNC_C("ib_mv_nonupdated_column_offpage");
750
751 upd_field_t upd_field;
752 upd_field.field_no = unsigned(longest_i);
753 upd_field.orig_len = 0;
754 upd_field.exp = NULL;
755 upd_field.old_v_val = NULL;
756 dfield_copy(&upd_field.new_val,
757 dfield->clone(upd->heap));
758 upd->append(upd_field);
759 ut_ad(upd->is_modified(longest_i));
760
761 ut_ad(upd_field.new_val.len
762 >= BTR_EXTERN_FIELD_REF_SIZE);
763 ut_ad(upd_field.new_val.len == local_len);
764 ut_ad(upd_field.new_val.len == dfield_get_len(dfield));
765 }
766 }
767
768 ut_ad(n_fields == vector->n_fields);
769
770 return(vector);
771}
772
773/**************************************************************//**
774Puts back to entry the data stored in vector. Note that to ensure the
775fields in entry can accommodate the data, vector must have been created
776from entry with dtuple_convert_big_rec. */
777void
778dtuple_convert_back_big_rec(
779/*========================*/
780 dict_index_t* index MY_ATTRIBUTE((unused)), /*!< in: index */
781 dtuple_t* entry, /*!< in: entry whose data was put to vector */
782 big_rec_t* vector) /*!< in, own: big rec vector; it is
783 freed in this function */
784{
785 big_rec_field_t* b = vector->fields;
786 const big_rec_field_t* const end = b + vector->n_fields;
787
788 for (; b < end; b++) {
789 dfield_t* dfield;
790 ulint local_len;
791
792 dfield = dtuple_get_nth_field(entry, b->field_no);
793 local_len = dfield_get_len(dfield);
794
795 ut_ad(dfield_is_ext(dfield));
796 ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
797
798 local_len -= BTR_EXTERN_FIELD_REF_SIZE;
799
800 /* Only in REDUNDANT and COMPACT format, we store
801 up to DICT_ANTELOPE_MAX_INDEX_COL_LEN (768) bytes
802 locally */
803 ut_ad(local_len <= DICT_ANTELOPE_MAX_INDEX_COL_LEN);
804
805 dfield_set_data(dfield,
806 (char*) b->data - local_len,
807 b->len + local_len);
808 }
809
810 mem_heap_free(vector->heap);
811}
812
813/** Allocate a big_rec_t object in the given memory heap, and for storing
814n_fld number of fields.
815@param[in] heap memory heap in which this object is allocated
816@param[in] n_fld maximum number of fields that can be stored in
817 this object
818
819@return the allocated object */
820big_rec_t*
821big_rec_t::alloc(
822 mem_heap_t* heap,
823 ulint n_fld)
824{
825 big_rec_t* rec = static_cast<big_rec_t*>(
826 mem_heap_alloc(heap, sizeof(big_rec_t)));
827
828 new(rec) big_rec_t(n_fld);
829
830 rec->heap = heap;
831 rec->fields = static_cast<big_rec_field_t*>(
832 mem_heap_alloc(heap,
833 n_fld * sizeof(big_rec_field_t)));
834
835 rec->n_fields = 0;
836 return(rec);
837}
838
839/** Create a deep copy of this object.
840@param[in,out] heap memory heap in which the clone will be created
841@return the cloned object */
842dfield_t*
843dfield_t::clone(mem_heap_t* heap) const
844{
845 const ulint size = len == UNIV_SQL_NULL ? 0 : len;
846 dfield_t* obj = static_cast<dfield_t*>(
847 mem_heap_alloc(heap, sizeof(dfield_t) + size));
848
849 ut_ad(len != UNIV_SQL_DEFAULT);
850 obj->ext = ext;
851 obj->len = len;
852 obj->type = type;
853 obj->spatial_status = spatial_status;
854
855 if (len != UNIV_SQL_NULL) {
856 obj->data = obj + 1;
857 memcpy(obj->data, data, len);
858 } else {
859 obj->data = 0;
860 }
861
862 return(obj);
863}
864