Bugfix: wrong row store type in macro meta dumper and loader

This commit is contained in:
ND501 2024-09-03 17:25:38 +00:00 committed by ob-robot
parent 8ef7e5add9
commit 830aa8e728
4 changed files with 206 additions and 69 deletions

View File

@ -12,6 +12,7 @@
#define USING_LOG_PREFIX STORAGE
#include <iostream>
#include <gtest/gtest.h>
#define private public
#define protected public
@ -336,6 +337,119 @@ TEST_F(TestIndexDumper, get_from_mem)
ASSERT_NE(nullptr, meta_block_info.micro_block_desc_);
}
TEST_F(TestIndexDumper, get_from_mem_and_change_row_store_type)
{
ObArray<ObDataMacroBlockMeta> data_macro_metas;
const ObITableReadInfo &index_read_info = tablet_handle_.get_obj()->get_rowkey_read_info();
ObSSTableSecMetaIterator meta_iter;
ObDataMacroBlockMeta data_macro_meta;
ObDatumRange range;
range.set_whole_range();
ASSERT_EQ(OB_SUCCESS, meta_iter.open(
range,
ObMacroBlockMetaType::DATA_BLOCK_META,
sstable_,
index_read_info,
allocator_));
int tmp_ret = OB_SUCCESS;
while (OB_SUCCESS == tmp_ret) {
tmp_ret = meta_iter.get_next(data_macro_meta);
if (OB_SUCCESS == tmp_ret) {
ObDataMacroBlockMeta *deep_copy_meta = nullptr;
ASSERT_EQ(OB_SUCCESS, data_macro_meta.deep_copy(deep_copy_meta, allocator_));
ASSERT_EQ(OB_SUCCESS, data_macro_metas.push_back(
*(deep_copy_meta)));
}
}
ASSERT_EQ(OB_ITER_END, tmp_ret);
ASSERT_TRUE(data_macro_metas.count() > 0);
ObIndexBlockInfo meta_block_info;
ObIndexTreeBlockDumper index_tree_dumper;
ObDataStoreDesc mem_desc;
ASSERT_EQ(OB_SUCCESS, mem_desc.shallow_copy(root_index_builder_->index_store_desc_.get_desc()));
mem_desc.micro_block_size_ = mem_desc.get_micro_block_size_limit();
ASSERT_EQ(OB_SUCCESS, index_tree_dumper.init(root_index_builder_->data_store_desc_.get_desc(),
mem_desc, mem_desc.sstable_index_builder_, root_index_builder_->container_store_desc_, allocator_, allocator_, true));
ObDatumRow index_row;
ASSERT_EQ(OB_SUCCESS, index_row.init(allocator_, TEST_ROWKEY_COLUMN_CNT + 3));
for (int64_t i = 0; i < data_macro_metas.count(); ++i) {
ObIndexBlockRowDesc row_desc(mem_desc);
ObDataMacroBlockMeta &meta = data_macro_metas.at(i);
ASSERT_EQ(OB_SUCCESS, meta.build_row(index_row, allocator_));
ASSERT_EQ(OB_SUCCESS, ObBaseIndexBlockBuilder::meta_to_row_desc(meta, mem_desc, nullptr, row_desc));
ASSERT_EQ(OB_SUCCESS, index_tree_dumper.append_row(row_desc));
}
// close
ASSERT_EQ(OB_SUCCESS, index_tree_dumper.close(meta_block_info));
ASSERT_TRUE(meta_block_info.in_mem());
ASSERT_EQ(data_macro_metas.count(), meta_block_info.get_row_count());
ASSERT_EQ(1, meta_block_info.get_micro_block_count());
// row builder
ObWholeDataStoreDesc row_builder_desc;
ASSERT_EQ(OB_SUCCESS, row_builder_desc.assign(mem_desc));
common::ObRowStoreType before_row_store_type = mem_desc.get_row_store_type();
common::ObRowStoreType after_row_store_type;
if (before_row_store_type <= common::ObRowStoreType::SELECTIVE_ENCODING_ROW_STORE) {
after_row_store_type = common::ObRowStoreType::CS_ENCODING_ROW_STORE;
} else {
after_row_store_type = common::ObRowStoreType::FLAT_ROW_STORE;
}
row_builder_desc.get_desc().row_store_type_ = after_row_store_type;
ASSERT_NE(row_builder_desc.get_desc().get_row_store_type(), mem_desc.get_row_store_type());
ObIndexBlockRowBuilder row_builder;
ASSERT_EQ(OB_SUCCESS, row_builder.init(allocator_, row_builder_desc.get_desc(), row_builder_desc.get_desc()));
// test mem row
ObDatumRow load_row;
ObIndexBlockRowParser row_parser;
ObWholeDataStoreDesc desc;
ObDataMacroBlockMeta macro_meta;
ObIndexBlockLoader index_block_loader;
ASSERT_EQ(OB_SUCCESS, index_block_loader.init(allocator_));
ASSERT_EQ(OB_SUCCESS, index_block_loader.open(meta_block_info));
ASSERT_EQ(OB_SUCCESS, load_row.init(allocator_, TEST_ROWKEY_COLUMN_CNT + 3));
tmp_ret = OB_SUCCESS;
ASSERT_EQ(OB_SUCCESS, desc.assign(mem_desc));
int iter_cnt = 0;
while (OB_SUCCESS == tmp_ret) {
row_parser.reset();
load_row.reuse();
ObIndexBlockRowDesc row_desc;
const ObDatumRow * new_row = nullptr;
tmp_ret = index_block_loader.get_next_row(load_row);
if (OB_SUCCESS == tmp_ret) {
const ObDatumRow *row_to_append = NULL;
ASSERT_EQ(OB_SUCCESS, row_parser.init(mem_desc.get_rowkey_column_count(), load_row));
desc.get_desc().row_store_type_ = common::ObRowStoreType::DUMMY_ROW_STORE;
ASSERT_NE(desc.get_desc().row_store_type_, mem_desc.row_store_type_);
ASSERT_EQ(OB_SUCCESS, row_desc.init(desc.get_desc(), row_parser, load_row));
ASSERT_EQ(desc.get_desc().row_store_type_, mem_desc.row_store_type_);
ASSERT_EQ(OB_SUCCESS,row_builder.build_row(row_desc, new_row));
for (int64_t i = 0; i < TEST_ROWKEY_COLUMN_CNT + 3; ++i) {
bool bret = ObDatum::binary_equal(load_row.storage_datums_[i], new_row->storage_datums_[i]);
if (bret != true) {
ObIndexBlockRowParser tmp_row_parser;
const ObIndexBlockRowHeader *tmp_row_header = nullptr;
ASSERT_EQ(OB_SUCCESS, tmp_row_parser.init(mem_desc.get_rowkey_column_count(), load_row));
ASSERT_EQ(OB_SUCCESS, tmp_row_parser.get_header(tmp_row_header));
LOG_INFO("load row", KPC(tmp_row_header));
tmp_row_parser.reset();
ASSERT_EQ(OB_SUCCESS, tmp_row_parser.init(mem_desc.get_rowkey_column_count(), *new_row));
ASSERT_EQ(OB_SUCCESS, tmp_row_parser.get_header(tmp_row_header));
LOG_INFO("new row", KPC(tmp_row_header));
}
ASSERT_TRUE(bret);
}
++iter_cnt;
} else {
ASSERT_EQ(OB_ITER_END, tmp_ret);
break;
}
}
}
TEST_F(TestIndexDumper, get_from_disk)
{
ObArray<ObDataMacroBlockMeta> data_macro_metas;

View File

@ -1,14 +1,13 @@
/**
*
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan
* PubL v2. You may obtain a copy of Mulan PubL v2 at:
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PubL v2 for more details.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX STORAGE
@ -184,13 +183,6 @@ int ObIndexTreeRootCtx::add_clustered_index_block_micro_infos(
ObClusteredIndexBlockMicroInfos(macro_id, block_offset,
block_size, logic_micro_id)))) {
LOG_WARN("fail to push back clustered micro info", K(ret));
// TODO (baichangmin.bcm): can't compare to get_data_block_cnt() because
// meta_block_info_ is updated in close phase, not in process phase.
// } else if (OB_UNLIKELY(clustered_micro_info_array_->count() != get_data_block_cnt())) {
// ret = OB_ERR_UNEXPECTED;
// LOG_WARN("fail to add clustered index block micro infos, unexpected array size",
// K(ret), K(clustered_micro_info_array_->count()),
// K(get_data_block_cnt()));
} else {
LOG_DEBUG("add clustered index block micro infos", K(ret), K(macro_id),
K(block_offset), K(block_size), K(logic_micro_id));
@ -1088,7 +1080,6 @@ int ObSSTableIndexBuilder::merge_index_tree_from_all_mem_index_block(ObSSTableMe
} else {
const int64_t rowkey_column_count = index_store_desc_.get_desc().get_rowkey_column_count();
ObIndexBlockRowParser row_parser;
const ObIndexBlockRowHeader *index_row_header = nullptr;
const ObIndexBlockRowMinorMetaInfo *index_row_meta = nullptr;
for (int64_t i = 0; OB_SUCC(ret) && i < roots_.count(); ++i) {
index_block_loader_.reuse();
@ -1105,7 +1096,7 @@ int ObSSTableIndexBuilder::merge_index_tree_from_all_mem_index_block(ObSSTableMe
while (OB_SUCC(ret)) {
row_parser.reset();
index_row.reuse();
ObIndexBlockRowDesc row_desc(data_desc.get_desc());
ObIndexBlockRowDesc row_desc;
if (OB_FAIL(index_block_loader_.get_next_row(index_row))) {
if (OB_UNLIKELY(ret != OB_ITER_END)) {
STORAGE_LOG(WARN, "fail to get row", K(ret),
@ -1113,43 +1104,8 @@ int ObSSTableIndexBuilder::merge_index_tree_from_all_mem_index_block(ObSSTableMe
}
} else if (OB_FAIL(row_parser.init(rowkey_column_count, index_row))) {
STORAGE_LOG(WARN, "fail to init row parser", K(ret), K(rowkey_column_count), K(index_row));
} else if (OB_FAIL(row_desc.row_key_.assign(index_row.storage_datums_, rowkey_column_count))) {
STORAGE_LOG(WARN, "fail to assign src rowkey", K(ret), K(rowkey_column_count), K(index_row));
} else if (OB_FAIL(row_parser.get_header(index_row_header))){
STORAGE_LOG(WARN, "fail to get index row header", K(ret), K(row_parser));
} else {
row_desc.is_secondary_meta_ = false;
row_desc.is_macro_node_ = true;
// TODO(baichangmin & luhaopeng): if there is confusing bug, think about this macro id here.
row_desc.macro_id_ = index_row_header->get_macro_id();
row_desc.block_offset_ = index_row_header->block_offset_;
row_desc.block_size_ = index_row_header->block_size_;
row_desc.row_count_ = index_row_header->row_count_;
row_desc.is_deleted_ = index_row_header->is_deleted_;
row_desc.contain_uncommitted_row_ = index_row_header->contain_uncommitted_row_;
row_desc.micro_block_count_ = index_row_header->micro_block_count_;
row_desc.macro_block_count_ = 1;
row_desc.has_string_out_row_ = index_row_header->has_string_out_row_;
row_desc.has_lob_out_row_ = index_row_header->all_lob_in_row_;
row_desc.row_offset_ = row_parser.get_row_offset();
row_desc.is_serialized_agg_row_ = true;
const char *agg_row_buf = nullptr;
int64_t agg_buf_size = 0;
if (!index_store_desc_.get_desc().is_major_or_meta_merge_type()) {
if (OB_FAIL(row_parser.get_minor_meta(index_row_meta))) {
STORAGE_LOG(WARN, "fail to get minor meta", K(ret), K(row_parser));
} else {
row_desc.max_merged_trans_version_ = index_row_meta->max_merged_trans_version_;
row_desc.row_count_delta_ = index_row_meta->row_count_delta_;
}
} else if (!index_row_header->is_major_node() || !index_row_header->is_pre_aggregated()) {
// Do not have aggregate data
} else if (OB_FAIL(row_parser.get_agg_row(agg_row_buf, agg_buf_size))) {
STORAGE_LOG(WARN, "Fail to get aggregate", K(ret));
} else {
row_desc.serialized_agg_row_buf_ = agg_row_buf;
}
} else if (OB_FAIL(row_desc.init(data_desc.get_desc(), row_parser, index_row))) {
LOG_WARN("fail to init idx row desc", K(ret), K(data_desc.get_desc()), K(row_parser), K(index_row));
}
if (OB_FAIL(ret)) {
@ -2397,11 +2353,11 @@ int ObBaseIndexBlockBuilder::meta_to_row_desc(
{
int ret = OB_SUCCESS;
ObDataStoreDesc *data_desc = nullptr;
if (OB_UNLIKELY(nullptr == row_desc.data_store_desc_)) {
if (OB_UNLIKELY(nullptr == row_desc.get_data_store_desc())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid null data store desc", K(ret));
} else if (FALSE_IT(data_desc = const_cast<ObDataStoreDesc *>(
row_desc.data_store_desc_))) {
row_desc.get_data_store_desc()))) {
} else if (OB_FAIL(data_desc->static_desc_->end_scn_.convert_for_tx(
macro_meta.val_.snapshot_version_))) {
STORAGE_LOG(WARN, "fail to convert scn", K(ret),
@ -3305,7 +3261,7 @@ int ObDataIndexBlockBuilder::generate_macro_meta_row_desc(
ObIndexBlockRowDesc &macro_row_desc)
{
int ret = OB_SUCCESS;
macro_row_desc.data_store_desc_ = index_store_desc_;
macro_row_desc.set_data_store_desc(index_store_desc_);
if (OB_UNLIKELY(!micro_block_desc.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid micro block desc", K(ret), K(micro_block_desc));

View File

@ -46,6 +46,64 @@ ObIndexBlockRowDesc::ObIndexBlockRowDesc(const ObDataStoreDesc &data_store_desc)
{
}
int ObIndexBlockRowDesc::init(const ObDataStoreDesc &data_store_desc,
ObIndexBlockRowParser &idx_row_parser,
ObDatumRow &index_row)
{
int ret = OB_SUCCESS;
const ObIndexBlockRowHeader *index_row_header = nullptr;
const ObIndexBlockRowMinorMetaInfo *index_row_meta = nullptr;
const int64_t rowkey_column_count = data_store_desc.get_rowkey_column_count();
data_store_desc_ = &data_store_desc;
if (OB_FAIL(row_key_.assign(index_row.storage_datums_, rowkey_column_count))) {
STORAGE_LOG(WARN, "fail to assign src rowkey", K(ret), K(rowkey_column_count), K(index_row));
} else if (OB_FAIL(idx_row_parser.get_header(index_row_header))){
STORAGE_LOG(WARN, "fail to get index row header", K(ret), K(idx_row_parser));
} else {
ObDataStoreDesc *non_const_data_store_desc = const_cast<ObDataStoreDesc *>(data_store_desc_);
ObStaticDataStoreDesc *static_desc = non_const_data_store_desc->static_desc_;
non_const_data_store_desc->row_store_type_ = index_row_header->get_row_store_type();
static_desc->compressor_type_ = index_row_header->get_compressor_type();
static_desc->master_key_id_ = index_row_header->get_master_key_id();
static_desc->encrypt_id_ = index_row_header->get_encrypt_id();
MEMCPY(static_desc->encrypt_key_, index_row_header->get_encrypt_key(), sizeof(static_desc->encrypt_key_));
static_desc->schema_version_ = index_row_header->get_schema_version();
is_secondary_meta_ = false;
is_macro_node_ = true;
macro_id_ = index_row_header->get_macro_id();
block_offset_ = index_row_header->block_offset_;
block_size_ = index_row_header->block_size_;
row_count_ = index_row_header->row_count_;
is_deleted_ = index_row_header->is_deleted_;
contain_uncommitted_row_ = index_row_header->contain_uncommitted_row_;
micro_block_count_ = index_row_header->micro_block_count_;
macro_block_count_ = 1;
has_string_out_row_ = index_row_header->has_string_out_row_;
has_lob_out_row_ = !index_row_header->all_lob_in_row_;
row_offset_ = idx_row_parser.get_row_offset();
is_serialized_agg_row_ = true;
const char *agg_row_buf = nullptr;
int64_t agg_buf_size = 0;
if (!data_store_desc.is_major_or_meta_merge_type()) {
if (OB_FAIL(idx_row_parser.get_minor_meta(index_row_meta))) {
STORAGE_LOG(WARN, "fail to get minor meta", K(ret), K(idx_row_parser));
} else {
max_merged_trans_version_ = index_row_meta->max_merged_trans_version_;
row_count_delta_ = index_row_meta->row_count_delta_;
}
} else if (!index_row_header->is_major_node() || !index_row_header->is_pre_aggregated()) {
// Do not have aggregate data
} else if (OB_FAIL(idx_row_parser.get_agg_row(agg_row_buf, agg_buf_size))) {
STORAGE_LOG(WARN, "Fail to get aggregate", K(ret));
} else {
serialized_agg_row_buf_ = agg_row_buf;
}
}
return ret;
}
MacroBlockId ObIndexBlockRowHeader::DEFAULT_IDX_ROW_MACRO_ID(0, DEFAULT_IDX_ROW_MACRO_IDX, 0);
MacroBlockId ObIndexBlockRowHeader::INVALID_MACRO_BLOCK_ID;
ObLogicMicroBlockId ObIndexBlockRowHeader::INVALID_LOGICAL_MICRO_BLOCK_ID;
@ -249,10 +307,10 @@ int ObIndexBlockRowBuilder::calc_data_size(
LOG_WARN("Invalid index block row description", K(ret), K(desc));
} else if (desc.is_secondary_meta_) {
size = sizeof(ObIndexBlockRowHeader);
if (desc.data_store_desc_->is_major_or_meta_merge_type()) {
if (desc.get_data_store_desc()->is_major_or_meta_merge_type()) {
size += sizeof(int64_t); // add row offset for major sstable
}
} else if (desc.data_store_desc_->is_major_or_meta_merge_type()) {
} else if (desc.get_data_store_desc()->is_major_or_meta_merge_type()) {
size = sizeof(ObIndexBlockRowHeader);
size += sizeof(int64_t); // add row offset for major sstable
if (nullptr != desc.aggregated_row_) {
@ -284,14 +342,14 @@ int ObIndexBlockRowBuilder::append_header_and_meta(const ObIndexBlockRowDesc &de
} else {
header_ = reinterpret_cast<ObIndexBlockRowHeader *>(data_buf_);
header_->version_ = ObIndexBlockRowHeader::INDEX_BLOCK_HEADER_V2;
header_->row_store_type_ = static_cast<uint8_t>(desc.data_store_desc_->get_row_store_type());
header_->compressor_type_ = static_cast<uint8_t>(desc.data_store_desc_->get_compressor_type());
header_->row_store_type_ = static_cast<uint8_t>(desc.get_data_store_desc()->get_row_store_type());
header_->compressor_type_ = static_cast<uint8_t>(desc.get_data_store_desc()->get_compressor_type());
// This micro block is a index tree micro block or a meta tree micro block
header_->is_data_index_ = !desc.is_secondary_meta_;
header_->is_data_block_ = desc.is_data_block_;
header_->is_leaf_block_ = desc.is_macro_node_;
header_->is_macro_node_ = desc.is_macro_node_;
header_->is_major_node_ = desc.data_store_desc_->is_major_or_meta_merge_type();
header_->is_major_node_ = desc.get_data_store_desc()->is_major_or_meta_merge_type();
header_->has_string_out_row_ = desc.has_string_out_row_;
header_->all_lob_in_row_ = !desc.has_lob_out_row_;
header_->is_pre_aggregated_ = nullptr != desc.aggregated_row_;
@ -305,10 +363,10 @@ int ObIndexBlockRowBuilder::append_header_and_meta(const ObIndexBlockRowDesc &de
header_->block_size_ = desc.block_size_;
header_->macro_block_count_ = desc.macro_block_count_;
header_->micro_block_count_ = desc.micro_block_count_;
header_->master_key_id_ = desc.data_store_desc_->get_master_key_id();
header_->encrypt_id_ = desc.data_store_desc_->get_encrypt_id();
MEMCPY(header_->encrypt_key_, desc.data_store_desc_->get_encrypt_key(), sizeof(header_->encrypt_key_));
header_->schema_version_ = desc.data_store_desc_->get_schema_version();
header_->master_key_id_ = desc.get_data_store_desc()->get_master_key_id();
header_->encrypt_id_ = desc.get_data_store_desc()->get_encrypt_id();
MEMCPY(header_->encrypt_key_, desc.get_data_store_desc()->get_encrypt_key(), sizeof(header_->encrypt_key_));
header_->schema_version_ = desc.get_data_store_desc()->get_schema_version();
header_->row_count_ = desc.row_count_;
write_pos_ += sizeof(ObIndexBlockRowHeader);
@ -329,7 +387,7 @@ int ObIndexBlockRowBuilder::append_header_and_meta(const ObIndexBlockRowDesc &de
} else if (header_->is_data_index() && !header_->is_major_node()) {
ObIndexBlockRowMinorMetaInfo *minor_meta
= reinterpret_cast<ObIndexBlockRowMinorMetaInfo *>(data_buf_ + write_pos_);
minor_meta->snapshot_version_ = desc.data_store_desc_->get_end_scn().get_val_for_tx();
minor_meta->snapshot_version_ = desc.get_data_store_desc()->get_end_scn().get_val_for_tx();
header_->contain_uncommitted_row_ = desc.contain_uncommitted_row_;
minor_meta->max_merged_trans_version_ = desc.max_merged_trans_version_;
minor_meta->row_count_delta_ = desc.row_count_delta_;

View File

@ -37,10 +37,15 @@ class ObRowKeysInfo;
namespace blocksstable
{
class ObIndexBlockRowParser;
struct ObIndexBlockRowDesc
{
ObIndexBlockRowDesc();
ObIndexBlockRowDesc(const ObDataStoreDesc &data_store_desc);
int init(const ObDataStoreDesc &data_store_desc, ObIndexBlockRowParser &idx_row_parser, ObDatumRow &index_row);
OB_INLINE const ObDataStoreDesc * get_data_store_desc() const { return data_store_desc_; }
OB_INLINE void set_data_store_desc(const ObDataStoreDesc *data_store_desc) { data_store_desc_ = data_store_desc; }
OB_INLINE void set_for_clustered_index() { is_clustered_index_ = true; }
OB_INLINE bool is_valid() const
{
@ -54,7 +59,11 @@ struct ObIndexBlockRowDesc
return ret;
}
const ObDataStoreDesc *data_store_desc_;
private:
// TODO(baichangmin): set RowDesc to class.
const ObDataStoreDesc *data_store_desc_; // TODO(baichangmin): do not use pointer or reference here.
public:
union {
const ObDatumRow *aggregated_row_;
const char *serialized_agg_row_buf_;
@ -84,13 +93,13 @@ struct ObIndexBlockRowDesc
bool is_clustered_index_;
TO_STRING_KV(KP_(data_store_desc), KP_(aggregated_row), K_(row_key), K_(macro_id),
K_(logic_micro_id), K_(data_checksum),
K_(logic_micro_id), K_(shared_data_macro_id), K_(data_checksum),
K_(block_offset), K_(row_count), K_(row_count_delta),
K_(max_merged_trans_version), K_(block_size),
K_(macro_block_count), K_(micro_block_count), K_(row_offset),
K_(is_deleted), K_(contain_uncommitted_row), K_(is_data_block),
K_(is_secondary_meta), K_(is_macro_node), K_(has_string_out_row), K_(has_lob_out_row),
K_(is_last_row_last_flag), K_(is_serialized_agg_row), K_(is_clustered_index), K_(shared_data_macro_id));
K_(is_last_row_last_flag), K_(is_serialized_agg_row), K_(is_clustered_index));
};
struct ObIndexBlockRowHeader