Commit bfb3d327 authored by Marko Mäkelä's avatar Marko Mäkelä

Various fixes for ROW_FORMAT=REDUNDANT

rec_get_offsets(): Use the 'leaf' parameter for non-debug purposes.
Initialize all fields for ROW_FORMAT=REDUNDANT records that precede
an instant ADD COLUMN.

rec_offs_make_valid(): Add the parameter 'leaf'.

rec_copy_prefix_to_dtuple(): Assert that the tuple is only built
on the core fields. Instant ADD COLUMN only applies to the
clustered index, and we should never build a search key that has
more than the PRIMARY KEY and possibly DB_TRX_ID,DB_ROLL_PTR.
All these columns are always present.

dict_index_build_data_tuple(): Remove assertions that would be
duplicated in rec_copy_prefix_to_dtuple().

rec_get_n_nullable(): Get the number of nullable columns.

rec_init_offsets(): Support ROW_FORMAT=REDUNDANT records that
were written before instant ADD COLUMN.

cmp_rec_rec_with_match(): Implement comparison of MIN_REC_FLAG records.
parent 84167947
......@@ -170,13 +170,14 @@ PageBulk::insert(
ut_ad(m_heap != NULL);
rec_size = rec_offs_size(offsets);
ut_d(const bool is_leaf = page_rec_is_leaf(m_cur_rec));
#ifdef UNIV_DEBUG
/* Check whether records are in order. */
if (!page_rec_is_infimum(m_cur_rec)) {
rec_t* old_rec = m_cur_rec;
ulint* old_offsets = rec_get_offsets(
old_rec, m_index, NULL, page_rec_is_leaf(old_rec),
old_rec, m_index, NULL, is_leaf,
ULINT_UNDEFINED, &m_heap);
ut_ad(cmp_rec_rec(rec, old_rec, offsets, old_offsets, m_index)
......@@ -188,7 +189,7 @@ PageBulk::insert(
/* 1. Copy the record to page. */
rec_t* insert_rec = rec_copy(m_heap_top, rec, offsets);
rec_offs_make_valid(insert_rec, m_index, offsets);
rec_offs_make_valid(insert_rec, m_index, is_leaf, offsets);
/* 2. Insert the record in the linked list. */
rec_t* next_rec = page_rec_get_next(m_cur_rec);
......
......@@ -3666,7 +3666,8 @@ btr_cur_update_alloc_zip_func(
goto out_of_space;
}
rec_offs_make_valid(page_cur_get_rec(cursor), index, offsets);
rec_offs_make_valid(page_cur_get_rec(cursor), index,
page_is_leaf(page), offsets);
/* After recompressing a page, we must make sure that the free
bits in the insert buffer bitmap will not exceed the free
......@@ -4442,11 +4443,12 @@ btr_cur_pessimistic_update(
}
bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG);
ut_ad(!adjust || page_is_leaf(page));
if (btr_cur_compress_if_useful(cursor, adjust, mtr)) {
if (adjust) {
rec_offs_make_valid(
page_cursor->rec, index, *offsets);
rec_offs_make_valid(page_cursor->rec, index,
true, *offsets);
}
} else if (!dict_index_is_clust(index)
&& page_is_leaf(page)) {
......@@ -6166,7 +6168,7 @@ btr_estimate_number_of_different_key_vals(
page = btr_cur_get_page(&cursor);
rec = page_rec_get_next(page_get_infimum_rec(page));
ut_d(const bool is_leaf = page_is_leaf(page));
const bool is_leaf = page_is_leaf(page);
if (!page_rec_is_supremum(rec)) {
not_empty_flag = 1;
......@@ -6727,8 +6729,8 @@ struct btr_blob_log_check_t {
*m_block = btr_pcur_get_block(m_pcur);
*m_rec = btr_pcur_get_rec(m_pcur);
ut_d(rec_offs_make_valid(
*m_rec, index, const_cast<ulint*>(m_offsets)));
rec_offs_make_valid(*m_rec, index, true,
const_cast<ulint*>(m_offsets));
ut_ad(m_mtr->memo_contains_page_flagged(
*m_rec,
......
......@@ -5733,21 +5733,14 @@ dict_index_copy_rec_order_prefix(
@param[in,out] heap memory heap for allocation
@return own: data tuple */
dtuple_t*
dict_index_build_data_tuple_func(
dict_index_build_data_tuple(
const rec_t* rec,
const dict_index_t* index,
#ifdef UNIV_DEBUG
bool leaf,
#endif /* UNIV_DEBUG */
ulint n_fields,
mem_heap_t* heap)
{
dtuple_t* tuple;
ut_ad(dict_table_is_comp(index->table)
|| n_fields <= rec_get_n_fields_old(rec));
tuple = dtuple_create(heap, n_fields);
dtuple_t* tuple = dtuple_create(heap, n_fields);
dict_index_copy_types(tuple, index, n_fields);
......
......@@ -85,7 +85,7 @@ rtr_page_split_initialize_nodes(
stop = task + n_recs;
rec = page_rec_get_next(page_get_infimum_rec(page));
ut_d(const bool is_leaf = page_is_leaf(page));
const bool is_leaf = page_is_leaf(page);
*offsets = rec_get_offsets(rec, cursor->index, *offsets, is_leaf,
n_uniq, &heap);
......
......@@ -1495,22 +1495,13 @@ dict_index_copy_rec_order_prefix(
@param[in,out] heap memory heap for allocation
@return own: data tuple */
dtuple_t*
dict_index_build_data_tuple_func(
dict_index_build_data_tuple(
const rec_t* rec,
const dict_index_t* index,
#ifdef UNIV_DEBUG
bool leaf,
#endif /* UNIV_DEBUG */
ulint n_fields,
mem_heap_t* heap)
MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_DEBUG
# define dict_index_build_data_tuple(rec, index, leaf, n_fields, heap) \
dict_index_build_data_tuple_func(rec, index, leaf, n_fields, heap)
#else /* UNIV_DEBUG */
# define dict_index_build_data_tuple(rec, index, leaf, n_fields, heap) \
dict_index_build_data_tuple_func(rec, index, n_fields, heap)
#endif /* UNIV_DEBUG */
/*********************************************************************//**
Gets the space id of the root of the index tree.
......
......@@ -466,9 +466,7 @@ rec_get_offsets_func(
const rec_t* rec,
const dict_index_t* index,
ulint* offsets,
#ifdef UNIV_DEBUG
bool leaf,
#endif /* UNIV_DEBUG */
ulint n_fields,
#ifdef UNIV_DEBUG
const char* file, /*!< in: file name where called */
......@@ -478,7 +476,7 @@ rec_get_offsets_func(
#ifdef UNIV_DEBUG
MY_ATTRIBUTE((nonnull(1,2,6,8),warn_unused_result));
#else /* UNIV_DEBUG */
MY_ATTRIBUTE((nonnull(1,2,5),warn_unused_result));
MY_ATTRIBUTE((nonnull(1,2,6),warn_unused_result));
#endif /* UNIV_DEBUG */
#ifdef UNIV_DEBUG
......@@ -486,7 +484,7 @@ rec_get_offsets_func(
rec_get_offsets_func(rec,index,offsets,leaf,n,__FILE__,__LINE__,heap)
#else /* UNIV_DEBUG */
# define rec_get_offsets(rec, index, offsets, leaf, n, heap) \
rec_get_offsets_func(rec, index, offsets, n, heap)
rec_get_offsets_func(rec, index, offsets, leaf, n, heap)
#endif /* UNIV_DEBUG */
/******************************************************//**
......@@ -506,32 +504,31 @@ rec_get_offsets_reverse(
offsets[0] allocated elements */
MY_ATTRIBUTE((nonnull));
#ifdef UNIV_DEBUG
/************************************************************//**
Validates offsets returned by rec_get_offsets().
@return TRUE if valid */
UNIV_INLINE
ibool
/** Validate offsets returned by rec_get_offsets().
@param[in] rec record, or NULL
@param[in] index the index that the record belongs in, or NULL
@param[in,out] offsets the offsets of the record
@return true */
bool
rec_offs_validate(
/*==============*/
const rec_t* rec, /*!< in: record or NULL */
const dict_index_t* index, /*!< in: record descriptor or NULL */
const ulint* offsets)/*!< in: array returned by
rec_get_offsets() */
const rec_t* rec,
const dict_index_t* index,
const ulint* offsets)
MY_ATTRIBUTE((nonnull(3), warn_unused_result));
/************************************************************//**
Updates debug data in offsets, in order to avoid bogus
rec_offs_validate() failures. */
UNIV_INLINE
/** Update debug data in offsets, in order to tame rec_offs_validate().
@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,out] offsets offsets from rec_get_offsets() to adjust */
void
rec_offs_make_valid(
/*================*/
const rec_t* rec, /*!< in: record */
const dict_index_t* index, /*!< in: record descriptor */
ulint* offsets)/*!< in: array returned by
rec_get_offsets() */
const rec_t* rec,
const dict_index_t* index,
bool leaf,
ulint* offsets)
MY_ATTRIBUTE((nonnull));
#else
# define rec_offs_make_valid(rec, index, offsets) ((void) 0)
# define rec_offs_make_valid(rec, index, leaf, offsets)
#endif /* UNIV_DEBUG */
/************************************************************//**
......@@ -991,23 +988,14 @@ The fields are copied into the memory heap.
@param[in] n_fields number of fields to copy
@param[in,out] heap memory heap */
void
rec_copy_prefix_to_dtuple_func(
rec_copy_prefix_to_dtuple(
dtuple_t* tuple,
const rec_t* rec,
const dict_index_t* index,
#ifdef UNIV_DEBUG
bool is_leaf,
#endif /* UNIV_DEBUG */
ulint n_fields,
mem_heap_t* heap)
MY_ATTRIBUTE((nonnull));
#ifdef UNIV_DEBUG
# define rec_copy_prefix_to_dtuple(tuple,rec,index,leaf,n_fields,heap) \
rec_copy_prefix_to_dtuple_func(tuple,rec,index,leaf,n_fields,heap)
#else /* UNIV_DEBUG */
# define rec_copy_prefix_to_dtuple(tuple,rec,index,leaf,n_fields,heap) \
rec_copy_prefix_to_dtuple_func(tuple,rec,index,n_fields,heap)
#endif /* UNIV_DEBUG */
/***************************************************************//**
Validates the consistency of a physical record.
@return TRUE if ok */
......
......@@ -29,16 +29,16 @@ Created 5/30/1994 Heikki Tuuri
#include "dict0boot.h"
#include "btr0types.h"
/* Compact flag ORed to the extra size returned by rec_get_offsets() */
#define REC_OFFS_COMPACT ((ulint) 1 << 31)
/* SQL NULL flag in offsets returned by rec_get_offsets() */
#define REC_OFFS_SQL_NULL ((ulint) 1 << 31)
/* External flag in offsets returned by rec_get_offsets() */
#define REC_OFFS_EXTERNAL ((ulint) 1 << 30)
/* Default value flag in offsets returned by rec_get_offsets() */
#define REC_OFFS_DEFAULT ((ulint) 1 << 29)
/* Mask for offsets returned by rec_get_offsets() */
#define REC_OFFS_MASK (REC_OFFS_DEFAULT - 1)
/** Compact flag ORed to the extra size returned by rec_get_offsets() */
const ulint REC_OFFS_COMPACT = ~(ulint(~0) >> 1);
/** SQL NULL flag in offsets returned by rec_get_offsets() */
const ulint REC_OFFS_SQL_NULL = REC_OFFS_COMPACT;
/** External flag in offsets returned by rec_get_offsets() */
const ulint REC_OFFS_EXTERNAL = REC_OFFS_COMPACT >> 1;
/** Default value flag in offsets returned by rec_get_offsets() */
const ulint REC_OFFS_DEFAULT = REC_OFFS_COMPACT >> 2;
/** Mask for offsets returned by rec_get_offsets() */
const ulint REC_OFFS_MASK = REC_OFFS_DEFAULT - 1;
/* Offsets of the bit-fields in an old-style record. NOTE! In the table the
most significant bytes and bits are written below less significant.
......@@ -987,83 +987,6 @@ rec_offs_n_fields(
return(n_fields);
}
/************************************************************//**
Validates offsets returned by rec_get_offsets().
@return TRUE if valid */
UNIV_INLINE
ibool
rec_offs_validate(
/*==============*/
const rec_t* rec, /*!< in: record or NULL */
const dict_index_t* index, /*!< in: record descriptor or NULL */
const ulint* offsets)/*!< in: array returned by
rec_get_offsets() */
{
ulint i = rec_offs_n_fields(offsets);
ulint last = ULINT_MAX;
ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
if (rec) {
ut_ad((ulint) rec == offsets[2]);
if (!comp) {
ut_a(rec_get_n_fields_old(rec) >= i);
}
}
if (index) {
ulint max_n_fields;
ut_ad((ulint) index == offsets[3]);
max_n_fields = ut_max(
dict_index_get_n_fields(index),
dict_index_get_n_unique_in_tree(index) + 1);
if (comp && rec) {
switch (rec_get_status(rec)) {
case REC_STATUS_ORDINARY:
break;
case REC_STATUS_NODE_PTR:
max_n_fields = dict_index_get_n_unique_in_tree(
index) + 1;
break;
case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM:
max_n_fields = 1;
break;
default:
ut_error;
}
}
/* index->n_def == 0 for dummy indexes if !comp */
ut_a(!comp || index->n_def);
ut_a(!index->n_def || i <= max_n_fields);
}
while (i--) {
ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
ut_a(curr <= last);
last = curr;
}
return(TRUE);
}
#ifdef UNIV_DEBUG
/************************************************************//**
Updates debug data in offsets, in order to avoid bogus
rec_offs_validate() failures. */
UNIV_INLINE
void
rec_offs_make_valid(
/*================*/
const rec_t* rec, /*!< in: record */
const dict_index_t* index, /*!< in: record descriptor */
ulint* offsets)/*!< in: array returned by
rec_get_offsets() */
{
ut_ad(rec);
ut_ad(index);
ut_ad(offsets);
ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets));
offsets[2] = (ulint) rec;
offsets[3] = (ulint) index;
}
#endif /* UNIV_DEBUG */
/************************************************************//**
The following function is used to get an offset to the nth
data field in a record.
......
......@@ -662,7 +662,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 */
ut_d(bool is_leaf = page_is_leaf(page));
const bool is_leaf = page_is_leaf(page);
while (up - low > 1) {
mid = (low + up) / 2;
......@@ -860,7 +860,7 @@ page_cur_insert_rec_write_log(
ut_ad(!page_rec_is_comp(insert_rec)
== !dict_table_is_comp(index->table));
ut_d(const bool is_leaf = page_rec_is_leaf(cursor_rec));
const bool is_leaf = page_rec_is_leaf(cursor_rec);
{
mem_heap_t* heap = NULL;
......@@ -1134,7 +1134,7 @@ page_cur_parse_insert_rec(
/* Read from the log the inserted index record end segment which
differs from the cursor record */
ut_d(bool is_leaf = page_is_leaf(page));
const bool is_leaf = page_is_leaf(page);
offsets = rec_get_offsets(cursor_rec, index, offsets, is_leaf,
ULINT_UNDEFINED, &heap);
......@@ -1171,9 +1171,15 @@ page_cur_parse_insert_rec(
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
if (page_is_comp(page)) {
/* Make rec_get_offsets() and rec_offs_make_valid() happy. */
ut_d(rec_set_heap_no_new(buf + origin_offset,
PAGE_HEAP_NO_USER_LOW));
rec_set_info_and_status_bits(buf + origin_offset,
info_and_status_bits);
} else {
/* Make rec_get_offsets() and rec_offs_make_valid() happy. */
ut_d(rec_set_heap_no_old(buf + origin_offset,
PAGE_HEAP_NO_USER_LOW));
rec_set_info_bits_old(buf + origin_offset,
info_and_status_bits);
}
......@@ -1312,7 +1318,7 @@ page_cur_insert_rec_low(
/* 3. Create the record */
insert_rec = rec_copy(insert_buf, rec, offsets);
rec_offs_make_valid(insert_rec, index, offsets);
rec_offs_make_valid(insert_rec, index, page_is_leaf(page), offsets);
/* This is because assertion below is debug assertion */
#ifdef UNIV_DEBUG
......@@ -1602,7 +1608,8 @@ page_cur_insert_rec_zip(
/* This should be followed by
MLOG_ZIP_PAGE_COMPRESS_NO_DATA,
which should succeed. */
rec_offs_make_valid(insert_rec, index, offsets);
rec_offs_make_valid(insert_rec, index,
page_is_leaf(page), offsets);
} else {
ulint pos = page_rec_get_n_recs_before(insert_rec);
ut_ad(pos > 0);
......@@ -1618,7 +1625,8 @@ page_cur_insert_rec_zip(
level, page, index, mtr);
rec_offs_make_valid(
insert_rec, index, offsets);
insert_rec, index,
page_is_leaf(page), offsets);
return(insert_rec);
}
......@@ -1661,7 +1669,8 @@ page_cur_insert_rec_zip(
insert_rec = page + rec_get_next_offs(
cursor->rec, TRUE);
rec_offs_make_valid(
insert_rec, index, offsets);
insert_rec, index,
page_is_leaf(page), offsets);
return(insert_rec);
}
......@@ -1803,7 +1812,7 @@ page_cur_insert_rec_zip(
/* 3. Create the record */
insert_rec = rec_copy(insert_buf, rec, offsets);
rec_offs_make_valid(insert_rec, index, offsets);
rec_offs_make_valid(insert_rec, index, page_is_leaf(page), offsets);
/* 4. Insert the record in the linked list of records */
ut_ad(cursor->rec != insert_rec);
......@@ -2075,7 +2084,7 @@ page_copy_rec_list_end_to_created_page(
slot_index = 0;
n_recs = 0;
ut_d(const bool is_leaf = page_is_leaf(new_page));
const bool is_leaf = page_is_leaf(new_page);
do {
offsets = rec_get_offsets(rec, index, offsets, is_leaf,
......@@ -2120,7 +2129,7 @@ page_copy_rec_list_end_to_created_page(
heap_top += rec_size;
rec_offs_make_valid(insert_rec, index, offsets);
rec_offs_make_valid(insert_rec, index, is_leaf, offsets);
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
index, mtr);
prev_rec = insert_rec;
......
......@@ -599,7 +599,7 @@ 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 + UNIV_PAGE_SIZE - 10) == (ulint)
(page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
ut_d(const bool is_leaf = page_is_leaf(block->frame));
const bool is_leaf = page_is_leaf(block->frame);
cur2 = page_get_infimum_rec(buf_block_get_frame(new_block));
......@@ -1107,7 +1107,7 @@ page_delete_rec_list_end(
? MLOG_COMP_LIST_END_DELETE
: MLOG_LIST_END_DELETE, mtr);
ut_d(const bool is_leaf = page_is_leaf(page));
const bool is_leaf = page_is_leaf(page);
if (page_zip) {
mtr_log_t log_mode;
......@@ -1298,7 +1298,7 @@ page_delete_rec_list_start(
/* Individual deletes are not logged */
mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
ut_d(const bool is_leaf = page_rec_is_leaf(rec));
const bool is_leaf = page_rec_is_leaf(rec);
while (page_cur_get_rec(&cur1) != rec) {
offsets = rec_get_offsets(page_cur_get_rec(&cur1), index,
......
......@@ -2174,7 +2174,7 @@ page_zip_apply_log(
rec_get_offsets_reverse(data, index,
hs & REC_STATUS_NODE_PTR,
offsets);
rec_offs_make_valid(rec, index, offsets);
rec_offs_make_valid(rec, index, is_leaf, offsets);
/* Copy the extra bytes (backwards). */
{
......
......@@ -1153,10 +1153,9 @@ cmp_rec_rec_with_match(
/* Test if rec is the predefined minimum record */
if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
& REC_INFO_MIN_REC_FLAG)) {
/* There should only be one such record. */
ut_ad(!(rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG));
ret = -1;
ret = UNIV_UNLIKELY(rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG)
? 0 : -1;
goto order_resolved;
} else if (UNIV_UNLIKELY
(rec_get_info_bits(rec2, comp)
......
This diff is collapsed.
......@@ -436,7 +436,7 @@ row_build_low(
}
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(copy, index, const_cast<ulint*>(offsets));
rec_offs_make_valid(copy, index, true, const_cast<ulint*>(offsets));
if (!col_table) {
ut_ad(!col_map);
......@@ -526,7 +526,7 @@ row_build_low(
}
}
rec_offs_make_valid(rec, index, const_cast<ulint*>(offsets));
rec_offs_make_valid(rec, index, true, const_cast<ulint*>(offsets));
ut_ad(dtuple_check_typed(row));
......@@ -738,10 +738,12 @@ row_rec_to_index_entry(
copy_rec = rec_copy(buf, rec, offsets);
rec_offs_make_valid(copy_rec, index, const_cast<ulint*>(offsets));
rec_offs_make_valid(copy_rec, index, true,
const_cast<ulint*>(offsets));
entry = row_rec_to_index_entry_low(
copy_rec, index, offsets, n_ext, heap);
rec_offs_make_valid(rec, index, const_cast<ulint*>(offsets));
rec_offs_make_valid(rec, index, true,
const_cast<ulint*>(offsets));
dtuple_set_info_bits(entry,
rec_get_info_bits(rec, rec_offs_comp(offsets)));
......@@ -804,8 +806,7 @@ row_build_row_ref(
mem_heap_alloc(heap, rec_offs_size(offsets)));
rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets);
rec_offs_make_valid(rec, index, true, offsets);
}
table = index->table;
......
......@@ -1210,7 +1210,7 @@ row_vers_build_for_consistent_read(
in_heap, rec_offs_size(*offsets)));
*old_vers = rec_copy(buf, prev_version, *offsets);
rec_offs_make_valid(*old_vers, index, *offsets);
rec_offs_make_valid(*old_vers, index, true, *offsets);
if (vrow && *vrow) {
*vrow = dtuple_copy(*vrow, in_heap);
......@@ -1337,7 +1337,7 @@ row_vers_build_for_semi_consistent_read(
in_heap, rec_offs_size(*offsets)));
*old_vers = rec_copy(buf, version, *offsets);
rec_offs_make_valid(*old_vers, index, *offsets);
rec_offs_make_valid(*old_vers, index, true, *offsets);
if (vrow && *vrow) {
*vrow = dtuple_copy(*vrow, in_heap);
dtuple_dup_v_fld(*vrow, in_heap);
......
......@@ -2307,7 +2307,7 @@ trx_undo_prev_version_build(
heap, rec_offs_size(offsets)));
*old_vers = rec_copy(buf, rec, offsets);
rec_offs_make_valid(*old_vers, index, offsets);
rec_offs_make_valid(*old_vers, index, true, offsets);
row_upd_rec_in_place(*old_vers, index, offsets, update, NULL);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment