00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "rem0rec.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "rem0rec.ic"
00030 #endif
00031
00032 #include "mtr0mtr.h"
00033 #include "mtr0log.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 UNIV_INTERN ulint rec_dummy;
00146
00147
00150 static
00151 ibool
00152 rec_validate_old(
00153
00154 const rec_t* rec);
00156
00160 UNIV_INTERN
00161 ulint
00162 rec_get_n_extern_new(
00163
00164 const rec_t* rec,
00165 dict_index_t* index,
00166 ulint n)
00167 {
00168 const byte* nulls;
00169 const byte* lens;
00170 dict_field_t* field;
00171 ulint null_mask;
00172 ulint n_extern;
00173 ulint i;
00174
00175 ut_ad(dict_table_is_comp(index->table));
00176 ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
00177 ut_ad(n == ULINT_UNDEFINED || n <= dict_index_get_n_fields(index));
00178
00179 if (n == ULINT_UNDEFINED) {
00180 n = dict_index_get_n_fields(index);
00181 }
00182
00183 nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
00184 lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
00185 null_mask = 1;
00186 n_extern = 0;
00187 i = 0;
00188
00189
00190 do {
00191 ulint len;
00192
00193 field = dict_index_get_nth_field(index, i);
00194 if (!(dict_field_get_col(field)->prtype & DATA_NOT_NULL)) {
00195
00196
00197 if (UNIV_UNLIKELY(!(byte) null_mask)) {
00198 nulls--;
00199 null_mask = 1;
00200 }
00201
00202 if (*nulls & null_mask) {
00203 null_mask <<= 1;
00204
00205 continue;
00206 }
00207 null_mask <<= 1;
00208 }
00209
00210 if (UNIV_UNLIKELY(!field->fixed_len)) {
00211
00212 const dict_col_t* col
00213 = dict_field_get_col(field);
00214 len = *lens--;
00215
00216
00217
00218
00219
00220
00221
00222 if (UNIV_UNLIKELY(col->len > 255)
00223 || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) {
00224 if (len & 0x80) {
00225
00226 if (len & 0x40) {
00227 n_extern++;
00228 }
00229 lens--;
00230 }
00231 }
00232 }
00233 } while (++i < n);
00234
00235 return(n_extern);
00236 }
00237
00238
00242 UNIV_INTERN
00243 void
00244 rec_init_offsets_comp_ordinary(
00245
00246 const rec_t* rec,
00248 ulint extra,
00252 const dict_index_t* index,
00253 ulint* offsets)
00255 {
00256 ulint i = 0;
00257 ulint offs = 0;
00258 ulint any_ext = 0;
00259 const byte* nulls = rec - (extra + 1);
00260 const byte* lens = nulls
00261 - UT_BITS_IN_BYTES(index->n_nullable);
00262 dict_field_t* field;
00263 ulint null_mask = 1;
00264
00265 #ifdef UNIV_DEBUG
00266
00267
00268
00269 offsets[2] = (ulint) rec;
00270 offsets[3] = (ulint) index;
00271 #endif
00272
00273
00274 do {
00275 ulint len;
00276
00277 field = dict_index_get_nth_field(index, i);
00278 if (!(dict_field_get_col(field)->prtype
00279 & DATA_NOT_NULL)) {
00280
00281
00282 if (UNIV_UNLIKELY(!(byte) null_mask)) {
00283 nulls--;
00284 null_mask = 1;
00285 }
00286
00287 if (*nulls & null_mask) {
00288 null_mask <<= 1;
00289
00290
00291
00292
00293 len = offs | REC_OFFS_SQL_NULL;
00294 goto resolved;
00295 }
00296 null_mask <<= 1;
00297 }
00298
00299 if (UNIV_UNLIKELY(!field->fixed_len)) {
00300
00301 const dict_col_t* col
00302 = dict_field_get_col(field);
00303 len = *lens--;
00304
00305
00306
00307
00308
00309
00310
00311 if (UNIV_UNLIKELY(col->len > 255)
00312 || UNIV_UNLIKELY(col->mtype
00313 == DATA_BLOB)) {
00314 if (len & 0x80) {
00315
00316 len <<= 8;
00317 len |= *lens--;
00318
00319 offs += len & 0x3fff;
00320 if (UNIV_UNLIKELY(len
00321 & 0x4000)) {
00322 ut_ad(dict_index_is_clust
00323 (index));
00324 any_ext = REC_OFFS_EXTERNAL;
00325 len = offs
00326 | REC_OFFS_EXTERNAL;
00327 } else {
00328 len = offs;
00329 }
00330
00331 goto resolved;
00332 }
00333 }
00334
00335 len = offs += len;
00336 } else {
00337 len = offs += field->fixed_len;
00338 }
00339 resolved:
00340 rec_offs_base(offsets)[i + 1] = len;
00341 } while (++i < rec_offs_n_fields(offsets));
00342
00343 *rec_offs_base(offsets)
00344 = (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
00345 }
00346
00347
00361 static
00362 void
00363 rec_init_offsets(
00364
00365 const rec_t* rec,
00366 const dict_index_t* index,
00367 ulint* offsets)
00369 {
00370 ulint i = 0;
00371 ulint offs;
00372
00373 rec_offs_make_valid(rec, index, offsets);
00374
00375 if (dict_table_is_comp(index->table)) {
00376 const byte* nulls;
00377 const byte* lens;
00378 dict_field_t* field;
00379 ulint null_mask;
00380 ulint status = rec_get_status(rec);
00381 ulint n_node_ptr_field = ULINT_UNDEFINED;
00382
00383 switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
00384 case REC_STATUS_INFIMUM:
00385 case REC_STATUS_SUPREMUM:
00386
00387 rec_offs_base(offsets)[0]
00388 = REC_N_NEW_EXTRA_BYTES | REC_OFFS_COMPACT;
00389 rec_offs_base(offsets)[1] = 8;
00390 return;
00391 case REC_STATUS_NODE_PTR:
00392 n_node_ptr_field
00393 = dict_index_get_n_unique_in_tree(index);
00394 break;
00395 case REC_STATUS_ORDINARY:
00396 rec_init_offsets_comp_ordinary(rec,
00397 REC_N_NEW_EXTRA_BYTES,
00398 index, offsets);
00399 return;
00400 }
00401
00402 nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
00403 lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
00404 offs = 0;
00405 null_mask = 1;
00406
00407
00408 do {
00409 ulint len;
00410 if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
00411 len = offs += 4;
00412 goto resolved;
00413 }
00414
00415 field = dict_index_get_nth_field(index, i);
00416 if (!(dict_field_get_col(field)->prtype
00417 & DATA_NOT_NULL)) {
00418
00419
00420 if (UNIV_UNLIKELY(!(byte) null_mask)) {
00421 nulls--;
00422 null_mask = 1;
00423 }
00424
00425 if (*nulls & null_mask) {
00426 null_mask <<= 1;
00427
00428
00429
00430
00431 len = offs | REC_OFFS_SQL_NULL;
00432 goto resolved;
00433 }
00434 null_mask <<= 1;
00435 }
00436
00437 if (UNIV_UNLIKELY(!field->fixed_len)) {
00438
00439 const dict_col_t* col
00440 = dict_field_get_col(field);
00441 len = *lens--;
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 if (UNIV_UNLIKELY(col->len > 255)
00452 || UNIV_UNLIKELY(col->mtype
00453 == DATA_BLOB)) {
00454 if (len & 0x80) {
00455
00456
00457 len <<= 8;
00458 len |= *lens--;
00459
00460
00461
00462
00463
00464 ut_a(!(len & 0x4000));
00465 offs += len & 0x3fff;
00466 len = offs;
00467
00468 goto resolved;
00469 }
00470 }
00471
00472 len = offs += len;
00473 } else {
00474 len = offs += field->fixed_len;
00475 }
00476 resolved:
00477 rec_offs_base(offsets)[i + 1] = len;
00478 } while (++i < rec_offs_n_fields(offsets));
00479
00480 *rec_offs_base(offsets)
00481 = (rec - (lens + 1)) | REC_OFFS_COMPACT;
00482 } else {
00483
00484 offs = REC_N_OLD_EXTRA_BYTES;
00485 if (rec_get_1byte_offs_flag(rec)) {
00486 offs += rec_offs_n_fields(offsets);
00487 *rec_offs_base(offsets) = offs;
00488
00489 do {
00490 offs = rec_1_get_field_end_info(rec, i);
00491 if (offs & REC_1BYTE_SQL_NULL_MASK) {
00492 offs &= ~REC_1BYTE_SQL_NULL_MASK;
00493 offs |= REC_OFFS_SQL_NULL;
00494 }
00495 rec_offs_base(offsets)[1 + i] = offs;
00496 } while (++i < rec_offs_n_fields(offsets));
00497 } else {
00498 offs += 2 * rec_offs_n_fields(offsets);
00499 *rec_offs_base(offsets) = offs;
00500
00501 do {
00502 offs = rec_2_get_field_end_info(rec, i);
00503 if (offs & REC_2BYTE_SQL_NULL_MASK) {
00504 offs &= ~REC_2BYTE_SQL_NULL_MASK;
00505 offs |= REC_OFFS_SQL_NULL;
00506 }
00507 if (offs & REC_2BYTE_EXTERN_MASK) {
00508 offs &= ~REC_2BYTE_EXTERN_MASK;
00509 offs |= REC_OFFS_EXTERNAL;
00510 *rec_offs_base(offsets) |= REC_OFFS_EXTERNAL;
00511 }
00512 rec_offs_base(offsets)[1 + i] = offs;
00513 } while (++i < rec_offs_n_fields(offsets));
00514 }
00515 }
00516 }
00517
00518
00522 UNIV_INTERN
00523 ulint*
00524 rec_get_offsets_func(
00525
00526 const rec_t* rec,
00527 const dict_index_t* index,
00528 ulint* offsets,
00532 ulint n_fields,
00535 mem_heap_t** heap,
00536 const char* file,
00537 ulint line)
00538 {
00539 ulint n;
00540 ulint size;
00541
00542 ut_ad(rec);
00543 ut_ad(index);
00544 ut_ad(heap);
00545
00546 if (dict_table_is_comp(index->table)) {
00547 switch (UNIV_EXPECT(rec_get_status(rec),
00548 REC_STATUS_ORDINARY)) {
00549 case REC_STATUS_ORDINARY:
00550 n = dict_index_get_n_fields(index);
00551 break;
00552 case REC_STATUS_NODE_PTR:
00553 n = dict_index_get_n_unique_in_tree(index) + 1;
00554 break;
00555 case REC_STATUS_INFIMUM:
00556 case REC_STATUS_SUPREMUM:
00557
00558 n = 1;
00559 break;
00560 default:
00561 ut_error;
00562 return(NULL);
00563 }
00564 } else {
00565 n = rec_get_n_fields_old(rec);
00566 }
00567
00568 if (UNIV_UNLIKELY(n_fields < n)) {
00569 n = n_fields;
00570 }
00571
00572 size = n + (1 + REC_OFFS_HEADER_SIZE);
00573
00574 if (UNIV_UNLIKELY(!offsets)
00575 || UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) {
00576 if (UNIV_UNLIKELY(!*heap)) {
00577 *heap = mem_heap_create_func(size * sizeof(ulint),
00578 MEM_HEAP_DYNAMIC,
00579 file, line);
00580 }
00581 offsets = static_cast<unsigned long *>(mem_heap_alloc(*heap, size * sizeof(ulint)));
00582 rec_offs_set_n_alloc(offsets, size);
00583 }
00584
00585 rec_offs_set_n_fields(offsets, n);
00586 rec_init_offsets(rec, index, offsets);
00587 return(offsets);
00588 }
00589
00590
00593 UNIV_INTERN
00594 void
00595 rec_get_offsets_reverse(
00596
00597 const byte* extra,
00601 const dict_index_t* index,
00602 ulint node_ptr,
00604 ulint* offsets)
00606 {
00607 ulint n;
00608 ulint i;
00609 ulint offs;
00610 ulint any_ext;
00611 const byte* nulls;
00612 const byte* lens;
00613 dict_field_t* field;
00614 ulint null_mask;
00615 ulint n_node_ptr_field;
00616
00617 ut_ad(extra);
00618 ut_ad(index);
00619 ut_ad(offsets);
00620 ut_ad(dict_table_is_comp(index->table));
00621
00622 if (UNIV_UNLIKELY(node_ptr)) {
00623 n_node_ptr_field = dict_index_get_n_unique_in_tree(index);
00624 n = n_node_ptr_field + 1;
00625 } else {
00626 n_node_ptr_field = ULINT_UNDEFINED;
00627 n = dict_index_get_n_fields(index);
00628 }
00629
00630 ut_a(rec_offs_get_n_alloc(offsets) >= n + (1 + REC_OFFS_HEADER_SIZE));
00631 rec_offs_set_n_fields(offsets, n);
00632
00633 nulls = extra;
00634 lens = nulls + UT_BITS_IN_BYTES(index->n_nullable);
00635 i = offs = 0;
00636 null_mask = 1;
00637 any_ext = 0;
00638
00639
00640 do {
00641 ulint len;
00642 if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
00643 len = offs += 4;
00644 goto resolved;
00645 }
00646
00647 field = dict_index_get_nth_field(index, i);
00648 if (!(dict_field_get_col(field)->prtype & DATA_NOT_NULL)) {
00649
00650
00651 if (UNIV_UNLIKELY(!(byte) null_mask)) {
00652 nulls++;
00653 null_mask = 1;
00654 }
00655
00656 if (*nulls & null_mask) {
00657 null_mask <<= 1;
00658
00659
00660
00661
00662 len = offs | REC_OFFS_SQL_NULL;
00663 goto resolved;
00664 }
00665 null_mask <<= 1;
00666 }
00667
00668 if (UNIV_UNLIKELY(!field->fixed_len)) {
00669
00670 const dict_col_t* col
00671 = dict_field_get_col(field);
00672 len = *lens++;
00673
00674
00675
00676
00677
00678
00679
00680 if (UNIV_UNLIKELY(col->len > 255)
00681 || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) {
00682 if (len & 0x80) {
00683
00684 len <<= 8;
00685 len |= *lens++;
00686
00687 offs += len & 0x3fff;
00688 if (UNIV_UNLIKELY(len & 0x4000)) {
00689 any_ext = REC_OFFS_EXTERNAL;
00690 len = offs | REC_OFFS_EXTERNAL;
00691 } else {
00692 len = offs;
00693 }
00694
00695 goto resolved;
00696 }
00697 }
00698
00699 len = offs += len;
00700 } else {
00701 len = offs += field->fixed_len;
00702 }
00703 resolved:
00704 rec_offs_base(offsets)[i + 1] = len;
00705 } while (++i < rec_offs_n_fields(offsets));
00706
00707 ut_ad(lens >= extra);
00708 *rec_offs_base(offsets) = (lens - extra + REC_N_NEW_EXTRA_BYTES)
00709 | REC_OFFS_COMPACT | any_ext;
00710 }
00711
00712
00716 UNIV_INTERN
00717 ulint
00718 rec_get_nth_field_offs_old(
00719
00720 const rec_t* rec,
00721 ulint n,
00722 ulint* len)
00724 {
00725 ulint os;
00726 ulint next_os;
00727
00728 ut_ad(len);
00729 ut_a(rec);
00730 ut_a(n < rec_get_n_fields_old(rec));
00731
00732 if (rec_get_1byte_offs_flag(rec)) {
00733 os = rec_1_get_field_start_offs(rec, n);
00734
00735 next_os = rec_1_get_field_end_info(rec, n);
00736
00737 if (next_os & REC_1BYTE_SQL_NULL_MASK) {
00738 *len = UNIV_SQL_NULL;
00739
00740 return(os);
00741 }
00742
00743 next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK;
00744 } else {
00745 os = rec_2_get_field_start_offs(rec, n);
00746
00747 next_os = rec_2_get_field_end_info(rec, n);
00748
00749 if (next_os & REC_2BYTE_SQL_NULL_MASK) {
00750 *len = UNIV_SQL_NULL;
00751
00752 return(os);
00753 }
00754
00755 next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK
00756 | REC_2BYTE_EXTERN_MASK);
00757 }
00758
00759 *len = next_os - os;
00760
00761 ut_ad(*len < UNIV_PAGE_SIZE);
00762
00763 return(os);
00764 }
00765
00766
00769 UNIV_INTERN
00770 ulint
00771 rec_get_converted_size_comp_prefix(
00772
00773 const dict_index_t* index,
00777 const dfield_t* fields,
00778 ulint n_fields,
00779 ulint* extra)
00780 {
00781 ulint extra_size;
00782 ulint data_size;
00783 ulint i;
00784 ut_ad(index);
00785 ut_ad(fields);
00786 ut_ad(n_fields > 0);
00787 ut_ad(n_fields <= dict_index_get_n_fields(index));
00788
00789 extra_size = REC_N_NEW_EXTRA_BYTES
00790 + UT_BITS_IN_BYTES(index->n_nullable);
00791 data_size = 0;
00792
00793
00794 for (i = 0; i < n_fields; i++) {
00795 const dict_field_t* field;
00796 ulint len;
00797 const dict_col_t* col;
00798
00799 field = dict_index_get_nth_field(index, i);
00800 len = dfield_get_len(&fields[i]);
00801 col = dict_field_get_col(field);
00802
00803 ut_ad(dict_col_type_assert_equal(col,
00804 dfield_get_type(&fields[i])));
00805
00806 if (dfield_is_null(&fields[i])) {
00807
00808 ut_ad(!(col->prtype & DATA_NOT_NULL));
00809 continue;
00810 }
00811
00812 ut_ad(len <= col->len || col->mtype == DATA_BLOB);
00813
00814
00815
00816
00817
00818
00819
00820
00821 if (field->fixed_len) {
00822 ut_ad(len == field->fixed_len);
00823
00824 ut_ad(!field->prefix_len
00825 || field->fixed_len == field->prefix_len);
00826 } else if (dfield_is_ext(&fields[i])) {
00827 ut_ad(col->len >= 256 || col->mtype == DATA_BLOB);
00828 extra_size += 2;
00829 } else if (len < 128
00830 || (col->len < 256 && col->mtype != DATA_BLOB)) {
00831 extra_size++;
00832 } else {
00833
00834
00835
00836
00837 extra_size += 2;
00838 }
00839 data_size += len;
00840 }
00841
00842 if (UNIV_LIKELY_NULL(extra)) {
00843 *extra = extra_size;
00844 }
00845
00846 return(extra_size + data_size);
00847 }
00848
00849
00852 UNIV_INTERN
00853 ulint
00854 rec_get_converted_size_comp(
00855
00856 const dict_index_t* index,
00860 ulint status,
00861 const dfield_t* fields,
00862 ulint n_fields,
00863 ulint* extra)
00864 {
00865 ulint size;
00866 ut_ad(index);
00867 ut_ad(fields);
00868 ut_ad(n_fields > 0);
00869
00870 switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
00871 case REC_STATUS_ORDINARY:
00872 ut_ad(n_fields == dict_index_get_n_fields(index));
00873 size = 0;
00874 break;
00875 case REC_STATUS_NODE_PTR:
00876 n_fields--;
00877 ut_ad(n_fields == dict_index_get_n_unique_in_tree(index));
00878 ut_ad(dfield_get_len(&fields[n_fields]) == REC_NODE_PTR_SIZE);
00879 size = REC_NODE_PTR_SIZE;
00880 break;
00881 case REC_STATUS_INFIMUM:
00882 case REC_STATUS_SUPREMUM:
00883
00884 if (UNIV_LIKELY_NULL(extra)) {
00885 *extra = REC_N_NEW_EXTRA_BYTES;
00886 }
00887 return(REC_N_NEW_EXTRA_BYTES + 8);
00888 default:
00889 ut_error;
00890 return(ULINT_UNDEFINED);
00891 }
00892
00893 return(size + rec_get_converted_size_comp_prefix(index, fields,
00894 n_fields, extra));
00895 }
00896
00897
00899 UNIV_INTERN
00900 void
00901 rec_set_nth_field_null_bit(
00902
00903 rec_t* rec,
00904 ulint i,
00905 ibool val)
00906 {
00907 ulint info;
00908
00909 if (rec_get_1byte_offs_flag(rec)) {
00910
00911 info = rec_1_get_field_end_info(rec, i);
00912
00913 if (val) {
00914 info = info | REC_1BYTE_SQL_NULL_MASK;
00915 } else {
00916 info = info & ~REC_1BYTE_SQL_NULL_MASK;
00917 }
00918
00919 rec_1_set_field_end_info(rec, i, info);
00920
00921 return;
00922 }
00923
00924 info = rec_2_get_field_end_info(rec, i);
00925
00926 if (val) {
00927 info = info | REC_2BYTE_SQL_NULL_MASK;
00928 } else {
00929 info = info & ~REC_2BYTE_SQL_NULL_MASK;
00930 }
00931
00932 rec_2_set_field_end_info(rec, i, info);
00933 }
00934
00935
00938 UNIV_INTERN
00939 void
00940 rec_set_nth_field_sql_null(
00941
00942 rec_t* rec,
00943 ulint n)
00944 {
00945 ulint offset;
00946
00947 offset = rec_get_field_start_offs(rec, n);
00948
00949 data_write_sql_null(rec + offset, rec_get_nth_field_size(rec, n));
00950
00951 rec_set_nth_field_null_bit(rec, n, TRUE);
00952 }
00953
00954
00958 static
00959 rec_t*
00960 rec_convert_dtuple_to_rec_old(
00961
00962 byte* buf,
00963 const dtuple_t* dtuple,
00964 ulint n_ext)
00965 {
00966 const dfield_t* field;
00967 ulint n_fields;
00968 ulint data_size;
00969 rec_t* rec;
00970 ulint end_offset;
00971 ulint ored_offset;
00972 ulint len;
00973 ulint i;
00974
00975 ut_ad(buf && dtuple);
00976 ut_ad(dtuple_validate(dtuple));
00977 ut_ad(dtuple_check_typed(dtuple));
00978
00979 n_fields = dtuple_get_n_fields(dtuple);
00980 data_size = dtuple_get_data_size(dtuple, 0);
00981
00982 ut_ad(n_fields > 0);
00983
00984
00985
00986 rec = buf + rec_get_converted_extra_size(data_size, n_fields, n_ext);
00987 #ifdef UNIV_DEBUG
00988
00989
00990 memset(buf, 0xff, rec - buf + data_size);
00991 #endif
00992
00993 rec_set_n_fields_old(rec, n_fields);
00994
00995
00996 rec_set_info_bits_old(rec, dtuple_get_info_bits(dtuple)
00997 & REC_INFO_BITS_MASK);
00998
00999
01000
01001 end_offset = 0;
01002
01003 if (!n_ext && data_size <= REC_1BYTE_OFFS_LIMIT) {
01004
01005 rec_set_1byte_offs_flag(rec, TRUE);
01006
01007 for (i = 0; i < n_fields; i++) {
01008
01009 field = dtuple_get_nth_field(dtuple, i);
01010
01011 if (dfield_is_null(field)) {
01012 len = dtype_get_sql_null_size(
01013 dfield_get_type(field), 0);
01014 data_write_sql_null(rec + end_offset, len);
01015
01016 end_offset += len;
01017 ored_offset = end_offset
01018 | REC_1BYTE_SQL_NULL_MASK;
01019 } else {
01020
01021 len = dfield_get_len(field);
01022
01023 memcpy(rec + end_offset,
01024 dfield_get_data(field), len);
01025
01026 end_offset += len;
01027 ored_offset = end_offset;
01028 }
01029
01030 rec_1_set_field_end_info(rec, i, ored_offset);
01031 }
01032 } else {
01033 rec_set_1byte_offs_flag(rec, FALSE);
01034
01035 for (i = 0; i < n_fields; i++) {
01036
01037 field = dtuple_get_nth_field(dtuple, i);
01038
01039 if (dfield_is_null(field)) {
01040 len = dtype_get_sql_null_size(
01041 dfield_get_type(field), 0);
01042 data_write_sql_null(rec + end_offset, len);
01043
01044 end_offset += len;
01045 ored_offset = end_offset
01046 | REC_2BYTE_SQL_NULL_MASK;
01047 } else {
01048
01049 len = dfield_get_len(field);
01050
01051 memcpy(rec + end_offset,
01052 dfield_get_data(field), len);
01053
01054 end_offset += len;
01055 ored_offset = end_offset;
01056
01057 if (dfield_is_ext(field)) {
01058 ored_offset |= REC_2BYTE_EXTERN_MASK;
01059 }
01060 }
01061
01062 rec_2_set_field_end_info(rec, i, ored_offset);
01063 }
01064 }
01065
01066 return(rec);
01067 }
01068
01069
01071 UNIV_INTERN
01072 void
01073 rec_convert_dtuple_to_rec_comp(
01074
01075 rec_t* rec,
01076 ulint extra,
01080 const dict_index_t* index,
01081 ulint status,
01082 const dfield_t* fields,
01083 ulint n_fields)
01084 {
01085 const dfield_t* field;
01086 const dtype_t* type;
01087 byte* end;
01088 byte* nulls;
01089 byte* lens;
01090 ulint len;
01091 ulint i;
01092 ulint n_node_ptr_field;
01093 ulint fixed_len;
01094 ulint null_mask = 1;
01095 ut_ad(extra == 0 || dict_table_is_comp(index->table));
01096 ut_ad(extra == 0 || extra == REC_N_NEW_EXTRA_BYTES);
01097 ut_ad(n_fields > 0);
01098
01099 switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
01100 case REC_STATUS_ORDINARY:
01101 ut_ad(n_fields <= dict_index_get_n_fields(index));
01102 n_node_ptr_field = ULINT_UNDEFINED;
01103 break;
01104 case REC_STATUS_NODE_PTR:
01105 ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1);
01106 n_node_ptr_field = n_fields - 1;
01107 break;
01108 case REC_STATUS_INFIMUM:
01109 case REC_STATUS_SUPREMUM:
01110 ut_ad(n_fields == 1);
01111 n_node_ptr_field = ULINT_UNDEFINED;
01112 break;
01113 default:
01114 ut_error;
01115 return;
01116 }
01117
01118 end = rec;
01119 nulls = rec - (extra + 1);
01120 lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
01121
01122 memset(lens + 1, 0, nulls - lens);
01123
01124
01125
01126 for (i = 0, field = fields; i < n_fields; i++, field++) {
01127 const dict_field_t* ifield;
01128
01129 type = dfield_get_type(field);
01130 len = dfield_get_len(field);
01131
01132 if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
01133 ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
01134 ut_ad(len == 4);
01135 memcpy(end, dfield_get_data(field), len);
01136 end += 4;
01137 break;
01138 }
01139
01140 if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
01141
01142 ut_ad(index->n_nullable > 0);
01143
01144 if (UNIV_UNLIKELY(!(byte) null_mask)) {
01145 nulls--;
01146 null_mask = 1;
01147 }
01148
01149 ut_ad(*nulls < null_mask);
01150
01151
01152 if (dfield_is_null(field)) {
01153 *nulls |= null_mask;
01154 null_mask <<= 1;
01155 continue;
01156 }
01157
01158 null_mask <<= 1;
01159 }
01160
01161 ut_ad(!dfield_is_null(field));
01162
01163 ifield = dict_index_get_nth_field(index, i);
01164 fixed_len = ifield->fixed_len;
01165
01166
01167
01168
01169
01170
01171 if (fixed_len) {
01172 ut_ad(len == fixed_len);
01173 ut_ad(!dfield_is_ext(field));
01174 } else if (dfield_is_ext(field)) {
01175 ut_ad(ifield->col->len >= 256
01176 || ifield->col->mtype == DATA_BLOB);
01177 ut_ad(len <= REC_MAX_INDEX_COL_LEN
01178 + BTR_EXTERN_FIELD_REF_SIZE);
01179 *lens-- = (byte) (len >> 8) | 0xc0;
01180 *lens-- = (byte) len;
01181 } else {
01182 ut_ad(len <= dtype_get_len(type)
01183 || dtype_get_mtype(type) == DATA_BLOB);
01184 if (len < 128
01185 || (dtype_get_len(type) < 256
01186 && dtype_get_mtype(type) != DATA_BLOB)) {
01187
01188 *lens-- = (byte) len;
01189 } else {
01190 ut_ad(len < 16384);
01191 *lens-- = (byte) (len >> 8) | 0x80;
01192 *lens-- = (byte) len;
01193 }
01194 }
01195
01196 memcpy(end, dfield_get_data(field), len);
01197 end += len;
01198 }
01199 }
01200
01201
01205 static
01206 rec_t*
01207 rec_convert_dtuple_to_rec_new(
01208
01209 byte* buf,
01211 const dict_index_t* index,
01212 const dtuple_t* dtuple)
01213 {
01214 ulint extra_size;
01215 ulint status;
01216 rec_t* rec;
01217
01218 status = dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK;
01219 rec_get_converted_size_comp(index, status,
01220 dtuple->fields, dtuple->n_fields,
01221 &extra_size);
01222 rec = buf + extra_size;
01223
01224 rec_convert_dtuple_to_rec_comp(
01225 rec, REC_N_NEW_EXTRA_BYTES, index, status,
01226 dtuple->fields, dtuple->n_fields);
01227
01228
01229 rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple));
01230
01231 return(rec);
01232 }
01233
01234
01238 UNIV_INTERN
01239 rec_t*
01240 rec_convert_dtuple_to_rec(
01241
01242 byte* buf,
01244 const dict_index_t* index,
01245 const dtuple_t* dtuple,
01246 ulint n_ext)
01248 {
01249 rec_t* rec;
01250
01251 ut_ad(buf && index && dtuple);
01252 ut_ad(dtuple_validate(dtuple));
01253 ut_ad(dtuple_check_typed(dtuple));
01254
01255 if (dict_table_is_comp(index->table)) {
01256 rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
01257 } else {
01258 rec = rec_convert_dtuple_to_rec_old(buf, dtuple, n_ext);
01259 }
01260
01261 #ifdef UNIV_DEBUG
01262 {
01263 mem_heap_t* heap = NULL;
01264 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01265 const ulint* offsets;
01266 ulint i;
01267 rec_offs_init(offsets_);
01268
01269 offsets = rec_get_offsets(rec, index,
01270 offsets_, ULINT_UNDEFINED, &heap);
01271 ut_ad(rec_validate(rec, offsets));
01272 ut_ad(dtuple_get_n_fields(dtuple)
01273 == rec_offs_n_fields(offsets));
01274
01275 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
01276 ut_ad(!dfield_is_ext(dtuple_get_nth_field(dtuple, i))
01277 == !rec_offs_nth_extern(offsets, i));
01278 }
01279
01280 if (UNIV_LIKELY_NULL(heap)) {
01281 mem_heap_free(heap);
01282 }
01283 }
01284 #endif
01285 return(rec);
01286 }
01287
01288
01291 UNIV_INTERN
01292 void
01293 rec_copy_prefix_to_dtuple(
01294
01295 dtuple_t* tuple,
01296 const rec_t* rec,
01297 const dict_index_t* index,
01298 ulint n_fields,
01300 mem_heap_t* heap)
01301 {
01302 ulint i;
01303 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01304 ulint* offsets = offsets_;
01305 rec_offs_init(offsets_);
01306
01307 offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap);
01308
01309 ut_ad(rec_validate(rec, offsets));
01310 ut_ad(dtuple_check_typed(tuple));
01311
01312 dtuple_set_info_bits(tuple, rec_get_info_bits(
01313 rec, dict_table_is_comp(index->table)));
01314
01315 for (i = 0; i < n_fields; i++) {
01316 dfield_t* field;
01317 const byte* data;
01318 ulint len;
01319
01320 field = dtuple_get_nth_field(tuple, i);
01321 data = rec_get_nth_field(rec, offsets, i, &len);
01322
01323 if (len != UNIV_SQL_NULL) {
01324 dfield_set_data(field,
01325 mem_heap_dup(heap, data, len), len);
01326 ut_ad(!rec_offs_nth_extern(offsets, i));
01327 } else {
01328 dfield_set_null(field);
01329 }
01330 }
01331 }
01332
01333
01337 static
01338 rec_t*
01339 rec_copy_prefix_to_buf_old(
01340
01341 const rec_t* rec,
01342 ulint n_fields,
01343 ulint area_end,
01344 byte** buf,
01346 ulint* buf_size)
01347 {
01348 rec_t* copy_rec;
01349 ulint area_start;
01350 ulint prefix_len;
01351
01352 if (rec_get_1byte_offs_flag(rec)) {
01353 area_start = REC_N_OLD_EXTRA_BYTES + n_fields;
01354 } else {
01355 area_start = REC_N_OLD_EXTRA_BYTES + 2 * n_fields;
01356 }
01357
01358 prefix_len = area_start + area_end;
01359
01360 if ((*buf == NULL) || (*buf_size < prefix_len)) {
01361 if (*buf != NULL) {
01362 mem_free(*buf);
01363 }
01364
01365 *buf = static_cast<byte *>(mem_alloc2(prefix_len, buf_size));
01366 }
01367
01368 ut_memcpy(*buf, rec - area_start, prefix_len);
01369
01370 copy_rec = *buf + area_start;
01371
01372 rec_set_n_fields_old(copy_rec, n_fields);
01373
01374 return(copy_rec);
01375 }
01376
01377
01381 UNIV_INTERN
01382 rec_t*
01383 rec_copy_prefix_to_buf(
01384
01385 const rec_t* rec,
01386 const dict_index_t* index,
01387 ulint n_fields,
01389 byte** buf,
01392 ulint* buf_size)
01393 {
01394 const byte* nulls;
01395 const byte* lens;
01396 ulint i;
01397 ulint prefix_len;
01398 ulint null_mask;
01399 ulint status;
01400
01401 UNIV_PREFETCH_RW(*buf);
01402
01403 if (!dict_table_is_comp(index->table)) {
01404 ut_ad(rec_validate_old(rec));
01405 return(rec_copy_prefix_to_buf_old(
01406 rec, n_fields,
01407 rec_get_field_start_offs(rec, n_fields),
01408 buf, buf_size));
01409 }
01410
01411 status = rec_get_status(rec);
01412
01413 switch (status) {
01414 case REC_STATUS_ORDINARY:
01415 ut_ad(n_fields <= dict_index_get_n_fields(index));
01416 break;
01417 case REC_STATUS_NODE_PTR:
01418
01419 ut_ad(n_fields <= dict_index_get_n_unique_in_tree(index));
01420 break;
01421 case REC_STATUS_INFIMUM:
01422 case REC_STATUS_SUPREMUM:
01423
01424 default:
01425 ut_error;
01426 return(NULL);
01427 }
01428
01429 nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
01430 lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
01431 UNIV_PREFETCH_R(lens);
01432 prefix_len = 0;
01433 null_mask = 1;
01434
01435
01436 for (i = 0; i < n_fields; i++) {
01437 const dict_field_t* field;
01438 const dict_col_t* col;
01439
01440 field = dict_index_get_nth_field(index, i);
01441 col = dict_field_get_col(field);
01442
01443 if (!(col->prtype & DATA_NOT_NULL)) {
01444
01445 if (UNIV_UNLIKELY(!(byte) null_mask)) {
01446 nulls--;
01447 null_mask = 1;
01448 }
01449
01450 if (*nulls & null_mask) {
01451 null_mask <<= 1;
01452 continue;
01453 }
01454
01455 null_mask <<= 1;
01456 }
01457
01458 if (field->fixed_len) {
01459 prefix_len += field->fixed_len;
01460 } else {
01461 ulint len = *lens--;
01462
01463
01464
01465
01466
01467
01468
01469 if (col->len > 255 || col->mtype == DATA_BLOB) {
01470 if (len & 0x80) {
01471
01472 len &= 0x3f;
01473 len <<= 8;
01474 len |= *lens--;
01475 UNIV_PREFETCH_R(lens);
01476 }
01477 }
01478 prefix_len += len;
01479 }
01480 }
01481
01482 UNIV_PREFETCH_R(rec + prefix_len);
01483
01484 prefix_len += rec - (lens + 1);
01485
01486 if ((*buf == NULL) || (*buf_size < prefix_len)) {
01487 if (*buf != NULL) {
01488 mem_free(*buf);
01489 }
01490
01491 *buf = static_cast<byte *>(mem_alloc2(prefix_len, buf_size));
01492 }
01493
01494 memcpy(*buf, lens + 1, prefix_len);
01495
01496 return(*buf + (rec - (lens + 1)));
01497 }
01498
01499
01502 static
01503 ibool
01504 rec_validate_old(
01505
01506 const rec_t* rec)
01507 {
01508 const byte* data;
01509 ulint len;
01510 ulint n_fields;
01511 ulint len_sum = 0;
01512 ulint sum = 0;
01513 ulint i;
01514
01515 ut_a(rec);
01516 n_fields = rec_get_n_fields_old(rec);
01517
01518 if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
01519 fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
01520 (ulong) n_fields);
01521 return(FALSE);
01522 }
01523
01524 for (i = 0; i < n_fields; i++) {
01525 data = rec_get_nth_field_old(rec, i, &len);
01526
01527 if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
01528 fprintf(stderr,
01529 "InnoDB: Error: record field %lu len %lu\n",
01530 (ulong) i,
01531 (ulong) len);
01532 return(FALSE);
01533 }
01534
01535 if (len != UNIV_SQL_NULL) {
01536 len_sum += len;
01537 sum += *(data + len -1);
01538
01539
01540
01541 } else {
01542 len_sum += rec_get_nth_field_size(rec, i);
01543 }
01544 }
01545
01546 if (len_sum != rec_get_data_size_old(rec)) {
01547 fprintf(stderr,
01548 "InnoDB: Error: record len should be %lu, len %lu\n",
01549 (ulong) len_sum,
01550 rec_get_data_size_old(rec));
01551 return(FALSE);
01552 }
01553
01554 rec_dummy = sum;
01555
01556 return(TRUE);
01557 }
01558
01559
01562 UNIV_INTERN
01563 ibool
01564 rec_validate(
01565
01566 const rec_t* rec,
01567 const ulint* offsets)
01568 {
01569 const byte* data;
01570 ulint len;
01571 ulint n_fields;
01572 ulint len_sum = 0;
01573 ulint sum = 0;
01574 ulint i;
01575
01576 ut_a(rec);
01577 n_fields = rec_offs_n_fields(offsets);
01578
01579 if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
01580 fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
01581 (ulong) n_fields);
01582 return(FALSE);
01583 }
01584
01585 ut_a(rec_offs_comp(offsets) || n_fields <= rec_get_n_fields_old(rec));
01586
01587 for (i = 0; i < n_fields; i++) {
01588 data = rec_get_nth_field(rec, offsets, i, &len);
01589
01590 if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
01591 fprintf(stderr,
01592 "InnoDB: Error: record field %lu len %lu\n",
01593 (ulong) i,
01594 (ulong) len);
01595 return(FALSE);
01596 }
01597
01598 if (len != UNIV_SQL_NULL) {
01599 len_sum += len;
01600 sum += *(data + len -1);
01601
01602
01603
01604 } else if (!rec_offs_comp(offsets)) {
01605 len_sum += rec_get_nth_field_size(rec, i);
01606 }
01607 }
01608
01609 if (len_sum != rec_offs_data_size(offsets)) {
01610 fprintf(stderr,
01611 "InnoDB: Error: record len should be %lu, len %lu\n",
01612 (ulong) len_sum,
01613 (ulong) rec_offs_data_size(offsets));
01614 return(FALSE);
01615 }
01616
01617 rec_dummy = sum;
01618
01619 if (!rec_offs_comp(offsets)) {
01620 ut_a(rec_validate_old(rec));
01621 }
01622
01623 return(TRUE);
01624 }
01625
01626
01628 UNIV_INTERN
01629 void
01630 rec_print_old(
01631
01632 FILE* file,
01633 const rec_t* rec)
01634 {
01635 const byte* data;
01636 ulint len;
01637 ulint n;
01638 ulint i;
01639
01640 ut_ad(rec);
01641
01642 n = rec_get_n_fields_old(rec);
01643
01644 fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
01645 " %u-byte offsets; info bits %lu\n",
01646 (ulong) n,
01647 rec_get_1byte_offs_flag(rec) ? 1 : 2,
01648 (ulong) rec_get_info_bits(rec, FALSE));
01649
01650 for (i = 0; i < n; i++) {
01651
01652 data = rec_get_nth_field_old(rec, i, &len);
01653
01654 fprintf(file, " %lu:", (ulong) i);
01655
01656 if (len != UNIV_SQL_NULL) {
01657 if (len <= 30) {
01658
01659 ut_print_buf(file, data, len);
01660 } else {
01661 ut_print_buf(file, data, 30);
01662
01663 fprintf(file, " (total %lu bytes)",
01664 (ulong) len);
01665 }
01666 } else {
01667 fprintf(file, " SQL NULL, size %lu ",
01668 rec_get_nth_field_size(rec, i));
01669 }
01670
01671 putc(';', file);
01672 putc('\n', file);
01673 }
01674
01675 rec_validate_old(rec);
01676 }
01677
01678 #ifndef UNIV_HOTBACKUP
01679
01682 UNIV_INTERN
01683 void
01684 rec_print_comp(
01685
01686 FILE* file,
01687 const rec_t* rec,
01688 const ulint* offsets)
01689 {
01690 ulint i;
01691
01692 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
01693 const byte* data;
01694 ulint len;
01695
01696 data = rec_get_nth_field(rec, offsets, i, &len);
01697
01698 fprintf(file, " %lu:", (ulong) i);
01699
01700 if (len != UNIV_SQL_NULL) {
01701 if (len <= 30) {
01702
01703 ut_print_buf(file, data, len);
01704 } else {
01705 ut_print_buf(file, data, 30);
01706
01707 fprintf(file, " (total %lu bytes)",
01708 (ulong) len);
01709 }
01710 } else {
01711 fputs(" SQL NULL", file);
01712 }
01713 putc(';', file);
01714 putc('\n', file);
01715 }
01716 }
01717
01718
01720 UNIV_INTERN
01721 void
01722 rec_print_new(
01723
01724 FILE* file,
01725 const rec_t* rec,
01726 const ulint* offsets)
01727 {
01728 ut_ad(rec);
01729 ut_ad(offsets);
01730 ut_ad(rec_offs_validate(rec, NULL, offsets));
01731
01732 if (!rec_offs_comp(offsets)) {
01733 rec_print_old(file, rec);
01734 return;
01735 }
01736
01737 fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
01738 " compact format; info bits %lu\n",
01739 (ulong) rec_offs_n_fields(offsets),
01740 (ulong) rec_get_info_bits(rec, TRUE));
01741
01742 rec_print_comp(file, rec, offsets);
01743 rec_validate(rec, offsets);
01744 }
01745
01746
01748 UNIV_INTERN
01749 void
01750 rec_print(
01751
01752 FILE* file,
01753 const rec_t* rec,
01754 const dict_index_t* index)
01755 {
01756 ut_ad(index);
01757
01758 if (!dict_table_is_comp(index->table)) {
01759 rec_print_old(file, rec);
01760 return;
01761 } else {
01762 mem_heap_t* heap = NULL;
01763 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01764 rec_offs_init(offsets_);
01765
01766 rec_print_new(file, rec,
01767 rec_get_offsets(rec, index, offsets_,
01768 ULINT_UNDEFINED, &heap));
01769 if (UNIV_LIKELY_NULL(heap)) {
01770 mem_heap_free(heap);
01771 }
01772 }
01773 }
01774 #endif