00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "row0upd.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "row0upd.ic"
00030 #endif
00031
00032 #include "dict0dict.h"
00033 #include "trx0undo.h"
00034 #include "rem0rec.h"
00035 #ifndef UNIV_HOTBACKUP
00036 #include "dict0boot.h"
00037 #include "dict0crea.h"
00038 #include "mach0data.h"
00039 #include "btr0btr.h"
00040 #include "btr0cur.h"
00041 #include "que0que.h"
00042 #include "row0ext.h"
00043 #include "row0ins.h"
00044 #include "row0sel.h"
00045 #include "row0row.h"
00046 #include "rem0cmp.h"
00047 #include "lock0lock.h"
00048 #include "log0log.h"
00049 #include "pars0sym.h"
00050 #include "eval0eval.h"
00051 #include "buf0lru.h"
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
00120 static
00121 ibool
00122 row_upd_changes_first_fields_binary(
00123
00124 dtuple_t* entry,
00125 dict_index_t* index,
00126 const upd_t* update,
00127 ulint n);
00130
00139 static
00140 ibool
00141 row_upd_index_is_referenced(
00142
00143 dict_index_t* index,
00144 trx_t* trx)
00145 {
00146 dict_table_t* table = index->table;
00147 dict_foreign_t* foreign;
00148 ibool froze_data_dict = FALSE;
00149 ibool is_referenced = FALSE;
00150
00151 if (!UT_LIST_GET_FIRST(table->referenced_list)) {
00152
00153 return(FALSE);
00154 }
00155
00156 if (trx->dict_operation_lock_mode == 0) {
00157 row_mysql_freeze_data_dictionary(trx);
00158 froze_data_dict = TRUE;
00159 }
00160
00161 foreign = UT_LIST_GET_FIRST(table->referenced_list);
00162
00163 while (foreign) {
00164 if (foreign->referenced_index == index) {
00165
00166 is_referenced = TRUE;
00167 goto func_exit;
00168 }
00169
00170 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
00171 }
00172
00173 func_exit:
00174 if (froze_data_dict) {
00175 row_mysql_unfreeze_data_dictionary(trx);
00176 }
00177
00178 return(is_referenced);
00179 }
00180
00181
00189 static
00190 ulint
00191 row_upd_check_references_constraints(
00192
00193 upd_node_t* node,
00194 btr_pcur_t* pcur,
00196 dict_table_t* table,
00197 dict_index_t* index,
00198 ulint* offsets,
00199 que_thr_t* thr,
00200 mtr_t* mtr)
00201 {
00202 dict_foreign_t* foreign;
00203 mem_heap_t* heap;
00204 dtuple_t* entry;
00205 trx_t* trx;
00206 const rec_t* rec;
00207 ulint n_ext;
00208 ulint err;
00209 ibool got_s_lock = FALSE;
00210
00211 if (UT_LIST_GET_FIRST(table->referenced_list) == NULL) {
00212
00213 return(DB_SUCCESS);
00214 }
00215
00216 trx = thr_get_trx(thr);
00217
00218 rec = btr_pcur_get_rec(pcur);
00219 ut_ad(rec_offs_validate(rec, index, offsets));
00220
00221 heap = mem_heap_create(500);
00222
00223 entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets,
00224 &n_ext, heap);
00225
00226 mtr_commit(mtr);
00227
00228 mtr_start(mtr);
00229
00230 if (trx->dict_operation_lock_mode == 0) {
00231 got_s_lock = TRUE;
00232
00233 row_mysql_freeze_data_dictionary(trx);
00234 }
00235
00236 foreign = UT_LIST_GET_FIRST(table->referenced_list);
00237
00238 while (foreign) {
00239
00240
00241
00242
00243
00244 if (foreign->referenced_index == index
00245 && (node->is_delete
00246 || row_upd_changes_first_fields_binary(
00247 entry, index, node->update,
00248 foreign->n_fields))) {
00249
00250 if (foreign->foreign_table == NULL) {
00251 dict_table_get(foreign->foreign_table_name,
00252 FALSE);
00253 }
00254
00255 if (foreign->foreign_table) {
00256 mutex_enter(&(dict_sys->mutex));
00257
00258 (foreign->foreign_table
00259 ->n_foreign_key_checks_running)++;
00260
00261 mutex_exit(&(dict_sys->mutex));
00262 }
00263
00264
00265
00266
00267
00268
00269 err = row_ins_check_foreign_constraint(
00270 FALSE, foreign, table, entry, thr);
00271
00272 if (foreign->foreign_table) {
00273 mutex_enter(&(dict_sys->mutex));
00274
00275 ut_a(foreign->foreign_table
00276 ->n_foreign_key_checks_running > 0);
00277
00278 (foreign->foreign_table
00279 ->n_foreign_key_checks_running)--;
00280
00281 mutex_exit(&(dict_sys->mutex));
00282 }
00283
00284 if (err != DB_SUCCESS) {
00285
00286 goto func_exit;
00287 }
00288 }
00289
00290 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
00291 }
00292
00293 err = DB_SUCCESS;
00294
00295 func_exit:
00296 if (got_s_lock) {
00297 row_mysql_unfreeze_data_dictionary(trx);
00298 }
00299
00300 mem_heap_free(heap);
00301
00302 return(err);
00303 }
00304
00305
00308 UNIV_INTERN
00309 upd_node_t*
00310 upd_node_create(
00311
00312 mem_heap_t* heap)
00313 {
00314 upd_node_t* node;
00315
00316 node = static_cast<upd_node_t *>(mem_heap_alloc(heap, sizeof(upd_node_t)));
00317 node->common.type = QUE_NODE_UPDATE;
00318
00319 node->state = UPD_NODE_UPDATE_CLUSTERED;
00320 node->in_mysql_interface = FALSE;
00321
00322 node->row = NULL;
00323 node->ext = NULL;
00324 node->upd_row = NULL;
00325 node->upd_ext = NULL;
00326 node->index = NULL;
00327 node->update = NULL;
00328
00329 node->foreign = NULL;
00330 node->cascade_heap = NULL;
00331 node->cascade_node = NULL;
00332
00333 node->select = NULL;
00334
00335 node->heap = mem_heap_create(128);
00336 node->magic_n = UPD_NODE_MAGIC_N;
00337
00338 node->cmpl_info = 0;
00339
00340 return(node);
00341 }
00342 #endif
00343
00344
00347 UNIV_INTERN
00348 void
00349 row_upd_rec_sys_fields_in_recovery(
00350
00351 rec_t* rec,
00352 page_zip_des_t* page_zip,
00353 const ulint* offsets,
00354 ulint pos,
00355 trx_id_t trx_id,
00356 roll_ptr_t roll_ptr)
00357 {
00358 ut_ad(rec_offs_validate(rec, NULL, offsets));
00359
00360 if (UNIV_LIKELY_NULL(page_zip)) {
00361 page_zip_write_trx_id_and_roll_ptr(
00362 page_zip, rec, offsets, pos, trx_id, roll_ptr);
00363 } else {
00364 byte* field;
00365 ulint len;
00366
00367 field = rec_get_nth_field(rec, offsets, pos, &len);
00368 ut_ad(len == DATA_TRX_ID_LEN);
00369 #if DATA_TRX_ID + 1 != DATA_ROLL_PTR
00370 # error "DATA_TRX_ID + 1 != DATA_ROLL_PTR"
00371 #endif
00372 trx_write_trx_id(field, trx_id);
00373 trx_write_roll_ptr(field + DATA_TRX_ID_LEN, roll_ptr);
00374 }
00375 }
00376
00377 #ifndef UNIV_HOTBACKUP
00378
00380 UNIV_INTERN
00381 void
00382 row_upd_index_entry_sys_field(
00383
00384 dtuple_t* entry,
00388 dict_index_t* index,
00389 ulint type,
00390 ib_uint64_t val)
00391 {
00392 dfield_t* dfield;
00393 byte* field;
00394 ulint pos;
00395
00396 ut_ad(dict_index_is_clust(index));
00397
00398 pos = dict_index_get_sys_col_pos(index, type);
00399
00400 dfield = dtuple_get_nth_field(entry, pos);
00401 field = static_cast<byte *>(dfield_get_data(dfield));
00402
00403 if (type == DATA_TRX_ID) {
00404 trx_write_trx_id(field, val);
00405 } else {
00406 ut_ad(type == DATA_ROLL_PTR);
00407 trx_write_roll_ptr(field, val);
00408 }
00409 }
00410
00411
00416 UNIV_INTERN
00417 ibool
00418 row_upd_changes_field_size_or_external(
00419
00420 dict_index_t* index,
00421 const ulint* offsets,
00422 const upd_t* update)
00423 {
00424 const upd_field_t* upd_field;
00425 const dfield_t* new_val;
00426 ulint old_len;
00427 ulint new_len;
00428 ulint n_fields;
00429 ulint i;
00430
00431 ut_ad(rec_offs_validate(NULL, index, offsets));
00432 n_fields = upd_get_n_fields(update);
00433
00434 for (i = 0; i < n_fields; i++) {
00435 upd_field = upd_get_nth_field(update, i);
00436
00437 new_val = &(upd_field->new_val);
00438 new_len = dfield_get_len(new_val);
00439
00440 if (dfield_is_null(new_val) && !rec_offs_comp(offsets)) {
00441
00442
00443
00444
00445
00446 new_len = dict_col_get_sql_null_size(
00447 dict_index_get_nth_col(index,
00448 upd_field->field_no),
00449 0);
00450 }
00451
00452 old_len = rec_offs_nth_size(offsets, upd_field->field_no);
00453
00454 if (rec_offs_comp(offsets)
00455 && rec_offs_nth_sql_null(offsets,
00456 upd_field->field_no)) {
00457
00458
00459
00460
00461
00462
00463
00464 old_len = UNIV_SQL_NULL;
00465 }
00466
00467 if (dfield_is_ext(new_val) || old_len != new_len
00468 || rec_offs_nth_extern(offsets, upd_field->field_no)) {
00469
00470 return(TRUE);
00471 }
00472 }
00473
00474 return(FALSE);
00475 }
00476 #endif
00477
00478
00484 UNIV_INTERN
00485 void
00486 row_upd_rec_in_place(
00487
00488 rec_t* rec,
00489 dict_index_t* index,
00490 const ulint* offsets,
00491 const upd_t* update,
00492 page_zip_des_t* page_zip)
00494 {
00495 const upd_field_t* upd_field;
00496 const dfield_t* new_val;
00497 ulint n_fields;
00498 ulint i;
00499
00500 ut_ad(rec_offs_validate(rec, index, offsets));
00501
00502 if (rec_offs_comp(offsets)) {
00503 rec_set_info_bits_new(rec, update->info_bits);
00504 } else {
00505 rec_set_info_bits_old(rec, update->info_bits);
00506 }
00507
00508 n_fields = upd_get_n_fields(update);
00509
00510 for (i = 0; i < n_fields; i++) {
00511 upd_field = upd_get_nth_field(update, i);
00512 new_val = &(upd_field->new_val);
00513 ut_ad(!dfield_is_ext(new_val) ==
00514 !rec_offs_nth_extern(offsets, upd_field->field_no));
00515
00516 rec_set_nth_field(rec, offsets, upd_field->field_no,
00517 dfield_get_data(new_val),
00518 dfield_get_len(new_val));
00519 }
00520
00521 if (UNIV_LIKELY_NULL(page_zip)) {
00522 page_zip_write_rec(page_zip, rec, index, offsets, 0);
00523 }
00524 }
00525
00526 #ifndef UNIV_HOTBACKUP
00527
00531 UNIV_INTERN
00532 byte*
00533 row_upd_write_sys_vals_to_log(
00534
00535 dict_index_t* index,
00536 trx_t* trx,
00537 roll_ptr_t roll_ptr,
00538 byte* log_ptr,
00540 mtr_t* )
00541 {
00542 ut_ad(dict_index_is_clust(index));
00543 ut_ad(mtr);
00544
00545 log_ptr += mach_write_compressed(log_ptr,
00546 dict_index_get_sys_col_pos(
00547 index, DATA_TRX_ID));
00548
00549 trx_write_roll_ptr(log_ptr, roll_ptr);
00550 log_ptr += DATA_ROLL_PTR_LEN;
00551
00552 log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
00553
00554 return(log_ptr);
00555 }
00556 #endif
00557
00558
00561 UNIV_INTERN
00562 byte*
00563 row_upd_parse_sys_vals(
00564
00565 byte* ptr,
00566 byte* end_ptr,
00567 ulint* pos,
00568 trx_id_t* trx_id,
00569 roll_ptr_t* roll_ptr)
00570 {
00571 ptr = mach_parse_compressed(ptr, end_ptr, pos);
00572
00573 if (ptr == NULL) {
00574
00575 return(NULL);
00576 }
00577
00578 if (end_ptr < ptr + DATA_ROLL_PTR_LEN) {
00579
00580 return(NULL);
00581 }
00582
00583 *roll_ptr = trx_read_roll_ptr(ptr);
00584 ptr += DATA_ROLL_PTR_LEN;
00585
00586 ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
00587
00588 return(ptr);
00589 }
00590
00591 #ifndef UNIV_HOTBACKUP
00592
00594 UNIV_INTERN
00595 void
00596 row_upd_index_write_log(
00597
00598 const upd_t* update,
00599 byte* log_ptr,
00603 mtr_t* mtr)
00604 {
00605 const upd_field_t* upd_field;
00606 const dfield_t* new_val;
00607 ulint len;
00608 ulint n_fields;
00609 byte* buf_end;
00610 ulint i;
00611
00612 n_fields = upd_get_n_fields(update);
00613
00614 buf_end = log_ptr + MLOG_BUF_MARGIN;
00615
00616 mach_write_to_1(log_ptr, update->info_bits);
00617 log_ptr++;
00618 log_ptr += mach_write_compressed(log_ptr, n_fields);
00619
00620 for (i = 0; i < n_fields; i++) {
00621
00622 #if MLOG_BUF_MARGIN <= 30
00623 # error "MLOG_BUF_MARGIN <= 30"
00624 #endif
00625
00626 if (log_ptr + 30 > buf_end) {
00627 mlog_close(mtr, log_ptr);
00628
00629 log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN);
00630 buf_end = log_ptr + MLOG_BUF_MARGIN;
00631 }
00632
00633 upd_field = upd_get_nth_field(update, i);
00634
00635 new_val = &(upd_field->new_val);
00636
00637 len = dfield_get_len(new_val);
00638
00639 log_ptr += mach_write_compressed(log_ptr, upd_field->field_no);
00640 log_ptr += mach_write_compressed(log_ptr, len);
00641
00642 if (len != UNIV_SQL_NULL) {
00643 if (log_ptr + len < buf_end) {
00644 memcpy(log_ptr, dfield_get_data(new_val), len);
00645
00646 log_ptr += len;
00647 } else {
00648 mlog_close(mtr, log_ptr);
00649
00650 mlog_catenate_string(mtr,
00651 static_cast<byte *>(dfield_get_data(new_val)),
00652 len);
00653
00654 log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN);
00655 buf_end = log_ptr + MLOG_BUF_MARGIN;
00656 }
00657 }
00658 }
00659
00660 mlog_close(mtr, log_ptr);
00661 }
00662 #endif
00663
00664
00667 UNIV_INTERN
00668 byte*
00669 row_upd_index_parse(
00670
00671 byte* ptr,
00672 byte* end_ptr,
00673 mem_heap_t* heap,
00675 upd_t** update_out)
00676 {
00677 upd_t* update;
00678 upd_field_t* upd_field;
00679 dfield_t* new_val;
00680 ulint len;
00681 ulint n_fields;
00682 ulint info_bits;
00683 ulint i;
00684
00685 if (end_ptr < ptr + 1) {
00686
00687 return(NULL);
00688 }
00689
00690 info_bits = mach_read_from_1(ptr);
00691 ptr++;
00692 ptr = mach_parse_compressed(ptr, end_ptr, &n_fields);
00693
00694 if (ptr == NULL) {
00695
00696 return(NULL);
00697 }
00698
00699 update = upd_create(n_fields, heap);
00700 update->info_bits = info_bits;
00701
00702 for (i = 0; i < n_fields; i++) {
00703 ulint field_no;
00704 upd_field = upd_get_nth_field(update, i);
00705 new_val = &(upd_field->new_val);
00706
00707 ptr = mach_parse_compressed(ptr, end_ptr, &field_no);
00708
00709 if (ptr == NULL) {
00710
00711 return(NULL);
00712 }
00713
00714 upd_field->field_no = field_no;
00715
00716 ptr = mach_parse_compressed(ptr, end_ptr, &len);
00717
00718 if (ptr == NULL) {
00719
00720 return(NULL);
00721 }
00722
00723 if (len != UNIV_SQL_NULL) {
00724
00725 if (end_ptr < ptr + len) {
00726
00727 return(NULL);
00728 }
00729
00730 dfield_set_data(new_val,
00731 mem_heap_dup(heap, ptr, len), len);
00732 ptr += len;
00733 } else {
00734 dfield_set_null(new_val);
00735 }
00736 }
00737
00738 *update_out = update;
00739
00740 return(ptr);
00741 }
00742
00743 #ifndef UNIV_HOTBACKUP
00744
00749 UNIV_INTERN
00750 upd_t*
00751 row_upd_build_sec_rec_difference_binary(
00752
00753 dict_index_t* index,
00754 const dtuple_t* entry,
00755 const rec_t* rec,
00756 trx_t* trx,
00757 mem_heap_t* heap)
00758 {
00759 upd_field_t* upd_field;
00760 const dfield_t* dfield;
00761 const byte* data;
00762 ulint len;
00763 upd_t* update;
00764 ulint n_diff;
00765 ulint i;
00766 ulint offsets_[REC_OFFS_SMALL_SIZE];
00767 const ulint* offsets;
00768 rec_offs_init(offsets_);
00769
00770
00771 ut_a(!dict_index_is_clust(index));
00772
00773 update = upd_create(dtuple_get_n_fields(entry), heap);
00774
00775 n_diff = 0;
00776 offsets = rec_get_offsets(rec, index, offsets_,
00777 ULINT_UNDEFINED, &heap);
00778
00779 for (i = 0; i < dtuple_get_n_fields(entry); i++) {
00780
00781 data = rec_get_nth_field(rec, offsets, i, &len);
00782
00783 dfield = dtuple_get_nth_field(entry, i);
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 if (!dfield_data_is_binary_equal(dfield, len, data)) {
00797
00798 upd_field = upd_get_nth_field(update, n_diff);
00799
00800 dfield_copy(&(upd_field->new_val), dfield);
00801
00802 upd_field_set_field_no(upd_field, i, index, trx);
00803
00804 n_diff++;
00805 }
00806 }
00807
00808 update->n_fields = n_diff;
00809
00810 return(update);
00811 }
00812
00813
00819 UNIV_INTERN
00820 upd_t*
00821 row_upd_build_difference_binary(
00822
00823 dict_index_t* index,
00824 const dtuple_t* entry,
00825 const rec_t* rec,
00826 trx_t* trx,
00827 mem_heap_t* heap)
00828 {
00829 upd_field_t* upd_field;
00830 const dfield_t* dfield;
00831 const byte* data;
00832 ulint len;
00833 upd_t* update;
00834 ulint n_diff;
00835 ulint roll_ptr_pos;
00836 ulint trx_id_pos;
00837 ulint i;
00838 ulint offsets_[REC_OFFS_NORMAL_SIZE];
00839 const ulint* offsets;
00840 rec_offs_init(offsets_);
00841
00842
00843 ut_a(dict_index_is_clust(index));
00844
00845 update = upd_create(dtuple_get_n_fields(entry), heap);
00846
00847 n_diff = 0;
00848
00849 roll_ptr_pos = dict_index_get_sys_col_pos(index, DATA_ROLL_PTR);
00850 trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
00851
00852 offsets = rec_get_offsets(rec, index, offsets_,
00853 ULINT_UNDEFINED, &heap);
00854
00855 for (i = 0; i < dtuple_get_n_fields(entry); i++) {
00856
00857 data = rec_get_nth_field(rec, offsets, i, &len);
00858
00859 dfield = dtuple_get_nth_field(entry, i);
00860
00861
00862
00863
00864 if (i == trx_id_pos || i == roll_ptr_pos) {
00865
00866 goto skip_compare;
00867 }
00868
00869 if (UNIV_UNLIKELY(!dfield_is_ext(dfield)
00870 != !rec_offs_nth_extern(offsets, i))
00871 || !dfield_data_is_binary_equal(dfield, len, data)) {
00872
00873 upd_field = upd_get_nth_field(update, n_diff);
00874
00875 dfield_copy(&(upd_field->new_val), dfield);
00876
00877 upd_field_set_field_no(upd_field, i, index, trx);
00878
00879 n_diff++;
00880 }
00881 skip_compare:
00882 ;
00883 }
00884
00885 update->n_fields = n_diff;
00886
00887 return(update);
00888 }
00889
00890
00895 static
00896 byte*
00897 row_upd_ext_fetch(
00898
00899 const byte* data,
00902 ulint local_len,
00903 ulint zip_size,
00906 ulint* len,
00908 mem_heap_t* heap)
00909 {
00910 byte* buf = static_cast<byte *>(mem_heap_alloc(heap, *len));
00911
00912 *len = btr_copy_externally_stored_field_prefix(buf, *len,
00913 zip_size,
00914 data, local_len);
00915
00916 ut_a(*len);
00917
00918 return(buf);
00919 }
00920
00921
00924 static
00925 void
00926 row_upd_index_replace_new_col_val(
00927
00928 dfield_t* dfield,
00930 const dict_field_t* field,
00931 const dict_col_t* col,
00932 const upd_field_t* uf,
00933 mem_heap_t* heap,
00935 ulint zip_size)
00937 {
00938 ulint len;
00939 const byte* data;
00940
00941 dfield_copy_data(dfield, &uf->new_val);
00942
00943 if (dfield_is_null(dfield)) {
00944 return;
00945 }
00946
00947 len = dfield_get_len(dfield);
00948 data = static_cast<const byte *>(dfield_get_data(dfield));
00949
00950 if (field->prefix_len > 0) {
00951 ibool fetch_ext = dfield_is_ext(dfield)
00952 && len < (ulint) field->prefix_len
00953 + BTR_EXTERN_FIELD_REF_SIZE;
00954
00955 if (fetch_ext) {
00956 ulint l = len;
00957
00958 len = field->prefix_len;
00959
00960 data = row_upd_ext_fetch(data, l, zip_size,
00961 &len, heap);
00962 }
00963
00964 len = dtype_get_at_most_n_mbchars(col->prtype,
00965 col->mbminmaxlen,
00966 field->prefix_len, len,
00967 (const char*) data);
00968
00969 dfield_set_data(dfield, data, len);
00970
00971 if (!fetch_ext) {
00972 dfield_dup(dfield, heap);
00973 }
00974
00975 return;
00976 }
00977
00978 switch (uf->orig_len) {
00979 byte* buf;
00980 case BTR_EXTERN_FIELD_REF_SIZE:
00981
00982
00983
00984
00985
00986 dfield_set_data(dfield,
00987 data + len - BTR_EXTERN_FIELD_REF_SIZE,
00988 BTR_EXTERN_FIELD_REF_SIZE);
00989 dfield_set_ext(dfield);
00990
00991 case 0:
00992 dfield_dup(dfield, heap);
00993 break;
00994 default:
00995
00996
00997
00998 ut_a(uf->orig_len > BTR_EXTERN_FIELD_REF_SIZE);
00999 buf = static_cast<byte *>(mem_heap_alloc(heap, uf->orig_len));
01000
01001 memcpy(buf, data,
01002 uf->orig_len - BTR_EXTERN_FIELD_REF_SIZE);
01003
01004 memcpy(buf + uf->orig_len - BTR_EXTERN_FIELD_REF_SIZE,
01005 data + len - BTR_EXTERN_FIELD_REF_SIZE,
01006 BTR_EXTERN_FIELD_REF_SIZE);
01007
01008 dfield_set_data(dfield, buf, uf->orig_len);
01009 dfield_set_ext(dfield);
01010 break;
01011 }
01012 }
01013
01014
01017 UNIV_INTERN
01018 void
01019 row_upd_index_replace_new_col_vals_index_pos(
01020
01021 dtuple_t* entry,
01025 dict_index_t* index,
01027 const upd_t* update,
01030 ibool order_only,
01034 mem_heap_t* heap)
01036 {
01037 ulint i;
01038 ulint n_fields;
01039 const ulint zip_size = dict_table_zip_size(index->table);
01040
01041 ut_ad(index);
01042
01043 dtuple_set_info_bits(entry, update->info_bits);
01044
01045 if (order_only) {
01046 n_fields = dict_index_get_n_unique(index);
01047 } else {
01048 n_fields = dict_index_get_n_fields(index);
01049 }
01050
01051 for (i = 0; i < n_fields; i++) {
01052 const dict_field_t* field;
01053 const dict_col_t* col;
01054 const upd_field_t* uf;
01055
01056 field = dict_index_get_nth_field(index, i);
01057 col = dict_field_get_col(field);
01058 uf = upd_get_field_by_field_no(update, i);
01059
01060 if (uf) {
01061 row_upd_index_replace_new_col_val(
01062 dtuple_get_nth_field(entry, i),
01063 field, col, uf, heap, zip_size);
01064 }
01065 }
01066 }
01067
01068
01071 UNIV_INTERN
01072 void
01073 row_upd_index_replace_new_col_vals(
01074
01075 dtuple_t* entry,
01079 dict_index_t* index,
01081 const upd_t* update,
01084 mem_heap_t* heap)
01086 {
01087 ulint i;
01088 const dict_index_t* clust_index
01089 = dict_table_get_first_index(index->table);
01090 const ulint zip_size
01091 = dict_table_zip_size(index->table);
01092
01093 dtuple_set_info_bits(entry, update->info_bits);
01094
01095 for (i = 0; i < dict_index_get_n_fields(index); i++) {
01096 const dict_field_t* field;
01097 const dict_col_t* col;
01098 const upd_field_t* uf;
01099
01100 field = dict_index_get_nth_field(index, i);
01101 col = dict_field_get_col(field);
01102 uf = upd_get_field_by_field_no(
01103 update, dict_col_get_clust_pos(col, clust_index));
01104
01105 if (uf) {
01106 row_upd_index_replace_new_col_val(
01107 dtuple_get_nth_field(entry, i),
01108 field, col, uf, heap, zip_size);
01109 }
01110 }
01111 }
01112
01113
01115 UNIV_INTERN
01116 void
01117 row_upd_replace(
01118
01119 dtuple_t* row,
01124 row_ext_t** ext,
01126 const dict_index_t* index,
01127 const upd_t* update,
01129 mem_heap_t* heap)
01130 {
01131 ulint col_no;
01132 ulint i;
01133 ulint n_cols;
01134 ulint n_ext_cols;
01135 ulint* ext_cols;
01136 const dict_table_t* table;
01137
01138 ut_ad(row);
01139 ut_ad(ext);
01140 ut_ad(index);
01141 ut_ad(dict_index_is_clust(index));
01142 ut_ad(update);
01143 ut_ad(heap);
01144
01145 n_cols = dtuple_get_n_fields(row);
01146 table = index->table;
01147 ut_ad(n_cols == dict_table_get_n_cols(table));
01148
01149 ext_cols = static_cast<ulint *>(mem_heap_alloc(heap, n_cols * sizeof *ext_cols));
01150 n_ext_cols = 0;
01151
01152 dtuple_set_info_bits(row, update->info_bits);
01153
01154 for (col_no = 0; col_no < n_cols; col_no++) {
01155
01156 const dict_col_t* col
01157 = dict_table_get_nth_col(table, col_no);
01158 const ulint clust_pos
01159 = dict_col_get_clust_pos(col, index);
01160 dfield_t* dfield;
01161
01162 if (UNIV_UNLIKELY(clust_pos == ULINT_UNDEFINED)) {
01163
01164 continue;
01165 }
01166
01167 dfield = dtuple_get_nth_field(row, col_no);
01168
01169 for (i = 0; i < upd_get_n_fields(update); i++) {
01170
01171 const upd_field_t* upd_field
01172 = upd_get_nth_field(update, i);
01173
01174 if (upd_field->field_no != clust_pos) {
01175
01176 continue;
01177 }
01178
01179 dfield_copy_data(dfield, &upd_field->new_val);
01180 break;
01181 }
01182
01183 if (dfield_is_ext(dfield) && col->ord_part) {
01184 ext_cols[n_ext_cols++] = col_no;
01185 }
01186 }
01187
01188 if (n_ext_cols) {
01189 *ext = row_ext_create(n_ext_cols, ext_cols, row,
01190 dict_table_zip_size(table), heap);
01191 } else {
01192 *ext = NULL;
01193 }
01194 }
01195
01196
01203 UNIV_INTERN
01204 ibool
01205 row_upd_changes_ord_field_binary(
01206
01207 const dtuple_t* row,
01211 dict_index_t* index,
01212 const upd_t* update)
01215 {
01216 ulint n_unique;
01217 ulint n_upd_fields;
01218 ulint i, j;
01219 dict_index_t* clust_index;
01220
01221 ut_ad(update && index);
01222
01223 n_unique = dict_index_get_n_unique(index);
01224 n_upd_fields = upd_get_n_fields(update);
01225
01226 clust_index = dict_table_get_first_index(index->table);
01227
01228 for (i = 0; i < n_unique; i++) {
01229
01230 const dict_field_t* ind_field;
01231 const dict_col_t* col;
01232 ulint col_pos;
01233 ulint col_no;
01234
01235 ind_field = dict_index_get_nth_field(index, i);
01236 col = dict_field_get_col(ind_field);
01237 col_pos = dict_col_get_clust_pos(col, clust_index);
01238 col_no = dict_col_get_no(col);
01239
01240 for (j = 0; j < n_upd_fields; j++) {
01241
01242 const upd_field_t* upd_field
01243 = upd_get_nth_field(update, j);
01244
01245
01246
01247
01248
01249
01250 if (col_pos == upd_field->field_no
01251 && (row == NULL
01252 || ind_field->prefix_len > 0
01253 || !dfield_datas_are_binary_equal(
01254 dtuple_get_nth_field(row, col_no),
01255 &(upd_field->new_val)))) {
01256
01257 return(TRUE);
01258 }
01259 }
01260 }
01261
01262 return(FALSE);
01263 }
01264
01265
01270 UNIV_INTERN
01271 ibool
01272 row_upd_changes_some_index_ord_field_binary(
01273
01274 const dict_table_t* table,
01275 const upd_t* update)
01276 {
01277 upd_field_t* upd_field;
01278 dict_index_t* index;
01279 ulint i;
01280
01281 index = dict_table_get_first_index(table);
01282
01283 for (i = 0; i < upd_get_n_fields(update); i++) {
01284
01285 upd_field = upd_get_nth_field(update, i);
01286
01287 if (dict_field_get_col(dict_index_get_nth_field(
01288 index, upd_field->field_no))
01289 ->ord_part) {
01290
01291 return(TRUE);
01292 }
01293 }
01294
01295 return(FALSE);
01296 }
01297
01298
01303 static
01304 ibool
01305 row_upd_changes_first_fields_binary(
01306
01307 dtuple_t* entry,
01308 dict_index_t* index,
01309 const upd_t* update,
01310 ulint n)
01311 {
01312 ulint n_upd_fields;
01313 ulint i, j;
01314 dict_index_t* clust_index;
01315
01316 ut_ad(update && index);
01317 ut_ad(n <= dict_index_get_n_fields(index));
01318
01319 n_upd_fields = upd_get_n_fields(update);
01320 clust_index = dict_table_get_first_index(index->table);
01321
01322 for (i = 0; i < n; i++) {
01323
01324 const dict_field_t* ind_field;
01325 const dict_col_t* col;
01326 ulint col_pos;
01327
01328 ind_field = dict_index_get_nth_field(index, i);
01329 col = dict_field_get_col(ind_field);
01330 col_pos = dict_col_get_clust_pos(col, clust_index);
01331
01332 ut_a(ind_field->prefix_len == 0);
01333
01334 for (j = 0; j < n_upd_fields; j++) {
01335
01336 upd_field_t* upd_field
01337 = upd_get_nth_field(update, j);
01338
01339 if (col_pos == upd_field->field_no
01340 && !dfield_datas_are_binary_equal(
01341 dtuple_get_nth_field(entry, i),
01342 &(upd_field->new_val))) {
01343
01344 return(TRUE);
01345 }
01346 }
01347 }
01348
01349 return(FALSE);
01350 }
01351
01352
01354 UNIV_INLINE
01355 void
01356 row_upd_copy_columns(
01357
01358 rec_t* rec,
01359 const ulint* offsets,
01360 sym_node_t* column)
01362 {
01363 byte* data;
01364 ulint len;
01365
01366 while (column) {
01367 data = rec_get_nth_field(rec, offsets,
01368 column->field_nos[SYM_CLUST_FIELD_NO],
01369 &len);
01370 eval_node_copy_and_alloc_val(column, data, len);
01371
01372 column = UT_LIST_GET_NEXT(col_var_list, column);
01373 }
01374 }
01375
01376
01379 UNIV_INLINE
01380 void
01381 row_upd_eval_new_vals(
01382
01383 upd_t* update)
01384 {
01385 que_node_t* exp;
01386 upd_field_t* upd_field;
01387 ulint n_fields;
01388 ulint i;
01389
01390 n_fields = upd_get_n_fields(update);
01391
01392 for (i = 0; i < n_fields; i++) {
01393 upd_field = upd_get_nth_field(update, i);
01394
01395 exp = upd_field->exp;
01396
01397 eval_exp(exp);
01398
01399 dfield_copy_data(&(upd_field->new_val), que_node_get_val(exp));
01400 }
01401 }
01402
01403
01405 static
01406 void
01407 row_upd_store_row(
01408
01409 upd_node_t* node)
01410 {
01411 dict_index_t* clust_index;
01412 rec_t* rec;
01413 mem_heap_t* heap = NULL;
01414 row_ext_t** ext;
01415 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01416 const ulint* offsets;
01417 rec_offs_init(offsets_);
01418
01419 ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES);
01420
01421 if (node->row != NULL) {
01422 mem_heap_empty(node->heap);
01423 }
01424
01425 clust_index = dict_table_get_first_index(node->table);
01426
01427 rec = btr_pcur_get_rec(node->pcur);
01428
01429 offsets = rec_get_offsets(rec, clust_index, offsets_,
01430 ULINT_UNDEFINED, &heap);
01431
01432 if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
01433
01434
01435
01436 ext = &node->ext;
01437 } else {
01438
01439
01440
01441 ext = NULL;
01442 node->ext = NULL;
01443 }
01444
01445 node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
01446 NULL, ext, node->heap);
01447 if (node->is_delete) {
01448 node->upd_row = NULL;
01449 node->upd_ext = NULL;
01450 } else {
01451 node->upd_row = dtuple_copy(node->row, node->heap);
01452 row_upd_replace(node->upd_row, &node->upd_ext,
01453 clust_index, node->update, node->heap);
01454 }
01455
01456 if (UNIV_LIKELY_NULL(heap)) {
01457 mem_heap_free(heap);
01458 }
01459 }
01460
01461
01465 static
01466 ulint
01467 row_upd_sec_index_entry(
01468
01469 upd_node_t* node,
01470 que_thr_t* thr)
01471 {
01472 mtr_t mtr;
01473 const rec_t* rec;
01474 btr_pcur_t pcur;
01475 mem_heap_t* heap;
01476 dtuple_t* entry;
01477 dict_index_t* index;
01478 btr_cur_t* btr_cur;
01479 ibool referenced;
01480 ulint err = DB_SUCCESS;
01481 trx_t* trx = thr_get_trx(thr);
01482 ulint mode = BTR_MODIFY_LEAF;
01483 enum row_search_result search_result;
01484
01485 index = node->index;
01486
01487 referenced = row_upd_index_is_referenced(index, trx);
01488
01489 heap = mem_heap_create(1024);
01490
01491
01492 entry = row_build_index_entry(node->row, node->ext, index, heap);
01493 ut_a(entry);
01494
01495 mtr_start(&mtr);
01496
01497
01498
01499 btr_pcur_get_btr_cur(&pcur)->thr = thr;
01500
01501
01502
01503
01504 if (!referenced) {
01505 mode |= BTR_DELETE_MARK;
01506 }
01507
01508 search_result = row_search_index_entry(index, entry, mode,
01509 &pcur, &mtr);
01510
01511 btr_cur = btr_pcur_get_btr_cur(&pcur);
01512
01513 rec = btr_cur_get_rec(btr_cur);
01514
01515 switch (search_result) {
01516 case ROW_NOT_DELETED_REF:
01517 ut_error;
01518 break;
01519 case ROW_BUFFERED:
01520
01521 break;
01522
01523 case ROW_NOT_FOUND:
01524 fputs("InnoDB: error in sec index entry update in\n"
01525 "InnoDB: ", stderr);
01526 dict_index_name_print(stderr, trx, index);
01527 fputs("\n"
01528 "InnoDB: tuple ", stderr);
01529 dtuple_print(stderr, entry);
01530 fputs("\n"
01531 "InnoDB: record ", stderr);
01532 rec_print(stderr, rec, index);
01533 putc('\n', stderr);
01534
01535 trx_print(stderr, trx, 0);
01536
01537 fputs("\n"
01538 "InnoDB: Submit a detailed bug report"
01539 " to http://bugs.mysql.com\n", stderr);
01540 break;
01541 case ROW_FOUND:
01542
01543
01544
01545
01546 if (!rec_get_deleted_flag(
01547 rec, dict_table_is_comp(index->table))) {
01548
01549 err = btr_cur_del_mark_set_sec_rec(
01550 0, btr_cur, TRUE, thr, &mtr);
01551
01552 if (err == DB_SUCCESS && referenced) {
01553
01554 ulint* offsets;
01555
01556 offsets = rec_get_offsets(
01557 rec, index, NULL, ULINT_UNDEFINED,
01558 &heap);
01559
01560
01561
01562 err = row_upd_check_references_constraints(
01563 node, &pcur, index->table,
01564 index, offsets, thr, &mtr);
01565 }
01566 }
01567 break;
01568 }
01569
01570 btr_pcur_close(&pcur);
01571 mtr_commit(&mtr);
01572
01573 if (node->is_delete || err != DB_SUCCESS) {
01574
01575 goto func_exit;
01576 }
01577
01578
01579 entry = row_build_index_entry(node->upd_row, node->upd_ext,
01580 index, heap);
01581 ut_a(entry);
01582
01583
01584 err = row_ins_index_entry(index, entry, 0, TRUE, thr);
01585
01586 func_exit:
01587 mem_heap_free(heap);
01588
01589 return(err);
01590 }
01591
01592
01597 static
01598 ulint
01599 row_upd_sec_step(
01600
01601 upd_node_t* node,
01602 que_thr_t* thr)
01603 {
01604 ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC)
01605 || (node->state == UPD_NODE_UPDATE_SOME_SEC));
01606 ut_ad(!dict_index_is_clust(node->index));
01607
01608 if (node->state == UPD_NODE_UPDATE_ALL_SEC
01609 || row_upd_changes_ord_field_binary(node->row, node->index,
01610 node->update)) {
01611 return(row_upd_sec_index_entry(node, thr));
01612 }
01613
01614 return(DB_SUCCESS);
01615 }
01616
01617
01624 static
01625 ulint
01626 row_upd_clust_rec_by_insert(
01627
01628 upd_node_t* node,
01629 dict_index_t* index,
01630 que_thr_t* thr,
01631 ibool referenced,
01633 mtr_t* mtr)
01634 {
01635 mem_heap_t* heap = NULL;
01636 btr_pcur_t* pcur;
01637 btr_cur_t* btr_cur;
01638 trx_t* trx;
01639 dict_table_t* table;
01640 dtuple_t* entry;
01641 ulint err;
01642 ibool change_ownership = FALSE;
01643
01644 ut_ad(node);
01645 ut_ad(dict_index_is_clust(index));
01646
01647 trx = thr_get_trx(thr);
01648 table = node->table;
01649 pcur = node->pcur;
01650 btr_cur = btr_pcur_get_btr_cur(pcur);
01651
01652 if (node->state != UPD_NODE_INSERT_CLUSTERED) {
01653 rec_t* rec;
01654 dict_index_t* node_index;
01655 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01656 ulint* offsets;
01657 rec_offs_init(offsets_);
01658
01659 err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
01660 btr_cur, TRUE, thr, mtr);
01661 if (err != DB_SUCCESS) {
01662 mtr_commit(mtr);
01663 return(err);
01664 }
01665
01666
01667
01668
01669
01670
01671 rec = btr_cur_get_rec(btr_cur);
01672 node_index = dict_table_get_first_index(table);
01673 offsets = rec_get_offsets(rec, node_index, offsets_,
01674 ULINT_UNDEFINED, &heap);
01675 change_ownership = btr_cur_mark_extern_inherited_fields(
01676 btr_cur_get_page_zip(btr_cur), rec, node_index, offsets,
01677 node->update, mtr);
01678 if (referenced) {
01679
01680
01681
01682 err = row_upd_check_references_constraints(
01683 node, pcur, table, node_index, offsets, thr, mtr);
01684
01685 if (err != DB_SUCCESS) {
01686
01687 mtr_commit(mtr);
01688
01689 if (UNIV_LIKELY_NULL(heap)) {
01690 mem_heap_free(heap);
01691 }
01692
01693 return(err);
01694 }
01695 }
01696 }
01697
01698 mtr_commit(mtr);
01699
01700 if (!heap) {
01701 heap = mem_heap_create(500);
01702 }
01703 node->state = UPD_NODE_INSERT_CLUSTERED;
01704
01705 entry = row_build_index_entry(node->upd_row, node->upd_ext,
01706 index, heap);
01707 ut_a(entry);
01708
01709 row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
01710
01711 if (change_ownership) {
01712
01713
01714
01715
01716
01717 btr_cur_unmark_dtuple_extern_fields(entry);
01718
01719
01720
01721
01722 btr_cur_mark_dtuple_inherited_extern(entry, node->update);
01723 }
01724
01725 err = row_ins_index_entry(index, entry,
01726 node->upd_ext ? node->upd_ext->n_ext : 0,
01727 TRUE, thr);
01728 mem_heap_free(heap);
01729
01730 return(err);
01731 }
01732
01733
01738 static
01739 ulint
01740 row_upd_clust_rec(
01741
01742 upd_node_t* node,
01743 dict_index_t* index,
01744 que_thr_t* thr,
01745 mtr_t* mtr)
01746 {
01747 mem_heap_t* heap = NULL;
01748 big_rec_t* big_rec = NULL;
01749 btr_pcur_t* pcur;
01750 btr_cur_t* btr_cur;
01751 ulint err;
01752
01753 ut_ad(node);
01754 ut_ad(dict_index_is_clust(index));
01755
01756 pcur = node->pcur;
01757 btr_cur = btr_pcur_get_btr_cur(pcur);
01758
01759 ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
01760 dict_table_is_comp(index->table)));
01761
01762
01763
01764
01765
01766 if (node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE) {
01767 err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG,
01768 btr_cur, node->update,
01769 node->cmpl_info, thr, mtr);
01770 } else {
01771 err = btr_cur_optimistic_update(BTR_NO_LOCKING_FLAG,
01772 btr_cur, node->update,
01773 node->cmpl_info, thr, mtr);
01774 }
01775
01776 mtr_commit(mtr);
01777
01778 if (UNIV_LIKELY(err == DB_SUCCESS)) {
01779
01780 return(DB_SUCCESS);
01781 }
01782
01783 if (buf_LRU_buf_pool_running_out()) {
01784
01785 return(DB_LOCK_TABLE_FULL);
01786 }
01787
01788
01789
01790 mtr_start(mtr);
01791
01792
01793
01794
01795
01796
01797
01798 ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
01799
01800 ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
01801 dict_table_is_comp(index->table)));
01802
01803 err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
01804 &heap, &big_rec, node->update,
01805 node->cmpl_info, thr, mtr);
01806 mtr_commit(mtr);
01807
01808 if (err == DB_SUCCESS && big_rec) {
01809 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01810 rec_t* rec;
01811 rec_offs_init(offsets_);
01812
01813 mtr_start(mtr);
01814
01815 ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
01816 rec = btr_cur_get_rec(btr_cur);
01817 err = btr_store_big_rec_extern_fields(
01818 index, btr_cur_get_block(btr_cur), rec,
01819 rec_get_offsets(rec, index, offsets_,
01820 ULINT_UNDEFINED, &heap),
01821 big_rec, mtr);
01822 mtr_commit(mtr);
01823 }
01824
01825 if (UNIV_LIKELY_NULL(heap)) {
01826 mem_heap_free(heap);
01827 }
01828
01829 if (big_rec) {
01830 dtuple_big_rec_free(big_rec);
01831 }
01832
01833 return(err);
01834 }
01835
01836
01839 static
01840 ulint
01841 row_upd_del_mark_clust_rec(
01842
01843 upd_node_t* node,
01844 dict_index_t* index,
01845 ulint* offsets,
01847 que_thr_t* thr,
01848 ibool referenced,
01851 mtr_t* mtr)
01852 {
01853 btr_pcur_t* pcur;
01854 btr_cur_t* btr_cur;
01855 ulint err;
01856
01857 ut_ad(node);
01858 ut_ad(dict_index_is_clust(index));
01859 ut_ad(node->is_delete);
01860
01861 pcur = node->pcur;
01862 btr_cur = btr_pcur_get_btr_cur(pcur);
01863
01864
01865
01866
01867 row_upd_store_row(node);
01868
01869
01870
01871
01872 err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
01873 btr_cur, TRUE, thr, mtr);
01874 if (err == DB_SUCCESS && referenced) {
01875
01876
01877 err = row_upd_check_references_constraints(
01878 node, pcur, index->table, index, offsets, thr, mtr);
01879 }
01880
01881 mtr_commit(mtr);
01882
01883 return(err);
01884 }
01885
01886
01890 static
01891 ulint
01892 row_upd_clust_step(
01893
01894 upd_node_t* node,
01895 que_thr_t* thr)
01896 {
01897 dict_index_t* index;
01898 btr_pcur_t* pcur;
01899 ibool success;
01900 ulint err;
01901 mtr_t* mtr;
01902 mtr_t mtr_buf;
01903 rec_t* rec;
01904 mem_heap_t* heap = NULL;
01905 ulint offsets_[REC_OFFS_NORMAL_SIZE];
01906 ulint* offsets;
01907 ibool referenced;
01908 rec_offs_init(offsets_);
01909
01910 index = dict_table_get_first_index(node->table);
01911
01912 referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
01913
01914 pcur = node->pcur;
01915
01916
01917 mtr = &mtr_buf;
01918
01919 mtr_start(mtr);
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929 ut_a(pcur->rel_pos == BTR_PCUR_ON);
01930
01931 success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
01932
01933 if (!success) {
01934 err = DB_RECORD_NOT_FOUND;
01935
01936 mtr_commit(mtr);
01937
01938 return(err);
01939 }
01940
01941
01942
01943
01944
01945 if (node->is_delete && node->table->id == DICT_INDEXES_ID) {
01946
01947 dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr);
01948
01949 mtr_commit(mtr);
01950
01951 mtr_start(mtr);
01952
01953 success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur,
01954 mtr);
01955 if (!success) {
01956 err = DB_ERROR;
01957
01958 mtr_commit(mtr);
01959
01960 return(err);
01961 }
01962 }
01963
01964 rec = btr_pcur_get_rec(pcur);
01965 offsets = rec_get_offsets(rec, index, offsets_,
01966 ULINT_UNDEFINED, &heap);
01967
01968 if (!node->has_clust_rec_x_lock) {
01969 err = lock_clust_rec_modify_check_and_lock(
01970 0, btr_pcur_get_block(pcur),
01971 rec, index, offsets, thr);
01972 if (err != DB_SUCCESS) {
01973 mtr_commit(mtr);
01974 goto exit_func;
01975 }
01976 }
01977
01978
01979
01980 if (node->is_delete) {
01981 err = row_upd_del_mark_clust_rec(
01982 node, index, offsets, thr, referenced, mtr);
01983
01984 if (err == DB_SUCCESS) {
01985 node->state = UPD_NODE_UPDATE_ALL_SEC;
01986 node->index = dict_table_get_next_index(index);
01987 }
01988 exit_func:
01989 if (UNIV_LIKELY_NULL(heap)) {
01990 mem_heap_free(heap);
01991 }
01992 return(err);
01993 }
01994
01995
01996
01997
01998 if (UNIV_UNLIKELY(!node->in_mysql_interface)) {
01999
02000
02001 row_upd_copy_columns(rec, offsets,
02002 UT_LIST_GET_FIRST(node->columns));
02003 row_upd_eval_new_vals(node->update);
02004 }
02005
02006 if (UNIV_LIKELY_NULL(heap)) {
02007 mem_heap_free(heap);
02008 }
02009
02010 if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) {
02011
02012 err = row_upd_clust_rec(node, index, thr, mtr);
02013 return(err);
02014 }
02015
02016 row_upd_store_row(node);
02017
02018 if (row_upd_changes_ord_field_binary(node->row, index, node->update)) {
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031 err = row_upd_clust_rec_by_insert(
02032 node, index, thr, referenced, mtr);
02033
02034 if (err != DB_SUCCESS) {
02035
02036 return(err);
02037 }
02038
02039 node->state = UPD_NODE_UPDATE_ALL_SEC;
02040 } else {
02041 err = row_upd_clust_rec(node, index, thr, mtr);
02042
02043 if (err != DB_SUCCESS) {
02044
02045 return(err);
02046 }
02047
02048 node->state = UPD_NODE_UPDATE_SOME_SEC;
02049 }
02050
02051 node->index = dict_table_get_next_index(index);
02052
02053 return(err);
02054 }
02055
02056
02062 static
02063 ulint
02064 row_upd(
02065
02066 upd_node_t* node,
02067 que_thr_t* thr)
02068 {
02069 ulint err = DB_SUCCESS;
02070
02071 ut_ad(node && thr);
02072
02073 if (UNIV_LIKELY(node->in_mysql_interface)) {
02074
02075
02076
02077
02078 if (node->is_delete
02079 || row_upd_changes_some_index_ord_field_binary(
02080 node->table, node->update)) {
02081 node->cmpl_info = 0;
02082 } else {
02083 node->cmpl_info = UPD_NODE_NO_ORD_CHANGE;
02084 }
02085 }
02086
02087 if (node->state == UPD_NODE_UPDATE_CLUSTERED
02088 || node->state == UPD_NODE_INSERT_CLUSTERED) {
02089
02090 log_free_check();
02091 err = row_upd_clust_step(node, thr);
02092
02093 if (err != DB_SUCCESS) {
02094
02095 goto function_exit;
02096 }
02097 }
02098
02099 if (!node->is_delete && (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
02100
02101 goto function_exit;
02102 }
02103
02104 while (node->index != NULL) {
02105
02106 log_free_check();
02107 err = row_upd_sec_step(node, thr);
02108
02109 if (err != DB_SUCCESS) {
02110
02111 goto function_exit;
02112 }
02113
02114 node->index = dict_table_get_next_index(node->index);
02115 }
02116
02117 function_exit:
02118 if (err == DB_SUCCESS) {
02119
02120
02121 if (node->row != NULL) {
02122 node->row = NULL;
02123 node->ext = NULL;
02124 node->upd_row = NULL;
02125 node->upd_ext = NULL;
02126 mem_heap_empty(node->heap);
02127 }
02128
02129 node->state = UPD_NODE_UPDATE_CLUSTERED;
02130 }
02131
02132 return(err);
02133 }
02134
02135
02139 UNIV_INTERN
02140 que_thr_t*
02141 row_upd_step(
02142
02143 que_thr_t* thr)
02144 {
02145 upd_node_t* node;
02146 sel_node_t* sel_node;
02147 que_node_t* parent;
02148 ulint err = DB_SUCCESS;
02149 trx_t* trx;
02150
02151 ut_ad(thr);
02152
02153 trx = thr_get_trx(thr);
02154
02155 trx_start_if_not_started(trx);
02156
02157 node = static_cast<upd_node_t *>(thr->run_node);
02158
02159 sel_node = node->select;
02160
02161 parent = que_node_get_parent(node);
02162
02163 ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE);
02164
02165 if (thr->prev_node == parent) {
02166 node->state = UPD_NODE_SET_IX_LOCK;
02167 }
02168
02169 if (node->state == UPD_NODE_SET_IX_LOCK) {
02170
02171 if (!node->has_clust_rec_x_lock) {
02172
02173
02174
02175 err = lock_table(0, node->table, LOCK_IX, thr);
02176
02177 if (err != DB_SUCCESS) {
02178
02179 goto error_handling;
02180 }
02181 }
02182
02183 node->state = UPD_NODE_UPDATE_CLUSTERED;
02184
02185 if (node->searched_update) {
02186
02187 sel_node->state = SEL_NODE_OPEN;
02188
02189
02190
02191 thr->run_node = sel_node;
02192
02193 return(thr);
02194 }
02195 }
02196
02197
02198
02199 if (sel_node && (sel_node->state != SEL_NODE_FETCH)) {
02200
02201 if (!node->searched_update) {
02202
02203
02204
02205 ut_error;
02206
02207 err = DB_ERROR;
02208
02209 goto error_handling;
02210 }
02211
02212 ut_ad(sel_node->state == SEL_NODE_NO_MORE_ROWS);
02213
02214
02215
02216
02217 thr->run_node = parent;
02218
02219 return(thr);
02220 }
02221
02222
02223
02224 err = row_upd(node, thr);
02225
02226 error_handling:
02227 trx->error_state = err;
02228
02229 if (err != DB_SUCCESS) {
02230 return(NULL);
02231 }
02232
02233
02234
02235 if (node->searched_update) {
02236
02237
02238 thr->run_node = sel_node;
02239 } else {
02240
02241
02242 thr->run_node = parent;
02243 }
02244
02245 node->state = UPD_NODE_UPDATE_CLUSTERED;
02246
02247 return(thr);
02248 }
02249 #endif