/** * 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: * 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. */ #include #define private public #define protected public #include "lib/container/ob_iarray.h" #include "storage/compaction/ob_partition_merge_util.h" #include "storage/memtable/ob_memtable_interface.h" #include "storage/ob_partition_component_factory.h" #include "blocksstable/ob_data_file_prepare.h" #include "blocksstable/ob_row_generate.h" #include "storage/ob_ms_row_iterator.h" #include "observer/ob_service.h" #include "storage/memtable/ob_memtable.h" #include "storage/memtable/ob_memtable_iterator.h" #include "storage/memtable/ob_memtable_mutator.h" #include "common/cell/ob_cell_reader.h" #include "lib/allocator/page_arena.h" #include "lib/container/ob_se_array.h" #include "storage/ob_i_store.h" #include "share/ob_srv_rpc_proxy.h" #include "storage/ob_i_table.h" #include "storage/compaction/ob_partition_merge_builder.h" #include "ob_multi_version_sstable_test.h" #include "mock_ob_partition_report.h" #include "storage/ob_sstable_merge_info_mgr.h" #include "memtable/utils_rowkey_builder.h" #include "memtable/utils_mock_row.h" #include "storage/compaction/ob_partition_merge.h" #include "ob_uncommitted_trans_test.h" #include "mockcontainer/mock_ob_trans_service.h" namespace oceanbase { using namespace common; using namespace share::schema; using namespace blocksstable; using namespace compaction; using namespace memtable; using namespace observer; using namespace unittest; using namespace rpc::frame; using namespace memtable; namespace storage { typedef compaction::ObIPartitionMergeFuser::MERGE_ITER_ARRAY MERGE_ITER_ARRAY; class TestNewMinorFuserMerge : public ObMultiVersionSSTableTest { public: static const int64_t MAX_PARALLEL_DEGREE = 10; TestNewMinorFuserMerge() : ObMultiVersionSSTableTest("test_new_minor_fuser") {} virtual ~TestNewMinorFuserMerge() {} virtual void SetUp() { init_tenant_mgr(); ObTableMgr::get_instance().init(); ObMultiVersionSSTableTest::SetUp(); ObPartitionKey pkey(combine_id(TENANT_ID, TABLE_ID), 0, 0); ASSERT_EQ(OB_SUCCESS, ObPartitionService::get_instance().get_pg_index().init()); ASSERT_EQ(OB_SUCCESS, ObPartitionService::get_instance().get_pg_index().add_partition(pkey, pkey)); ObPartitionKey& part = const_cast(test_trans_part_ctx_.get_partition()); test_trans_part_ctx_.set_partition_key(pkey); // trans_service_.part_trans_ctx_mgr_.mgr_cache_.set(pkey.hash(), &test_trans_part_ctx_); trans_service_.part_trans_ctx_mgr_.partition_ctx_map_.insert_and_get(pkey, &test_trans_part_ctx_); store_ctx_.trans_table_guard_ = new transaction::ObTransStateTableGuard(); ObPartitionService::get_instance().txs_ = &trans_service_; } virtual void TearDown() { ObMultiVersionSSTableTest::TearDown(); ObTableMgr::get_instance().destroy(); ObPartitionService::get_instance().get_pg_index().destroy(); } void prepare_merge_context(const storage::ObTablesHandle& tables_handle, const ObMergeType& merge_type, const bool is_full_merge, const ObVersionRange& trans_version_range, ObSSTableMergeCtx& merge_context, const ObObjType* type_list = NULL); void build_sstable(ObSSTableMergeCtx& ctx, ObSSTable*& merged_sstable); int create_sstable(const storage::ObCreateSSTableParamWithTable& param, ObTableHandle& handle); void build_two_sstable(ObSSTableMergeCtx& ctx, ObSSTable*& mini_sstable, ObSSTable*& complement_minor_sstable); void prepare_query_param(const ObVersionRange& trans_version_range); void prepare_schema(const ObObjType* type_list); void prepare_schema(); void build_parallel_merge(ObSSTableMergeCtx& ctx, const char** rowkey_data); int init_tenant_mgr(); ObArray columns_; ObTableIterParam param_; ObTableAccessContext context_; ObArenaAllocator allocator_; ObArray projector_; ObStoreCtx store_ctx_; MockObIPartitionReport report_; share::schema::ObTenantSchema tenant_schema_; ObMockIterator range_iter_; transaction::MockObTransService trans_service_; TestUncommittedMinorMergeScan test_trans_part_ctx_; TestUncommittedMinorMergeScan scan_trans_part_ctx_; }; void TestNewMinorFuserMerge::prepare_query_param(const ObVersionRange& trans_version_range) { columns_.reset(); param_.reset(); context_.reset(); block_cache_ws_.reset(); projector_.reset(); ObQueryFlag query_flag; query_flag.whole_macro_scan_ = true; query_flag.multi_version_minor_merge_ = true; ObColDesc col_desc; int multi_version_col_cnt = ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); const int schema_rowkey_cnt = rowkey_cnt_ - multi_version_col_cnt; // schema rowkey count int trans_version_col = ObMultiVersionRowkeyHelpper::get_trans_version_col_store_index(schema_rowkey_cnt, multi_version_col_cnt); int sql_no_col = ObMultiVersionRowkeyHelpper::get_sql_sequence_col_store_index(schema_rowkey_cnt, multi_version_col_cnt); for (int i = 0; i < column_cnt_; i++) { if (trans_version_col != i && sql_no_col != i) { col_desc.col_id_ = i + OB_APP_MIN_COLUMN_ID; col_desc.col_type_ = data_iter_[0].get_column_type()[i]; OK(columns_.push_back(col_desc)); } } for (int i = 0; i < column_cnt_ - multi_version_col_cnt; i++) { OK(projector_.push_back(i)); } param_.table_id_ = combine_id(TENANT_ID, TABLE_ID); param_.schema_version_ = SCHEMA_VERSION; param_.rowkey_cnt_ = schema_rowkey_cnt; // schema rowkey count param_.out_cols_ = &columns_; OK(block_cache_ws_.init(TENANT_ID)); context_.query_flag_ = query_flag; context_.store_ctx_ = &store_ctx_; context_.allocator_ = &allocator_; context_.stmt_allocator_ = &allocator_; context_.block_cache_ws_ = &block_cache_ws_; context_.trans_version_range_ = trans_version_range; context_.read_out_type_ = SPARSE_ROW_STORE; store_ctx_.trans_table_guard_->set_trans_state_table(&scan_trans_part_ctx_); context_.is_inited_ = true; } void TestNewMinorFuserMerge::prepare_schema() { int ret = OB_SUCCESS; int64_t micro_block_size = 16 * 1024; const uint64_t tenant_id = TENANT_ID; const uint64_t table_id = combine_id(tenant_id, TABLE_ID); ObColumnSchemaV2 column; // generate data table schema table_schema_.reset(); ret = table_schema_.set_table_name("test_merge_multi_version"); ASSERT_EQ(OB_SUCCESS, ret); table_schema_.set_tenant_id(tenant_id); table_schema_.set_tablegroup_id(1); table_schema_.set_database_id(1); table_schema_.set_table_id(table_id); table_schema_.set_rowkey_column_num(TEST_ROWKEY_COLUMN_CNT); table_schema_.set_max_used_column_id(TEST_COLUMN_CNT); table_schema_.set_block_size(micro_block_size); table_schema_.set_compress_func_name("none"); table_schema_.set_row_store_type(SPARSE_ROW_STORE); // init column char name[OB_MAX_FILE_NAME_LENGTH]; memset(name, 0, sizeof(name)); ObColDesc col_desc; const int64_t column_ids[] = {16, 17, 20, 21}; for (int64_t i = 0; i < TEST_COLUMN_CNT; ++i) { ObObjType obj_type = ObIntType; const int64_t column_id = column_ids[i]; if (i == 1) { obj_type = ObVarcharType; } column.reset(); column.set_table_id(table_id); column.set_column_id(column_id); sprintf(name, "test%020ld", i); ASSERT_EQ(OB_SUCCESS, column.set_column_name(name)); column.set_data_type(obj_type); column.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); column.set_data_length(10); if (i < TEST_ROWKEY_COLUMN_CNT) { column.set_rowkey_position(i + 1); } else { column.set_rowkey_position(0); } COMMON_LOG(INFO, "add column", K(i), K(column)); ASSERT_EQ(OB_SUCCESS, table_schema_.add_column(column)); col_desc.col_id_ = column.get_column_id(); col_desc.col_type_ = column.get_meta_type(); ASSERT_EQ(OB_SUCCESS, columns_.push_back(col_desc)); } COMMON_LOG(INFO, "dump stable schema", LITERAL_K(TEST_ROWKEY_COLUMN_CNT), K(table_schema_)); } void TestNewMinorFuserMerge::prepare_schema(const ObObjType* type_list) { int ret = OB_SUCCESS; int64_t micro_block_size = 16 * 1024; const uint64_t tenant_id = TENANT_ID; const uint64_t table_id = combine_id(tenant_id, TABLE_ID); ObColumnSchemaV2 column; // generate data table schema table_schema_.reset(); ret = table_schema_.set_table_name("test_merge_multi_version"); ASSERT_EQ(OB_SUCCESS, ret); table_schema_.set_tenant_id(tenant_id); table_schema_.set_tablegroup_id(1); table_schema_.set_database_id(1); table_schema_.set_table_id(table_id); table_schema_.set_rowkey_column_num(TEST_ROWKEY_COLUMN_CNT); table_schema_.set_max_used_column_id(TEST_COLUMN_CNT); table_schema_.set_block_size(micro_block_size); table_schema_.set_compress_func_name("none"); table_schema_.set_row_store_type(SPARSE_ROW_STORE); // init column char name[OB_MAX_FILE_NAME_LENGTH]; memset(name, 0, sizeof(name)); ObColDesc col_desc; const int64_t column_ids[] = {16, 17, 20, 21}; for (int64_t i = 0; i < TEST_COLUMN_CNT; ++i) { ObObjType obj_type = type_list[i]; const int64_t column_id = column_ids[i]; column.reset(); column.set_table_id(table_id); column.set_column_id(column_id); sprintf(name, "test%020ld", i); ASSERT_EQ(OB_SUCCESS, column.set_column_name(name)); column.set_data_type(obj_type); column.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); column.set_data_length(10); if (i < TEST_ROWKEY_COLUMN_CNT) { column.set_rowkey_position(i + 1); } else { column.set_rowkey_position(0); } COMMON_LOG(INFO, "add column", K(i), K(column)); ASSERT_EQ(OB_SUCCESS, table_schema_.add_column(column)); col_desc.col_id_ = column.get_column_id(); col_desc.col_type_ = column.get_meta_type(); ASSERT_EQ(OB_SUCCESS, columns_.push_back(col_desc)); } COMMON_LOG(INFO, "dump stable schema", LITERAL_K(TEST_ROWKEY_COLUMN_CNT), K(table_schema_)); } void TestNewMinorFuserMerge::prepare_merge_context(const storage::ObTablesHandle& tables_handle, const ObMergeType& merge_type, const bool is_full_merge, const ObVersionRange& trans_version_range, ObSSTableMergeCtx& merge_context, const ObObjType* type_list /* = NULL*/) { ObMultiVersionColDescGenerate multi_version_col_desc_gen; const ObMultiVersionRowInfo* multi_version_row_info = NULL; bool has_lob = false; bool has_memtable = false; if (OB_NOT_NULL(type_list)) { prepare_schema(type_list); } else { prepare_schema(); } merge_context.base_schema_version_ = table_schema_.get_schema_version(); merge_context.schema_version_ = table_schema_.get_schema_version(); ASSERT_EQ(OB_SUCCESS, merge_context.tables_handle_.assign(tables_handle)); merge_context.data_table_schema_ = &table_schema_; merge_context.is_full_merge_ = is_full_merge; merge_context.merge_level_ = MACRO_BLOCK_MERGE_LEVEL; merge_context.report_ = &report_; merge_context.param_.merge_type_ = merge_type; merge_context.param_.schedule_merge_type_ = merge_type; merge_context.param_.merge_version_ = 0; merge_context.param_.index_id_ = table_schema_.get_table_id(); merge_context.param_.pkey_.init(table_schema_.get_table_id(), 0 /*partition id*/, 0 /*partition count*/); merge_context.param_.pg_key_ = merge_context.param_.pkey_; merge_context.sstable_version_range_ = trans_version_range; merge_context.mv_dep_table_schema_ = NULL; merge_context.table_schema_ = &table_schema_; merge_context.logical_data_version_ = trans_version_range.snapshot_version_; ObStorageFile* file = NULL; ASSERT_EQ(OB_SUCCESS, ObFileSystemUtil::get_pg_file_with_guard(merge_context.param_.pg_key_, merge_context.pg_guard_, file)); ASSERT_EQ(OB_SUCCESS, multi_version_col_desc_gen.init(&table_schema_)); ASSERT_EQ(OB_SUCCESS, multi_version_col_desc_gen.generate_multi_version_row_info(multi_version_row_info)); COMMON_LOG(INFO, "dump multi_version_row_info", "rowley_cnt", multi_version_row_info->rowkey_column_cnt_, "multi_version_rowkey_cnt", multi_version_row_info->multi_version_rowkey_column_cnt_); merge_context.multi_version_row_info_ = *multi_version_row_info; merge_context.multi_version_row_info_.trans_version_index_ = 2; merge_context.progressive_merge_start_version_ = 0; merge_context.progressive_merge_num_ = 0; for (int64_t i = 0; i < tables_handle.get_count(); ++i) { if (tables_handle.get_table(i)->is_memtable()) { has_memtable = true; } } ASSERT_EQ(OB_SUCCESS, merge_context.init_parallel_merge()); ASSERT_EQ(OB_SUCCESS, merge_context.merge_context_.init(1 /*merge count*/, has_lob, &merge_context.column_stats_, has_memtable)); ASSERT_EQ(OB_SUCCESS, merge_context.merge_context_for_complement_minor_sstable_.init( 1 /*merge count*/, has_lob, &merge_context.column_stats_, has_memtable)); } int TestNewMinorFuserMerge::create_sstable(const storage::ObCreateSSTableParamWithTable& param, ObTableHandle& handle) { int ret = OB_SUCCESS; ObSSTable* table = NULL; void* buf = nullptr; if (!param.is_valid() || (!ObITable::is_sstable(param.table_key_.table_type_))) { ret = OB_INVALID_ARGUMENT; STORAGE_LOG(WARN, "invalid args", K(ret), K(param)); } else if (OB_ISNULL(buf = allocator_.alloc(sizeof(ObSSTable)))) { ret = OB_ALLOCATE_MEMORY_FAILED; STORAGE_LOG(WARN, "fail to allocate memory for sstable", K(ret)); } else if (FALSE_IT(table = new (buf) ObSSTable())) { } else if (OB_FAIL(table->init(param.table_key_))) { STORAGE_LOG(WARN, "failed to init sstable", K(ret), K(param.table_key_)); } else if (OB_FAIL(table->set_storage_file_handle(get_storage_file_handle()))) { STORAGE_LOG(WARN, "failed to set storage file handle", K(ret)); } else if (OB_FAIL(table->open(param))) { STORAGE_LOG(WARN, "Failed to open sstable", K(ret)); } else if (OB_FAIL(handle.set_table(table))) { STORAGE_LOG(WARN, "failed to set table to handle", K(ret)); } return ret; } int TestNewMinorFuserMerge::init_tenant_mgr() { ObTenantManager& tm = ObTenantManager::get_instance(); ObAddr self; self.set_ip_addr("127.0.0.1", 8086); rpc::frame::ObReqTransport req_transport(NULL, NULL); obrpc::ObSrvRpcProxy rpc_proxy; obrpc::ObCommonRpcProxy common_rpc_proxy; share::ObRsMgr rs_mgr; int ret = tm.init(self, rpc_proxy, common_rpc_proxy, rs_mgr, &req_transport, &ObServerConfig::get_instance()); ret = tm.add_tenant(OB_SYS_TENANT_ID); EXPECT_EQ(OB_SUCCESS, ret); const int64_t ulmt = 16LL << 30; const int64_t llmt = 8LL << 30; ret = tm.set_tenant_mem_limit(OB_SYS_TENANT_ID, ulmt, llmt); EXPECT_EQ(OB_SUCCESS, ret); return OB_SUCCESS; } void TestNewMinorFuserMerge::build_sstable(ObSSTableMergeCtx& ctx, ObSSTable*& merged_sstable) { ObCreateSSTableParamWithTable param; param.table_key_.table_type_ = ctx.get_merged_table_type(); param.table_key_.pkey_ = ctx.param_.pkey_; param.table_key_.table_id_ = ctx.param_.index_id_; param.table_key_.version_ = ctx.param_.merge_version_; param.table_key_.trans_version_range_ = ctx.sstable_version_range_; param.table_key_.log_ts_range_.start_log_ts_ = 0; param.table_key_.log_ts_range_.end_log_ts_ = 10; param.table_key_.log_ts_range_.max_log_ts_ = 10; param.logical_data_version_ = param.table_key_.trans_version_range_.snapshot_version_; param.schema_ = &table_schema_; param.schema_version_ = 10; param.checksum_method_ = blocksstable::CCM_VALUE_ONLY; int ret = OB_SUCCESS; void* buf = nullptr; storage::ObTableHandle table_handle; OB_FILE_SYSTEM.get_partition_service().get_pg_key(ctx.param_.pkey_, param.pg_key_); ASSERT_EQ(OB_SUCCESS, create_sstable(param, table_handle)); ASSERT_EQ(OB_SUCCESS, table_handle.get_sstable(merged_sstable)); for (int64_t i = 0; OB_SUCC(ret) && i < ctx.merge_context_.block_ctxs_.count(); ++i) { if (OB_ISNULL(ctx.merge_context_.block_ctxs_.at(i))) { ret = OB_ERR_SYS; STORAGE_LOG(WARN, "data block ctx must not be null", K(ret)); } else { ASSERT_EQ(OB_SUCCESS, merged_sstable->append_macro_blocks(*ctx.merge_context_.block_ctxs_.at(i))); } } ASSERT_EQ(OB_SUCCESS, merged_sstable->close()); /* if (OB_FAIL(ctx.merge_context_.create_sstable(param, ctx.pg_guard_, table_handle))) { STORAGE_LOG(WARN, "fail to create sstable", K(ret), K(ctx.param_), K(table_handle)); } else if (OB_FAIL(table_handle.get_sstable(merged_sstable))) { STORAGE_LOG(WARN, "fail to get sstable", K(ret)); } ASSERT_EQ(OB_SUCCESS, create_sstable(param, ctx.merged_table_handle_)); ASSERT_EQ(OB_SUCCESS, ctx.merged_table_handle_.get_sstable(merged_sstable)); ASSERT_EQ(OB_SUCCESS, merged_sstable->close()); */ // ASSERT_EQ(OB_SUCCESS, ObTableMgr::get_instance().complete_sstable(ctx.merged_table_handle_)); } void TestNewMinorFuserMerge::build_two_sstable( ObSSTableMergeCtx& ctx, ObSSTable*& mini_sstable, ObSSTable*& complement_minor_sstable) { ObCreateSSTableParamWithTable param; param.table_key_.table_type_ = ctx.get_merged_table_type(); param.table_key_.pkey_ = ctx.param_.pkey_; param.table_key_.table_id_ = ctx.param_.index_id_; param.table_key_.version_ = ctx.param_.merge_version_; param.table_key_.trans_version_range_ = ctx.sstable_version_range_; param.table_key_.log_ts_range_.start_log_ts_ = 0; param.table_key_.log_ts_range_.end_log_ts_ = 10; param.table_key_.log_ts_range_.max_log_ts_ = 10; param.logical_data_version_ = param.table_key_.trans_version_range_.snapshot_version_; param.schema_ = &table_schema_; param.schema_version_ = 10; param.checksum_method_ = blocksstable::CCM_VALUE_ONLY; ASSERT_EQ(OB_SUCCESS, create_sstable(param, ctx.merged_table_handle_)); ASSERT_EQ(OB_SUCCESS, ctx.merged_table_handle_.get_sstable(mini_sstable)); ASSERT_EQ(OB_SUCCESS, mini_sstable->close()); // ASSERT_EQ(OB_SUCCESS, ObTableMgr::get_instance().complete_sstable(ctx.merged_table_handle_)); param.table_key_.table_type_ = ObITable::COMPLEMENT_MINOR_SSTABLE; ASSERT_EQ(OB_SUCCESS, create_sstable(param, ctx.merged_complement_minor_table_handle_)); ASSERT_EQ(OB_SUCCESS, ctx.merged_complement_minor_table_handle_.get_sstable(complement_minor_sstable)); ASSERT_EQ(OB_SUCCESS, complement_minor_sstable->close()); // ASSERT_EQ(OB_SUCCESS, ObTableMgr::get_instance().complete_sstable(ctx.merged_complement_minor_table_handle_)); } void TestNewMinorFuserMerge::build_parallel_merge(ObSSTableMergeCtx& ctx, const char** rowkey_data) { ObExtStoreRange merge_range; const ObStoreRow* row = nullptr; const int64_t rowkey_col_cnt = TEST_ROWKEY_COLUMN_CNT; const int64_t mv_rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); ASSERT_TRUE(nullptr != rowkey_data); range_iter_.reset(); ctx.parallel_merge_ctx_.range_array_.reset(); OK(range_iter_.from(rowkey_data[0])); ASSERT_TRUE(range_iter_.count() > 0); for (int64_t i = 0; i <= range_iter_.count(); i++) { if (0 == i) { merge_range.get_range().get_start_key().set_min(); merge_range.get_range().set_left_open(); } if (i == range_iter_.count()) { merge_range.get_range().get_end_key().set_max(); } else { OK(range_iter_.get_row(i, row)); ASSERT_TRUE(nullptr != row); merge_range.get_range().get_end_key().assign(row->row_val_.cells_, mv_rowkey_cnt); for (int64_t i = rowkey_col_cnt; i < mv_rowkey_cnt; i++) { merge_range.get_range().get_end_key().get_obj_ptr()[i].set_max_value(); } } merge_range.get_range().set_right_closed(); ASSERT_EQ(OB_SUCCESS, ctx.parallel_merge_ctx_.range_array_.push_back(merge_range)); merge_range.reset(); if (i < range_iter_.count()) { merge_range.get_range().get_start_key().assign(row->row_val_.cells_, mv_rowkey_cnt); for (int64_t i = rowkey_col_cnt; i < mv_rowkey_cnt; i++) { merge_range.get_range().get_start_key().get_obj_ptr()[i].set_max_value(); } merge_range.get_range().set_left_open(); } } ASSERT_TRUE(ctx.parallel_merge_ctx_.range_array_.count() > 0); for (int64_t i = 0; i < ctx.parallel_merge_ctx_.range_array_.count(); i++) { ASSERT_EQ(OB_SUCCESS, ctx.parallel_merge_ctx_.range_array_.at(i).to_collation_free_range_on_demand_and_cutoff_range( ctx.parallel_merge_ctx_.allocator_)); } ctx.parallel_merge_ctx_.concurrent_cnt_ = ctx.parallel_merge_ctx_.range_array_.count(); ctx.parallel_merge_ctx_.parallel_type_ = ObParallelMergeCtx::PARALLEL_MINI_MINOR; STORAGE_LOG(INFO, "parallel merge context prepared", K(ctx.parallel_merge_ctx_)); ctx.merge_context_.destroy(); ASSERT_EQ(OB_SUCCESS, ctx.merge_context_.init( ctx.parallel_merge_ctx_.concurrent_cnt_ /*merge count*/, false, &ctx.column_stats_, false)); } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_rowkey_across_macro_block) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var1 -9 -8 2 NOP EXIST CL\n" "1 var1 -7 -12 2 NOP EXIST N\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -7 NOP 2 EXIST N\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -5 2 NOP EXIST L\n" "2 var2 -8 -8 5 NOP EXIST L\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1); prepare_one_macro(¯o_data[1], 1); prepare_one_macro(¯o_data[2], 1); prepare_one_macro(¯o_data[3], 1); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var1 -10 0 3 NOP EXIST CLF\n" "1 var1 -7 -14 9 NOP EXIST L\n" "2 var2 -8 -22 NOP 6 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var1 -10 0 3 NOP EXIST CF\n" "0 var1 -9 0 2 NOP EXIST CL\n" "1 var1 -7 0 9 6 EXIST CL\n" "2 var2 -8 0 5 6 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_rowkey_across_macro_block2) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var1 -9 -8 2 NOP EXIST CL\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -6 -7 NOP 2 EXIST C\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -5 -5 NOP 9 EXIST CL\n" "2 var2 -8 -8 5 NOP EXIST L\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1); prepare_one_macro(¯o_data[1], 1); prepare_one_macro(¯o_data[2], 1); prepare_one_macro(¯o_data[3], 1); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var1 -10 0 3 NOP EXIST CLF\n" "1 var1 -7 -24 NOP 19 EXIST L\n" "2 var2 -8 -22 3 6 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var1 -10 0 3 NOP EXIST CF\n" "0 var1 -9 0 2 NOP EXIST CL\n" "1 var1 -7 0 NOP 19 EXIST C\n" "1 var1 -6 0 NOP 2 EXIST C\n" "1 var1 -5 0 NOP 9 EXIST CL\n" "2 var2 -8 0 3 6 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_rowkey_across_macro_block3) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -6 -8 2 7 EXIST CL\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -6 -7 NOP 2 EXIST C\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -5 -5 NOP 9 EXIST CL\n" "2 var2 -8 -8 5 NOP EXIST L\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1); prepare_one_macro(¯o_data[1], 1); prepare_one_macro(¯o_data[2], 1); prepare_one_macro(¯o_data[3], 1); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[3]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -10 0 3 NOP EXIST CF\n" "0 var0 -9 -24 NOP 19 EXIST N\n" "0 var0 -8 -22 3 6 EXIST N\n"; macro_data2[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -6 -16 3 NOP EXIST CL\n" "1 var1 -12 -24 3 19 EXIST CF\n" "1 var1 -8 -22 3 6 EXIST N\n"; macro_data2[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -15 3 NOP EXIST CL\n" "2 var2 -8 -22 NOP 6 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_one_macro(¯o_data2[1], 1); prepare_one_macro(¯o_data2[2], 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -10 0 3 7 EXIST CF\n" // two compact row need to compact together "0 var0 -9 0 NOP 19 EXIST N\n" "0 var0 -8 0 3 6 EXIST N\n" "0 var0 -6 0 3 7 EXIST CL\n" "1 var1 -12 0 3 19 EXIST CF\n" "1 var1 -8 0 3 6 EXIST C\n" "1 var1 -7 0 3 6 EXIST C\n" "1 var1 -6 0 NOP 2 EXIST C\n" "1 var1 -5 0 NOP 9 EXIST CL\n" "2 var2 -8 0 5 6 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_multi_sstable) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -1 -9 7 NOP EXIST CLF\n" "1 var1 -7 -12 5 28 EXIST CF\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -4 0 5 2 EXIST L\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1); prepare_one_macro(¯o_data[1], 1); prepare_one_macro(¯o_data[2], 1); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -24 NOP 21 EXIST L\n" "2 var2 -9 -22 18 NOP EXIST F\n" "2 var2 -4 -15 NOP 7 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -12 0 NOP 19 EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 5; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -1 0 7 NOP EXIST CLF\n" "1 var1 -12 0 5 19 EXIST CF\n" "1 var1 -7 0 5 21 EXIST C\n" "1 var1 -4 0 5 2 EXIST CL\n" "2 var2 -9 0 18 7 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_multi_sstable2) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -4 0 NOP 9 EXIST L\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1); prepare_one_macro(¯o_data[1], 1); prepare_one_macro(¯o_data[2], 1); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -11 9 NOP EXIST CL\n" "1 var1 -7 -24 NOP 19 EXIST L\n" "2 var2 -9 -22 12 NOP EXIST F\n" "2 var2 -4 -15 NOP 7 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -12 0 1 19 EXIST CF\n" "1 var1 -8 -2 1 6 EXIST N\n" "1 var1 -7 -35 7 NOP EXIST L\n" "2 var2 -9 -25 18 NOP EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 9 12 EXIST CL\n" "1 var1 -12 0 1 19 EXIST CF\n" "1 var1 -8 0 1 6 EXIST N\n" "1 var1 -7 0 7 19 EXIST N\n" "1 var1 -4 0 NOP 9 EXIST CL\n" "2 var2 -9 0 18 7 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_multi_sstable3) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -7 NOP 2 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 0 NOP 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -11 9 NOP EXIST CL\n" "1 var1 -7 -24 18 NOP EXIST CL\n" "2 var2 -9 -22 NOP 9 EXIST C\n" "2 var2 -4 -15 NOP 7 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -12 0 NOP 19 EXIST CF\n" "1 var1 -8 -2 1 6 EXIST N\n" "1 var1 -7 -35 NOP 7 EXIST CL\n" "2 var2 -9 -25 18 NOP EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 9 12 EXIST CL\n" "1 var1 -12 0 18 19 EXIST CF\n" // two compact rows with same rowkey & diff // trans_version need compact "1 var1 -8 0 1 6 EXIST N\n" "1 var1 -7 0 18 7 EXIST CL\n" "2 var2 -9 0 18 9 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_multi_sstable_has_same_row) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -7 NOP 2 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 0 NOP 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n" "1 var1 -7 -24 18 NOP EXIST CL\n" "2 var2 -9 -5 1 9 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 7 12 EXIST CL\n" "1 var1 -7 0 18 6 EXIST CL\n" "2 var2 -9 0 1 9 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_new_sstable_had_old_rows) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -7 NOP 2 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 0 NOP 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n" "1 var1 -12 0 7 NOP EXIST CF\n" "1 var1 -7 -24 18 NOP EXIST C\n" "1 var1 -2 0 21 NOP EXIST N\n" "1 var1 -1 0 91 12 EXIST L\n" "2 var2 -9 -5 1 9 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 5; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 7 12 EXIST CL\n" "1 var1 -12 0 7 6 EXIST CF\n" "1 var1 -7 0 18 6 EXIST C\n" "1 var1 -2 0 21 12 EXIST CL\n" "2 var2 -9 0 1 9 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_new_sstable_had_old_rows2) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -7 7 12 EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -7 NOP 2 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 0 NOP 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -14 -19 71 NOP EXIST N\n" "0 var0 -9 -9 NOP 12 EXIST CL\n" "1 var1 -7 -24 NOP 68 EXIST N\n" "1 var1 -6 0 21 NOP EXIST N\n" "1 var1 -4 0 91 12 EXIST L\n" "2 var2 -9 -5 1 9 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -14 0 71 12 EXIST C\n" "0 var0 -9 0 7 12 EXIST CL\n" "1 var1 -7 0 21 68 EXIST C\n" "1 var1 -6 0 21 NOP EXIST N\n" "1 var1 -4 0 91 12 EXIST CL\n" "2 var2 -9 0 1 9 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_delete_row) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -7 7 12 EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -10 NOP 6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 -7 NOP 2 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -7 0 NOP 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -14 -19 71 NOP EXIST N\n" "0 var0 -9 -9 NOP 12 EXIST CL\n" "1 var1 -7 -24 NOP NOP DELETE N\n" "1 var1 -6 0 21 NOP EXIST N\n" "1 var1 -4 0 91 12 EXIST L\n" "2 var2 -9 -5 1 9 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -14 0 71 12 EXIST C\n" "0 var0 -9 0 7 12 EXIST CL\n" "1 var1 -7 0 NOP NOP DELETE C\n" "1 var1 -6 0 21 NOP EXIST N\n" "1 var1 -4 0 91 12 EXIST CL\n" "2 var2 -9 0 1 9 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_test_allocator) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -9 -7 biubiu NOP EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 -10 NOP kkkkk3 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 -7 NOP pppp6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 0 char77 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "2 var2 -9 -5 NOP nnnnn EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -14 -19 bbbbb NOP EXIST N\n" "0 var0 -9 -9 NOP huluhulu EXIST CL\n" "1 var1 -7 -24 NOP NOP EXIST L\n" "2 var2 -9 -5 1 NOP EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; const ObObjType type_list[] = {ObIntType, ObVarcharType, ObVarcharType, ObVarcharType}; prepare_merge_context( tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context, type_list); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -14 0 bbbbb huluhulu EXIST C\n" "0 var0 -9 0 biubiu huluhulu EXIST CL\n" "1 var1 -7 0 char77 kkkkk3 EXIST CL\n" "2 var2 -9 0 1 nnnnn EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_test_allocator2) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[10]; int index = 0; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -9 -7 biubiu NOP EXIST CL\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 -12 NOP NOP EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 -10 NOP hkgqhjkgqhkghqkhgkqh EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 -7 NOP pppp6 EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "1 var1 -7 0 char77 9 EXIST L\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "2 var2 -9 -5 NOP nnnnn EXIST N\n"; macro_data[index++] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "2 var2 -9 -3 1 8 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); for (int i = 0; i < index; ++i) { prepare_one_macro(¯o_data[i], 1); } prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -14 -19 bbbbb NOP EXIST N\n" "0 var0 -9 -9 NOP huluhulu EXIST CL\n" "1 var1 -7 -24 NOP NOP EXIST L\n" "2 var2 -9 -5 1 NOP EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -14 -39 NOP akhgfajkhg EXIST CL\n" "1 var1 -7 -40 qjkfjkqhgkq NOP EXIST L\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 12, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; const ObObjType type_list[] = {ObIntType, ObVarcharType, ObVarcharType, ObVarcharType}; prepare_merge_context( tables_handle, MINI_MINOR_MERGE, false /*is_full_merge*/, trans_version_range, merge_context, type_list); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint var var flag multi_version_row_flag\n" "0 var0 -14 0 bbbbb akhgfajkhg EXIST C\n" "0 var0 -9 0 biubiu huluhulu EXIST CL\n" "1 var1 -7 0 qjkfjkqhgkq hkgqhjkgqhkghqkhgkqh EXIST CL\n" "2 var2 -9 0 1 nnnnn EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0 /*idx*/)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true /*cmp multi version row flag*/)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_uncommitted_row_running) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n" "1 var1 MIN -12 NOP NOP EXIST U\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -10 NOP 6 EXIST U\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -7 NOP 2 EXIST U\n" "1 var1 MIN -6 NOP 2 EXIST U\n" "1 var1 -4 0 NOP 9 EXIST L\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[1], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[2], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[3], 1); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -11 9 NOP EXIST CL\n" "1 var1 MIN -26 NOP 11 EXIST U\n" "1 var1 MIN -24 NOP 19 EXIST LU\n" "2 var2 -9 -22 12 NOP EXIST F\n" "2 var2 -4 -15 NOP 7 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -35 7 NOP EXIST LU\n" "2 var2 -9 -25 18 NOP EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); // make all trans running int ret = OB_SUCCESS; test_trans_part_ctx_.clear_all(); if (OB_FAIL(test_trans_part_ctx_.set_all_transaction_status(transaction::ObTransTableStatusType::RUNNING))) { STORAGE_LOG(ERROR, "add transaction status failed", K(ret)); } ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = INT64_MAX; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 9 12 EXIST CL\n" "1 var1 MIN -35 7 NOP EXIST U\n" "1 var1 MIN -26 NOP 11 EXIST U\n" "1 var1 MIN -24 NOP 19 EXIST U\n" "1 var1 MIN -12 NOP NOP EXIST U\n" "1 var1 MIN -10 NOP 6 EXIST U\n" "1 var1 MIN -7 NOP 2 EXIST U\n" "1 var1 MIN -6 NOP 2 EXIST U\n" "1 var1 -4 0 NOP 9 EXIST CL\n" "2 var2 -9 0 18 7 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0)); build_sstable(merge_context, merged_sstable); scan_trans_part_ctx_.clear_all(); scan_trans_part_ctx_.set_all_transaction_status(transaction::ObTransTableStatusType::RUNNING); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_uncommitted_row_abort) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n" "1 var1 MIN -12 NOP NOP EXIST U\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -10 NOP 6 EXIST U\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -7 NOP 2 EXIST U\n" "1 var1 MIN -6 NOP 2 EXIST U\n" "1 var1 -4 0 NOP 9 EXIST CL\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[1], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[2], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[3], 1, INT64_MAX); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -11 9 NOP EXIST CL\n" "1 var1 MIN -26 NOP 11 EXIST U\n" "1 var1 MIN -24 NOP 19 EXIST LU\n" "2 var2 -9 -22 12 NOP EXIST F\n" "2 var2 -4 -15 NOP 7 EXIST CL\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -35 7 NOP EXIST LU\n" "2 var2 -9 -25 18 NOP EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); // make all trans running int ret = OB_SUCCESS; test_trans_part_ctx_.clear_all(); if (OB_FAIL(test_trans_part_ctx_.set_all_transaction_status(transaction::ObTransTableStatusType::ABORT))) { STORAGE_LOG(ERROR, "add transaction status failed", K(ret)); } ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 9 12 EXIST CL\n" "1 var1 -4 0 NOP 9 EXIST CL\n" "2 var2 -9 0 18 7 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege scan_trans_part_ctx_.clear_all(); scan_trans_part_ctx_.set_all_transaction_status(transaction::ObTransTableStatusType::ABORT); ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_uncommitted_row_commit) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n" "1 var1 MIN -12 NOP NOP EXIST U\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -10 NOP 6 EXIST U\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -7 NOP 2 EXIST U\n" "1 var1 MIN -6 NOP 2 EXIST U\n" "1 var1 -4 0 NOP 9 EXIST L\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[1], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[2], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[3], 1, INT64_MAX); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -11 9 NOP EXIST CL\n" "1 var1 MIN -26 NOP 11 EXIST U\n" "1 var1 MIN -24 NOP 19 EXIST LU\n" "2 var2 -9 -22 12 NOP EXIST F\n" "2 var2 -4 -15 NOP 7 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -35 7 NOP EXIST LU\n" "2 var2 -9 -25 18 NOP EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); // make all trans running int ret = OB_SUCCESS; test_trans_part_ctx_.clear_all(); if (OB_FAIL(test_trans_part_ctx_.set_all_transaction_status(transaction::ObTransTableStatusType::COMMIT, 18))) { STORAGE_LOG(ERROR, "add transaction status failed", K(ret)); } ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 9 12 EXIST CL\n" "1 var1 -18 0 7 11 EXIST C\n" "1 var1 -4 0 NOP 9 EXIST CL\n" "2 var2 -9 0 18 7 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_uncommitted_row_commit2) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[4]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -9 7 12 EXIST CL\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -12 NOP NOP EXIST U\n" "1 var1 MIN -10 NOP 6 EXIST U\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 MIN -7 NOP 2 EXIST U\n" "1 var1 MIN -6 7 2 EXIST U\n" "1 var1 -4 0 NOP 9 EXIST L\n"; macro_data[3] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -5 NOP 9 EXIST CL\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data, 1); prepare_one_macro(¯o_data[1], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[2], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[3], 1, INT64_MAX); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); ObSSTable sstable2; const char* macro_data2[1]; macro_data2[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 -11 9 NOP EXIST CL\n" "2 var2 -9 -22 12 NOP EXIST F\n" "2 var2 -4 -15 NOP 7 EXIST L\n"; prepare_data_start(sstable2, macro_data2, rowkey_cnt, 10, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data2, 1); prepare_data_end(sstable2); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable2)); STORAGE_LOG(INFO, "finish prepare sstable2"); ObSSTable sstable3; const char* macro_data3[1]; macro_data3[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "2 var2 -9 -25 18 NOP EXIST CLF\n"; prepare_data_start(sstable3, macro_data3, rowkey_cnt, 20, "none", FLAT_ROW_STORE, 0); prepare_one_macro(macro_data3, 1); prepare_data_end(sstable3); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable3)); STORAGE_LOG(INFO, "finish prepare sstable3"); int ret = OB_SUCCESS; test_trans_part_ctx_.clear_all(); if (OB_FAIL(test_trans_part_ctx_.set_all_transaction_status(transaction::ObTransTableStatusType::COMMIT, 18))) { STORAGE_LOG(ERROR, "add transaction status failed", K(ret)); } ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "0 var0 -9 0 9 12 EXIST CL\n" "1 var1 -18 0 7 6 EXIST C\n" "1 var1 -4 0 NOP 9 EXIST CL\n" "2 var2 -9 0 18 7 EXIST CF\n" "2 var2 -4 0 NOP 7 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } TEST_F(TestNewMinorFuserMerge, test_new_minor_fuser_with_multi_delete_row) { GCONF._enable_sparse_row = false; ObMemtableCtxFactory mem_ctx; ObSSTableMergeCtx merge_context; const int64_t rowkey_cnt = TEST_ROWKEY_COLUMN_CNT + ObMultiVersionRowkeyHelpper::get_extra_rowkey_col_cnt(); storage::ObTablesHandle tables_handle; ObSSTable sstable1; const char* macro_data[3]; macro_data[0] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag trans_id\n" "1 var1 MIN -12 27 NOP EXIST U trans_id_1\n" "1 var1 MIN -11 24 NOP EXIST U trans_id_1\n"; macro_data[1] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag trans_id\n" "1 var1 MIN -10 NOP NOP DELETE U trans_id_2\n"; macro_data[2] = "bigint var bigint bigint bigint bigint flag multi_version_row_flag trans_id\n" "1 var1 MIN -7 NOP 2 EXIST U trans_id_2\n" "1 var1 MIN -6 7 2 EXIST U trans_id_2\n" "1 var1 -4 0 NOP 9 EXIST L trans_id_0\n"; prepare_data_start(sstable1, macro_data, rowkey_cnt, 9, "none", FLAT_ROW_STORE, 0); prepare_one_macro(¯o_data[0], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[1], 1, INT64_MAX, nullptr, nullptr, true); prepare_one_macro(¯o_data[2], 1, INT64_MAX, nullptr, nullptr, true); prepare_data_end(sstable1); ASSERT_EQ(OB_SUCCESS, tables_handle.add_table(&sstable1)); STORAGE_LOG(INFO, "finish prepare sstable1"); int ret = OB_SUCCESS; test_trans_part_ctx_.clear_all(); transaction::ObTransTableStatusType status1[] = { transaction::ObTransTableStatusType::COMMIT, transaction::ObTransTableStatusType::COMMIT}; int64_t commit_trans_version1[] = {40, 18}; for (int i = 0; OB_SUCC(ret) && i < 2; ++i) { if (OB_FAIL(test_trans_part_ctx_.add_transaction_status(status1[i], commit_trans_version1[i]))) { STORAGE_LOG(ERROR, "add transaction status failed", K(ret), K(i)); } } ObVersionRange trans_version_range; trans_version_range.snapshot_version_ = 100; trans_version_range.multi_version_start_ = 1; trans_version_range.base_version_ = 1; prepare_merge_context(tables_handle, MINI_MINOR_MERGE, false, trans_version_range, merge_context); ObMockIterator res_iter; ObStoreRowIterator* scanner = NULL; ObExtStoreRange range; const char* result1 = "bigint var bigint bigint bigint bigint flag multi_version_row_flag\n" "1 var1 -40 0 27 NOP EXIST C\n" "1 var1 -18 0 NOP NOP DELETE C\n" "1 var1 -4 0 NOP 9 EXIST CL\n"; // minor mrege ObMacroBlockBuilder builder; ObSSTable* merged_sstable = nullptr; ASSERT_EQ(OB_SUCCESS, ObPartitionMergeUtil::merge_partition(&mem_ctx, merge_context, builder, 0)); build_sstable(merge_context, merged_sstable); res_iter.reset(); range.get_range().set_whole_range(); prepare_query_param(trans_version_range); ASSERT_EQ(OB_SUCCESS, range.to_collation_free_range_on_demand_and_cutoff_range(allocator_)); if (OB_NOT_NULL(merged_sstable)) { context_.read_out_type_ = FLAT_ROW_STORE; ASSERT_EQ(OB_SUCCESS, merged_sstable->scan(param_, context_, range, scanner)); ASSERT_EQ(OB_SUCCESS, res_iter.from(result1)); ASSERT_TRUE(res_iter.equals(*scanner, true)); scanner->~ObStoreRowIterator(); } else { STORAGE_LOG(ERROR, "merged_sstable is null"); } } } // namespace storage } // namespace oceanbase int main(int argc, char** argv) { system("rm -rf test_new_minor_fuser.log*"); OB_LOGGER.set_file_name("test_new_minor_fuser.log"); OB_LOGGER.set_log_level("DEBUG"); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }