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_index_get_n_fields(index),
611
dict_table_zip_size(index->table))) {
614
ulint longest_i = ULINT_MAX;
618
for (i = dict_index_get_n_unique_in_tree(index);
619
i < dtuple_get_n_fields(entry); i++) {
622
dfield = dtuple_get_nth_field(entry, i);
623
ifield = dict_index_get_nth_field(index, i);
625
/* Skip fixed-length, NULL, externally stored,
628
if (ifield->fixed_len
629
|| dfield_is_null(dfield)
630
|| dfield_is_ext(dfield)
631
|| dfield_get_len(dfield) <= local_len
632
|| dfield_get_len(dfield)
633
<= BTR_EXTERN_FIELD_REF_SIZE * 2) {
637
savings = dfield_get_len(dfield) - local_len;
639
/* Check that there would be savings */
640
if (longest >= savings) {
652
/* Cannot shorten more */
659
/* Move data from field longest_i to big rec vector.
661
We store the first bytes locally to the record. Then
662
we can calculate all ordering fields in all indexes
663
from locally stored data. */
665
dfield = dtuple_get_nth_field(entry, longest_i);
666
ifield = dict_index_get_nth_field(index, longest_i);
667
local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
669
b = &vector->fields[n_fields];
670
b->field_no = longest_i;
671
b->len = dfield_get_len(dfield) - local_prefix_len;
672
b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
674
/* Allocate the locally stored part of the column. */
675
data = mem_heap_alloc(heap, local_len);
677
/* Copy the local prefix. */
678
memcpy(data, dfield_get_data(dfield), local_prefix_len);
679
/* Clear the extern field reference (BLOB pointer). */
680
memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
682
/* The following would fail the Valgrind checks in
683
page_cur_insert_rec_low() and page_cur_insert_rec_zip().
684
The BLOB pointers in the record will be initialized after
685
the record and the BLOBs have been written. */
686
UNIV_MEM_ALLOC(data + local_prefix_len,
687
BTR_EXTERN_FIELD_REF_SIZE);
690
dfield_set_data(dfield, data, local_len);
691
dfield_set_ext(dfield);
695
ut_ad(n_fields < dtuple_get_n_fields(entry));
698
vector->n_fields = n_fields;
702
/******************************************************************
703
Puts back to entry the data stored in vector. Note that to ensure the
704
fields in entry can accommodate the data, vector must have been created
705
from entry with dtuple_convert_big_rec. */
708
dtuple_convert_back_big_rec(
709
/*========================*/
710
dict_index_t* index __attribute__((unused)), /* in: index */
711
dtuple_t* entry, /* in: entry whose data was put to vector */
712
big_rec_t* vector) /* in, own: big rec vector; it is
713
freed in this function */
715
big_rec_field_t* b = vector->fields;
716
const big_rec_field_t* const end = b + vector->n_fields;
718
for (; b < end; b++) {
722
dfield = dtuple_get_nth_field(entry, b->field_no);
723
local_len = dfield_get_len(dfield);
725
ut_ad(dfield_is_ext(dfield));
726
ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
728
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
730
ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
732
dfield_set_data(dfield,
733
(char*) b->data - local_len,
737
mem_heap_free(vector->heap);