00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "data0data.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "data0data.ic"
00030 #endif
00031
00032 #ifndef UNIV_HOTBACKUP
00033 #include "rem0rec.h"
00034 #include "rem0cmp.h"
00035 #include "page0page.h"
00036 #include "page0zip.h"
00037 #include "dict0dict.h"
00038 #include "btr0cur.h"
00039
00040 #include <ctype.h>
00041 #endif
00042
00043 #ifdef UNIV_DEBUG
00044
00047 UNIV_INTERN byte data_error;
00048
00049 # ifndef UNIV_DEBUG_VALGRIND
00050
00051 UNIV_INTERN ulint data_dummy;
00052 # endif
00053 #endif
00054
00055 #ifndef UNIV_HOTBACKUP
00056
00059 UNIV_INTERN
00060 ibool
00061 dfield_data_is_binary_equal(
00062
00063 const dfield_t* field,
00064 ulint len,
00065 const byte* data)
00066 {
00067 if (len != dfield_get_len(field)) {
00068
00069 return(FALSE);
00070 }
00071
00072 if (len == UNIV_SQL_NULL) {
00073
00074 return(TRUE);
00075 }
00076
00077 if (0 != memcmp(dfield_get_data(field), data, len)) {
00078
00079 return(FALSE);
00080 }
00081
00082 return(TRUE);
00083 }
00084
00085
00089 UNIV_INTERN
00090 int
00091 dtuple_coll_cmp(
00092
00093 const dtuple_t* tuple1,
00094 const dtuple_t* tuple2)
00095 {
00096 ulint n_fields;
00097 ulint i;
00098
00099 ut_ad(tuple1 && tuple2);
00100 ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
00101 ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
00102 ut_ad(dtuple_check_typed(tuple1));
00103 ut_ad(dtuple_check_typed(tuple2));
00104
00105 n_fields = dtuple_get_n_fields(tuple1);
00106
00107 if (n_fields != dtuple_get_n_fields(tuple2)) {
00108
00109 return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
00110 }
00111
00112 for (i = 0; i < n_fields; i++) {
00113 int cmp;
00114 const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
00115 const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
00116
00117 cmp = cmp_dfield_dfield(field1, field2);
00118
00119 if (cmp) {
00120 return(cmp);
00121 }
00122 }
00123
00124 return(0);
00125 }
00126
00127
00130 UNIV_INTERN
00131 void
00132 dtuple_set_n_fields(
00133
00134 dtuple_t* tuple,
00135 ulint n_fields)
00136 {
00137 ut_ad(tuple);
00138
00139 tuple->n_fields = n_fields;
00140 tuple->n_fields_cmp = n_fields;
00141 }
00142
00143
00146 static
00147 ibool
00148 dfield_check_typed_no_assert(
00149
00150 const dfield_t* field)
00151 {
00152 if (dfield_get_type(field)->mtype > DATA_MYSQL
00153 || dfield_get_type(field)->mtype < DATA_VARCHAR) {
00154
00155 fprintf(stderr,
00156 "InnoDB: Error: data field type %lu, len %lu\n",
00157 (ulong) dfield_get_type(field)->mtype,
00158 (ulong) dfield_get_len(field));
00159 return(FALSE);
00160 }
00161
00162 return(TRUE);
00163 }
00164
00165
00168 UNIV_INTERN
00169 ibool
00170 dtuple_check_typed_no_assert(
00171
00172 const dtuple_t* tuple)
00173 {
00174 const dfield_t* field;
00175 ulint i;
00176
00177 if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
00178 fprintf(stderr,
00179 "InnoDB: Error: index entry has %lu fields\n",
00180 (ulong) dtuple_get_n_fields(tuple));
00181 dump:
00182 fputs("InnoDB: Tuple contents: ", stderr);
00183 dtuple_print(stderr, tuple);
00184 putc('\n', stderr);
00185
00186 return(FALSE);
00187 }
00188
00189 for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
00190
00191 field = dtuple_get_nth_field(tuple, i);
00192
00193 if (!dfield_check_typed_no_assert(field)) {
00194 goto dump;
00195 }
00196 }
00197
00198 return(TRUE);
00199 }
00200 #endif
00201
00202 #ifdef UNIV_DEBUG
00203
00206 UNIV_INTERN
00207 ibool
00208 dfield_check_typed(
00209
00210 const dfield_t* field)
00211 {
00212 if (dfield_get_type(field)->mtype > DATA_MYSQL
00213 || dfield_get_type(field)->mtype < DATA_VARCHAR) {
00214
00215 fprintf(stderr,
00216 "InnoDB: Error: data field type %lu, len %lu\n",
00217 (ulong) dfield_get_type(field)->mtype,
00218 (ulong) dfield_get_len(field));
00219
00220 ut_error;
00221 }
00222
00223 return(TRUE);
00224 }
00225
00226
00229 UNIV_INTERN
00230 ibool
00231 dtuple_check_typed(
00232
00233 const dtuple_t* tuple)
00234 {
00235 const dfield_t* field;
00236 ulint i;
00237
00238 for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
00239
00240 field = dtuple_get_nth_field(tuple, i);
00241
00242 ut_a(dfield_check_typed(field));
00243 }
00244
00245 return(TRUE);
00246 }
00247
00248
00252 UNIV_INTERN
00253 ibool
00254 dtuple_validate(
00255
00256 const dtuple_t* tuple)
00257 {
00258 const dfield_t* field;
00259 ulint n_fields;
00260 ulint len;
00261 ulint i;
00262
00263 ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
00264
00265 n_fields = dtuple_get_n_fields(tuple);
00266
00267
00268
00269
00270 for (i = 0; i < n_fields; i++) {
00271
00272 field = dtuple_get_nth_field(tuple, i);
00273 len = dfield_get_len(field);
00274
00275 if (!dfield_is_null(field)) {
00276
00277 const byte* data = dfield_get_data(field);
00278 #ifndef UNIV_DEBUG_VALGRIND
00279 ulint j;
00280
00281 for (j = 0; j < len; j++) {
00282
00283 data_dummy += *data;
00284
00285
00286 data++;
00287 }
00288 #endif
00289
00290 UNIV_MEM_ASSERT_RW(data, len);
00291 }
00292 }
00293
00294 ut_a(dtuple_check_typed(tuple));
00295
00296 return(TRUE);
00297 }
00298 #endif
00299
00300 #ifndef UNIV_HOTBACKUP
00301
00303 UNIV_INTERN
00304 void
00305 dfield_print(
00306
00307 const dfield_t* dfield)
00308 {
00309 ulint i;
00310
00311 ulint len = dfield_get_len(dfield);
00312 const byte *data = static_cast<const byte *>(dfield_get_data(dfield));
00313
00314 if (dfield_is_null(dfield)) {
00315 fputs("NULL", stderr);
00316
00317 return;
00318 }
00319
00320 switch (dtype_get_mtype(dfield_get_type(dfield))) {
00321 case DATA_CHAR:
00322 case DATA_VARCHAR:
00323 for (i = 0; i < len; i++) {
00324 int c = *data++;
00325 putc(isprint(c) ? c : ' ', stderr);
00326 }
00327
00328 if (dfield_is_ext(dfield)) {
00329 fputs("(external)", stderr);
00330 }
00331 break;
00332 case DATA_INT:
00333 ut_a(len == 4);
00334 fprintf(stderr, "%d", (int)mach_read_from_4(data));
00335 break;
00336 default:
00337 ut_error;
00338 }
00339 }
00340
00341
00344 UNIV_INTERN
00345 void
00346 dfield_print_also_hex(
00347
00348 const dfield_t* dfield)
00349 {
00350 const byte* data;
00351 ulint len;
00352 ulint prtype;
00353 ulint i;
00354 ibool print_also_hex;
00355
00356 len = dfield_get_len(dfield);
00357 data = static_cast<const byte *>(dfield_get_data(dfield));
00358
00359 if (dfield_is_null(dfield)) {
00360 fputs("NULL", stderr);
00361
00362 return;
00363 }
00364
00365 prtype = dtype_get_prtype(dfield_get_type(dfield));
00366
00367 ib_id_t id= 0;
00368 ulint val= 0;
00369 static const ulint UNSIGNED_MASK= 0x80000000;
00370
00371 switch (dtype_get_mtype(dfield_get_type(dfield))) {
00372 case DATA_INT:
00373 switch (len) {
00374 case 1:
00375 val = mach_read_from_1(data);
00376
00377 if (!(prtype & DATA_UNSIGNED)) {
00378 val &= ~0x80;
00379 fprintf(stderr, "%ld", (long) val);
00380 } else {
00381 fprintf(stderr, "%lu", (ulong) val);
00382 }
00383 break;
00384
00385 case 2:
00386 val = mach_read_from_2(data);
00387
00388 if (!(prtype & DATA_UNSIGNED)) {
00389 val &= ~0x8000;
00390 fprintf(stderr, "%ld", (long) val);
00391 } else {
00392 fprintf(stderr, "%lu", (ulong) val);
00393 }
00394 break;
00395
00396 case 3:
00397 val = mach_read_from_3(data);
00398
00399 if (!(prtype & DATA_UNSIGNED)) {
00400 val &= ~0x800000;
00401 fprintf(stderr, "%ld", (long) val);
00402 } else {
00403 fprintf(stderr, "%lu", (ulong) val);
00404 }
00405 break;
00406
00407 case 4:
00408 val = mach_read_from_4(data);
00409
00410 if (!(prtype & DATA_UNSIGNED)) {
00411 val &= ~UNSIGNED_MASK;
00412 fprintf(stderr, "%ld", (long) val);
00413 } else {
00414 fprintf(stderr, "%lu", (ulong) val);
00415 }
00416 break;
00417
00418 case 6:
00419 id = mach_read_from_6(data);
00420 fprintf(stderr, "%llu", (ullint) id);
00421 break;
00422
00423 case 7:
00424 id = mach_read_from_7(data);
00425 fprintf(stderr, "%llu", (ullint) id);
00426 break;
00427 case 8:
00428 id = mach_read_from_8(data);
00429 fprintf(stderr, "%llu", (ullint) id);
00430 break;
00431 default:
00432 goto print_hex;
00433 }
00434 break;
00435
00436 case DATA_SYS:
00437 switch (prtype & DATA_SYS_PRTYPE_MASK) {
00438 case DATA_TRX_ID:
00439 id = mach_read_from_6(data);
00440
00441 fprintf(stderr, "trx_id " TRX_ID_FMT, id);
00442 break;
00443
00444 case DATA_ROLL_PTR:
00445 id = mach_read_from_7(data);
00446
00447 fprintf(stderr, "roll_ptr " TRX_ID_FMT, id);
00448 break;
00449
00450 case DATA_ROW_ID:
00451 id = mach_read_from_6(data);
00452
00453 fprintf(stderr, "row_id " TRX_ID_FMT, id);
00454 break;
00455
00456 default:
00457 id = mach_ull_read_compressed(data);
00458
00459 fprintf(stderr, "mix_id " TRX_ID_FMT, id);
00460 }
00461 break;
00462
00463 case DATA_CHAR:
00464 case DATA_VARCHAR:
00465 print_also_hex = FALSE;
00466
00467 for (i = 0; i < len; i++) {
00468 int c = *data++;
00469
00470 if (!isprint(c)) {
00471 print_also_hex = TRUE;
00472
00473 fprintf(stderr, "\\x%02x", (unsigned char) c);
00474 } else {
00475 putc(c, stderr);
00476 }
00477 }
00478
00479 if (dfield_is_ext(dfield)) {
00480 fputs("(external)", stderr);
00481 }
00482
00483 if (!print_also_hex) {
00484 break;
00485 }
00486
00487 data = static_cast<const byte *>(dfield_get_data(dfield));
00488
00489
00490 case DATA_BINARY:
00491 default:
00492 print_hex:
00493 fputs(" Hex: ",stderr);
00494
00495 for (i = 0; i < len; i++) {
00496 fprintf(stderr, "%02lx", (ulint) *data++);
00497 }
00498
00499 if (dfield_is_ext(dfield)) {
00500 fputs("(external)", stderr);
00501 }
00502 }
00503 }
00504
00505
00507 static
00508 void
00509 dfield_print_raw(
00510
00511 FILE* f,
00512 const dfield_t* dfield)
00513 {
00514 ulint len = dfield_get_len(dfield);
00515 if (!dfield_is_null(dfield)) {
00516 ulint print_len = ut_min(len, 1000);
00517 ut_print_buf(f, dfield_get_data(dfield), print_len);
00518 if (len != print_len) {
00519 fprintf(f, "(total %lu bytes%s)",
00520 (ulong) len,
00521 dfield_is_ext(dfield) ? ", external" : "");
00522 }
00523 } else {
00524 fputs(" SQL NULL", f);
00525 }
00526 }
00527
00528
00530 UNIV_INTERN
00531 void
00532 dtuple_print(
00533
00534 FILE* f,
00535 const dtuple_t* tuple)
00536 {
00537 ulint n_fields;
00538 ulint i;
00539
00540 n_fields = dtuple_get_n_fields(tuple);
00541
00542 fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
00543
00544 for (i = 0; i < n_fields; i++) {
00545 fprintf(f, " %lu:", (ulong) i);
00546
00547 dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
00548
00549 putc(';', f);
00550 putc('\n', f);
00551 }
00552
00553 ut_ad(dtuple_validate(tuple));
00554 }
00555
00556
00564 UNIV_INTERN
00565 big_rec_t*
00566 dtuple_convert_big_rec(
00567
00568 dict_index_t* index,
00569 dtuple_t* entry,
00570 ulint* n_ext)
00572 {
00573 mem_heap_t* heap;
00574 big_rec_t* vector;
00575 dfield_t* dfield;
00576 dict_field_t* ifield;
00577 ulint size;
00578 ulint n_fields;
00579 ulint local_len;
00580 ulint local_prefix_len;
00581
00582 if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
00583 return(NULL);
00584 }
00585
00586 if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
00587
00588 local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
00589 } else {
00590
00591 local_len = BTR_EXTERN_FIELD_REF_SIZE;
00592 }
00593
00594 ut_a(dtuple_check_typed_no_assert(entry));
00595
00596 size = rec_get_converted_size(index, entry, *n_ext);
00597
00598 if (UNIV_UNLIKELY(size > 1000000000)) {
00599 fprintf(stderr,
00600 "InnoDB: Warning: tuple size very big: %lu\n",
00601 (ulong) size);
00602 fputs("InnoDB: Tuple contents: ", stderr);
00603 dtuple_print(stderr, entry);
00604 putc('\n', stderr);
00605 }
00606
00607 heap = mem_heap_create(size + dtuple_get_n_fields(entry)
00608 * sizeof(big_rec_field_t) + 1000);
00609
00610 vector = static_cast<big_rec_t *>(mem_heap_alloc(heap, sizeof(big_rec_t)));
00611
00612 vector->heap = heap;
00613 vector->fields = static_cast<big_rec_field_t *>(mem_heap_alloc(heap, dtuple_get_n_fields(entry)
00614 * sizeof(big_rec_field_t)));
00615
00616
00617
00618
00619
00620 n_fields = 0;
00621
00622 while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
00623 *n_ext),
00624 dict_table_is_comp(index->table),
00625 dict_index_get_n_fields(index),
00626 dict_table_zip_size(index->table))) {
00627 ulint i;
00628 ulint longest = 0;
00629 ulint longest_i = ULINT_MAX;
00630 byte* data;
00631 big_rec_field_t* b;
00632
00633 for (i = dict_index_get_n_unique_in_tree(index);
00634 i < dtuple_get_n_fields(entry); i++) {
00635 ulint savings;
00636
00637 dfield = dtuple_get_nth_field(entry, i);
00638 ifield = dict_index_get_nth_field(index, i);
00639
00640
00641
00642
00643 if (ifield->fixed_len
00644 || dfield_is_null(dfield)
00645 || dfield_is_ext(dfield)
00646 || dfield_get_len(dfield) <= local_len
00647 || dfield_get_len(dfield)
00648 <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
00649 goto skip_field;
00650 }
00651
00652 savings = dfield_get_len(dfield) - local_len;
00653
00654
00655 if (longest >= savings) {
00656 goto skip_field;
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 if (ifield->col->mtype != DATA_BLOB
00670 && ifield->col->len < 256) {
00671 goto skip_field;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 if (ifield->col->mtype != DATA_BLOB
00685 && ifield->col->len < 256) {
00686 goto skip_field;
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 if (ifield->col->mtype != DATA_BLOB
00700 && ifield->col->len < 256) {
00701 goto skip_field;
00702 }
00703
00704 longest_i = i;
00705 longest = savings;
00706
00707 skip_field:
00708 continue;
00709 }
00710
00711 if (!longest) {
00712
00713
00714 mem_heap_free(heap);
00715
00716 return(NULL);
00717 }
00718
00719
00720
00721
00722
00723
00724
00725 dfield = dtuple_get_nth_field(entry, longest_i);
00726 ifield = dict_index_get_nth_field(index, longest_i);
00727 local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
00728
00729 b = &vector->fields[n_fields];
00730 b->field_no = longest_i;
00731 b->len = dfield_get_len(dfield) - local_prefix_len;
00732 b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
00733
00734
00735 data = static_cast<unsigned char *>(mem_heap_alloc(heap, local_len));
00736
00737
00738 memcpy(data, dfield_get_data(dfield), local_prefix_len);
00739
00740 memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
00741 #if 0
00742
00743
00744
00745
00746 UNIV_MEM_ALLOC(data + local_prefix_len,
00747 BTR_EXTERN_FIELD_REF_SIZE);
00748 #endif
00749
00750 dfield_set_data(dfield, data, local_len);
00751 dfield_set_ext(dfield);
00752
00753 n_fields++;
00754 (*n_ext)++;
00755 ut_ad(n_fields < dtuple_get_n_fields(entry));
00756 }
00757
00758 vector->n_fields = n_fields;
00759 return(vector);
00760 }
00761
00762
00766 UNIV_INTERN
00767 void
00768 dtuple_convert_back_big_rec(
00769
00770 dict_index_t* ,
00771 dtuple_t* entry,
00772 big_rec_t* vector)
00774 {
00775 big_rec_field_t* b = vector->fields;
00776 const big_rec_field_t* const end = b + vector->n_fields;
00777
00778 for (; b < end; b++) {
00779 dfield_t* dfield;
00780 ulint local_len;
00781
00782 dfield = dtuple_get_nth_field(entry, b->field_no);
00783 local_len = dfield_get_len(dfield);
00784
00785 ut_ad(dfield_is_ext(dfield));
00786 ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
00787
00788 local_len -= BTR_EXTERN_FIELD_REF_SIZE;
00789
00790 ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
00791
00792 dfield_set_data(dfield,
00793 (char*) b->data - local_len,
00794 b->len + local_len);
00795 }
00796
00797 mem_heap_free(vector->heap);
00798 }
00799 #endif