diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-02-15 10:22:03 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-02-15 10:22:03 +0200 |
commit | b006d2ead4640f0ab4e29687fd7d24988b1c98f1 (patch) | |
tree | a478984bcd7f4bb2e0fd0496eae77b871077a380 /storage/innobase/row/row0vers.cc | |
parent | b782971c58b5656820429b8ef3fae5fd82f5a0f7 (diff) | |
parent | dc09f8f29cb2b9fdce7d5d5a623fdc8dcf1814f9 (diff) | |
download | mariadb-git-b006d2ead4640f0ab4e29687fd7d24988b1c98f1.tar.gz |
Merge bb-10.2-ext into 10.3
Diffstat (limited to 'storage/innobase/row/row0vers.cc')
-rw-r--r-- | storage/innobase/row/row0vers.cc | 214 |
1 files changed, 93 insertions, 121 deletions
diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index c5663c0c828..648643ce932 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -44,25 +44,31 @@ Created 2/6/1997 Heikki Tuuri #include "lock0lock.h" #include "row0mysql.h" -/** Check whether all non-virtual columns in a virtual index match that of in -the cluster index -@param[in,out] caller_trx trx of current thread -@param[in] index the secondary index -@param[in] row the cluster index row in dtuple form -@param[in] ext externally stored column prefix or NULL -@param[in] ientry the secondary index entry -@param[in,out] heap heap used to build virtual dtuple -@param[in,out] n_non_v_col number of non-virtual columns in the index -@return true if all matches, false otherwise */ +/** Check whether all non-virtual index fields are equal. +@param[in] index the secondary index +@param[in] a first index entry to compare +@param[in] b second index entry to compare +@return whether all non-virtual fields are equal */ static bool -row_vers_non_vc_match( - dict_index_t* index, - const dtuple_t* row, - const row_ext_t* ext, - const dtuple_t* ientry, - mem_heap_t* heap, - ulint* n_non_v_col); +row_vers_non_virtual_fields_equal( + const dict_index_t* index, + const dfield_t* a, + const dfield_t* b) +{ + const dict_field_t* end = &index->fields[index->n_fields]; + + for (const dict_field_t* ifield = index->fields; ifield != end; + ifield++) { + if (!dict_col_is_virtual(ifield->col) + && cmp_dfield_dfield(a++, b++)) { + return false; + } + } + + return true; +} + /** Determine if an active transaction has inserted or modified a secondary index record. @param[in,out] caller_trx trx of current thread @@ -242,15 +248,29 @@ row_vers_impl_x_locked_low( } if (!cur_vrow) { - ulint n_non_v_col = 0; + /* Build index entry out of row */ + entry = row_build_index_entry(row, ext, index, + heap); + + /* entry could only be NULL (the + clustered index record could contain + BLOB pointers that are NULL) if we + were accessing a freshly inserted + record before it was fully inserted. + prev_version cannot possibly be such + an incomplete record, because its + transaction would have to be committed + in order for later versions of the + record to be able to exist. */ + ut_ad(entry); /* If the indexed virtual columns has changed, there must be log record to generate vrow. Otherwise, it is not changed, so no need to compare */ - if (row_vers_non_vc_match( - index, row, ext, ientry, heap, - &n_non_v_col) == 0) { + if (!row_vers_non_virtual_fields_equal( + index, + ientry->fields, entry->fields)) { if (rec_del != vers_del) { break; } @@ -267,12 +287,14 @@ row_vers_impl_x_locked_low( entry = row_build_index_entry(row, ext, index, heap); - /* entry may be NULL if a record was inserted in place - of a deleted record, and the BLOB pointers of the new - record were not initialized yet. But in that case, - prev_version should be NULL. */ - - ut_a(entry != NULL); + /* entry could only be NULL (the clustered index + record could contain BLOB pointers that are NULL) if + we were accessing a freshly inserted record before it + was fully inserted. prev_version cannot possibly be + such an incomplete record, because its transaction + would have to be committed in order for later versions + of the record to be able to exist. */ + ut_ad(entry); /* If we get here, we know that the trx_id transaction modified prev_version. Let us check if prev_version @@ -421,61 +443,6 @@ row_vers_must_preserve_del_marked( return(!purge_sys->view.changes_visible(trx_id, name)); } -/** Check whether all non-virtual columns in a virtual index match that of in -the cluster index -@param[in] index the secondary index -@param[in] row the cluster index row in dtuple form -@param[in] ext externally stored column prefix or NULL -@param[in] ientry the secondary index entry -@param[in,out] heap heap used to build virtual dtuple -@param[in,out] n_non_v_col number of non-virtual columns in the index -@return true if all matches, false otherwise */ -static -bool -row_vers_non_vc_match( - dict_index_t* index, - const dtuple_t* row, - const row_ext_t* ext, - const dtuple_t* ientry, - mem_heap_t* heap, - ulint* n_non_v_col) -{ - const dfield_t* field1; - dfield_t* field2; - ulint n_fields = dtuple_get_n_fields(ientry); - ulint ret = true; - - *n_non_v_col = 0; - - /* Build index entry out of row */ - dtuple_t* nentry = row_build_index_entry(row, ext, index, heap); - - for (ulint i = 0; i < n_fields; i++) { - const dict_field_t* ind_field = dict_index_get_nth_field( - index, i); - - const dict_col_t* col = ind_field->col; - - /* Only check non-virtual columns */ - if (dict_col_is_virtual(col)) { - continue; - } - - if (ret) { - field1 = dtuple_get_nth_field(ientry, i); - field2 = dtuple_get_nth_field(nentry, i); - - if (cmp_dfield_dfield(field1, field2) != 0) { - ret = false; - } - } - - (*n_non_v_col)++; - } - - return(ret); -} - /** build virtual column value from current cluster index record data @param[in,out] row the cluster index row in dtuple form @param[in] clust_index clustered index @@ -626,8 +593,7 @@ that of current cluster index record, which is recreated from information stored in undo log @param[in] in_purge called by purge thread @param[in] rec record in the clustered index -@param[in] row the cluster index row in dtuple form -@param[in] ext externally stored column prefix or NULL +@param[in] icentry the index entry built from a cluster row @param[in] clust_index cluster index @param[in] clust_offsets offsets on the cluster record @param[in] index the secondary index @@ -643,8 +609,7 @@ bool row_vers_vc_matches_cluster( bool in_purge, const rec_t* rec, - const dtuple_t* row, - row_ext_t* ext, + const dtuple_t* icentry, dict_index_t* clust_index, ulint* clust_offsets, dict_index_t* index, @@ -669,15 +634,27 @@ row_vers_vc_matches_cluster( dfield_t* field2; ulint i; - tuple_heap = mem_heap_create(1024); - /* First compare non-virtual columns (primary keys) */ - if (!row_vers_non_vc_match(index, row, ext, ientry, tuple_heap, - &n_non_v_col)) { - mem_heap_free(tuple_heap); - return(false); + ut_ad(index->n_fields == n_fields); + ut_ad(n_fields == dtuple_get_n_fields(icentry)); + { + const dfield_t* a = ientry->fields; + const dfield_t* b = icentry->fields; + + for (const dict_field_t *ifield = index->fields, + *const end = &index->fields[index->n_fields]; + ifield != end; ifield++, a++, b++) { + if (!dict_col_is_virtual(ifield->col)) { + if (cmp_dfield_dfield(a, b)) { + return false; + } + n_non_v_col++; + } + } } + tuple_heap = mem_heap_create(1024); + ut_ad(n_fields > n_non_v_col); *vrow = dtuple_create_with_vcol(v_heap ? v_heap : tuple_heap, 0, num_v); @@ -946,27 +923,28 @@ row_vers_old_has_index_entry( entry = row_build_index_entry( row, ext, index, heap); if (entry && !dtuple_coll_cmp(ientry, entry)) { - - mem_heap_free(heap); - - if (v_heap) { - mem_heap_free(v_heap); - } - - return(TRUE); + goto safe_to_purge; } } else { - if (row_vers_vc_matches_cluster( - also_curr, rec, row, ext, clust_index, - clust_offsets, index, ientry, roll_ptr, - trx_id, NULL, &vrow, mtr)) { - mem_heap_free(heap); - - if (v_heap) { - mem_heap_free(v_heap); - } - - return(TRUE); + /* Build index entry out of row */ + entry = row_build_index_entry(row, ext, index, heap); + /* entry could only be NULL if + the clustered index record is an uncommitted + inserted record whose BLOBs have not been + written yet. The secondary index record + can be safely removed, because it cannot + possibly refer to this incomplete + clustered index record. (Insert would + always first be completed for the + clustered index record, then proceed to + secondary indexes.) */ + + if (entry && row_vers_vc_matches_cluster( + also_curr, rec, entry, + clust_index, clust_offsets, + index, ientry, roll_ptr, + trx_id, NULL, &vrow, mtr)) { + goto safe_to_purge; } } clust_offsets = rec_get_offsets(rec, clust_index, NULL, @@ -999,7 +977,7 @@ row_vers_old_has_index_entry( a different binary value in a char field, but the collation identifies the old and new value anyway! */ if (entry && !dtuple_coll_cmp(ientry, entry)) { - +safe_to_purge: mem_heap_free(heap); if (v_heap) { @@ -1096,13 +1074,7 @@ row_vers_old_has_index_entry( and new value anyway! */ if (entry && !dtuple_coll_cmp(ientry, entry)) { - - mem_heap_free(heap); - if (v_heap) { - mem_heap_free(v_heap); - } - - return(TRUE); + goto safe_to_purge; } } |