1
/************************************************************************
2
SQL data field and tuple
4
(c) 1994-1996 Innobase Oy
6
Created 5/30/1994 Heikki Tuuri
7
*************************************************************************/
12
#include "data0data.ic"
17
#include "page0page.h"
19
#include "dict0dict.h"
25
/* data pointers of tuple fields are initialized to point here
27
UNIV_INTERN byte data_error;
29
/* this is used to fool the compiler in dtuple_validate */
30
UNIV_INTERN ulint data_dummy;
31
#endif /* UNIV_DEBUG */
33
/*************************************************************************
34
Tests if dfield data length and content is equal to the given. */
37
dfield_data_is_binary_equal(
38
/*========================*/
39
/* out: TRUE if equal */
40
const dfield_t* field, /* in: field */
41
ulint len, /* in: data length or UNIV_SQL_NULL */
42
const byte* data) /* in: data */
44
if (len != dfield_get_len(field)) {
49
if (len == UNIV_SQL_NULL) {
54
if (0 != memcmp(dfield_get_data(field), data, len)) {
62
/****************************************************************
63
Compare two data tuples, respecting the collation of character fields. */
68
/* out: 1, 0 , -1 if tuple1 is greater, equal,
69
less, respectively, than tuple2 */
70
const dtuple_t* tuple1, /* in: tuple 1 */
71
const dtuple_t* tuple2) /* in: tuple 2 */
76
ut_ad(tuple1 && tuple2);
77
ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
78
ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
79
ut_ad(dtuple_check_typed(tuple1));
80
ut_ad(dtuple_check_typed(tuple2));
82
n_fields = dtuple_get_n_fields(tuple1);
84
if (n_fields != dtuple_get_n_fields(tuple2)) {
86
return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
89
for (i = 0; i < n_fields; i++) {
91
const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
92
const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
94
cmp = cmp_dfield_dfield(field1, field2);
104
/*************************************************************************
105
Sets number of fields used in a tuple. Normally this is set in
106
dtuple_create, but if you want later to set it smaller, you can use this. */
111
dtuple_t* tuple, /* in: tuple */
112
ulint n_fields) /* in: number of fields */
116
tuple->n_fields = n_fields;
117
tuple->n_fields_cmp = n_fields;
120
/**************************************************************
121
Checks that a data field is typed. */
124
dfield_check_typed_no_assert(
125
/*=========================*/
126
/* out: TRUE if ok */
127
const dfield_t* field) /* in: data field */
129
if (dfield_get_type(field)->mtype > DATA_MYSQL
130
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
133
"InnoDB: Error: data field type %lu, len %lu\n",
134
(ulong) dfield_get_type(field)->mtype,
135
(ulong) dfield_get_len(field));
142
/**************************************************************
143
Checks that a data tuple is typed. */
146
dtuple_check_typed_no_assert(
147
/*=========================*/
148
/* out: TRUE if ok */
149
const dtuple_t* tuple) /* in: tuple */
151
const dfield_t* field;
154
if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
156
"InnoDB: Error: index entry has %lu fields\n",
157
(ulong) dtuple_get_n_fields(tuple));
159
fputs("InnoDB: Tuple contents: ", stderr);
160
dtuple_print(stderr, tuple);
166
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
168
field = dtuple_get_nth_field(tuple, i);
170
if (!dfield_check_typed_no_assert(field)) {
178
/**************************************************************
179
Checks that a data field is typed. Asserts an error if not. */
184
/* out: TRUE if ok */
185
const dfield_t* field) /* in: data field */
187
if (dfield_get_type(field)->mtype > DATA_MYSQL
188
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
191
"InnoDB: Error: data field type %lu, len %lu\n",
192
(ulong) dfield_get_type(field)->mtype,
193
(ulong) dfield_get_len(field));
201
/**************************************************************
202
Checks that a data tuple is typed. Asserts an error if not. */
207
/* out: TRUE if ok */
208
const dtuple_t* tuple) /* in: tuple */
210
const dfield_t* field;
213
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
215
field = dtuple_get_nth_field(tuple, i);
217
ut_a(dfield_check_typed(field));
224
/**************************************************************
225
Validates the consistency of a tuple which must be complete, i.e,
226
all fields must have been set. */
231
/* out: TRUE if ok */
232
const dtuple_t* tuple) /* in: tuple */
234
const dfield_t* field;
241
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
243
n_fields = dtuple_get_n_fields(tuple);
245
/* We dereference all the data of each field to test
248
for (i = 0; i < n_fields; i++) {
250
field = dtuple_get_nth_field(tuple, i);
251
len = dfield_get_len(field);
253
if (!dfield_is_null(field)) {
255
data = dfield_get_data(field);
256
UNIV_MEM_ASSERT_RW(data, len);
258
for (j = 0; j < len; j++) {
260
data_dummy += *data; /* fool the compiler not
268
ut_a(dtuple_check_typed(tuple));
272
#endif /* UNIV_DEBUG */
274
/*****************************************************************
275
Pretty prints a dfield value according to its data type. */
280
const dfield_t* dfield) /* in: dfield */
286
len = dfield_get_len(dfield);
287
data = dfield_get_data(dfield);
289
if (dfield_is_null(dfield)) {
290
fputs("NULL", stderr);
295
switch (dtype_get_mtype(dfield_get_type(dfield))) {
298
for (i = 0; i < len; i++) {
300
putc(isprint(c) ? c : ' ', stderr);
303
if (dfield_is_ext(dfield)) {
304
fputs("(external)", stderr);
308
ut_a(len == 4); /* only works for 32-bit integers */
309
fprintf(stderr, "%d", (int)mach_read_from_4(data));
316
/*****************************************************************
317
Pretty prints a dfield value according to its data type. Also the hex string
318
is printed if a string contains non-printable characters. */
321
dfield_print_also_hex(
322
/*==================*/
323
const dfield_t* dfield) /* in: dfield */
329
ibool print_also_hex;
331
len = dfield_get_len(dfield);
332
data = dfield_get_data(dfield);
334
if (dfield_is_null(dfield)) {
335
fputs("NULL", stderr);
340
prtype = dtype_get_prtype(dfield_get_type(dfield));
342
switch (dtype_get_mtype(dfield_get_type(dfield))) {
348
val = mach_read_from_1(data);
350
if (!(prtype & DATA_UNSIGNED)) {
352
fprintf(stderr, "%ld", (long) val);
354
fprintf(stderr, "%lu", (ulong) val);
359
val = mach_read_from_2(data);
361
if (!(prtype & DATA_UNSIGNED)) {
363
fprintf(stderr, "%ld", (long) val);
365
fprintf(stderr, "%lu", (ulong) val);
370
val = mach_read_from_3(data);
372
if (!(prtype & DATA_UNSIGNED)) {
374
fprintf(stderr, "%ld", (long) val);
376
fprintf(stderr, "%lu", (ulong) val);
381
val = mach_read_from_4(data);
383
if (!(prtype & DATA_UNSIGNED)) {
385
fprintf(stderr, "%ld", (long) val);
387
fprintf(stderr, "%lu", (ulong) val);
392
id = mach_read_from_6(data);
393
fprintf(stderr, "{%lu %lu}",
394
ut_dulint_get_high(id),
395
ut_dulint_get_low(id));
399
id = mach_read_from_7(data);
400
fprintf(stderr, "{%lu %lu}",
401
ut_dulint_get_high(id),
402
ut_dulint_get_low(id));
405
id = mach_read_from_8(data);
406
fprintf(stderr, "{%lu %lu}",
407
ut_dulint_get_high(id),
408
ut_dulint_get_low(id));
416
switch (prtype & DATA_SYS_PRTYPE_MASK) {
418
id = mach_read_from_6(data);
420
fprintf(stderr, "trx_id " TRX_ID_FMT,
421
TRX_ID_PREP_PRINTF(id));
425
id = mach_read_from_7(data);
427
fprintf(stderr, "roll_ptr {%lu %lu}",
428
ut_dulint_get_high(id), ut_dulint_get_low(id));
432
id = mach_read_from_6(data);
434
fprintf(stderr, "row_id {%lu %lu}",
435
ut_dulint_get_high(id), ut_dulint_get_low(id));
439
id = mach_dulint_read_compressed(data);
441
fprintf(stderr, "mix_id {%lu %lu}",
442
ut_dulint_get_high(id), ut_dulint_get_low(id));
448
print_also_hex = FALSE;
450
for (i = 0; i < len; i++) {
454
print_also_hex = TRUE;
456
fprintf(stderr, "\\x%02x", (unsigned char) c);
462
if (dfield_is_ext(dfield)) {
463
fputs("(external)", stderr);
466
if (!print_also_hex) {
470
data = dfield_get_data(dfield);
476
fputs(" Hex: ",stderr);
478
for (i = 0; i < len; i++) {
479
fprintf(stderr, "%02lx", (ulint) *data++);
482
if (dfield_is_ext(dfield)) {
483
fputs("(external)", stderr);
488
/*****************************************************************
489
Print a dfield value using ut_print_buf. */
494
FILE* f, /* in: output stream */
495
const dfield_t* dfield) /* in: dfield */
497
ulint len = dfield_get_len(dfield);
498
if (!dfield_is_null(dfield)) {
499
ulint print_len = ut_min(len, 1000);
500
ut_print_buf(f, dfield_get_data(dfield), print_len);
501
if (len != print_len) {
502
fprintf(f, "(total %lu bytes%s)",
504
dfield_is_ext(dfield) ? ", external" : "");
507
fputs(" SQL NULL", f);
511
/**************************************************************
512
The following function prints the contents of a tuple. */
517
FILE* f, /* in: output stream */
518
const dtuple_t* tuple) /* in: tuple */
523
n_fields = dtuple_get_n_fields(tuple);
525
fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
527
for (i = 0; i < n_fields; i++) {
528
fprintf(f, " %lu:", (ulong) i);
530
dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
536
ut_ad(dtuple_validate(tuple));
539
/******************************************************************
540
Moves parts of long fields in entry to the big record vector so that
541
the size of tuple drops below the maximum record size allowed in the
542
database. Moves data only from those fields which are not necessary
543
to determine uniquely the insertion place of the tuple in the index. */
546
dtuple_convert_big_rec(
547
/*===================*/
548
/* out, own: created big record vector,
549
NULL if we are not able to shorten
550
the entry enough, i.e., if there are
551
too many fixed-length or short fields
552
in entry or the index is clustered */
553
dict_index_t* index, /* in: index */
554
dtuple_t* entry, /* in/out: index entry */
555
ulint* n_ext) /* in/out: number of
556
externally stored columns */
561
dict_field_t* ifield;
565
ulint local_prefix_len;
567
if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
571
if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
572
/* up to MySQL 5.1: store a 768-byte prefix locally */
573
local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
575
/* new-format table: do not store any BLOB prefix locally */
576
local_len = BTR_EXTERN_FIELD_REF_SIZE;
579
ut_a(dtuple_check_typed_no_assert(entry));
581
size = rec_get_converted_size(index, entry, *n_ext);
583
if (UNIV_UNLIKELY(size > 1000000000)) {
585
"InnoDB: Warning: tuple size very big: %lu\n",
587
fputs("InnoDB: Tuple contents: ", stderr);
588
dtuple_print(stderr, entry);
592
heap = mem_heap_create(size + dtuple_get_n_fields(entry)
593
* sizeof(big_rec_field_t) + 1000);
595
vector = mem_heap_alloc(heap, sizeof(big_rec_t));
598
vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
599
* sizeof(big_rec_field_t));
601
/* Decide which fields to shorten: the algorithm is to look for
602
a variable-length field that yields the biggest savings when
607
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
609
dict_table_is_comp(index->table),
610
dict_table_zip_size(index->table))) {
613
ulint longest_i = ULINT_MAX;
617
for (i = dict_index_get_n_unique_in_tree(index);
618
i < dtuple_get_n_fields(entry); i++) {
621
dfield = dtuple_get_nth_field(entry, i);
622
ifield = dict_index_get_nth_field(index, i);
624
/* Skip fixed-length, NULL, externally stored,
627
if (ifield->fixed_len
628
|| dfield_is_null(dfield)
629
|| dfield_is_ext(dfield)
630
|| dfield_get_len(dfield) <= local_len
631
|| dfield_get_len(dfield)
632
<= BTR_EXTERN_FIELD_REF_SIZE * 2) {
636
savings = dfield_get_len(dfield) - local_len;
638
/* Check that there would be savings */
639
if (longest >= savings) {
651
/* Cannot shorten more */
658
/* Move data from field longest_i to big rec vector.
660
We store the first bytes locally to the record. Then
661
we can calculate all ordering fields in all indexes
662
from locally stored data. */
664
dfield = dtuple_get_nth_field(entry, longest_i);
665
ifield = dict_index_get_nth_field(index, longest_i);
666
local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
668
b = &vector->fields[n_fields];
669
b->field_no = longest_i;
670
b->len = dfield_get_len(dfield) - local_prefix_len;
671
b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
673
/* Allocate the locally stored part of the column. */
674
data = mem_heap_alloc(heap, local_len);
676
/* Copy the local prefix. */
677
memcpy(data, dfield_get_data(dfield), local_prefix_len);
678
/* Clear the extern field reference (BLOB pointer). */
679
memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
681
/* The following would fail the Valgrind checks in
682
page_cur_insert_rec_low() and page_cur_insert_rec_zip().
683
The BLOB pointers in the record will be initialized after
684
the record and the BLOBs have been written. */
685
UNIV_MEM_ALLOC(data + local_prefix_len,
686
BTR_EXTERN_FIELD_REF_SIZE);
689
dfield_set_data(dfield, data, local_len);
690
dfield_set_ext(dfield);
694
ut_ad(n_fields < dtuple_get_n_fields(entry));
697
vector->n_fields = n_fields;
701
/******************************************************************
702
Puts back to entry the data stored in vector. Note that to ensure the
703
fields in entry can accommodate the data, vector must have been created
704
from entry with dtuple_convert_big_rec. */
707
dtuple_convert_back_big_rec(
708
/*========================*/
709
dict_index_t* index __attribute__((unused)), /* in: index */
710
dtuple_t* entry, /* in: entry whose data was put to vector */
711
big_rec_t* vector) /* in, own: big rec vector; it is
712
freed in this function */
714
big_rec_field_t* b = vector->fields;
715
const big_rec_field_t* const end = b + vector->n_fields;
717
for (; b < end; b++) {
721
dfield = dtuple_get_nth_field(entry, b->field_no);
722
local_len = dfield_get_len(dfield);
724
ut_ad(dfield_is_ext(dfield));
725
ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
727
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
729
ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
731
dfield_set_data(dfield,
732
(char*) b->data - local_len,
736
mem_heap_free(vector->heap);