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
SQL data field and tuple
22
Created 5/30/1994 Heikki Tuuri
23
*************************************************************************/
25
#include "data0data.h"
28
#include "data0data.ic"
31
#ifndef UNIV_HOTBACKUP
34
#include "page0page.h"
36
#include "dict0dict.h"
40
#endif /* !UNIV_HOTBACKUP */
43
/* data pointers of tuple fields are initialized to point here
45
UNIV_INTERN byte data_error;
47
# ifndef UNIV_DEBUG_VALGRIND
48
/* this is used to fool the compiler in dtuple_validate */
49
UNIV_INTERN ulint data_dummy;
50
# endif /* !UNIV_DEBUG_VALGRIND */
51
#endif /* UNIV_DEBUG */
53
#ifndef UNIV_HOTBACKUP
54
/*************************************************************************
55
Reset dfield variables. */
63
# ifndef UNIV_DEBUG_VALGRIND
65
# endif /* !UNIV_DEBUG_VALGRIND */
66
#endif /* UNIV_DEBUG */
69
/*************************************************************************
70
Tests if dfield data length and content is equal to the given. */
73
dfield_data_is_binary_equal(
74
/*========================*/
75
/* out: TRUE if equal */
76
const dfield_t* field, /* in: field */
77
ulint len, /* in: data length or UNIV_SQL_NULL */
78
const byte* data) /* in: data */
80
if (len != dfield_get_len(field)) {
85
if (len == UNIV_SQL_NULL) {
90
if (0 != memcmp(dfield_get_data(field), data, len)) {
98
/****************************************************************
99
Compare two data tuples, respecting the collation of character fields. */
104
/* out: 1, 0 , -1 if tuple1 is greater, equal,
105
less, respectively, than tuple2 */
106
void* cmp_ctx,/* in: client compare context */
107
const dtuple_t* tuple1, /* in: tuple 1 */
108
const dtuple_t* tuple2) /* in: tuple 2 */
113
ut_ad(tuple1 && tuple2);
114
ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
115
ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
116
ut_ad(dtuple_check_typed(tuple1));
117
ut_ad(dtuple_check_typed(tuple2));
119
n_fields = dtuple_get_n_fields(tuple1);
121
if (n_fields != dtuple_get_n_fields(tuple2)) {
123
return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
126
for (i = 0; i < n_fields; i++) {
128
const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
129
const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
131
cmp = cmp_dfield_dfield(cmp_ctx, field1, field2);
141
/*************************************************************************
142
Sets number of fields used in a tuple. Normally this is set in
143
dtuple_create, but if you want later to set it smaller, you can use this. */
148
dtuple_t* tuple, /* in: tuple */
149
ulint n_fields) /* in: number of fields */
153
tuple->n_fields = n_fields;
154
tuple->n_fields_cmp = n_fields;
157
/**************************************************************
158
Checks that a data field is typed. */
161
dfield_check_typed_no_assert(
162
/*=========================*/
163
/* out: TRUE if ok */
164
const dfield_t* field) /* in: data field */
166
if (dfield_get_type(field)->mtype > DATA_CLIENT
167
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
170
"InnoDB: Error: data field type %lu, len %lu\n",
171
(ulong) dfield_get_type(field)->mtype,
172
(ulong) dfield_get_len(field));
179
/**************************************************************
180
Checks that a data tuple is typed. */
183
dtuple_check_typed_no_assert(
184
/*=========================*/
185
/* out: TRUE if ok */
186
const dtuple_t* tuple) /* in: tuple */
188
const dfield_t* field;
191
if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
193
"InnoDB: Error: index entry has %lu fields\n",
194
(ulong) dtuple_get_n_fields(tuple));
196
fputs("InnoDB: Tuple contents: ", stderr);
197
dtuple_print(stderr, tuple);
203
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
205
field = dtuple_get_nth_field(tuple, i);
207
if (!dfield_check_typed_no_assert(field)) {
214
#endif /* !UNIV_HOTBACKUP */
217
/**************************************************************
218
Checks that a data field is typed. Asserts an error if not. */
223
/* out: TRUE if ok */
224
const dfield_t* field) /* in: data field */
226
if (dfield_get_type(field)->mtype > DATA_CLIENT
227
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
230
"InnoDB: Error: data field type %lu, len %lu\n",
231
(ulong) dfield_get_type(field)->mtype,
232
(ulong) dfield_get_len(field));
240
/**************************************************************
241
Checks that a data tuple is typed. Asserts an error if not. */
246
/* out: TRUE if ok */
247
const dtuple_t* tuple) /* in: tuple */
249
const dfield_t* field;
252
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
254
field = dtuple_get_nth_field(tuple, i);
256
ut_a(dfield_check_typed(field));
262
/**************************************************************
263
Validates the consistency of a tuple which must be complete, i.e,
264
all fields must have been set. */
269
/* out: TRUE if ok */
270
const dtuple_t* tuple) /* in: tuple */
272
const dfield_t* field;
277
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
279
n_fields = dtuple_get_n_fields(tuple);
281
/* We dereference all the data of each field to test
284
for (i = 0; i < n_fields; i++) {
286
field = dtuple_get_nth_field(tuple, i);
287
len = dfield_get_len(field);
289
if (!dfield_is_null(field)) {
291
const byte* data = dfield_get_data(field);
292
#ifndef UNIV_DEBUG_VALGRIND
295
for (j = 0; j < len; j++) {
297
data_dummy += *data; /* fool the compiler not
302
#endif /* !UNIV_DEBUG_VALGRIND */
304
UNIV_MEM_ASSERT_RW(data, len);
308
ut_a(dtuple_check_typed(tuple));
312
#endif /* UNIV_DEBUG */
314
#ifndef UNIV_HOTBACKUP
315
/*****************************************************************
316
Pretty prints a dfield value according to its data type. */
321
const dfield_t* dfield) /* in: dfield */
327
len = dfield_get_len(dfield);
328
data = dfield_get_data(dfield);
330
if (dfield_is_null(dfield)) {
331
fputs("NULL", stderr);
336
switch (dtype_get_mtype(dfield_get_type(dfield))) {
339
for (i = 0; i < len; i++) {
341
putc(isprint(c) ? c : ' ', stderr);
344
if (dfield_is_ext(dfield)) {
345
fputs("(external)", stderr);
349
ut_a(len == 4); /* only works for 32-bit integers */
350
fprintf(stderr, "%d", (int)mach_read_from_4(data));
357
/*****************************************************************
358
Pretty prints a dfield value according to its data type. Also the hex string
359
is printed if a string contains non-printable characters. */
362
dfield_print_also_hex(
363
/*==================*/
364
const dfield_t* dfield) /* in: dfield */
370
ibool print_also_hex;
372
len = dfield_get_len(dfield);
373
data = dfield_get_data(dfield);
375
if (dfield_is_null(dfield)) {
376
fputs("NULL", stderr);
381
prtype = dtype_get_prtype(dfield_get_type(dfield));
383
switch (dtype_get_mtype(dfield_get_type(dfield))) {
389
val = mach_read_from_1(data);
391
if (!(prtype & DATA_UNSIGNED)) {
393
fprintf(stderr, "%ld", (long) val);
395
fprintf(stderr, "%lu", (ulong) val);
400
val = mach_read_from_2(data);
402
if (!(prtype & DATA_UNSIGNED)) {
404
fprintf(stderr, "%ld", (long) val);
406
fprintf(stderr, "%lu", (ulong) val);
411
val = mach_read_from_3(data);
413
if (!(prtype & DATA_UNSIGNED)) {
415
fprintf(stderr, "%ld", (long) val);
417
fprintf(stderr, "%lu", (ulong) val);
422
val = mach_read_from_4(data);
424
if (!(prtype & DATA_UNSIGNED)) {
426
fprintf(stderr, "%ld", (long) val);
428
fprintf(stderr, "%lu", (ulong) val);
433
id = mach_read_from_6(data);
434
fprintf(stderr, "{%lu %lu}",
435
ut_dulint_get_high(id),
436
ut_dulint_get_low(id));
440
id = mach_read_from_7(data);
441
fprintf(stderr, "{%lu %lu}",
442
ut_dulint_get_high(id),
443
ut_dulint_get_low(id));
446
id = mach_read_from_8(data);
447
fprintf(stderr, "{%lu %lu}",
448
ut_dulint_get_high(id),
449
ut_dulint_get_low(id));
457
switch (prtype & DATA_SYS_PRTYPE_MASK) {
459
id = mach_read_from_6(data);
461
fprintf(stderr, "trx_id " TRX_ID_FMT,
462
TRX_ID_PREP_PRINTF(id));
466
id = mach_read_from_7(data);
468
fprintf(stderr, "roll_ptr {%lu %lu}",
469
ut_dulint_get_high(id), ut_dulint_get_low(id));
473
id = mach_read_from_6(data);
475
fprintf(stderr, "row_id {%lu %lu}",
476
ut_dulint_get_high(id), ut_dulint_get_low(id));
480
id = mach_dulint_read_compressed(data);
482
fprintf(stderr, "mix_id {%lu %lu}",
483
ut_dulint_get_high(id), ut_dulint_get_low(id));
489
print_also_hex = FALSE;
491
for (i = 0; i < len; i++) {
495
print_also_hex = TRUE;
497
fprintf(stderr, "\\x%02x", (unsigned char) c);
503
if (dfield_is_ext(dfield)) {
504
fputs("(external)", stderr);
507
if (!print_also_hex) {
511
data = dfield_get_data(dfield);
517
fputs(" Hex: ",stderr);
519
for (i = 0; i < len; i++) {
520
fprintf(stderr, "%02lx", (ulint) *data++);
523
if (dfield_is_ext(dfield)) {
524
fputs("(external)", stderr);
529
/*****************************************************************
530
Print a dfield value using ut_print_buf. */
535
FILE* f, /* in: output stream */
536
const dfield_t* dfield) /* in: dfield */
538
ulint len = dfield_get_len(dfield);
539
if (!dfield_is_null(dfield)) {
540
ulint print_len = ut_min(len, 1000);
541
ut_print_buf(f, dfield_get_data(dfield), print_len);
542
if (len != print_len) {
543
fprintf(f, "(total %lu bytes%s)",
545
dfield_is_ext(dfield) ? ", external" : "");
548
fputs(" SQL NULL", f);
552
/**************************************************************
553
The following function prints the contents of a tuple. */
558
FILE* f, /* in: output stream */
559
const dtuple_t* tuple) /* in: tuple */
564
n_fields = dtuple_get_n_fields(tuple);
566
fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
568
for (i = 0; i < n_fields; i++) {
569
fprintf(f, " %lu:", (ulong) i);
571
dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
577
ut_ad(dtuple_validate(tuple));
580
/******************************************************************
581
Moves parts of long fields in entry to the big record vector so that
582
the size of tuple drops below the maximum record size allowed in the
583
database. Moves data only from those fields which are not necessary
584
to determine uniquely the insertion place of the tuple in the index. */
587
dtuple_convert_big_rec(
588
/*===================*/
589
/* out, own: created big record vector,
590
NULL if we are not able to shorten
591
the entry enough, i.e., if there are
592
too many fixed-length or short fields
593
in entry or the index is clustered */
594
dict_index_t* index, /* in: index */
595
dtuple_t* entry, /* in/out: index entry */
596
ulint* n_ext) /* in/out: number of
597
externally stored columns */
602
dict_field_t* ifield;
606
ulint local_prefix_len;
608
if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
612
if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
613
/* up to v5.1: store a 768-byte prefix locally */
614
local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
616
/* new-format table: do not store any BLOB prefix locally */
617
local_len = BTR_EXTERN_FIELD_REF_SIZE;
620
ut_a(dtuple_check_typed_no_assert(entry));
622
size = rec_get_converted_size(index, entry, *n_ext);
624
if (UNIV_UNLIKELY(size > 1000000000)) {
626
"InnoDB: Warning: tuple size very big: %lu\n",
628
fputs("InnoDB: Tuple contents: ", stderr);
629
dtuple_print(stderr, entry);
633
heap = mem_heap_create(size + dtuple_get_n_fields(entry)
634
* sizeof(big_rec_field_t) + 1000);
636
vector = mem_heap_alloc(heap, sizeof(big_rec_t));
639
vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
640
* sizeof(big_rec_field_t));
642
/* Decide which fields to shorten: the algorithm is to look for
643
a variable-length field that yields the biggest savings when
648
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
650
dict_table_is_comp(index->table),
651
dict_index_get_n_fields(index),
652
dict_table_zip_size(index->table))) {
655
ulint longest_i = ULINT_MAX;
659
for (i = dict_index_get_n_unique_in_tree(index);
660
i < dtuple_get_n_fields(entry); i++) {
663
dfield = dtuple_get_nth_field(entry, i);
664
ifield = dict_index_get_nth_field(index, i);
666
/* Skip fixed-length, NULL, externally stored,
669
if (ifield->fixed_len
670
|| dfield_is_null(dfield)
671
|| dfield_is_ext(dfield)
672
|| dfield_get_len(dfield) <= local_len
673
|| dfield_get_len(dfield)
674
<= BTR_EXTERN_FIELD_REF_SIZE * 2) {
678
savings = dfield_get_len(dfield) - local_len;
680
/* Check that there would be savings */
681
if (longest >= savings) {
693
/* Cannot shorten more */
700
/* Move data from field longest_i to big rec vector.
702
We store the first bytes locally to the record. Then
703
we can calculate all ordering fields in all indexes
704
from locally stored data. */
706
dfield = dtuple_get_nth_field(entry, longest_i);
707
ifield = dict_index_get_nth_field(index, longest_i);
708
local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
710
b = &vector->fields[n_fields];
711
b->field_no = longest_i;
712
b->len = dfield_get_len(dfield) - local_prefix_len;
713
b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
715
/* Allocate the locally stored part of the column. */
716
data = mem_heap_alloc(heap, local_len);
718
/* Copy the local prefix. */
719
memcpy(data, dfield_get_data(dfield), local_prefix_len);
720
/* Clear the extern field reference (BLOB pointer). */
721
memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
723
/* The following would fail the Valgrind checks in
724
page_cur_insert_rec_low() and page_cur_insert_rec_zip().
725
The BLOB pointers in the record will be initialized after
726
the record and the BLOBs have been written. */
727
UNIV_MEM_ALLOC(data + local_prefix_len,
728
BTR_EXTERN_FIELD_REF_SIZE);
731
dfield_set_data(dfield, data, local_len);
732
dfield_set_ext(dfield);
736
ut_ad(n_fields < dtuple_get_n_fields(entry));
739
vector->n_fields = n_fields;
743
/******************************************************************
744
Puts back to entry the data stored in vector. Note that to ensure the
745
fields in entry can accommodate the data, vector must have been created
746
from entry with dtuple_convert_big_rec. */
749
dtuple_convert_back_big_rec(
750
/*========================*/
751
dict_index_t* index __attribute__((unused)), /* in: index */
752
dtuple_t* entry, /* in: entry whose data was put to vector */
753
big_rec_t* vector) /* in, own: big rec vector; it is
754
freed in this function */
756
big_rec_field_t* b = vector->fields;
757
const big_rec_field_t* const end = b + vector->n_fields;
759
for (; b < end; b++) {
763
dfield = dtuple_get_nth_field(entry, b->field_no);
764
local_len = dfield_get_len(dfield);
766
ut_ad(dfield_is_ext(dfield));
767
ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
769
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
771
ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
773
dfield_set_data(dfield,
774
(char*) b->data - local_len,
778
mem_heap_free(vector->heap);
780
#endif /* !UNIV_HOTBACKUP */