From b8c8692fd93b68df8f70db5ffab82ed0d67008b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 13 Apr 2021 10:28:13 +0300 Subject: MDEV-24620 ASAN heap-buffer-overflow in btr_pcur_restore_position() Between btr_pcur_store_position() and btr_pcur_restore_position() it is possible that purge empties a table and enlarges index->n_core_fields and index->n_core_null_bytes. Therefore, we must cache index->n_core_fields in btr_pcur_t::old_n_core_fields so that btr_pcur_t::old_rec can be parsed correctly. Unfortunately, this is a huge change, because we will replace "bool leaf" parameters with "ulint n_core" (passing index->n_core_fields, or 0 for non-leaf pages). For special cases where we know that index->is_instant() cannot hold, we may also pass index->n_fields. --- storage/innobase/btr/btr0btr.cc | 51 ++++++++++++++--------- storage/innobase/btr/btr0bulk.cc | 28 ++++++++----- storage/innobase/btr/btr0cur.cc | 43 +++++++++++--------- storage/innobase/btr/btr0defragment.cc | 9 +++-- storage/innobase/btr/btr0pcur.cc | 51 +++++++++++++++++++---- storage/innobase/btr/btr0sea.cc | 31 ++++++++------ storage/innobase/dict/dict0dict.cc | 51 ++++------------------- storage/innobase/dict/dict0mem.cc | 5 ++- storage/innobase/dict/dict0stats.cc | 32 ++++++++------- storage/innobase/fts/fts0fts.cc | 11 +++-- storage/innobase/gis/gis0rtree.cc | 68 +++++++++++++++++-------------- storage/innobase/gis/gis0sea.cc | 67 +++++++++++++++--------------- storage/innobase/ibuf/ibuf0ibuf.cc | 9 +++-- storage/innobase/include/btr0pcur.h | 6 ++- storage/innobase/include/dict0dict.h | 17 +------- storage/innobase/include/dict0mem.h | 11 ++++- storage/innobase/include/gis0rtree.ic | 5 ++- storage/innobase/include/page0cur.ic | 5 ++- storage/innobase/include/rem0rec.h | 12 +++--- storage/innobase/lock/lock0lock.cc | 15 ++++--- storage/innobase/page/page0cur.cc | 61 +++++++++++++++------------- storage/innobase/page/page0page.cc | 33 +++++++-------- storage/innobase/page/page0zip.cc | 32 ++++++++------- storage/innobase/rem/rem0rec.cc | 74 ++++++++++++++++++++-------------- storage/innobase/row/row0import.cc | 6 ++- storage/innobase/row/row0ins.cc | 25 +++++++----- storage/innobase/row/row0log.cc | 13 +++--- storage/innobase/row/row0merge.cc | 6 ++- storage/innobase/row/row0mysql.cc | 17 ++++---- storage/innobase/row/row0purge.cc | 11 ++--- storage/innobase/row/row0row.cc | 10 +++-- storage/innobase/row/row0sel.cc | 57 ++++++++++++++++---------- storage/innobase/row/row0uins.cc | 5 ++- storage/innobase/row/row0umod.cc | 13 +++--- storage/innobase/row/row0undo.cc | 5 ++- storage/innobase/row/row0upd.cc | 22 +++++----- storage/innobase/row/row0vers.cc | 40 ++++++++++-------- storage/innobase/trx/trx0i_s.cc | 3 +- storage/innobase/trx/trx0rec.cc | 5 ++- storage/innobase/ut/ut0ut.cc | 4 +- 40 files changed, 548 insertions(+), 421 deletions(-) (limited to 'storage/innobase') diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 2c5e7f96655..2842f9a6bc0 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2020, MariaDB Corporation. +Copyright (c) 2014, 2021, 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 @@ -890,7 +890,7 @@ btr_page_get_father_node_ptr_func( node_ptr = btr_cur_get_rec(cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != page_no) { @@ -907,10 +907,11 @@ btr_page_get_father_node_ptr_func( print_rec = page_rec_get_next( page_get_infimum_rec(page_align(user_rec))); offsets = rec_get_offsets(print_rec, index, offsets, - page_rec_is_leaf(user_rec), + page_rec_is_leaf(user_rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); page_rec_print(print_rec, offsets); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); page_rec_print(node_ptr, offsets); @@ -2214,7 +2215,9 @@ btr_page_get_split_rec( incl_data += insert_size; } else { offsets = rec_get_offsets(rec, cursor->index, offsets, - page_is_leaf(page), + page_is_leaf(page) + ? cursor->index->n_core_fields + : 0, ULINT_UNDEFINED, &heap); incl_data += rec_offs_size(offsets); } @@ -2323,7 +2326,9 @@ btr_page_insert_fits( space after rec is removed from page. */ *offsets = rec_get_offsets(rec, cursor->index, *offsets, - page_is_leaf(page), + page_is_leaf(page) + ? cursor->index->n_core_fields + : 0, ULINT_UNDEFINED, heap); total_data -= rec_offs_size(*offsets); @@ -2610,7 +2615,8 @@ btr_page_tuple_smaller( first_rec = page_cur_get_rec(&pcur); *offsets = rec_get_offsets( - first_rec, cursor->index, *offsets, page_is_leaf(block->frame), + first_rec, cursor->index, *offsets, + page_is_leaf(block->frame) ? cursor->index->n_core_fields : 0, n_uniq, heap); return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0); @@ -2894,7 +2900,9 @@ func_start: first_rec = move_limit = split_rec; *offsets = rec_get_offsets(split_rec, cursor->index, *offsets, - page_is_leaf(page), n_uniq, heap); + page_is_leaf(page) + ? cursor->index->n_core_fields : 0, + n_uniq, heap); insert_left = !tuple || cmp_dtuple_rec(tuple, split_rec, *offsets) < 0; @@ -3665,7 +3673,7 @@ retry: rec_offs* offsets2 = NULL; /* For rtree, we need to update father's mbr. */ - if (dict_index_is_spatial(index)) { + if (index->is_spatial()) { /* We only support merge pages with the same parent page */ if (!rtr_check_same_block( @@ -3683,7 +3691,8 @@ retry: offsets2 = rec_get_offsets( btr_cur_get_rec(&cursor2), index, NULL, - page_is_leaf(cursor2.page_cur.block->frame), + page_is_leaf(cursor2.page_cur.block->frame) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); /* Check if parent entry needs to be updated */ @@ -3857,13 +3866,14 @@ retry: #endif /* UNIV_DEBUG */ /* For rtree, we need to update father's mbr. */ - if (dict_index_is_spatial(index)) { + if (index->is_spatial()) { rec_offs* offsets2; ulint rec_info; offsets2 = rec_get_offsets( btr_cur_get_rec(&cursor2), index, NULL, - page_is_leaf(cursor2.page_cur.block->frame), + page_is_leaf(cursor2.page_cur.block->frame) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); ut_ad(btr_node_ptr_get_child_page_no( @@ -4341,7 +4351,7 @@ btr_print_recursive( node_ptr = page_cur_get_rec(&cursor); *offsets = rec_get_offsets( - node_ptr, index, *offsets, false, + node_ptr, index, *offsets, 0, ULINT_UNDEFINED, heap); btr_print_recursive(index, btr_node_ptr_get_child(node_ptr, @@ -4490,7 +4500,9 @@ btr_index_rec_validate( page = page_align(rec); - if (dict_index_is_ibuf(index)) { + ut_ad(index->n_core_fields); + + if (index->is_ibuf()) { /* The insert buffer index tree can contain records from any other index: we cannot check the number of fields or their length */ @@ -4536,7 +4548,8 @@ btr_index_rec_validate( } } - offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); for (unsigned i = 0; i < index->n_fields; i++) { @@ -4792,7 +4805,7 @@ btr_validate_level( page_cur_move_to_next(&cursor); node_ptr = page_cur_get_rec(&cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); savepoint2 = mtr_set_savepoint(&mtr); @@ -4916,10 +4929,12 @@ loop: right_rec = page_rec_get_next(page_get_infimum_rec( right_page)); offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), + page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); offsets2 = rec_get_offsets(right_rec, index, offsets2, - page_is_leaf(right_page), + page_is_leaf(right_page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); /* For spatial index, we cannot guarantee the key ordering diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 69f605dc905..c05cf2a7b7a 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -193,7 +193,8 @@ PageBulk::insert( if (!page_rec_is_infimum_low(page_offset(m_cur_rec))) { rec_t* old_rec = m_cur_rec; rec_offs* old_offsets = rec_get_offsets( - old_rec, m_index, NULL, is_leaf, + old_rec, m_index, NULL, is_leaf + ? m_index->n_core_fields : 0, ULINT_UNDEFINED, &m_heap); ut_ad(cmp_rec_rec(rec, old_rec, offsets, old_offsets, m_index) @@ -447,6 +448,7 @@ PageBulk::getSplitRec() ut_ad(m_page_zip != NULL); ut_ad(m_rec_no >= 2); + ut_ad(!m_index->is_instant()); ut_ad(page_get_free_space_of_empty(m_is_comp) > m_free_space); total_used_size = page_get_free_space_of_empty(m_is_comp) @@ -456,13 +458,13 @@ PageBulk::getSplitRec() n_recs = 0; offsets = NULL; rec = page_get_infimum_rec(m_page); + const ulint n_core = page_is_leaf(m_page) ? m_index->n_core_fields : 0; do { rec = page_rec_get_next(rec); ut_ad(page_rec_is_user_rec(rec)); - offsets = rec_get_offsets(rec, m_index, offsets, - page_is_leaf(m_page), + offsets = rec_get_offsets(rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); total_recs_size += rec_offs_size(offsets); n_recs++; @@ -491,9 +493,11 @@ PageBulk::copyIn( ut_ad(m_rec_no == 0); ut_ad(page_rec_is_user_rec(rec)); + const ulint n_core = page_rec_is_leaf(rec) + ? m_index->n_core_fields : 0; + do { - offsets = rec_get_offsets(rec, m_index, offsets, - page_rec_is_leaf(split_rec), + offsets = rec_get_offsets(rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); insert(rec, offsets); @@ -534,8 +538,10 @@ PageBulk::copyOut( /* Set last record's next in page */ rec_offs* offsets = NULL; rec = page_rec_get_prev(split_rec); - offsets = rec_get_offsets(rec, m_index, offsets, - page_rec_is_leaf(split_rec), + const ulint n_core = page_rec_is_leaf(split_rec) + ? m_index->n_core_fields : 0; + + offsets = rec_get_offsets(rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); page_rec_set_next(rec, page_get_supremum_rec(m_page)); @@ -543,8 +549,7 @@ PageBulk::copyOut( m_cur_rec = rec; m_heap_top = rec_get_end(rec, offsets); - offsets = rec_get_offsets(last_rec, m_index, offsets, - page_rec_is_leaf(split_rec), + offsets = rec_get_offsets(last_rec, m_index, offsets, n_core, ULINT_UNDEFINED, &m_heap); m_free_space += ulint(rec_get_end(last_rec, offsets) - m_heap_top) @@ -975,7 +980,8 @@ BtrBulk::insert( /* Convert tuple to rec. */ rec = rec_convert_dtuple_to_rec(static_cast(mem_heap_alloc( page_bulk->m_heap, rec_size)), m_index, tuple, n_ext); - offsets = rec_get_offsets(rec, m_index, offsets, !level, + offsets = rec_get_offsets(rec, m_index, offsets, level + ? 0 : m_index->n_core_fields, ULINT_UNDEFINED, &page_bulk->m_heap); page_bulk->insert(rec, offsets); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index cb00d009973..45ba84e319c 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -479,7 +479,8 @@ incompatible: from the cache. */ mem_heap_t* heap = NULL; - rec_offs* offsets = rec_get_offsets(rec, index, NULL, true, + rec_offs* offsets = rec_get_offsets(rec, index, NULL, + index->n_core_fields, ULINT_UNDEFINED, &heap); if (rec_offs_any_default(offsets)) { inconsistent: @@ -1920,7 +1921,7 @@ retry_page_get: node_ptr = page_cur_get_rec(page_cursor); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for @@ -2051,7 +2052,7 @@ need_opposite_intention: offsets2 = rec_get_offsets( first_rec, index, offsets2, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); cmp_rec_rec(node_ptr, first_rec, offsets, offsets2, index, false, &matched_fields); @@ -2069,7 +2070,7 @@ need_opposite_intention: offsets2 = rec_get_offsets( last_rec, index, offsets2, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); cmp_rec_rec( node_ptr, last_rec, offsets, offsets2, index, @@ -2238,7 +2239,7 @@ need_opposite_intention: offsets = rec_get_offsets( my_node_ptr, index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); ulint my_page_no = btr_node_ptr_get_child_page_no( @@ -2690,7 +2691,7 @@ btr_cur_open_at_index_side_func( node_ptr = page_cur_get_rec(page_cursor); offsets = rec_get_offsets(node_ptr, cursor->index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -2985,7 +2986,7 @@ btr_cur_open_at_rnd_pos_func( node_ptr = page_cur_get_rec(page_cursor); offsets = rec_get_offsets(node_ptr, cursor->index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); /* If the rec is the first or last in the page for pessimistic delete intention, it might cause node_ptr insert @@ -3932,7 +3933,8 @@ btr_cur_parse_update_in_place( flags != (BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG) - || page_is_leaf(page), + || page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (!(flags & BTR_KEEP_SYS_FLAG)) { @@ -4318,7 +4320,7 @@ btr_cur_optimistic_update( ut_ad(fil_page_index_page_check(page)); ut_ad(btr_page_get_index_id(page) == index->id); - *offsets = rec_get_offsets(rec, index, *offsets, true, + *offsets = rec_get_offsets(rec, index, *offsets, index->n_core_fields, ULINT_UNDEFINED, heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(rec, *offsets) @@ -5158,7 +5160,8 @@ btr_cur_parse_del_mark_set_clust_rec( if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_rec_sys_fields_in_recovery( rec, page_zip, - rec_get_offsets(rec, index, offsets, true, + rec_get_offsets(rec, index, offsets, + index->n_core_fields, pos + 2, &heap), pos, trx_id, roll_ptr); } else { @@ -5167,7 +5170,8 @@ btr_cur_parse_del_mark_set_clust_rec( ut_ad(memcmp(rec_get_nth_field( rec, rec_get_offsets(rec, index, - offsets, true, + offsets, index + ->n_core_fields, pos, &heap), pos, &offset), field_ref_zero, DATA_TRX_ID_LEN)); @@ -5502,7 +5506,8 @@ btr_cur_optimistic_delete_func( rec = btr_cur_get_rec(cursor); - offsets = rec_get_offsets(rec, cursor->index, offsets, true, + offsets = rec_get_offsets(rec, cursor->index, offsets, + cursor->index->n_core_fields, ULINT_UNDEFINED, &heap); const ibool no_compress_needed = !rec_offs_any_extern(offsets) @@ -5711,7 +5716,8 @@ btr_cur_pessimistic_delete( ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ - offsets = rec_get_offsets(rec, index, NULL, page_is_leaf(page), + offsets = rec_get_offsets(rec, index, NULL, page_is_leaf(page) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (rec_offs_any_extern(offsets)) { @@ -5807,7 +5813,7 @@ discard_page: pointer as the predefined minimum record */ min_mark_next_rec = true; - } else if (dict_index_is_spatial(index)) { + } else if (index->is_spatial()) { /* For rtree, if delete the leftmost node pointer, we need to update parent page. */ rtr_mbr_t father_mbr; @@ -5822,7 +5828,7 @@ discard_page: &father_cursor); offsets = rec_get_offsets( btr_cur_get_rec(&father_cursor), index, NULL, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); father_rec = btr_cur_get_rec(&father_cursor); rtr_read_mbr(rec_get_nth_field( @@ -6744,12 +6750,13 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index) page = btr_cur_get_page(&cursor); rec = page_rec_get_next(page_get_infimum_rec(page)); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) + ? index->n_core_fields : 0; if (!page_rec_is_supremum(rec)) { not_empty_flag = 1; offsets_rec = rec_get_offsets(rec, index, offsets_rec, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); if (n_not_null != NULL) { @@ -6770,7 +6777,7 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index) offsets_next_rec = rec_get_offsets(next_rec, index, offsets_next_rec, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index 522c356fbb0..99b15965281 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2012, 2014 Facebook, Inc. All Rights Reserved. -Copyright (C) 2014, 2019, MariaDB Corporation. +Copyright (C) 2014, 2021, 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 @@ -340,12 +340,12 @@ btr_defragment_calc_n_recs_for_size( ulint size = 0; page_cur_t cur; + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; page_cur_set_before_first(block, &cur); page_cur_move_to_next(&cur); while (page_cur_get_rec(&cur) != page_get_supremum_rec(page)) { rec_t* cur_rec = page_cur_get_rec(&cur); - offsets = rec_get_offsets(cur_rec, index, offsets, - page_is_leaf(page), + offsets = rec_get_offsets(cur_rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); ulint rec_size = rec_offs_size(offsets); size += rec_size; @@ -357,6 +357,9 @@ btr_defragment_calc_n_recs_for_size( page_cur_move_to_next(&cur); } *n_recs_size = size; + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } return n_recs; } diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 9c6189acbce..ef626e12cf4 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -61,6 +61,7 @@ btr_pcur_reset( cursor->btr_cur.index = NULL; cursor->btr_cur.page_cur.rec = NULL; cursor->old_rec = NULL; + cursor->old_n_core_fields = 0; cursor->old_n_fields = 0; cursor->old_stored = false; @@ -178,9 +179,28 @@ before_first: cursor->rel_pos = BTR_PCUR_ON; } - cursor->old_rec = dict_index_copy_rec_order_prefix( - index, rec, &cursor->old_n_fields, - &cursor->old_rec_buf, &cursor->buf_size); + UNIV_PREFETCH_R(rec); + + if (index->is_ibuf()) { + cursor->old_n_fields = uint16(rec_get_n_fields_old(rec)); + } else { + cursor->old_n_fields = static_cast( + dict_index_get_n_unique_in_tree(index)); + if (index->is_spatial() && !page_rec_is_leaf(rec)) { + ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) + == DICT_INDEX_SPATIAL_NODEPTR_SIZE); + /* For R-tree, we have to compare + the child page numbers as well. */ + cursor->old_n_fields + = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; + } + } + + cursor->old_n_core_fields = index->n_core_fields; + cursor->old_rec = rec_copy_prefix_to_buf(rec, index, + cursor->old_n_fields, + &cursor->old_rec_buf, + &cursor->buf_size); cursor->block_when_stored.store(block); @@ -212,6 +232,7 @@ btr_pcur_copy_stored_position( + (pcur_donate->old_rec - pcur_donate->old_rec_buf); } + pcur_receive->old_n_core_fields = pcur_donate->old_n_core_fields; pcur_receive->old_n_fields = pcur_donate->old_n_fields; } @@ -303,6 +324,8 @@ btr_pcur_restore_position_func( } ut_a(cursor->old_rec); + ut_a(cursor->old_n_core_fields); + ut_a(cursor->old_n_core_fields <= index->n_core_fields); ut_a(cursor->old_n_fields); switch (latch_mode) { @@ -336,11 +359,16 @@ btr_pcur_restore_position_func( rec_offs_init(offsets2_); heap = mem_heap_create(256); + ut_ad(cursor->old_n_core_fields + == index->n_core_fields); + offsets1 = rec_get_offsets( - cursor->old_rec, index, offsets1, true, + cursor->old_rec, index, offsets1, + cursor->old_n_core_fields, cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, offsets2, true, + rec, index, offsets2, + index->n_core_fields, cursor->old_n_fields, &heap); ut_ad(!cmp_rec_rec(cursor->old_rec, @@ -365,8 +393,14 @@ btr_pcur_restore_position_func( heap = mem_heap_create(256); - tuple = dict_index_build_data_tuple(cursor->old_rec, index, true, - cursor->old_n_fields, heap); + tuple = dtuple_create(heap, cursor->old_n_fields); + + dict_index_copy_types(tuple, index, cursor->old_n_fields); + + rec_copy_prefix_to_dtuple(tuple, cursor->old_rec, index, + cursor->old_n_core_fields, + cursor->old_n_fields, heap); + ut_ad(dtuple_check_typed(tuple)); /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; @@ -405,7 +439,8 @@ btr_pcur_restore_position_func( && btr_pcur_is_on_user_rec(cursor) && !cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), rec_get_offsets(btr_pcur_get_rec(cursor), - index, offsets, true, + index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap))) { /* We have to store the NEW value for the modify clock, diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index b0b75ded890..1b8375d60fe 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -703,7 +703,8 @@ btr_search_update_hash_ref( ulint fold = rec_fold( rec, - rec_get_offsets(rec, index, offsets_, true, + rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, index->id); @@ -762,7 +763,8 @@ btr_search_check_guess( match = 0; - offsets = rec_get_offsets(rec, cursor->index, offsets, true, + offsets = rec_get_offsets(rec, cursor->index, offsets, + cursor->index->n_core_fields, n_unique, &heap); cmp = cmp_dtuple_rec_with_match(tuple, rec, offsets, &match); @@ -813,7 +815,8 @@ btr_search_check_guess( } offsets = rec_get_offsets(prev_rec, cursor->index, offsets, - true, n_unique, &heap); + cursor->index->n_core_fields, + n_unique, &heap); cmp = cmp_dtuple_rec_with_match( tuple, prev_rec, offsets, &match); if (mode == PAGE_CUR_GE) { @@ -836,7 +839,8 @@ btr_search_check_guess( } offsets = rec_get_offsets(next_rec, cursor->index, offsets, - true, n_unique, &heap); + cursor->index->n_core_fields, + n_unique, &heap); cmp = cmp_dtuple_rec_with_match( tuple, next_rec, offsets, &match); if (mode == PAGE_CUR_LE) { @@ -1202,7 +1206,7 @@ retry: while (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id); @@ -1428,7 +1432,7 @@ btr_search_build_page_hash_index( ut_a(index->id == btr_page_get_index_id(page)); offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); ut_ad(page_rec_is_supremum(rec) @@ -1459,7 +1463,7 @@ btr_search_build_page_hash_index( } offsets = rec_get_offsets( - next_rec, index, offsets, true, + next_rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, index->id); @@ -1699,7 +1703,8 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor) rec = btr_cur_get_rec(cursor); - fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, true, + fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap), block->curr_n_fields, block->curr_n_bytes, index->id); if (UNIV_LIKELY_NULL(heap)) { @@ -1876,13 +1881,14 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) ins_rec = page_rec_get_next_const(rec); next_rec = page_rec_get_next_const(ins_rec); - offsets = rec_get_offsets(ins_rec, index, offsets, true, + offsets = rec_get_offsets(ins_rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id); if (!page_rec_is_supremum(next_rec)) { offsets = rec_get_offsets( - next_rec, index, offsets, true, + next_rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, n_bytes, index->id); @@ -1894,7 +1900,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, index)) { offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, index->n_core_fields, btr_search_get_n_fields(n_fields, n_bytes), &heap); fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id); } else { @@ -2100,7 +2106,8 @@ btr_search_hash_table_validate(ulint hash_table_id) page_index_id = btr_page_get_index_id(block->frame); offsets = rec_get_offsets( - node->data, block->index, offsets, true, + node->data, block->index, offsets, + block->index->n_core_fields, btr_search_get_n_fields(block->curr_n_fields, block->curr_n_bytes), &heap); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 1abcb2f9065..1f05eb80e5d 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2021, 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 @@ -5035,7 +5035,9 @@ dict_index_build_node_ptr( dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4); - rec_copy_prefix_to_dtuple(tuple, rec, index, !level, n_unique, heap); + rec_copy_prefix_to_dtuple(tuple, rec, index, + level ? 0 : index->n_core_fields, + n_unique, heap); dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) | REC_STATUS_NODE_PTR); @@ -5044,46 +5046,6 @@ dict_index_build_node_ptr( return(tuple); } -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ -{ - ulint n; - - UNIV_PREFETCH_R(rec); - - if (dict_index_is_ibuf(index)) { - ut_ad(!dict_table_is_comp(index->table)); - n = rec_get_n_fields_old(rec); - } else { - if (page_rec_is_leaf(rec)) { - n = dict_index_get_n_unique_in_tree(index); - } else if (dict_index_is_spatial(index)) { - ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) - == DICT_INDEX_SPATIAL_NODEPTR_SIZE); - /* For R-tree, we have to compare - the child page numbers as well. */ - n = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; - } else { - n = dict_index_get_n_unique_in_tree(index); - } - } - - *n_fields = n; - return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size)); -} - /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index @@ -5099,11 +5061,14 @@ dict_index_build_data_tuple( ulint n_fields, mem_heap_t* heap) { + ut_ad(!index->is_clust()); + dtuple_t* tuple = dtuple_create(heap, n_fields); dict_index_copy_types(tuple, index, n_fields); - rec_copy_prefix_to_dtuple(tuple, rec, index, leaf, n_fields, heap); + rec_copy_prefix_to_dtuple(tuple, rec, index, + leaf ? n_fields : 0, n_fields, heap); ut_ad(dtuple_check_typed(tuple)); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index ea2f51d0f04..265642ef210 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2021, 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 @@ -1544,7 +1544,8 @@ dict_index_t::vers_history_row( rec_t* clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, this, &clust_index, &mtr); if (clust_rec) { - offsets = rec_get_offsets(clust_rec, clust_index, offsets, true, + offsets = rec_get_offsets(clust_rec, clust_index, offsets, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); history_row = clust_index->vers_history_row(clust_rec, offsets); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index ba9ab056201..e36e2184e2d 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2009, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2020, MariaDB Corporation. +Copyright (c) 2015, 2021, 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 @@ -1158,7 +1158,7 @@ dict_stats_analyze_index_level( prev_rec_offsets = rec_get_offsets( prev_rec, index, prev_rec_offsets, - true, + index->n_core_fields, n_uniq, &heap); prev_rec = rec_copy_prefix_to_buf( @@ -1170,8 +1170,9 @@ dict_stats_analyze_index_level( continue; } - rec_offsets = rec_get_offsets( - rec, index, rec_offsets, !level, n_uniq, &heap); + rec_offsets = rec_get_offsets(rec, index, rec_offsets, + level ? 0 : index->n_core_fields, + n_uniq, &heap); (*total_recs)++; @@ -1179,7 +1180,8 @@ dict_stats_analyze_index_level( ulint matched_fields; prev_rec_offsets = rec_get_offsets( - prev_rec, index, prev_rec_offsets, !level, + prev_rec, index, prev_rec_offsets, + level ? 0 : index->n_core_fields, n_uniq, &heap); cmp_rec_rec(prev_rec, rec, @@ -1333,7 +1335,7 @@ be big enough) @param[in] index index of the page @param[in] page the page to scan @param[in] n_prefix look at the first n_prefix columns -@param[in] is_leaf whether this is the leaf page +@param[in] n_core 0, or index->n_core_fields for leaf @param[out] n_diff number of distinct records encountered @param[out] n_external_pages if this is non-NULL then it will be set to the number of externally stored pages which were encountered @@ -1348,7 +1350,7 @@ dict_stats_scan_page( const dict_index_t* index, const page_t* page, ulint n_prefix, - bool is_leaf, + ulint n_core, ib_uint64_t* n_diff, ib_uint64_t* n_external_pages) { @@ -1360,9 +1362,9 @@ dict_stats_scan_page( Because offsets1,offsets2 should be big enough, this memory heap should never be used. */ mem_heap_t* heap = NULL; - ut_ad(is_leaf == page_is_leaf(page)); + ut_ad(!!n_core == page_is_leaf(page)); const rec_t* (*get_next)(const rec_t*) - = !is_leaf || srv_stats_include_delete_marked + = !n_core || srv_stats_include_delete_marked ? page_rec_get_next_const : page_rec_get_next_non_del_marked; @@ -1381,7 +1383,7 @@ dict_stats_scan_page( return(NULL); } - offsets_rec = rec_get_offsets(rec, index, offsets_rec, is_leaf, + offsets_rec = rec_get_offsets(rec, index, offsets_rec, n_core, ULINT_UNDEFINED, &heap); if (should_count_external_pages) { @@ -1398,7 +1400,7 @@ dict_stats_scan_page( ulint matched_fields; offsets_next_rec = rec_get_offsets(next_rec, index, - offsets_next_rec, is_leaf, + offsets_next_rec, n_core, ULINT_UNDEFINED, &heap); @@ -1412,7 +1414,7 @@ dict_stats_scan_page( (*n_diff)++; - if (!is_leaf) { + if (!n_core) { break; } } @@ -1498,7 +1500,7 @@ dict_stats_analyze_index_below_cur( rec = btr_cur_get_rec(cur); ut_ad(!page_rec_is_leaf(rec)); - offsets_rec = rec_get_offsets(rec, index, offsets1, false, + offsets_rec = rec_get_offsets(rec, index, offsets1, 0, ULINT_UNDEFINED, &heap); page_id_t page_id(index->table->space_id, @@ -1532,7 +1534,7 @@ dict_stats_analyze_index_below_cur( /* search for the first non-boring record on the page */ offsets_rec = dict_stats_scan_page( &rec, offsets1, offsets2, index, page, n_prefix, - false, n_diff, NULL); + 0, n_diff, NULL); /* pages on level > 0 are not allowed to be empty */ ut_a(offsets_rec != NULL); @@ -1577,7 +1579,7 @@ dict_stats_analyze_index_below_cur( offsets_rec = dict_stats_scan_page( &rec, offsets1, offsets2, index, page, n_prefix, - true, n_diff, + index->n_core_fields, n_diff, n_external_pages); #if 0 diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index c469055a763..ae60a6a9875 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2020, MariaDB Corporation. +Copyright (c) 2016, 2021, 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 @@ -3495,7 +3495,8 @@ fts_add_doc_by_id( } - offsets = rec_get_offsets(clust_rec, clust_index, NULL, true, + offsets = rec_get_offsets(clust_rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); for (ulint i = 0; i < num_idx; ++i) { @@ -3671,7 +3672,8 @@ fts_get_max_doc_id( ut_ad(!rec_is_metadata(rec, index)); offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &heap); + rec, index, offsets, index->n_core_fields, + ULINT_UNDEFINED, &heap); data = rec_get_nth_field(rec, offsets, 0, &len); @@ -5166,7 +5168,8 @@ fts_get_doc_id_from_rec( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &my_heap); + rec, index, offsets, index->n_core_fields, + ULINT_UNDEFINED, &my_heap); col_no = dict_col_get_index_pos( &table->cols[table->fts->doc_col], index); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index 31344372c80..3ac2fbc0093 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 2021, 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 @@ -87,8 +87,9 @@ rtr_page_split_initialize_nodes( stop = task + n_recs; rec = page_rec_get_next(page_get_infimum_rec(page)); - const bool is_leaf = page_is_leaf(page); - *offsets = rec_get_offsets(rec, cursor->index, *offsets, is_leaf, + const ulint n_core = page_is_leaf(page) + ? cursor->index->n_core_fields : 0; + *offsets = rec_get_offsets(rec, cursor->index, *offsets, n_core, n_uniq, &heap); source_cur = rec_get_nth_field(rec, *offsets, 0, &len); @@ -101,7 +102,7 @@ rtr_page_split_initialize_nodes( rec = page_rec_get_next(rec); *offsets = rec_get_offsets(rec, cursor->index, *offsets, - is_leaf, n_uniq, &heap); + n_core, n_uniq, &heap); source_cur = rec_get_nth_field(rec, *offsets, 0, &len); } @@ -308,7 +309,8 @@ rtr_update_mbr_field( page_zip = buf_block_get_page_zip(block); child = btr_node_ptr_get_child_page_no(rec, offsets); - const bool is_leaf = page_is_leaf(block->frame); + const ulint n_core = page_is_leaf(block->frame) + ? index->n_core_fields : 0; if (new_rec) { child_rec = new_rec; @@ -324,7 +326,7 @@ rtr_update_mbr_field( if (cursor2) { rec_t* del_rec = btr_cur_get_rec(cursor2); offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), - index, NULL, false, + index, NULL, 0, ULINT_UNDEFINED, &heap); del_page_no = btr_node_ptr_get_child_page_no(del_rec, offsets2); cur2_pos = page_rec_get_n_recs_before(btr_cur_get_rec(cursor2)); @@ -389,7 +391,7 @@ rtr_update_mbr_field( = page_rec_get_nth(page, cur2_pos); } offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), - index, NULL, false, + index, NULL, 0, ULINT_UNDEFINED, &heap); ut_ad(del_page_no == btr_node_ptr_get_child_page_no( cursor2->page_cur.rec, @@ -427,7 +429,7 @@ rtr_update_mbr_field( ut_ad(old_rec != insert_rec); page_cur_position(old_rec, block, &page_cur); - offsets2 = rec_get_offsets(old_rec, index, NULL, is_leaf, + offsets2 = rec_get_offsets(old_rec, index, NULL, n_core, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&page_cur, index, offsets2, mtr); @@ -457,7 +459,7 @@ update_mbr: cur2_rec = cursor2->page_cur.rec; offsets2 = rec_get_offsets(cur2_rec, index, NULL, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cur2_rec_info = rec_get_info_bits(cur2_rec, @@ -517,7 +519,7 @@ update_mbr: if (ins_suc) { btr_cur_position(index, insert_rec, block, cursor); offsets = rec_get_offsets(insert_rec, - index, offsets, is_leaf, + index, offsets, n_core, ULINT_UNDEFINED, &heap); } @@ -532,7 +534,7 @@ update_mbr: cur2_rec = btr_cur_get_rec(cursor2); offsets2 = rec_get_offsets(cur2_rec, index, NULL, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); /* If the cursor2 position is on a wrong rec, we @@ -546,7 +548,7 @@ update_mbr: while (!page_rec_is_supremum(cur2_rec)) { offsets2 = rec_get_offsets(cur2_rec, index, NULL, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cur2_pno = btr_node_ptr_get_child_page_no( @@ -834,7 +836,8 @@ rtr_split_page_move_rec_list( rec_move = static_cast(mem_heap_alloc( heap, sizeof (*rec_move) * max_to_move)); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) + ? index->n_core_fields : 0; /* Insert the recs in group 2 to new page. */ for (cur_split_node = node_array; @@ -844,10 +847,10 @@ rtr_split_page_move_rec_list( block, cur_split_node->key); offsets = rec_get_offsets(cur_split_node->key, - index, offsets, is_leaf, + index, offsets, n_core, ULINT_UNDEFINED, &heap); - ut_ad(!is_leaf || cur_split_node->key != first_rec); + ut_ad(!n_core || cur_split_node->key != first_rec); rec = page_cur_insert_rec_low( page_cur_get_rec(&new_page_cursor), @@ -882,7 +885,7 @@ rtr_split_page_move_rec_list( same temp-table in parallel. max_trx_id is ignored for temp tables because it not required for MVCC. */ - if (is_leaf && !index->table->is_temporary()) { + if (n_core && !index->table->is_temporary()) { page_update_max_trx_id(new_block, NULL, page_get_max_trx_id(page), mtr); @@ -935,7 +938,7 @@ rtr_split_page_move_rec_list( block, &page_cursor); offsets = rec_get_offsets( page_cur_get_rec(&page_cursor), index, - offsets, is_leaf, ULINT_UNDEFINED, + offsets, n_core, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&page_cursor, index, offsets, mtr); @@ -1134,6 +1137,9 @@ func_start: /* Update the lock table */ lock_rtr_move_rec_list(new_block, block, rec_move, moved); + const ulint n_core = page_level + ? 0 : cursor->index->n_core_fields; + /* Delete recs in first group from the new page. */ for (cur_split_node = rtr_split_node_array; cur_split_node < end_split_node - 1; ++cur_split_node) { @@ -1152,7 +1158,7 @@ func_start: *offsets = rec_get_offsets( page_cur_get_rec(page_cursor), - cursor->index, *offsets, !page_level, + cursor->index, *offsets, n_core, ULINT_UNDEFINED, heap); page_cur_delete_rec(page_cursor, @@ -1169,7 +1175,7 @@ func_start: block, page_cursor); *offsets = rec_get_offsets( page_cur_get_rec(page_cursor), - cursor->index, *offsets, !page_level, + cursor->index, *offsets, n_core, ULINT_UNDEFINED, heap); page_cur_delete_rec(page_cursor, cursor->index, *offsets, mtr); @@ -1398,7 +1404,8 @@ rtr_page_copy_rec_list_end_no_locks( rec_offs offsets_2[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets2 = offsets_2; ulint moved = 0; - bool is_leaf = page_is_leaf(new_page); + const ulint n_core = page_is_leaf(new_page) + ? index->n_core_fields : 0; rec_offs_init(offsets_1); rec_offs_init(offsets_2); @@ -1427,14 +1434,14 @@ rtr_page_copy_rec_list_end_no_locks( cur_rec = page_rec_get_next(cur_rec); } - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) { ulint cur_matched_fields = 0; int cmp; offsets2 = rec_get_offsets(cur_rec, index, offsets2, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cmp = cmp_rec_rec(cur1_rec, cur_rec, offsets1, offsets2, index, false, @@ -1446,7 +1453,7 @@ rtr_page_copy_rec_list_end_no_locks( /* Skip small recs. */ page_cur_move_to_next(&page_cur); cur_rec = page_cur_get_rec(&page_cur); - } else if (is_leaf) { + } else if (n_core) { if (rec_get_deleted_flag(cur1_rec, dict_table_is_comp(index->table))) { goto next; @@ -1469,7 +1476,7 @@ rtr_page_copy_rec_list_end_no_locks( cur_rec = page_cur_get_rec(&page_cur); - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur_rec, index, @@ -1525,7 +1532,8 @@ rtr_page_copy_rec_list_start_no_locks( rec_offs* offsets2 = offsets_2; page_cur_t page_cur; ulint moved = 0; - bool is_leaf = page_is_leaf(buf_block_get_frame(block)); + const ulint n_core = page_is_leaf(buf_block_get_frame(block)) + ? index->n_core_fields : 0; rec_offs_init(offsets_1); rec_offs_init(offsets_2); @@ -1545,14 +1553,14 @@ rtr_page_copy_rec_list_start_no_locks( cur_rec = page_rec_get_next(cur_rec); } - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); while (!page_rec_is_supremum(cur_rec)) { ulint cur_matched_fields = 0; offsets2 = rec_get_offsets(cur_rec, index, offsets2, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); int cmp = cmp_rec_rec(cur1_rec, cur_rec, offsets1, offsets2, index, false, @@ -1565,7 +1573,7 @@ rtr_page_copy_rec_list_start_no_locks( /* Skip small recs. */ page_cur_move_to_next(&page_cur); cur_rec = page_cur_get_rec(&page_cur); - } else if (is_leaf) { + } else if (n_core) { if (rec_get_deleted_flag( cur1_rec, dict_table_is_comp(index->table))) { @@ -1589,7 +1597,7 @@ rtr_page_copy_rec_list_start_no_locks( cur_rec = page_cur_get_rec(&page_cur); - offsets1 = rec_get_offsets(cur1_rec, index, offsets1, is_leaf, + offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur_rec, index, @@ -1743,7 +1751,7 @@ rtr_check_same_block( while (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets( - rec, index, NULL, false, ULINT_UNDEFINED, &heap); + rec, index, NULL, 0, ULINT_UNDEFINED, &heap); if (btr_node_ptr_get_child_page_no(rec, offsets) == page_no) { btr_cur_position(index, rec, parentb, cursor); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index ff5cbcfa9aa..e5ba43faa0b 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -530,8 +530,7 @@ rtr_compare_cursor_rec( rec = btr_cur_get_rec(cursor); - offsets = rec_get_offsets( - rec, index, NULL, false, ULINT_UNDEFINED, heap); + offsets = rec_get_offsets(rec, index, NULL, 0, ULINT_UNDEFINED, heap); return(btr_node_ptr_get_child_page_no(rec, offsets) == page_no); } @@ -836,7 +835,8 @@ rtr_page_get_father_node_ptr( user_rec = btr_cur_get_rec(cursor); ut_a(page_rec_is_user_rec(user_rec)); - offsets = rec_get_offsets(user_rec, index, offsets, !level, + offsets = rec_get_offsets(user_rec, index, offsets, + level ? 0 : index->n_fields, ULINT_UNDEFINED, &heap); rtr_get_mbr_from_rec(user_rec, offsets, &mbr); @@ -853,7 +853,7 @@ rtr_page_get_father_node_ptr( node_ptr = btr_cur_get_rec(cursor); ut_ad(!page_rec_is_comp(node_ptr) || rec_get_status(node_ptr) == REC_STATUS_NODE_PTR); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); ulint child_page = btr_node_ptr_get_child_page_no(node_ptr, offsets); @@ -871,13 +871,14 @@ rtr_page_get_father_node_ptr( print_rec = page_rec_get_next( page_get_infimum_rec(page_align(user_rec))); offsets = rec_get_offsets(print_rec, index, offsets, - page_rec_is_leaf(user_rec), + page_rec_is_leaf(user_rec) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); error << "; child "; rec_print(error.m_oss, print_rec, rec_get_info_bits(print_rec, rec_offs_comp(offsets)), offsets); - offsets = rec_get_offsets(node_ptr, index, offsets, false, + offsets = rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, &heap); error << "; parent "; rec_print(error.m_oss, print_rec, @@ -1323,10 +1324,12 @@ rtr_cur_restore_position( heap = mem_heap_create(256); offsets1 = rec_get_offsets( - r_cursor->old_rec, index, NULL, !level, + r_cursor->old_rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, r_cursor->old_n_fields, &heap); offsets2 = rec_get_offsets( - rec, index, NULL, !level, + rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, r_cursor->old_n_fields, &heap); comp = rec_offs_comp(offsets1); @@ -1394,12 +1397,12 @@ search_again: rec = btr_pcur_get_rec(r_cursor); - offsets1 = rec_get_offsets( - r_cursor->old_rec, index, NULL, !level, - r_cursor->old_n_fields, &heap); - offsets2 = rec_get_offsets( - rec, index, NULL, !level, - r_cursor->old_n_fields, &heap); + offsets1 = rec_get_offsets(r_cursor->old_rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, + r_cursor->old_n_fields, &heap); + offsets2 = rec_get_offsets(rec, index, NULL, + level ? 0 : r_cursor->old_n_fields, + r_cursor->old_n_fields, &heap); comp = rec_offs_comp(offsets1); @@ -1689,7 +1692,7 @@ rtr_cur_search_with_match( page = buf_block_get_frame(block); const ulint level = btr_page_get_level(page); - const bool is_leaf = !level; + const ulint n_core = level ? 0 : index->n_fields; if (mode == PAGE_CUR_RTREE_LOCATE) { ut_ad(level != 0); @@ -1711,7 +1714,7 @@ rtr_cur_search_with_match( ulint new_rec_size = rec_get_converted_size(index, tuple, 0); - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); @@ -1732,10 +1735,10 @@ rtr_cur_search_with_match( } while (!page_rec_is_supremum(rec)) { - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); - if (!is_leaf) { + if (!n_core) { switch (mode) { case PAGE_CUR_CONTAIN: case PAGE_CUR_INTERSECT: @@ -1816,7 +1819,7 @@ rtr_cur_search_with_match( to rtr_info->path for non-leaf nodes, or rtr_info->matches for leaf nodes */ if (rtr_info && mode != PAGE_CUR_RTREE_INSERT) { - if (!is_leaf) { + if (!n_core) { ulint page_no; node_seq_t new_seq; bool is_loc; @@ -1827,7 +1830,7 @@ rtr_cur_search_with_match( == PAGE_CUR_RTREE_GET_FATHER); offsets = rec_get_offsets( - rec, index, offsets, false, + rec, index, offsets, 0, ULINT_UNDEFINED, &heap); page_no = btr_node_ptr_get_child_page_no( @@ -1876,7 +1879,8 @@ rtr_cur_search_with_match( /* Collect matched records on page */ offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, + index->n_fields, ULINT_UNDEFINED, &heap); rtr_leaf_push_match_rec( rec, rtr_info, offsets, @@ -1899,7 +1903,7 @@ rtr_cur_search_with_match( /* All records on page are searched */ if (page_rec_is_supremum(rec)) { - if (!is_leaf) { + if (!n_core) { if (!found) { /* No match case, if it is for insertion, then we select the record that result in @@ -1909,7 +1913,7 @@ rtr_cur_search_with_match( ut_ad(least_inc < DBL_MAX); offsets = rec_get_offsets( best_rec, index, offsets, - false, ULINT_UNDEFINED, &heap); + 0, ULINT_UNDEFINED, &heap); child_no = btr_node_ptr_get_child_page_no( best_rec, offsets); @@ -1961,11 +1965,11 @@ rtr_cur_search_with_match( /* Verify the record to be positioned is the same as the last record in matched_rec vector */ offsets2 = rec_get_offsets(test_rec.r_rec, index, - offsets2, true, + offsets2, index->n_fields, ULINT_UNDEFINED, &heap); offsets = rec_get_offsets(last_match_rec, index, - offsets, true, + offsets, index->n_fields, ULINT_UNDEFINED, &heap); ut_ad(cmp_rec_rec(test_rec.r_rec, last_match_rec, @@ -1982,9 +1986,8 @@ rtr_cur_search_with_match( ulint child_no; ut_ad(!last_match_rec && rec); - offsets = rec_get_offsets( - rec, index, offsets, false, - ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, 0, + ULINT_UNDEFINED, &heap); child_no = btr_node_ptr_get_child_page_no(rec, offsets); @@ -1992,7 +1995,7 @@ rtr_cur_search_with_match( index, rtr_info->parent_path, level, child_no, block, rec, 0); - } else if (rtr_info && found && !is_leaf) { + } else if (rtr_info && found && !n_core) { rec = last_match_rec; } @@ -2002,11 +2005,11 @@ rtr_cur_search_with_match( #ifdef UNIV_DEBUG /* Verify that we are positioned at the same child page as pushed in the path stack */ - if (!is_leaf && (!page_rec_is_supremum(rec) || found) + if (!n_core && (!page_rec_is_supremum(rec) || found) && mode != PAGE_CUR_RTREE_INSERT) { ulint page_no; - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); page_no = btr_node_ptr_get_child_page_no(rec, offsets); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index f517b49c999..4bebb7d1257 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -3906,7 +3906,7 @@ dump: row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */ ut_ad(rec_get_deleted_flag(rec, page_is_comp(page))); - offsets = rec_get_offsets(rec, index, NULL, true, + offsets = rec_get_offsets(rec, index, NULL, index->n_fields, ULINT_UNDEFINED, &heap); update = row_upd_build_sec_rec_difference_binary( rec, index, offsets, entry, heap); @@ -4079,7 +4079,8 @@ ibuf_delete( ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); - ut_ad(!dict_index_is_spatial(index)); + ut_ad(!index->is_spatial()); + ut_ad(!index->is_clust()); low_match = page_cur_search(block, index, entry, &page_cur); @@ -4098,8 +4099,8 @@ ibuf_delete( rec_offs_init(offsets_); - offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, + ULINT_UNDEFINED, &heap); if (page_get_n_recs(page) <= 1 || !(REC_INFO_DELETED_FLAG diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index 38960b1d15c..b0b61a4d1ff 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -497,8 +497,10 @@ struct btr_pcur_t{ /** if cursor position is stored, contains an initial segment of the latest record cursor was positioned either on, before or after */ rec_t* old_rec; + /** btr_cur.index->n_core_fields when old_rec was copied */ + uint16 old_n_core_fields; /** number of fields in old_rec */ - ulint old_n_fields; + uint16 old_n_fields; /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on whether cursor was on, before, or after the old_rec record */ enum btr_pcur_pos_t rel_pos; diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 1c6dbcd3580..37eae6641af 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2021, 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 @@ -1348,21 +1348,6 @@ dict_index_build_node_ptr( ulint level) /*!< in: level of rec in tree: 0 means leaf level */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 8fc82955b73..40c343652fb 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2021, 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 @@ -1070,6 +1070,15 @@ struct dict_index_t{ return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF)); } + /** @return whether this is a generated clustered index */ + bool is_gen_clust() const { return type == DICT_CLUSTERED; } + + /** @return whether this is a clustered index */ + bool is_clust() const { return type & DICT_CLUSTERED; } + + /** @return whether this is a unique index */ + bool is_unique() const { return type & DICT_UNIQUE; } + /** @return whether this is a spatial index */ bool is_spatial() const { return UNIV_UNLIKELY(type & DICT_SPATIAL); } diff --git a/storage/innobase/include/gis0rtree.ic b/storage/innobase/include/gis0rtree.ic index a22164931b2..89676fb2386 100644 --- a/storage/innobase/include/gis0rtree.ic +++ b/storage/innobase/include/gis0rtree.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -57,7 +57,8 @@ rtr_page_cal_mbr( page = buf_block_get_frame(block); rec = page_rec_get_next(page_get_infimum_rec(page)); - offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page) + ? index->n_fields : 0, ULINT_UNDEFINED, &heap); do { diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index 4d7b5c3a42f..7896aa64792 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2021, 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 @@ -278,7 +278,8 @@ page_cur_tuple_insert( index, tuple, n_ext); *offsets = rec_get_offsets(rec, index, *offsets, - page_is_leaf(cursor->block->frame), + page_is_leaf(cursor->block->frame) + ? index->n_core_fields : 0, ULINT_UNDEFINED, heap); if (buf_block_get_page_zip(cursor->block)) { diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 41980cde2c8..7d7af9e2beb 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -554,7 +554,7 @@ rec_get_n_extern_new( @param[in] index the index that the record belongs to @param[in,out] offsets array comprising offsets[0] allocated elements, or an array from rec_get_offsets(), or NULL -@param[in] leaf whether this is a leaf-page record +@param[in] n_core 0, or index->n_core_fields for leaf page @param[in] n_fields maximum number of offsets to compute (ULINT_UNDEFINED to compute all offsets) @param[in,out] heap memory heap @@ -564,7 +564,7 @@ rec_get_offsets_func( const rec_t* rec, const dict_index_t* index, rec_offs* offsets, - bool leaf, + ulint n_core, ulint n_fields, #ifdef UNIV_DEBUG const char* file, /*!< in: file name where called */ @@ -1121,7 +1121,9 @@ rec_get_converted_size( The fields are copied into the memory heap. @param[out] tuple data tuple @param[in] rec index record, or a copy thereof -@param[in] is_leaf whether rec is a leaf page record +@param[in] index index of rec +@param[in] n_core index->n_core_fields at the time rec was + copied, or 0 if non-leaf page record @param[in] n_fields number of fields to copy @param[in,out] heap memory heap */ void @@ -1129,7 +1131,7 @@ rec_copy_prefix_to_dtuple( dtuple_t* tuple, const rec_t* rec, const dict_index_t* index, - bool is_leaf, + ulint n_core, ulint n_fields, mem_heap_t* heap) MY_ATTRIBUTE((nonnull)); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index bd09f3b81ca..b3086842624 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4486,7 +4486,8 @@ static void lock_rec_print(FILE* file, const lock_t* lock, mtr_t& mtr) ut_ad(!page_rec_is_metadata(rec)); offsets = rec_get_offsets( - rec, lock->index, offsets, true, + rec, lock->index, offsets, + lock->index->n_core_fields, ULINT_UNDEFINED, &heap); putc(' ', file); @@ -5032,8 +5033,8 @@ loop: ut_ad(!lock_rec_get_nth_bit(lock, i) || page_rec_is_leaf(rec)); offsets = rec_get_offsets(rec, lock->index, offsets, - true, ULINT_UNDEFINED, - &heap); + lock->index->n_core_fields, + ULINT_UNDEFINED, &heap); /* If this thread is holding the file space latch (fil_space_t::latch), the following @@ -5364,7 +5365,8 @@ lock_rec_insert_check_and_lock( const rec_offs* offsets; rec_offs_init(offsets_); - offsets = rec_get_offsets(next_rec, index, offsets_, true, + offsets = rec_get_offsets(next_rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate( @@ -5704,7 +5706,8 @@ lock_sec_rec_modify_check_and_lock( const rec_offs* offsets; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(lock_rec_queue_validate( @@ -5916,7 +5919,7 @@ lock_clust_rec_read_check_and_lock_alt( rec_offs_init(offsets_); ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); err = lock_clust_rec_read_check_and_lock(flags, block, rec, index, offsets, mode, gap_mode, thr); diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index cf3ffe671ed..e4007fca83b 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 2021, 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 @@ -75,7 +75,7 @@ page_cur_try_search_shortcut( ut_ad(page_is_leaf(page)); rec = page_header_get_ptr(page, PAGE_LAST_INSERT); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, dtuple_get_n_fields(tuple), &heap); ut_ad(rec); @@ -90,7 +90,8 @@ page_cur_try_search_shortcut( next_rec = page_rec_get_next_const(rec); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, index, offsets, true, + offsets = rec_get_offsets(next_rec, index, offsets, + index->n_core_fields, dtuple_get_n_fields(tuple), &heap); if (cmp_dtuple_rec_with_match(tuple, next_rec, offsets, @@ -159,7 +160,7 @@ page_cur_try_search_shortcut_bytes( ut_ad(page_is_leaf(page)); rec = page_header_get_ptr(page, PAGE_LAST_INSERT); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, dtuple_get_n_fields(tuple), &heap); ut_ad(rec); @@ -180,7 +181,8 @@ page_cur_try_search_shortcut_bytes( next_rec = page_rec_get_next_const(rec); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, index, offsets, true, + offsets = rec_get_offsets(next_rec, index, offsets, + index->n_core_fields, dtuple_get_n_fields(tuple), &heap); if (cmp_dtuple_rec_with_match_bytes( @@ -321,14 +323,14 @@ page_cur_search_with_match( #endif /* UNIV_ZIP_DEBUG */ ut_d(page_check_dir(page)); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; #ifdef BTR_CUR_HASH_ADAPT - if (is_leaf + if (n_core && page_get_direction(page) == PAGE_RIGHT && page_header_get_offs(page, PAGE_LAST_INSERT) && mode == PAGE_CUR_LE - && !dict_index_is_spatial(index) + && !index->is_spatial() && page_header_get_field(page, PAGE_N_DIRECTION) > 3 && page_cur_try_search_shortcut( block, index, tuple, @@ -344,10 +346,10 @@ page_cur_search_with_match( /* If the mode is for R-tree indexes, use the special MBR related compare functions */ - if (dict_index_is_spatial(index) && mode > PAGE_CUR_LE) { + if (index->is_spatial() && mode > PAGE_CUR_LE) { /* For leaf level insert, we still use the traditional compare function for now */ - if (mode == PAGE_CUR_RTREE_INSERT && is_leaf) { + if (mode == PAGE_CUR_RTREE_INSERT && n_core) { mode = PAGE_CUR_LE; } else { rtr_cur_search_with_match( @@ -392,7 +394,7 @@ page_cur_search_with_match( offsets = offsets_; offsets = rec_get_offsets( - mid_rec, index, offsets, is_leaf, + mid_rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match( @@ -446,7 +448,7 @@ up_slot_match: offsets = offsets_; offsets = rec_get_offsets( - mid_rec, index, offsets, is_leaf, + mid_rec, index, offsets, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match( @@ -627,7 +629,7 @@ page_cur_search_with_match_bytes( /* Perform binary search until the lower and upper limit directory slots come to the distance 1 of each other */ - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; while (up - low > 1) { mid = (low + up) / 2; @@ -639,7 +641,7 @@ page_cur_search_with_match_bytes( up_matched_fields, up_matched_bytes); offsets = rec_get_offsets( - mid_rec, index, offsets_, is_leaf, + mid_rec, index, offsets_, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match_bytes( @@ -707,7 +709,7 @@ up_slot_match: } offsets = rec_get_offsets( - mid_rec, index, offsets_, is_leaf, + mid_rec, index, offsets_, n_core, dtuple_get_n_fields_cmp(tuple), &heap); cmp = cmp_dtuple_rec_with_match_bytes( @@ -817,7 +819,8 @@ page_cur_insert_rec_write_log( ut_ad(!page_rec_is_comp(insert_rec) == !dict_table_is_comp(index->table)); - const bool is_leaf = page_rec_is_leaf(cursor_rec); + const ulint n_core = page_rec_is_leaf(cursor_rec) + ? index->n_core_fields : 0; { mem_heap_t* heap = NULL; @@ -831,9 +834,9 @@ page_cur_insert_rec_write_log( rec_offs_init(ins_offs_); cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_, - is_leaf, ULINT_UNDEFINED, &heap); + n_core, ULINT_UNDEFINED, &heap); ins_offs = rec_get_offsets(insert_rec, index, ins_offs_, - is_leaf, ULINT_UNDEFINED, &heap); + n_core, ULINT_UNDEFINED, &heap); extra_size = rec_offs_extra_size(ins_offs); cur_extra_size = rec_offs_extra_size(cur_offs); @@ -1091,9 +1094,9 @@ page_cur_parse_insert_rec( /* Read from the log the inserted index record end segment which differs from the cursor record */ - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; - offsets = rec_get_offsets(cursor_rec, index, offsets, is_leaf, + offsets = rec_get_offsets(cursor_rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (!(end_seg_len & 0x1UL)) { @@ -1142,7 +1145,7 @@ page_cur_parse_insert_rec( page_cur_position(cursor_rec, block, &cursor); offsets = rec_get_offsets(buf + origin_offset, index, offsets, - is_leaf, ULINT_UNDEFINED, &heap); + n_core, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr))) { @@ -1323,7 +1326,8 @@ page_cur_insert_rec_low( rec_offs_init(foffsets_); foffsets = rec_get_offsets( - free_rec, index, foffsets, page_is_leaf(page), + free_rec, index, foffsets, + page_is_leaf(page) ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (rec_offs_size(foffsets) < rec_size) { if (UNIV_LIKELY_NULL(heap)) { @@ -1736,7 +1740,8 @@ page_cur_insert_rec_zip( rec_offs_init(foffsets_); foffsets = rec_get_offsets(free_rec, index, foffsets, - page_rec_is_leaf(free_rec), + page_rec_is_leaf(free_rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap); if (rec_offs_size(foffsets) < rec_size) { too_small: @@ -2103,10 +2108,11 @@ page_copy_rec_list_end_to_created_page( slot_index = 0; n_recs = 0; - const bool is_leaf = page_is_leaf(new_page); + const ulint n_core = page_is_leaf(new_page) + ? index->n_core_fields : 0; do { - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); insert_rec = rec_copy(heap_top, rec, offsets); @@ -2148,7 +2154,7 @@ page_copy_rec_list_end_to_created_page( heap_top += rec_size; - rec_offs_make_valid(insert_rec, index, is_leaf, offsets); + rec_offs_make_valid(insert_rec, index, n_core != 0, offsets); page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec, index, mtr); prev_rec = insert_rec; @@ -2285,7 +2291,8 @@ page_cur_parse_delete_rec( page_cur_delete_rec(&cursor, index, rec_get_offsets(rec, index, offsets_, - page_rec_is_leaf(rec), + page_rec_is_leaf(rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap), mtr); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 38796d8cb8d..d69fdc7a202 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -560,7 +560,8 @@ page_copy_rec_list_end_no_locks( ut_a(page_is_comp(new_page) == page_rec_is_comp(rec)); ut_a(mach_read_from_2(new_page + srv_page_size - 10) == (ulint) (page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM)); - const bool is_leaf = page_is_leaf(block->frame); + const ulint n_core = page_is_leaf(block->frame) + ? index->n_core_fields : 0; cur2 = page_get_infimum_rec(buf_block_get_frame(new_block)); @@ -568,7 +569,7 @@ page_copy_rec_list_end_no_locks( while (!page_cur_is_after_last(&cur1)) { rec_t* ins_rec; - offsets = rec_get_offsets(cur1.rec, index, offsets, is_leaf, + offsets = rec_get_offsets(cur1.rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); ins_rec = page_cur_insert_rec_low(cur2, index, cur1.rec, offsets, mtr); @@ -800,7 +801,7 @@ page_copy_rec_list_start( cur2 = ret; - const bool is_leaf = page_rec_is_leaf(rec); + const ulint n_core = page_rec_is_leaf(rec) ? index->n_core_fields : 0; /* Copy records from the original page to the new page */ if (index->is_spatial()) { @@ -822,7 +823,7 @@ page_copy_rec_list_start( } else { while (page_cur_get_rec(&cur1) != rec) { offsets = rec_get_offsets(cur1.rec, index, offsets, - is_leaf, + n_core, ULINT_UNDEFINED, &heap); cur2 = page_cur_insert_rec_low(cur2, index, cur1.rec, offsets, mtr); @@ -842,7 +843,7 @@ page_copy_rec_list_start( same temp-table in parallel. max_trx_id is ignored for temp tables because it not required for MVCC. */ - if (is_leaf && dict_index_is_sec_or_ibuf(index) + if (n_core && dict_index_is_sec_or_ibuf(index) && !index->table->is_temporary()) { page_update_max_trx_id(new_block, NULL, page_get_max_trx_id(page_align(rec)), @@ -1073,7 +1074,7 @@ delete_all: ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; if (page_zip) { mtr_log_t log_mode; @@ -1087,7 +1088,7 @@ delete_all: page_cur_t cur; page_cur_position(rec, block, &cur); - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); rec = rec_get_next_ptr(rec, TRUE); #ifdef UNIV_ZIP_DEBUG @@ -1120,8 +1121,7 @@ delete_all: do { ulint s; - offsets = rec_get_offsets(rec2, index, offsets, - is_leaf, + offsets = rec_get_offsets(rec2, index, offsets, n_core, ULINT_UNDEFINED, &heap); s = rec_offs_size(offsets); ut_ad(ulint(rec2 - page) + s @@ -1267,11 +1267,12 @@ page_delete_rec_list_start( /* Individual deletes are not logged */ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); - const bool is_leaf = page_rec_is_leaf(rec); + const ulint n_core = page_rec_is_leaf(rec) + ? index->n_core_fields : 0; while (page_cur_get_rec(&cur1) != rec) { offsets = rec_get_offsets(page_cur_get_rec(&cur1), index, - offsets, is_leaf, + offsets, n_core, ULINT_UNDEFINED, &heap); page_cur_delete_rec(&cur1, index, offsets, mtr); } @@ -2482,9 +2483,10 @@ wrong_page_type: rec = page_get_infimum_rec(page); + const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; + for (;;) { - offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (page_is_comp(page) && page_rec_is_user_rec(rec) @@ -2732,8 +2734,7 @@ n_owned_zero: rec = page_header_get_ptr(page, PAGE_FREE); while (rec != NULL) { - offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), + offsets = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) { ret = FALSE; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 382d4d5eeb3..d9146407833 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2020, MariaDB Corporation. +Copyright (c) 2014, 2021, 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 @@ -881,7 +881,7 @@ page_zip_compress_node_ptrs( do { const rec_t* rec = *recs++; - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); /* Only leaf nodes may contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); @@ -1130,7 +1130,7 @@ page_zip_compress_clust( do { const rec_t* rec = *recs++; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, ULINT_UNDEFINED, &heap); ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index)); @@ -2052,7 +2052,7 @@ page_zip_apply_log( sorted by address (indexed by heap_no - PAGE_HEAP_NO_USER_LOW) */ ulint n_dense,/*!< in: size of recs[] */ - bool is_leaf,/*!< in: whether this is a leaf page */ + ulint n_core, /*!< in: index->n_fields, or 0 for non-leaf */ ulint trx_id_col,/*!< in: column number of trx_id in the index, or ULINT_UNDEFINED if none */ ulint heap_status, @@ -2128,7 +2128,7 @@ page_zip_apply_log( /* Clear the data bytes of the record. */ mem_heap_t* heap = NULL; rec_offs* offs; - offs = rec_get_offsets(rec, index, offsets, is_leaf, + offs = rec_get_offsets(rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); memset(rec, 0, rec_offs_data_size(offs)); @@ -2142,7 +2142,7 @@ page_zip_apply_log( rec_get_offsets_reverse(data, index, hs & REC_STATUS_NODE_PTR, offsets); - rec_offs_make_valid(rec, index, is_leaf, offsets); + rec_offs_make_valid(rec, index, n_core != 0, offsets); /* Copy the extra bytes (backwards). */ { @@ -2322,7 +2322,7 @@ page_zip_decompress_node_ptrs( } /* Read the offsets. The status bits are needed here. */ - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); /* Non-leaf nodes should not have any externally @@ -2409,7 +2409,7 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, false, + recs, n_dense, 0, ULINT_UNDEFINED, heap_status, index, offsets); @@ -2440,7 +2440,7 @@ zlib_done: for (slot = 0; slot < n_dense; slot++) { rec_t* rec = recs[slot]; - offsets = rec_get_offsets(rec, index, offsets, false, + offsets = rec_get_offsets(rec, index, offsets, 0, ULINT_UNDEFINED, &heap); /* Non-leaf nodes should not have any externally stored columns. */ @@ -2562,7 +2562,8 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, true, + recs, n_dense, + index->n_fields, ULINT_UNDEFINED, heap_status, index, offsets); @@ -2765,7 +2766,7 @@ page_zip_decompress_clust( } /* Read the offsets. The status bits are needed here. */ - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, ULINT_UNDEFINED, &heap); /* This is a leaf page in a clustered index. */ @@ -2892,7 +2893,8 @@ zlib_done: const byte* mod_log_ptr; mod_log_ptr = page_zip_apply_log(d_stream->next_in, d_stream->avail_in + 1, - recs, n_dense, true, + recs, n_dense, + index->n_fields, trx_id_col, heap_status, index, offsets); @@ -2928,7 +2930,7 @@ zlib_done: rec_t* rec = recs[slot]; bool exists = !page_zip_dir_find_free( page_zip, page_offset(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_fields, ULINT_UNDEFINED, &heap); dst = rec_get_nth_field(rec, offsets, @@ -3452,7 +3454,7 @@ page_zip_validate_low( page + PAGE_NEW_INFIMUM, TRUE); trec = page_rec_get_next_low( temp_page + PAGE_NEW_INFIMUM, TRUE); - const bool is_leaf = page_is_leaf(page); + const ulint n_core = page_is_leaf(page) ? index->n_fields : 0; do { if (page_offset(rec) != page_offset(trec)) { @@ -3467,7 +3469,7 @@ page_zip_validate_low( if (index) { /* Compare the data. */ offsets = rec_get_offsets( - rec, index, offsets, is_leaf, + rec, index, offsets, n_core, ULINT_UNDEFINED, &heap); if (memcmp(rec - rec_offs_extra_size(offsets), diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index c81e0031557..221e1f46b4f 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -290,9 +290,9 @@ rec_init_offsets_comp_ordinary( ulint n_fields = n_core; ulint null_mask = 1; - ut_ad(index->n_core_fields >= n_core); ut_ad(n_core > 0); - ut_ad(index->n_fields >= n_core); + ut_ad(index->n_core_fields >= n_core); + ut_ad(index->n_fields >= index->n_core_fields); ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); ut_ad(format == REC_LEAF_TEMP || format == REC_LEAF_TEMP_COLUMNS_ADDED || dict_table_is_comp(index->table)); @@ -300,6 +300,11 @@ rec_init_offsets_comp_ordinary( || index->n_fields == rec_offs_n_fields(offsets)); ut_d(ulint n_null= 0); + const unsigned n_core_null_bytes = UNIV_UNLIKELY(index->n_core_fields + != n_core) + ? UT_BITS_IN_BYTES(unsigned(index->get_n_nullable(n_core))) + : index->n_core_null_bytes; + switch (format) { case REC_LEAF_TEMP: if (dict_table_is_comp(index->table)) { @@ -311,9 +316,9 @@ rec_init_offsets_comp_ordinary( case REC_LEAF_ORDINARY: nulls -= REC_N_NEW_EXTRA_BYTES; ordinary: - lens = --nulls - index->n_core_null_bytes; + lens = --nulls - n_core_null_bytes; - ut_d(n_null = std::min(index->n_core_null_bytes * 8U, + ut_d(n_null = std::min(n_core_null_bytes * 8U, index->n_nullable)); break; case REC_LEAF_COLUMNS_ADDED: @@ -329,7 +334,7 @@ ordinary: const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable); ut_d(n_null = n_nullable); ut_ad(n_null <= index->n_nullable); - ut_ad(n_null_bytes >= index->n_core_null_bytes + ut_ad(n_null_bytes >= n_core_null_bytes || n_core < index->n_core_fields); lens = --nulls - n_null_bytes; } @@ -559,14 +564,14 @@ is (SQL_NULL), the field i is NULL. When the type of the offset at [i+1] is (STORED_OFFPAGE), the field i is stored externally. @param[in] rec record @param[in] index the index that the record belongs in -@param[in] leaf whether the record resides in a leaf page +@param[in] n_core 0, or index->n_core_fields for leaf page @param[in,out] offsets array of offsets, with valid rec_offs_n_fields() */ static void rec_init_offsets( const rec_t* rec, const dict_index_t* index, - bool leaf, + ulint n_core, rec_offs* offsets) { ulint i = 0; @@ -575,6 +580,8 @@ rec_init_offsets( ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); ut_d(memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec))); ut_d(memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index))); + ut_ad(index->n_fields >= n_core); + ut_ad(index->n_core_fields >= n_core); if (dict_table_is_comp(index->table)) { const byte* nulls; @@ -593,23 +600,21 @@ rec_init_offsets( rec_offs_base(offsets)[1] = 8; return; case REC_STATUS_NODE_PTR: - ut_ad(!leaf); + ut_ad(!n_core); n_node_ptr_field = dict_index_get_n_unique_in_tree_nonleaf( index); break; case REC_STATUS_COLUMNS_ADDED: - ut_ad(leaf); ut_ad(index->is_instant()); rec_init_offsets_comp_ordinary(rec, index, offsets, - index->n_core_fields, + n_core, NULL, REC_LEAF_COLUMNS_ADDED); return; case REC_STATUS_ORDINARY: - ut_ad(leaf); rec_init_offsets_comp_ordinary(rec, index, offsets, - index->n_core_fields, + n_core, NULL, REC_LEAF_ORDINARY); return; @@ -766,7 +771,7 @@ resolved: @param[in] index the index that the record belongs to @param[in,out] offsets array comprising offsets[0] allocated elements, or an array from rec_get_offsets(), or NULL -@param[in] leaf whether this is a leaf-page record +@param[in] n_core 0, or index->n_core_fields for leaf page @param[in] n_fields maximum number of offsets to compute (ULINT_UNDEFINED to compute all offsets) @param[in,out] heap memory heap @@ -776,7 +781,7 @@ rec_get_offsets_func( const rec_t* rec, const dict_index_t* index, rec_offs* offsets, - bool leaf, + ulint n_core, ulint n_fields, #ifdef UNIV_DEBUG const char* file, /*!< in: file name where called */ @@ -787,19 +792,22 @@ rec_get_offsets_func( ulint n; ulint size; + ut_ad(index->n_core_fields >= n_core); + ut_ad(index->n_fields >= index->n_core_fields); + if (dict_table_is_comp(index->table)) { switch (UNIV_EXPECT(rec_get_status(rec), REC_STATUS_ORDINARY)) { case REC_STATUS_COLUMNS_ADDED: case REC_STATUS_ORDINARY: - ut_ad(leaf); + ut_ad(n_core); n = dict_index_get_n_fields(index); break; case REC_STATUS_NODE_PTR: /* Node pointer records consist of the uniquely identifying fields of the record followed by a child page number field. */ - ut_ad(!leaf); + ut_ad(!n_core); n = dict_index_get_n_unique_in_tree_nonleaf(index) + 1; break; case REC_STATUS_INFIMUM: @@ -828,18 +836,18 @@ rec_get_offsets_func( >= PAGE_HEAP_NO_USER_LOW; /* The infimum and supremum records carry 1 field. */ ut_ad(is_user_rec || n == 1); - ut_ad(!is_user_rec || leaf || index->is_dummy + ut_ad(!is_user_rec || n_core || index->is_dummy || dict_index_is_ibuf(index) || n == n_fields /* dict_stats_analyze_index_level() */ || n == dict_index_get_n_unique_in_tree_nonleaf(index) + 1); - ut_ad(!is_user_rec || !leaf || index->is_dummy + ut_ad(!is_user_rec || !n_core || index->is_dummy || dict_index_is_ibuf(index) || n == n_fields /* btr_pcur_restore_position() */ || (n + (index->id == DICT_INDEXES_ID) - >= index->n_core_fields && n <= index->n_fields)); + >= n_core && n <= index->n_fields)); - if (is_user_rec && leaf && n < index->n_fields) { + if (is_user_rec && n_core && n < index->n_fields) { ut_ad(!index->is_dummy); ut_ad(!dict_index_is_ibuf(index)); n = index->n_fields; @@ -867,7 +875,7 @@ rec_get_offsets_func( } rec_offs_set_n_fields(offsets, n); - rec_init_offsets(rec, index, leaf, offsets); + rec_init_offsets(rec, index, n_core, offsets); return(offsets); } @@ -1764,7 +1772,9 @@ template void rec_convert_dtuple_to_temp( The fields are copied into the memory heap. @param[out] tuple data tuple @param[in] rec index record, or a copy thereof -@param[in] is_leaf whether rec is a leaf page record +@param[in] index index of rec +@param[in] n_core index->n_core_fields at the time rec was + copied, or 0 if non-leaf page record @param[in] n_fields number of fields to copy @param[in,out] heap memory heap */ void @@ -1772,7 +1782,7 @@ rec_copy_prefix_to_dtuple( dtuple_t* tuple, const rec_t* rec, const dict_index_t* index, - bool is_leaf, + ulint n_core, ulint n_fields, mem_heap_t* heap) { @@ -1780,10 +1790,11 @@ rec_copy_prefix_to_dtuple( rec_offs* offsets = offsets_; rec_offs_init(offsets_); - ut_ad(is_leaf || n_fields + ut_ad(n_core <= index->n_core_fields); + ut_ad(n_core || n_fields <= dict_index_get_n_unique_in_tree_nonleaf(index) + 1); - offsets = rec_get_offsets(rec, index, offsets, is_leaf, + offsets = rec_get_offsets(rec, index, offsets, n_core, n_fields, &heap); ut_ad(rec_validate(rec, offsets)); @@ -2421,7 +2432,8 @@ rec_print( rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_, - page_rec_is_leaf(rec), + page_rec_is_leaf(rec) + ? index->n_core_fields : 0, ULINT_UNDEFINED, &heap)); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -2497,7 +2509,8 @@ operator<<(std::ostream& o, const rec_index_print& r) { mem_heap_t* heap = NULL; rec_offs* offsets = rec_get_offsets( - r.m_rec, r.m_index, NULL, page_rec_is_leaf(r.m_rec), + r.m_rec, r.m_index, NULL, page_rec_is_leaf(r.m_rec) + ? r.m_index->n_core_fields : 0, ULINT_UNDEFINED, &heap); rec_print(o, r.m_rec, rec_get_info_bits(r.m_rec, rec_offs_comp(offsets)), @@ -2543,7 +2556,7 @@ rec_get_trx_id( ut_ad(trx_id_col > 0); ut_ad(trx_id_col != ULINT_UNDEFINED); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, trx_id_col + 1, &heap); trx_id = rec_get_nth_field(rec, offsets, trx_id_col, &len); @@ -2594,7 +2607,8 @@ wsrep_rec_get_foreign_key( ut_ad(index_ref); rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index_for, offsets_, true, + offsets = rec_get_offsets(rec, index_for, offsets_, + index_for->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(rec_offs_validate(rec, NULL, offsets)); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 0f9e309accb..d3ca5579d17 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1811,7 +1811,8 @@ PageConverter::update_records( if (deleted || clust_index) { m_offsets = rec_get_offsets( - rec, m_index->m_srv_index, m_offsets, true, + rec, m_index->m_srv_index, m_offsets, + m_index->m_srv_index->n_core_fields, ULINT_UNDEFINED, &m_heap); } @@ -2377,7 +2378,8 @@ row_import_set_sys_max_row_id( rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets_, true, ULINT_UNDEFINED, &heap); + rec, index, offsets_, index->n_core_fields, + ULINT_UNDEFINED, &heap); field = rec_get_nth_field( rec, offsets, diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index c17b5cc8d1d..9247c7680bc 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2020, MariaDB Corporation. +Copyright (c) 2016, 2021, 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 @@ -886,7 +886,7 @@ row_ins_foreign_fill_virtual( rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_); const rec_offs* offsets = - rec_get_offsets(rec, index, offsets_, true, + rec_get_offsets(rec, index, offsets_, index->n_core_fields, ULINT_UNDEFINED, &cascade->heap); TABLE* mysql_table= NULL; upd_t* update = cascade->update; @@ -1640,7 +1640,8 @@ row_ins_check_foreign_constraint( continue; } - offsets = rec_get_offsets(rec, check_index, offsets, true, + offsets = rec_get_offsets(rec, check_index, offsets, + check_index->n_core_fields, ULINT_UNDEFINED, &heap); if (page_rec_is_supremum(rec)) { @@ -2138,7 +2139,8 @@ row_ins_scan_sec_index_for_duplicate( continue; } - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); if (flags & BTR_NO_LOCKING_FLAG) { @@ -2275,7 +2277,8 @@ row_ins_duplicate_error_in_clust_online( ut_ad(!cursor->index->is_instant()); if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) { - *offsets = rec_get_offsets(rec, cursor->index, *offsets, true, + *offsets = rec_get_offsets(rec, cursor->index, *offsets, + cursor->index->n_fields, ULINT_UNDEFINED, heap); err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets); if (err != DB_SUCCESS) { @@ -2286,7 +2289,8 @@ row_ins_duplicate_error_in_clust_online( rec = page_rec_get_next_const(btr_cur_get_rec(cursor)); if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) { - *offsets = rec_get_offsets(rec, cursor->index, *offsets, true, + *offsets = rec_get_offsets(rec, cursor->index, *offsets, + cursor->index->n_fields, ULINT_UNDEFINED, heap); err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets); } @@ -2342,7 +2346,7 @@ row_ins_duplicate_error_in_clust( if (!page_rec_is_infimum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, - true, + cursor->index->n_core_fields, ULINT_UNDEFINED, &heap); /* We set a lock on the possible duplicate: this @@ -2408,7 +2412,7 @@ duplicate: if (!page_rec_is_supremum(rec)) { offsets = rec_get_offsets(rec, cursor->index, offsets, - true, + cursor->index->n_core_fields, ULINT_UNDEFINED, &heap); if (trx->duplicates) { @@ -2525,7 +2529,7 @@ row_ins_index_entry_big_rec( btr_pcur_open(index, entry, PAGE_CUR_LE, BTR_MODIFY_TREE, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, heap); DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern"); @@ -3084,7 +3088,8 @@ row_ins_sec_index_entry_low( prefix, we must convert the insert into a modify of an existing record */ offsets = rec_get_offsets( - btr_cur_get_rec(&cursor), index, offsets, true, + btr_cur_get_rec(&cursor), index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); err = row_ins_sec_index_entry_by_modify( diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index fb6b1738f74..6095d72bb86 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -1258,7 +1258,8 @@ row_log_table_get_pk( if (!offsets) { offsets = rec_get_offsets( - rec, index, NULL, true, + rec, index, NULL, + index->n_core_fields, pos + 1, heap); } @@ -1308,7 +1309,8 @@ row_log_table_get_pk( } if (!offsets) { - offsets = rec_get_offsets(rec, index, NULL, true, + offsets = rec_get_offsets(rec, index, NULL, + index->n_core_fields, ULINT_UNDEFINED, heap); } @@ -1980,7 +1982,8 @@ all_done: return(DB_SUCCESS); } - offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL, true, + offsets = rec_get_offsets(btr_pcur_get_rec(&pcur), index, NULL, + index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(btr_pcur_get_rec(&pcur), offsets)); @@ -2178,7 +2181,7 @@ func_exit_committed: /* Prepare to update (or delete) the record. */ rec_offs* cur_offsets = rec_get_offsets( - btr_pcur_get_rec(&pcur), index, NULL, true, + btr_pcur_get_rec(&pcur), index, NULL, index->n_core_fields, ULINT_UNDEFINED, &offsets_heap); if (!log->same_pk) { diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 2d3ce298f56..f77eae9a76d 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2038,7 +2038,8 @@ end_of_index: rec = page_cur_get_rec(cur); if (online) { - offsets = rec_get_offsets(rec, clust_index, NULL, true, + offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &row_heap); rec_trx_id = row_get_rec_trx_id(rec, clust_index, offsets); @@ -2130,7 +2131,8 @@ end_of_index: duplicate keys. */ continue; } else { - offsets = rec_get_offsets(rec, clust_index, NULL, true, + offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &row_heap); /* This is a locking ALTER TABLE. diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index d79cf29e53c..0b28fe03c41 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -689,6 +689,7 @@ row_mysql_handle_errors( dberr_t err; DBUG_ENTER("row_mysql_handle_errors"); + DEBUG_SYNC_C("row_mysql_handle_errors"); handle_new_error: err = trx->error_state; @@ -1800,12 +1801,11 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) clust_index = dict_table_get_first_index(table); - if (prebuilt->pcur->btr_cur.index == clust_index) { - btr_pcur_copy_stored_position(node->pcur, prebuilt->pcur); - } else { - btr_pcur_copy_stored_position(node->pcur, - prebuilt->clust_pcur); - } + btr_pcur_copy_stored_position(node->pcur, + prebuilt->pcur->btr_cur.index + == clust_index + ? prebuilt->pcur + : prebuilt->clust_pcur); ut_a(node->pcur->rel_pos == BTR_PCUR_ON); @@ -2023,7 +2023,8 @@ row_unlock_for_mysql( rec_offs* offsets = offsets_; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); rec_trx_id = row_get_rec_trx_id(rec, index, offsets); @@ -4795,7 +4796,7 @@ func_exit: rec = buf + mach_read_from_4(buf); - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, index->n_core_fields, ULINT_UNDEFINED, &heap); if (prev_entry != NULL) { diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 19e981ee30f..6a7f5921aa3 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -127,8 +127,8 @@ row_purge_remove_clust_if_poss_low( rec = btr_pcur_get_rec(&node->pcur); - offsets = rec_get_offsets( - rec, index, offsets_, true, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index, offsets_, index->n_core_fields, + ULINT_UNDEFINED, &heap); if (node->roll_ptr != row_get_rec_roll_ptr(rec, index, offsets)) { /* Someone else has modified the record later: do not remove */ @@ -803,7 +803,8 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr) rec_offs offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2]; rec_offs_init(offsets_); rec_offs* offsets = rec_get_offsets( - rec, index, offsets_, true, trx_id_pos + 2, &heap); + rec, index, offsets_, index->n_core_fields, + trx_id_pos + 2, &heap); ut_ad(heap == NULL); ut_ad(dict_index_get_nth_field(index, trx_id_pos) @@ -1360,7 +1361,7 @@ purge_node_t::validate_pcur() dict_index_t* clust_index = pcur.btr_cur.index; rec_offs* offsets = rec_get_offsets( - pcur.old_rec, clust_index, NULL, true, + pcur.old_rec, clust_index, NULL, pcur.old_n_core_fields, pcur.old_n_fields, &heap); /* Here we are comparing the purge ref record and the stored initial diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index f6b7a9f49b6..6f34c9fcc9b 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 2021, 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 @@ -422,7 +422,8 @@ row_build_low( ut_ad(!col_map || col_table); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); @@ -836,7 +837,7 @@ row_build_row_ref( ut_ad(heap != NULL); ut_ad(!dict_index_is_clust(index)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); /* Secondary indexes must not contain externally stored columns. */ ut_ad(!rec_offs_any_extern(offsets)); @@ -945,7 +946,8 @@ row_build_row_ref_in_tuple( ut_ad(clust_index); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 979aea2f953..248a6592913 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -200,9 +200,11 @@ row_sel_sec_rec_is_for_clust_rec( ib_vcol_row vc(heap); clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs, - true, ULINT_UNDEFINED, &heap); + sec_index->n_fields, + ULINT_UNDEFINED, &heap); n = dict_index_get_n_ordering_defined_by_user(sec_index); @@ -906,7 +908,9 @@ row_sel_get_clust_rec( offsets = rec_get_offsets(rec, btr_pcur_get_btr_cur(&plan->pcur)->index, - offsets, true, ULINT_UNDEFINED, &heap); + offsets, + btr_pcur_get_btr_cur(&plan->pcur)->index + ->n_core_fields, ULINT_UNDEFINED, &heap); row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets); @@ -941,7 +945,8 @@ row_sel_get_clust_rec( goto err_exit; } - offsets = rec_get_offsets(clust_rec, index, offsets, true, + offsets = rec_get_offsets(clust_rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); if (!node->read_view) { @@ -1161,7 +1166,8 @@ re_scan: rec = btr_pcur_get_rec(pcur); my_offsets = offsets_; - my_offsets = rec_get_offsets(rec, index, my_offsets, true, + my_offsets = rec_get_offsets(rec, index, my_offsets, + index->n_fields, ULINT_UNDEFINED, &heap); /* No match record */ @@ -1184,7 +1190,7 @@ re_scan: rtr_rec_t* rtr_rec = &(*it); my_offsets = rec_get_offsets( - rtr_rec->r_rec, index, my_offsets, true, + rtr_rec->r_rec, index, my_offsets, index->n_fields, ULINT_UNDEFINED, &heap); err = lock_sec_rec_read_check_and_lock( @@ -1493,7 +1499,7 @@ exhausted: rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_index_is_clust(index)) { @@ -1709,7 +1715,7 @@ rec_loop: trx = thr_get_trx(thr); offsets = rec_get_offsets(next_rec, index, offsets, - true, + index->n_core_fields, ULINT_UNDEFINED, &heap); /* If innodb_locks_unsafe_for_binlog option is used @@ -1774,7 +1780,8 @@ skip_lock: ulint lock_type; trx_t* trx; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); trx = thr_get_trx(thr); @@ -1861,7 +1868,7 @@ skip_lock: /* PHASE 3: Get previous version in a consistent read */ cons_read_requires_clust_rec = FALSE; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); if (consistent_read) { @@ -1892,7 +1899,8 @@ skip_lock: exhausted. */ offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); /* Fetch the columns needed in @@ -3217,7 +3225,8 @@ class Row_sel_get_clust_rec_for_mysql ut_ad(rec_offs_validate(cached_clust_rec, index, offsets)); ut_ad(index->first_user_field() <= rec_offs_n_fields(offsets)); - ut_ad(vers_offs == rec_get_offsets(cached_old_vers, index, vers_offs, true, + ut_ad(vers_offs == rec_get_offsets(cached_old_vers, index, vers_offs, + index->n_core_fields, index->db_trx_id(), &heap)); ut_ad(!heap); for (unsigned n= index->db_trx_id(); n--; ) @@ -3404,7 +3413,8 @@ Row_sel_get_clust_rec_for_mysql::operator()( goto func_exit; } - *offsets = rec_get_offsets(clust_rec, clust_index, *offsets, true, + *offsets = rec_get_offsets(clust_rec, clust_index, *offsets, + clust_index->n_core_fields, ULINT_UNDEFINED, offset_heap); if (prebuilt->select_lock_type != LOCK_NONE) { @@ -3478,7 +3488,8 @@ Row_sel_get_clust_rec_for_mysql::operator()( ut_d(check_eq(clust_index, *offsets)); *offsets = rec_get_offsets( old_vers, clust_index, *offsets, - true, ULINT_UNDEFINED, offset_heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, offset_heap); } } @@ -3901,7 +3912,7 @@ exhausted: /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ - *offsets = rec_get_offsets(rec, index, *offsets, true, + *offsets = rec_get_offsets(rec, index, *offsets, index->n_core_fields, ULINT_UNDEFINED, heap); if (!lock_clust_rec_cons_read_sees(rec, index, *offsets, @@ -4035,7 +4046,7 @@ row_sel_fill_vrow( ut_ad(!index->is_instant()); ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); *vrow = dtuple_create_with_vcol( @@ -4678,7 +4689,7 @@ wait_table_again: const rec_t* next_rec = page_rec_get_next_const(rec); offsets = rec_get_offsets(next_rec, index, offsets, - true, + index->n_core_fields, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(pcur, next_rec, index, offsets, @@ -4762,7 +4773,8 @@ rec_loop: level we do not lock gaps. Supremum record is really a gap and therefore we do not set locks there. */ - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); err = sel_set_rec_lock(pcur, rec, index, offsets, @@ -4865,7 +4877,7 @@ wrong_offs: ut_ad(fil_page_index_page_check(btr_pcur_get_page(pcur))); ut_ad(btr_page_get_index_id(btr_pcur_get_page(pcur)) == index->id); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &heap); if (UNIV_UNLIKELY(srv_force_recovery > 0)) { @@ -5128,7 +5140,8 @@ no_gap_lock: Do a normal locking read. */ offsets = rec_get_offsets( - rec, index, offsets, true, + rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); goto locks_ok; case DB_DEADLOCK: @@ -5502,7 +5515,7 @@ use_covering_index: /* We used 'offsets' for the clust rec, recalculate them for 'rec' */ offsets = rec_get_offsets(rec, index, offsets, - true, + index->n_core_fields, ULINT_UNDEFINED, &heap); result_rec = rec; @@ -5955,7 +5968,7 @@ row_search_autoinc_read_column( rec_offs_init(offsets_); ut_ad(page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, col_no + 1, &heap); if (rec_offs_nth_sql_null(offsets, col_no)) { diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index f72ad28e70e..756d6d54024 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -117,7 +117,8 @@ row_undo_ins_remove_clust_rec( const rec_t* rec = btr_cur_get_rec(btr_cur); mem_heap_t* heap = NULL; const rec_offs* offsets = rec_get_offsets( - rec, index, NULL, true, ULINT_UNDEFINED, &heap); + rec, index, NULL, index->n_core_fields, + ULINT_UNDEFINED, &heap); row_log_table_delete(rec, index, offsets, NULL); mem_heap_free(heap); } diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 288173a91c2..c7c19eaadb2 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -163,8 +163,9 @@ static ulint row_trx_id_offset(const rec_t* rec, const dict_index_t* index) rec_offs_init(offsets_); mem_heap_t* heap = NULL; const ulint trx_id_pos = index->n_uniq ? index->n_uniq : 1; - rec_offs* offsets = rec_get_offsets(rec, index, offsets_, true, - trx_id_pos + 1, &heap); + rec_offs* offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, + trx_id_pos + 1, &heap); ut_ad(!heap); ulint len; trx_id_offset = rec_get_nth_field_offs( @@ -409,7 +410,8 @@ row_undo_mod_clust( rec_offs offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2]; rec_offs_init(offsets_); offsets = rec_get_offsets( - rec, index, offsets_, true, trx_id_pos + 2, &heap); + rec, index, offsets_, index->n_core_fields, + trx_id_pos + 2, &heap); ulint len; ulint trx_id_offset = rec_get_nth_field_offs( offsets, trx_id_pos, &len); @@ -794,7 +796,8 @@ try_again: offsets_heap = NULL; offsets = rec_get_offsets( btr_cur_get_rec(btr_cur), - index, NULL, true, ULINT_UNDEFINED, &offsets_heap); + index, NULL, index->n_core_fields, ULINT_UNDEFINED, + &offsets_heap); update = row_upd_build_sec_rec_difference_binary( btr_cur_get_rec(btr_cur), index, offsets, entry, heap); if (upd_get_n_fields(update) == 0) { diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 762228503be..a8c35186a7d 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -187,7 +187,8 @@ row_undo_search_clust_to_pcur( rec = btr_pcur_get_rec(&node->pcur); - offsets = rec_get_offsets(rec, clust_index, offsets, true, + offsets = rec_get_offsets(rec, clust_index, offsets, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); found = row_get_rec_roll_ptr(rec, clust_index, offsets) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 97640debc03..c85caa30fe6 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1067,7 +1067,8 @@ row_upd_build_difference_binary( == trx_id_pos + 1); if (!offsets) { - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, + index->n_core_fields, ULINT_UNDEFINED, &heap); } else { ut_ad(rec_offs_validate(rec, index, offsets)); @@ -2218,7 +2219,8 @@ row_upd_store_row( rec = btr_pcur_get_rec(node->pcur); - offsets = rec_get_offsets(rec, clust_index, offsets_, true, + offsets = rec_get_offsets(rec, clust_index, offsets_, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_table_has_atomic_blobs(node->table)) { @@ -2451,7 +2453,7 @@ row_upd_sec_index_entry( && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { rec_offs* offsets = rec_get_offsets( - rec, index, NULL, true, + rec, index, NULL, index->n_core_fields, ULINT_UNDEFINED, &heap); err = wsrep_row_upd_check_foreign_constraints( @@ -2494,12 +2496,9 @@ row_upd_sec_index_entry( ut_ad(err == DB_SUCCESS); if (referenced) { - - rec_offs* offsets; - - offsets = rec_get_offsets( - rec, index, NULL, true, ULINT_UNDEFINED, - &heap); + rec_offs* offsets = rec_get_offsets( + rec, index, NULL, index->n_core_fields, + ULINT_UNDEFINED, &heap); /* NOTE that the following call loses the position of pcur ! */ @@ -2741,7 +2740,8 @@ row_upd_clust_rec_by_insert( we update the primary key. Delete-mark the old record in the clustered index and prepare to insert a new entry. */ rec = btr_cur_get_rec(btr_cur); - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, + index->n_core_fields, ULINT_UNDEFINED, &heap); ut_ad(page_rec_is_user_rec(rec)); @@ -3152,7 +3152,7 @@ row_upd_clust_step( } rec = btr_pcur_get_rec(pcur); - offsets = rec_get_offsets(rec, index, offsets_, true, + offsets = rec_get_offsets(rec, index, offsets_, index->n_core_fields, ULINT_UNDEFINED, &heap); if (!flags && !node->has_clust_rec_x_lock) { diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index aa2400a91ad..cde4e9e7b89 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -116,7 +116,8 @@ row_vers_impl_x_locked_low( heap = mem_heap_create(1024); clust_offsets = rec_get_offsets(clust_rec, clust_index, clust_offsets_, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets); if (trx_id == 0) { @@ -239,7 +240,8 @@ not_locked: } clust_offsets = rec_get_offsets( - prev_version, clust_index, clust_offsets_, true, + prev_version, clust_index, clust_offsets_, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); vers_del = rec_get_deleted_flag(prev_version, comp); @@ -569,7 +571,8 @@ row_vers_build_cur_vrow_low( clust_offsets = rec_get_offsets(prev_version, clust_index, NULL, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); ulint entry_len = dict_index_get_n_fields(index); @@ -711,7 +714,8 @@ row_vers_vc_matches_cluster( clust_offsets = rec_get_offsets(prev_version, clust_index, NULL, - true, ULINT_UNDEFINED, &heap); + clust_index->n_core_fields, + ULINT_UNDEFINED, &heap); ulint entry_len = dict_index_get_n_fields(index); @@ -849,7 +853,8 @@ row_vers_build_cur_vrow( index, roll_ptr, trx_id, v_heap, &cur_vrow, mtr); } - *clust_offsets = rec_get_offsets(rec, clust_index, NULL, true, + *clust_offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); return(cur_vrow); } @@ -906,7 +911,8 @@ row_vers_old_has_index_entry( comp = page_rec_is_comp(rec); ut_ad(!dict_table_is_comp(index->table) == !comp); heap = mem_heap_create(1024); - clust_offsets = rec_get_offsets(rec, clust_index, NULL, true, + clust_offsets = rec_get_offsets(rec, clust_index, NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_index_has_virtual(index)) { @@ -995,7 +1001,8 @@ row_vers_old_has_index_entry( } } clust_offsets = rec_get_offsets(rec, clust_index, NULL, - true, + clust_index + ->n_core_fields, ULINT_UNDEFINED, &heap); } else { @@ -1074,7 +1081,8 @@ unsafe_to_purge: } clust_offsets = rec_get_offsets(prev_version, clust_index, - NULL, true, + NULL, + clust_index->n_core_fields, ULINT_UNDEFINED, &heap); if (dict_index_has_virtual(index)) { @@ -1215,7 +1223,7 @@ row_vers_build_for_consistent_read( *offsets = rec_get_offsets( prev_version, index, *offsets, - true, ULINT_UNDEFINED, offset_heap); + index->n_core_fields, ULINT_UNDEFINED, offset_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(prev_version, *offsets)); @@ -1331,11 +1339,10 @@ committed_version_trx: semi-consistent read. */ version = rec; - *offsets = rec_get_offsets(version, - index, *offsets, - true, - ULINT_UNDEFINED, - offset_heap); + *offsets = rec_get_offsets( + version, index, *offsets, + index->n_core_fields, ULINT_UNDEFINED, + offset_heap); } buf = static_cast( @@ -1378,7 +1385,8 @@ committed_version_trx: } version = prev_version; - *offsets = rec_get_offsets(version, index, *offsets, true, + *offsets = rec_get_offsets(version, index, *offsets, + index->n_core_fields, ULINT_UNDEFINED, offset_heap); #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG ut_a(!rec_offs_any_null_extern(version, *offsets)); diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 71872ce45b2..59e0bed8006 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -713,7 +713,8 @@ fill_lock_data( ut_a(n_fields > 0); heap = NULL; - offsets = rec_get_offsets(rec, index, offsets, true, n_fields, &heap); + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, + n_fields, &heap); /* format and store the data */ diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 09e6ad79685..9c7106facaf 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -2412,7 +2412,8 @@ trx_undo_prev_version_build( rec_offs offsets_dbg[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_dbg); ut_a(!rec_offs_any_null_extern( - *old_vers, rec_get_offsets(*old_vers, index, offsets_dbg, true, + *old_vers, rec_get_offsets(*old_vers, index, offsets_dbg, + index->n_core_fields, ULINT_UNDEFINED, &heap))); #endif // defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index d331beb9230..7f7be193175 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, 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 @@ -667,7 +667,7 @@ const char * dbug_print_rec(const rec_t* rec, dict_index_t* index) rec_offs* offsets = offsets_; rec_offs_init(offsets_); mem_heap_t* tmp_heap = NULL; - offsets = rec_get_offsets(rec, index, offsets, true, + offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields, ULINT_UNDEFINED, &tmp_heap); rec_printer r(rec, offsets); strmake(dbug_print_buf, r.str().c_str(), sizeof(dbug_print_buf) - 1); -- cgit v1.2.1