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"
18
#include "dict0dict.h"
24
byte data_error; /* data pointers of tuple fields are initialized
25
to point here for error checking */
27
ulint data_dummy; /* this is used to fool the compiler in
29
#endif /* UNIV_DEBUG */
31
/* Some non-inlined functions used in the MySQL interface: */
33
dfield_set_data_noninline(
34
dfield_t* field, /* in: field */
35
void* data, /* in: data */
36
ulint len) /* in: length or UNIV_SQL_NULL */
38
dfield_set_data(field, data, len);
41
dfield_get_data_noninline(
42
dfield_t* field) /* in: field */
44
return(dfield_get_data(field));
47
dfield_get_len_noninline(
48
dfield_t* field) /* in: field */
50
return(dfield_get_len(field));
53
dtuple_get_n_fields_noninline(
54
dtuple_t* tuple) /* in: tuple */
56
return(dtuple_get_n_fields(tuple));
59
dtuple_get_nth_field_noninline(
60
dtuple_t* tuple, /* in: tuple */
61
ulint n) /* in: index of field */
63
return(dtuple_get_nth_field(tuple, n));
66
/*************************************************************************
67
Tests if dfield data length and content is equal to the given. */
70
dfield_data_is_binary_equal(
71
/*========================*/
72
/* out: TRUE if equal */
73
dfield_t* field, /* in: field */
74
ulint len, /* in: data length or UNIV_SQL_NULL */
75
byte* data) /* in: data */
77
if (len != field->len) {
82
if (len == UNIV_SQL_NULL) {
87
if (0 != ut_memcmp(field->data, data, len)) {
95
/****************************************************************
96
Returns TRUE if lengths of two dtuples are equal and respective data fields
97
in them are equal when compared with collation in char fields (not as binary
101
dtuple_datas_are_ordering_equal(
102
/*============================*/
103
/* out: TRUE if length and fieds are equal
104
when compared with cmp_data_data:
105
NOTE: in character type fields some letters
106
are identified with others! (collation) */
107
dtuple_t* tuple1, /* in: tuple 1 */
108
dtuple_t* tuple2) /* in: tuple 2 */
115
ut_ad(tuple1 && tuple2);
116
ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
117
ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
118
ut_ad(dtuple_check_typed(tuple1));
119
ut_ad(dtuple_check_typed(tuple2));
121
n_fields = dtuple_get_n_fields(tuple1);
123
if (n_fields != dtuple_get_n_fields(tuple2)) {
128
for (i = 0; i < n_fields; i++) {
130
field1 = dtuple_get_nth_field(tuple1, i);
131
field2 = dtuple_get_nth_field(tuple2, i);
133
if (0 != cmp_dfield_dfield(field1, field2)) {
142
/*************************************************************************
143
Creates a dtuple for use in MySQL. */
146
dtuple_create_for_mysql(
147
/*====================*/
148
/* out, own created dtuple */
149
void** heap, /* out: created memory heap */
150
ulint n_fields) /* in: number of fields */
152
*heap = (void*)mem_heap_create(500);
154
return(dtuple_create(*((mem_heap_t**)heap), n_fields));
157
/*************************************************************************
158
Frees a dtuple used in MySQL. */
161
dtuple_free_for_mysql(
162
/*==================*/
163
void* heap) /* in: memory heap where tuple was created */
165
mem_heap_free((mem_heap_t*)heap);
168
/*************************************************************************
169
Sets number of fields used in a tuple. Normally this is set in
170
dtuple_create, but if you want later to set it smaller, you can use this. */
175
dtuple_t* tuple, /* in: tuple */
176
ulint n_fields) /* in: number of fields */
180
tuple->n_fields = n_fields;
181
tuple->n_fields_cmp = n_fields;
184
/**************************************************************
185
Checks that a data field is typed. */
188
dfield_check_typed_no_assert(
189
/*=========================*/
190
/* out: TRUE if ok */
191
dfield_t* field) /* in: data field */
193
if (dfield_get_type(field)->mtype > DATA_MYSQL
194
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
197
"InnoDB: Error: data field type %lu, len %lu\n",
198
(ulong) dfield_get_type(field)->mtype,
199
(ulong) dfield_get_len(field));
206
/**************************************************************
207
Checks that a data tuple is typed. */
210
dtuple_check_typed_no_assert(
211
/*=========================*/
212
/* out: TRUE if ok */
213
dtuple_t* tuple) /* in: tuple */
218
if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
220
"InnoDB: Error: index entry has %lu fields\n",
221
(ulong) dtuple_get_n_fields(tuple));
223
fputs("InnoDB: Tuple contents: ", stderr);
224
dtuple_print(stderr, tuple);
230
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
232
field = dtuple_get_nth_field(tuple, i);
234
if (!dfield_check_typed_no_assert(field)) {
242
/**************************************************************
243
Checks that a data field is typed. Asserts an error if not. */
248
/* out: TRUE if ok */
249
dfield_t* field) /* in: data field */
251
if (dfield_get_type(field)->mtype > DATA_MYSQL
252
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
255
"InnoDB: Error: data field type %lu, len %lu\n",
256
(ulong) dfield_get_type(field)->mtype,
257
(ulong) dfield_get_len(field));
265
/**************************************************************
266
Checks that a data tuple is typed. Asserts an error if not. */
271
/* out: TRUE if ok */
272
dtuple_t* tuple) /* in: tuple */
277
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
279
field = dtuple_get_nth_field(tuple, i);
281
ut_a(dfield_check_typed(field));
288
/**************************************************************
289
Validates the consistency of a tuple which must be complete, i.e,
290
all fields must have been set. */
295
/* out: TRUE if ok */
296
dtuple_t* tuple) /* in: tuple */
305
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
307
n_fields = dtuple_get_n_fields(tuple);
309
/* We dereference all the data of each field to test
312
for (i = 0; i < n_fields; i++) {
314
field = dtuple_get_nth_field(tuple, i);
315
len = dfield_get_len(field);
317
if (len != UNIV_SQL_NULL) {
321
for (j = 0; j < len; j++) {
323
data_dummy += *data; /* fool the compiler not
331
ut_a(dtuple_check_typed(tuple));
335
#endif /* UNIV_DEBUG */
337
/*****************************************************************
338
Pretty prints a dfield value according to its data type. */
343
dfield_t* dfield) /* in: dfield */
350
len = dfield_get_len(dfield);
351
data = dfield_get_data(dfield);
353
if (len == UNIV_SQL_NULL) {
354
fputs("NULL", stderr);
359
mtype = dtype_get_mtype(dfield_get_type(dfield));
361
if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) {
363
for (i = 0; i < len; i++) {
365
putc(isprint(c) ? c : ' ', stderr);
367
} else if (mtype == DATA_INT) {
368
ut_a(len == 4); /* only works for 32-bit integers */
369
fprintf(stderr, "%d", (int)mach_read_from_4(data));
375
/*****************************************************************
376
Pretty prints a dfield value according to its data type. Also the hex string
377
is printed if a string contains non-printable characters. */
380
dfield_print_also_hex(
381
/*==================*/
382
dfield_t* dfield) /* in: dfield */
388
ibool print_also_hex;
390
len = dfield_get_len(dfield);
391
data = dfield_get_data(dfield);
393
if (len == UNIV_SQL_NULL) {
394
fputs("NULL", stderr);
399
mtype = dtype_get_mtype(dfield_get_type(dfield));
401
if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) {
403
print_also_hex = FALSE;
405
for (i = 0; i < len; i++) {
408
print_also_hex = TRUE;
414
if (!print_also_hex) {
419
fputs(" Hex: ", stderr);
421
data = dfield_get_data(dfield);
423
for (i = 0; i < len; i++) {
424
fprintf(stderr, "%02lx", (ulint)*data);
428
} else if (mtype == DATA_INT) {
429
ut_a(len == 4); /* only works for 32-bit integers */
430
fprintf(stderr, "%d", (int)mach_read_from_4(data));
436
/*****************************************************************
437
Print a dfield value using ut_print_buf. */
442
FILE* f, /* in: output stream */
443
dfield_t* dfield) /* in: dfield */
445
ulint len = dfield->len;
446
if (len != UNIV_SQL_NULL) {
447
ulint print_len = ut_min(len, 1000);
448
ut_print_buf(f, dfield->data, print_len);
449
if (len != print_len) {
450
fprintf(f, "(total %lu bytes)", (ulong) len);
453
fputs(" SQL NULL", f);
457
/**************************************************************
458
The following function prints the contents of a tuple. */
463
FILE* f, /* in: output stream */
464
dtuple_t* tuple) /* in: tuple */
469
n_fields = dtuple_get_n_fields(tuple);
471
fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
473
for (i = 0; i < n_fields; i++) {
474
fprintf(f, " %lu:", (ulong) i);
476
dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
482
ut_ad(dtuple_validate(tuple));
485
/******************************************************************
486
Moves parts of long fields in entry to the big record vector so that
487
the size of tuple drops below the maximum record size allowed in the
488
database. Moves data only from those fields which are not necessary
489
to determine uniquely the insertion place of the tuple in the index. */
492
dtuple_convert_big_rec(
493
/*===================*/
494
/* out, own: created big record vector,
495
NULL if we are not able to shorten
496
the entry enough, i.e., if there are
497
too many short fields in entry */
498
dict_index_t* index, /* in: index */
499
dtuple_t* entry, /* in: index entry */
500
ulint* ext_vec,/* in: array of externally stored fields,
501
or NULL: if a field already is externally
502
stored, then we cannot move it to the vector
503
this function returns */
504
ulint n_ext_vec)/* in: number of elements is ext_vec */
512
ulint longest_i = ULINT_MAX;
513
ibool is_externally_stored;
517
ut_a(dtuple_check_typed_no_assert(entry));
519
size = rec_get_converted_size(index, entry);
521
if (UNIV_UNLIKELY(size > 1000000000)) {
523
"InnoDB: Warning: tuple size very big: %lu\n",
525
fputs("InnoDB: Tuple contents: ", stderr);
526
dtuple_print(stderr, entry);
530
heap = mem_heap_create(size + dtuple_get_n_fields(entry)
531
* sizeof(big_rec_field_t) + 1000);
533
vector = mem_heap_alloc(heap, sizeof(big_rec_t));
536
vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
537
* sizeof(big_rec_field_t));
539
/* Decide which fields to shorten: the algorithm is to look for
540
the longest field whose type is DATA_BLOB */
544
while (rec_get_converted_size(index, entry)
545
>= ut_min(page_get_free_space_of_empty(
546
dict_table_is_comp(index->table)) / 2,
547
REC_MAX_DATA_SIZE)) {
550
for (i = dict_index_get_n_unique_in_tree(index);
551
i < dtuple_get_n_fields(entry); i++) {
553
/* Skip over fields which already are externally
556
is_externally_stored = FALSE;
559
for (j = 0; j < n_ext_vec; j++) {
560
if (ext_vec[j] == i) {
561
is_externally_stored = TRUE;
566
if (!is_externally_stored) {
568
dfield = dtuple_get_nth_field(entry, i);
570
if (dfield->len != UNIV_SQL_NULL
571
&& dfield->len > longest) {
573
longest = dfield->len;
580
/* We do not store externally fields which are smaller than
581
DICT_MAX_INDEX_COL_LEN */
583
#if DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT
584
# error "DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT"
587
if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10
588
+ DICT_MAX_INDEX_COL_LEN) {
589
/* Cannot shorten more */
596
/* Move data from field longest_i to big rec vector;
597
we do not let data size of the remaining entry
598
drop below 128 which is the limit for the 2-byte
599
offset storage format in a physical record. This
600
we accomplish by storing 128 bytes of data in entry
601
itself, and only the remaining part to big rec vec.
603
We store the first bytes locally to the record. Then
604
we can calculate all ordering fields in all indexes
605
from locally stored data. */
607
dfield = dtuple_get_nth_field(entry, longest_i);
608
vector->fields[n_fields].field_no = longest_i;
610
ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN);
612
vector->fields[n_fields].len = dfield->len
613
- DICT_MAX_INDEX_COL_LEN;
615
vector->fields[n_fields].data = mem_heap_alloc(
616
heap, vector->fields[n_fields].len);
618
/* Copy data (from the end of field) to big rec vector */
620
ut_memcpy(vector->fields[n_fields].data,
621
((byte*)dfield->data) + dfield->len
622
- vector->fields[n_fields].len,
623
vector->fields[n_fields].len);
624
dfield->len = dfield->len - vector->fields[n_fields].len
625
+ BTR_EXTERN_FIELD_REF_SIZE;
627
/* Set the extern field reference in dfield to zero */
628
memset(((byte*)dfield->data)
629
+ dfield->len - BTR_EXTERN_FIELD_REF_SIZE,
630
0, BTR_EXTERN_FIELD_REF_SIZE);
634
vector->n_fields = n_fields;
638
/******************************************************************
639
Puts back to entry the data stored in vector. Note that to ensure the
640
fields in entry can accommodate the data, vector must have been created
641
from entry with dtuple_convert_big_rec. */
644
dtuple_convert_back_big_rec(
645
/*========================*/
646
dict_index_t* index __attribute__((unused)), /* in: index */
647
dtuple_t* entry, /* in: entry whose data was put to vector */
648
big_rec_t* vector) /* in, own: big rec vector; it is
649
freed in this function */
654
for (i = 0; i < vector->n_fields; i++) {
656
dfield = dtuple_get_nth_field(entry,
657
vector->fields[i].field_no);
658
/* Copy data from big rec vector */
660
ut_memcpy(((byte*)dfield->data)
661
+ dfield->len - BTR_EXTERN_FIELD_REF_SIZE,
662
vector->fields[i].data,
663
vector->fields[i].len);
664
dfield->len = dfield->len + vector->fields[i].len
665
- BTR_EXTERN_FIELD_REF_SIZE;
668
mem_heap_free(vector->heap);
671
/******************************************************************
672
Frees the memory in a big rec vector. */
677
big_rec_t* vector) /* in, own: big rec vector; it is
678
freed in this function */
680
mem_heap_free(vector->heap);