|
1 | 1 | /***************************************************************************** |
2 | 2 |
|
3 | | -Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. |
| 3 | +Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | 4 |
|
5 | 5 | This program is free software; you can redistribute it and/or modify it under |
6 | 6 | the terms of the GNU General Public License as published by the Free Software |
@@ -469,7 +469,7 @@ row_vers_non_vc_match( |
469 | 469 |
|
470 | 470 | /** build virtual column value from current cluster index record data |
471 | 471 | @param[in,out] row the cluster index row in dtuple form |
472 | | -@param[in] clust_indexcluster index |
| 472 | +@param[in] clust_indexclustered index |
473 | 473 | @param[in] index the secondary index |
474 | 474 | @param[in] heap heap used to build virtual dtuple */ |
475 | 475 | static |
@@ -502,6 +502,115 @@ row_vers_build_clust_v_col( |
502 | 502 | } |
503 | 503 | } |
504 | 504 |
|
| 505 | +/** Build latest virtual column data from undo log |
| 506 | +@param[in] in_purge whether this is the purge thread |
| 507 | +@param[in] rec clustered index record |
| 508 | +@param[in] clust_index clustered index |
| 509 | +@param[in,out] clust_offsets offsets on the clustered index record |
| 510 | +@param[in] index the secondary index |
| 511 | +@param[in] roll_ptr the rollback pointer for the purging record |
| 512 | +@param[in] trx_id trx id for the purging record |
| 513 | +@param[in,out] v_heap heap used to build vrow |
| 514 | +@param[out] v_row dtuple holding the virtual rows |
| 515 | +@param[in,out] mtr mtr holding the latch on rec */ |
| 516 | +static |
| 517 | +void |
| 518 | +row_vers_build_cur_vrow_low( |
| 519 | +boolin_purge, |
| 520 | +const rec_t* rec, |
| 521 | +dict_index_t* clust_index, |
| 522 | +ulint* clust_offsets, |
| 523 | +dict_index_t* index, |
| 524 | +roll_ptr_troll_ptr, |
| 525 | +trx_id_ttrx_id, |
| 526 | +mem_heap_t* v_heap, |
| 527 | +const dtuple_t**vrow, |
| 528 | +mtr_t* mtr) |
| 529 | +{ |
| 530 | +const rec_t* version; |
| 531 | +rec_t* prev_version; |
| 532 | +mem_heap_t* heap = NULL; |
| 533 | +ulint num_v = dict_table_get_n_v_cols(index->table); |
| 534 | +const dfield_t* field; |
| 535 | +ulint i; |
| 536 | +boolall_filled = false; |
| 537 | + |
| 538 | +*vrow = dtuple_create_with_vcol(v_heap, 0, num_v); |
| 539 | +dtuple_init_v_fld(*vrow); |
| 540 | + |
| 541 | +for (i = 0; i < num_v; i++) { |
| 542 | +dfield_get_type(dtuple_get_nth_v_field(*vrow, i))->mtype |
| 543 | + = DATA_MISSING; |
| 544 | +} |
| 545 | + |
| 546 | +version = rec; |
| 547 | + |
| 548 | +/* If this is called by purge thread, set TRX_UNDO_PREV_IN_PURGE |
| 549 | +bit to search the undo log until we hit the current undo log with |
| 550 | +roll_ptr */ |
| 551 | +const ulint status = in_purge |
| 552 | +? TRX_UNDO_PREV_IN_PURGE | TRX_UNDO_GET_OLD_V_VALUE |
| 553 | +: TRX_UNDO_GET_OLD_V_VALUE; |
| 554 | + |
| 555 | +while (!all_filled) { |
| 556 | +mem_heap_t* heap2 = heap; |
| 557 | +heap = mem_heap_create(1024); |
| 558 | +roll_ptr_tcur_roll_ptr = row_get_rec_roll_ptr( |
| 559 | +version, clust_index, clust_offsets); |
| 560 | + |
| 561 | +trx_undo_prev_version_build( |
| 562 | +rec, mtr, version, clust_index, clust_offsets, |
| 563 | +heap, &prev_version, NULL, vrow, status); |
| 564 | + |
| 565 | +if (heap2) { |
| 566 | +mem_heap_free(heap2); |
| 567 | +} |
| 568 | + |
| 569 | +if (!prev_version) { |
| 570 | +/* Versions end here */ |
| 571 | +break; |
| 572 | +} |
| 573 | + |
| 574 | +clust_offsets = rec_get_offsets(prev_version, clust_index, |
| 575 | +NULL, ULINT_UNDEFINED, &heap); |
| 576 | + |
| 577 | +ulint entry_len = dict_index_get_n_fields(index); |
| 578 | + |
| 579 | +all_filled = true; |
| 580 | + |
| 581 | +for (i = 0; i < entry_len; i++) { |
| 582 | +const dict_field_t* ind_field |
| 583 | + = dict_index_get_nth_field(index, i); |
| 584 | +const dict_col_t* col = ind_field->col; |
| 585 | + |
| 586 | +if (!dict_col_is_virtual(col)) { |
| 587 | +continue; |
| 588 | +} |
| 589 | + |
| 590 | +const dict_v_col_t* v_col |
| 591 | += reinterpret_cast<const dict_v_col_t*>(col); |
| 592 | +field = dtuple_get_nth_v_field(*vrow, v_col->v_pos); |
| 593 | + |
| 594 | +if (dfield_get_type(field)->mtype == DATA_MISSING) { |
| 595 | +all_filled = false; |
| 596 | +break; |
| 597 | +} |
| 598 | + |
| 599 | +} |
| 600 | + |
| 601 | +trx_id_trec_trx_id = row_get_rec_trx_id( |
| 602 | +prev_version, clust_index, clust_offsets); |
| 603 | + |
| 604 | +if (rec_trx_id < trx_id || roll_ptr == cur_roll_ptr) { |
| 605 | +break; |
| 606 | +} |
| 607 | + |
| 608 | +version = prev_version; |
| 609 | +} |
| 610 | + |
| 611 | +mem_heap_free(heap); |
| 612 | +} |
| 613 | + |
505 | 614 | /** Check a virtual column value index secondary virtual index matches |
506 | 615 | that of current cluster index record, which is recreated from information |
507 | 616 | stored in undo log |
@@ -584,6 +693,9 @@ row_vers_vc_matches_cluster( |
584 | 693 | roll_ptr_tcur_roll_ptr = row_get_rec_roll_ptr( |
585 | 694 | version, clust_index, clust_offsets); |
586 | 695 |
|
| 696 | +ut_ad(cur_roll_ptr != 0); |
| 697 | +ut_ad(in_purge == (roll_ptr != 0)); |
| 698 | + |
587 | 699 | trx_undo_prev_version_build( |
588 | 700 | rec, mtr, version, clust_index, clust_offsets, |
589 | 701 | heap, &prev_version, NULL, vrow, status); |
@@ -696,27 +808,32 @@ row_vers_build_cur_vrow( |
696 | 808 | mtr_t* mtr) |
697 | 809 | { |
698 | 810 | const dtuple_t* cur_vrow = NULL; |
699 | | -row_ext_t* ext; |
700 | | - |
701 | | -dtuple_t* row = row_build(ROW_COPY_POINTERS, clust_index, |
702 | | -rec, *clust_offsets, |
703 | | -NULL, NULL, NULL, &ext, heap); |
704 | 811 |
|
705 | 812 | roll_ptr_t t_roll_ptr = row_get_rec_roll_ptr( |
706 | 813 | rec, clust_index, *clust_offsets); |
707 | 814 |
|
708 | 815 | /* if the row is newly inserted, then the virtual |
709 | 816 | columns need to be computed */ |
710 | 817 | if (trx_undo_roll_ptr_is_insert(t_roll_ptr)) { |
| 818 | + |
| 819 | +ut_ad(!rec_get_deleted_flag(rec, page_rec_is_comp(rec))); |
| 820 | + |
| 821 | +/* This is a newly inserted record and cannot |
| 822 | +be deleted, So the externally stored field |
| 823 | +cannot be freed yet. */ |
| 824 | +dtuple_t* row = row_build(ROW_COPY_POINTERS, clust_index, |
| 825 | + rec, *clust_offsets, |
| 826 | + NULL, NULL, NULL, NULL, heap); |
| 827 | + |
711 | 828 | row_vers_build_clust_v_col( |
712 | 829 | row, clust_index, index, heap); |
713 | 830 | cur_vrow = dtuple_copy(row, v_heap); |
714 | 831 | dtuple_dup_v_fld(cur_vrow, v_heap); |
715 | 832 | } else { |
716 | | -row_vers_vc_matches_cluster( |
717 | | -in_purge, rec, row, ext, clust_index, *clust_offsets, |
718 | | -index, ientry, roll_ptr, |
719 | | -trx_id, v_heap, &cur_vrow, mtr); |
| 833 | +/* Try to fetch virtual column data from undo log */ |
| 834 | +row_vers_build_cur_vrow_low( |
| 835 | +in_purge, rec, clust_index, *clust_offsets, |
| 836 | +index, roll_ptr, trx_id, v_heap, &cur_vrow, mtr); |
720 | 837 | } |
721 | 838 |
|
722 | 839 | *clust_offsets = rec_get_offsets(rec, clust_index, NULL, |
|
0 commit comments