1
/*****************************************************************************
3
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
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.
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.
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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/********************************************************************//**
20
@file data/data0data.c
21
SQL data field and tuple
23
Created 5/30/1994 Heikki Tuuri
24
*************************************************************************/
26
#include "data0data.h"
29
#include "data0data.ic"
32
#ifndef UNIV_HOTBACKUP
35
#include "page0page.h"
37
#include "dict0dict.h"
41
#endif /* !UNIV_HOTBACKUP */
44
/** Dummy variable to catch access to uninitialized fields. In the
45
debug version, dtuple_create() will make all fields of dtuple_t point
47
UNIV_INTERN byte data_error;
49
# ifndef UNIV_DEBUG_VALGRIND
50
/** this is used to fool the compiler in dtuple_validate */
51
UNIV_INTERN ulint data_dummy;
52
# endif /* !UNIV_DEBUG_VALGRIND */
53
#endif /* UNIV_DEBUG */
55
#ifndef UNIV_HOTBACKUP
56
/*********************************************************************//**
57
Tests if dfield data length and content is equal to the given.
58
@return TRUE if equal */
61
dfield_data_is_binary_equal(
62
/*========================*/
63
const dfield_t* field, /*!< in: field */
64
ulint len, /*!< in: data length or UNIV_SQL_NULL */
65
const byte* data) /*!< in: data */
67
if (len != dfield_get_len(field)) {
72
if (len == UNIV_SQL_NULL) {
77
if (0 != memcmp(dfield_get_data(field), data, len)) {
85
/************************************************************//**
86
Compare two data tuples, respecting the collation of character fields.
87
@return 1, 0 , -1 if tuple1 is greater, equal, less, respectively,
93
const dtuple_t* tuple1, /*!< in: tuple 1 */
94
const dtuple_t* tuple2) /*!< in: tuple 2 */
99
ut_ad(tuple1 && tuple2);
100
ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
101
ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
102
ut_ad(dtuple_check_typed(tuple1));
103
ut_ad(dtuple_check_typed(tuple2));
105
n_fields = dtuple_get_n_fields(tuple1);
107
if (n_fields != dtuple_get_n_fields(tuple2)) {
109
return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
112
for (i = 0; i < n_fields; i++) {
114
const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
115
const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
117
cmp = cmp_dfield_dfield(field1, field2);
127
/*********************************************************************//**
128
Sets number of fields used in a tuple. Normally this is set in
129
dtuple_create, but if you want later to set it smaller, you can use this. */
134
dtuple_t* tuple, /*!< in: tuple */
135
ulint n_fields) /*!< in: number of fields */
139
tuple->n_fields = n_fields;
140
tuple->n_fields_cmp = n_fields;
143
/**********************************************************//**
144
Checks that a data field is typed.
145
@return TRUE if ok */
148
dfield_check_typed_no_assert(
149
/*=========================*/
150
const dfield_t* field) /*!< in: data field */
152
if (dfield_get_type(field)->mtype > DATA_MYSQL
153
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
156
"InnoDB: Error: data field type %lu, len %lu\n",
157
(ulong) dfield_get_type(field)->mtype,
158
(ulong) dfield_get_len(field));
165
/**********************************************************//**
166
Checks that a data tuple is typed.
167
@return TRUE if ok */
170
dtuple_check_typed_no_assert(
171
/*=========================*/
172
const dtuple_t* tuple) /*!< in: tuple */
174
const dfield_t* field;
177
if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
179
"InnoDB: Error: index entry has %lu fields\n",
180
(ulong) dtuple_get_n_fields(tuple));
182
fputs("InnoDB: Tuple contents: ", stderr);
183
dtuple_print(stderr, tuple);
189
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
191
field = dtuple_get_nth_field(tuple, i);
193
if (!dfield_check_typed_no_assert(field)) {
200
#endif /* !UNIV_HOTBACKUP */
203
/**********************************************************//**
204
Checks that a data field is typed. Asserts an error if not.
205
@return TRUE if ok */
210
const dfield_t* field) /*!< in: data field */
212
if (dfield_get_type(field)->mtype > DATA_MYSQL
213
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
216
"InnoDB: Error: data field type %lu, len %lu\n",
217
(ulong) dfield_get_type(field)->mtype,
218
(ulong) dfield_get_len(field));
226
/**********************************************************//**
227
Checks that a data tuple is typed. Asserts an error if not.
228
@return TRUE if ok */
233
const dtuple_t* tuple) /*!< in: tuple */
235
const dfield_t* field;
238
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
240
field = dtuple_get_nth_field(tuple, i);
242
ut_a(dfield_check_typed(field));
248
/**********************************************************//**
249
Validates the consistency of a tuple which must be complete, i.e,
250
all fields must have been set.
251
@return TRUE if ok */
256
const dtuple_t* tuple) /*!< in: tuple */
258
const dfield_t* field;
263
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
265
n_fields = dtuple_get_n_fields(tuple);
267
/* We dereference all the data of each field to test
270
for (i = 0; i < n_fields; i++) {
272
field = dtuple_get_nth_field(tuple, i);
273
len = dfield_get_len(field);
275
if (!dfield_is_null(field)) {
277
const byte* data = dfield_get_data(field);
278
#ifndef UNIV_DEBUG_VALGRIND
281
for (j = 0; j < len; j++) {
283
data_dummy += *data; /* fool the compiler not
288
#endif /* !UNIV_DEBUG_VALGRIND */
290
UNIV_MEM_ASSERT_RW(data, len);
294
ut_a(dtuple_check_typed(tuple));
298
#endif /* UNIV_DEBUG */
300
#ifndef UNIV_HOTBACKUP
301
/*************************************************************//**
302
Pretty prints a dfield value according to its data type. */
307
const dfield_t* dfield) /*!< in: dfield */
313
len = dfield_get_len(dfield);
314
data = dfield_get_data(dfield);
316
if (dfield_is_null(dfield)) {
317
fputs("NULL", stderr);
322
switch (dtype_get_mtype(dfield_get_type(dfield))) {
325
for (i = 0; i < len; i++) {
327
putc(isprint(c) ? c : ' ', stderr);
330
if (dfield_is_ext(dfield)) {
331
fputs("(external)", stderr);
335
ut_a(len == 4); /* only works for 32-bit integers */
336
fprintf(stderr, "%d", (int)mach_read_from_4(data));
343
/*************************************************************//**
344
Pretty prints a dfield value according to its data type. Also the hex string
345
is printed if a string contains non-printable characters. */
348
dfield_print_also_hex(
349
/*==================*/
350
const dfield_t* dfield) /*!< in: dfield */
356
ibool print_also_hex;
358
len = dfield_get_len(dfield);
359
data = dfield_get_data(dfield);
361
if (dfield_is_null(dfield)) {
362
fputs("NULL", stderr);
367
prtype = dtype_get_prtype(dfield_get_type(dfield));
369
switch (dtype_get_mtype(dfield_get_type(dfield))) {
375
val = mach_read_from_1(data);
377
if (!(prtype & DATA_UNSIGNED)) {
379
fprintf(stderr, "%ld", (long) val);
381
fprintf(stderr, "%lu", (ulong) val);
386
val = mach_read_from_2(data);
388
if (!(prtype & DATA_UNSIGNED)) {
390
fprintf(stderr, "%ld", (long) val);
392
fprintf(stderr, "%lu", (ulong) val);
397
val = mach_read_from_3(data);
399
if (!(prtype & DATA_UNSIGNED)) {
401
fprintf(stderr, "%ld", (long) val);
403
fprintf(stderr, "%lu", (ulong) val);
408
val = mach_read_from_4(data);
410
if (!(prtype & DATA_UNSIGNED)) {
412
fprintf(stderr, "%ld", (long) val);
414
fprintf(stderr, "%lu", (ulong) val);
419
id = mach_read_from_6(data);
420
fprintf(stderr, "{%lu %lu}",
421
ut_dulint_get_high(id),
422
ut_dulint_get_low(id));
426
id = mach_read_from_7(data);
427
fprintf(stderr, "{%lu %lu}",
428
ut_dulint_get_high(id),
429
ut_dulint_get_low(id));
432
id = mach_read_from_8(data);
433
fprintf(stderr, "{%lu %lu}",
434
ut_dulint_get_high(id),
435
ut_dulint_get_low(id));
443
switch (prtype & DATA_SYS_PRTYPE_MASK) {
445
id = mach_read_from_6(data);
447
fprintf(stderr, "trx_id " TRX_ID_FMT,
448
TRX_ID_PREP_PRINTF(id));
452
id = mach_read_from_7(data);
454
fprintf(stderr, "roll_ptr {%lu %lu}",
455
ut_dulint_get_high(id), ut_dulint_get_low(id));
459
id = mach_read_from_6(data);
461
fprintf(stderr, "row_id {%lu %lu}",
462
ut_dulint_get_high(id), ut_dulint_get_low(id));
466
id = mach_dulint_read_compressed(data);
468
fprintf(stderr, "mix_id {%lu %lu}",
469
ut_dulint_get_high(id), ut_dulint_get_low(id));
475
print_also_hex = FALSE;
477
for (i = 0; i < len; i++) {
481
print_also_hex = TRUE;
483
fprintf(stderr, "\\x%02x", (unsigned char) c);
489
if (dfield_is_ext(dfield)) {
490
fputs("(external)", stderr);
493
if (!print_also_hex) {
497
data = dfield_get_data(dfield);
503
fputs(" Hex: ",stderr);
505
for (i = 0; i < len; i++) {
506
fprintf(stderr, "%02lx", (ulint) *data++);
509
if (dfield_is_ext(dfield)) {
510
fputs("(external)", stderr);
515
/*************************************************************//**
516
Print a dfield value using ut_print_buf. */
521
FILE* f, /*!< in: output stream */
522
const dfield_t* dfield) /*!< in: dfield */
524
ulint len = dfield_get_len(dfield);
525
if (!dfield_is_null(dfield)) {
526
ulint print_len = ut_min(len, 1000);
527
ut_print_buf(f, dfield_get_data(dfield), print_len);
528
if (len != print_len) {
529
fprintf(f, "(total %lu bytes%s)",
531
dfield_is_ext(dfield) ? ", external" : "");
534
fputs(" SQL NULL", f);
538
/**********************************************************//**
539
The following function prints the contents of a tuple. */
544
FILE* f, /*!< in: output stream */
545
const dtuple_t* tuple) /*!< in: tuple */
550
n_fields = dtuple_get_n_fields(tuple);
552
fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
554
for (i = 0; i < n_fields; i++) {
555
fprintf(f, " %lu:", (ulong) i);
557
dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
563
ut_ad(dtuple_validate(tuple));
566
/**************************************************************//**
567
Moves parts of long fields in entry to the big record vector so that
568
the size of tuple drops below the maximum record size allowed in the
569
database. Moves data only from those fields which are not necessary
570
to determine uniquely the insertion place of the tuple in the index.
571
@return own: created big record vector, NULL if we are not able to
572
shorten the entry enough, i.e., if there are too many fixed-length or
573
short fields in entry or the index is clustered */
576
dtuple_convert_big_rec(
577
/*===================*/
578
dict_index_t* index, /*!< in: index */
579
dtuple_t* entry, /*!< in/out: index entry */
580
ulint* n_ext) /*!< in/out: number of
581
externally stored columns */
586
dict_field_t* ifield;
590
ulint local_prefix_len;
592
if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
596
if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
597
/* up to MySQL 5.1: store a 768-byte prefix locally */
598
local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
600
/* new-format table: do not store any BLOB prefix locally */
601
local_len = BTR_EXTERN_FIELD_REF_SIZE;
604
ut_a(dtuple_check_typed_no_assert(entry));
606
size = rec_get_converted_size(index, entry, *n_ext);
608
if (UNIV_UNLIKELY(size > 1000000000)) {
610
"InnoDB: Warning: tuple size very big: %lu\n",
612
fputs("InnoDB: Tuple contents: ", stderr);
613
dtuple_print(stderr, entry);
617
heap = mem_heap_create(size + dtuple_get_n_fields(entry)
618
* sizeof(big_rec_field_t) + 1000);
620
vector = mem_heap_alloc(heap, sizeof(big_rec_t));
623
vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
624
* sizeof(big_rec_field_t));
626
/* Decide which fields to shorten: the algorithm is to look for
627
a variable-length field that yields the biggest savings when
632
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
634
dict_table_is_comp(index->table),
635
dict_index_get_n_fields(index),
636
dict_table_zip_size(index->table))) {
639
ulint longest_i = ULINT_MAX;
643
for (i = dict_index_get_n_unique_in_tree(index);
644
i < dtuple_get_n_fields(entry); i++) {
647
dfield = dtuple_get_nth_field(entry, i);
648
ifield = dict_index_get_nth_field(index, i);
650
/* Skip fixed-length, NULL, externally stored,
653
if (ifield->fixed_len
654
|| dfield_is_null(dfield)
655
|| dfield_is_ext(dfield)
656
|| dfield_get_len(dfield) <= local_len
657
|| dfield_get_len(dfield)
658
<= BTR_EXTERN_FIELD_REF_SIZE * 2) {
662
savings = dfield_get_len(dfield) - local_len;
664
/* Check that there would be savings */
665
if (longest >= savings) {
677
/* Cannot shorten more */
684
/* Move data from field longest_i to big rec vector.
686
We store the first bytes locally to the record. Then
687
we can calculate all ordering fields in all indexes
688
from locally stored data. */
690
dfield = dtuple_get_nth_field(entry, longest_i);
691
ifield = dict_index_get_nth_field(index, longest_i);
692
local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
694
b = &vector->fields[n_fields];
695
b->field_no = longest_i;
696
b->len = dfield_get_len(dfield) - local_prefix_len;
697
b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
699
/* Allocate the locally stored part of the column. */
700
data = mem_heap_alloc(heap, local_len);
702
/* Copy the local prefix. */
703
memcpy(data, dfield_get_data(dfield), local_prefix_len);
704
/* Clear the extern field reference (BLOB pointer). */
705
memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
707
/* The following would fail the Valgrind checks in
708
page_cur_insert_rec_low() and page_cur_insert_rec_zip().
709
The BLOB pointers in the record will be initialized after
710
the record and the BLOBs have been written. */
711
UNIV_MEM_ALLOC(data + local_prefix_len,
712
BTR_EXTERN_FIELD_REF_SIZE);
715
dfield_set_data(dfield, data, local_len);
716
dfield_set_ext(dfield);
720
ut_ad(n_fields < dtuple_get_n_fields(entry));
723
vector->n_fields = n_fields;
727
/**************************************************************//**
728
Puts back to entry the data stored in vector. Note that to ensure the
729
fields in entry can accommodate the data, vector must have been created
730
from entry with dtuple_convert_big_rec. */
733
dtuple_convert_back_big_rec(
734
/*========================*/
735
dict_index_t* index __attribute__((unused)), /*!< in: index */
736
dtuple_t* entry, /*!< in: entry whose data was put to vector */
737
big_rec_t* vector) /*!< in, own: big rec vector; it is
738
freed in this function */
740
big_rec_field_t* b = vector->fields;
741
const big_rec_field_t* const end = b + vector->n_fields;
743
for (; b < end; b++) {
747
dfield = dtuple_get_nth_field(entry, b->field_no);
748
local_len = dfield_get_len(dfield);
750
ut_ad(dfield_is_ext(dfield));
751
ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
753
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
755
ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
757
dfield_set_data(dfield,
758
(char*) b->data - local_len,
762
mem_heap_free(vector->heap);
764
#endif /* !UNIV_HOTBACKUP */