807 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			807 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * 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 "storage/ob_dml_param.h"
 | |
| #include "storage/ob_range_iterator.h"
 | |
| #include "lib/container/ob_iarray.h"
 | |
| #include <gtest/gtest.h>
 | |
| #include <gmock/gmock.h>
 | |
| 
 | |
| namespace oceanbase {
 | |
| using namespace common;
 | |
| using namespace storage;
 | |
| 
 | |
| namespace unittest {
 | |
| 
 | |
| class FakeTableScanParam : public ObTableScanParam {
 | |
| public:
 | |
|   FakeTableScanParam(ObOrderType order = ObOrderType::ASC)
 | |
|   {
 | |
|     fake_column_orders_.push_back(order);
 | |
|     column_orders_ = &fake_column_orders_;
 | |
|   }
 | |
|   virtual ~FakeTableScanParam()
 | |
|   {}
 | |
|   virtual bool is_valid() const
 | |
|   {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   common::ObArray<ObOrderType> fake_column_orders_;
 | |
| };
 | |
| 
 | |
| int add_get_range(const int64_t val, ObIAllocator& allocator, ObTableScanParam& param)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   ObObj* start_val = NULL;
 | |
|   ObObj* end_val = NULL;
 | |
|   if (NULL == (start_val = static_cast<ObObj*>(allocator.alloc(sizeof(ObObj)))) ||
 | |
|       NULL == (end_val = static_cast<ObObj*>(allocator.alloc(sizeof(ObObj))))) {
 | |
|     ret = OB_ALLOCATE_MEMORY_FAILED;
 | |
|     STORAGE_LOG(WARN, "out of memory", K(ret));
 | |
|   } else {
 | |
|     start_val->set_int(val);
 | |
|     end_val->set_int(val);
 | |
|     ObRowkey start_key(start_val, 1);
 | |
|     ObRowkey end_key(end_val, 1);
 | |
|     ObNewRange range;
 | |
|     range.table_id_ = 3003;
 | |
|     range.start_key_ = start_key;
 | |
|     range.end_key_ = end_key;
 | |
|     range.border_flag_.set_inclusive_start();
 | |
|     range.border_flag_.set_inclusive_end();
 | |
|     ret = param.key_ranges_.push_back(range);
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int add_scan_range(const int64_t s_val, const int64_t e_val, ObIAllocator& allocator, ObTableScanParam& param)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   if (e_val > s_val) {
 | |
|     ObObj* start_val = NULL;
 | |
|     ObObj* end_val = NULL;
 | |
|     if (NULL == (start_val = static_cast<ObObj*>(allocator.alloc(sizeof(ObObj)))) ||
 | |
|         NULL == (end_val = static_cast<ObObj*>(allocator.alloc(sizeof(ObObj))))) {
 | |
|       ret = OB_ALLOCATE_MEMORY_FAILED;
 | |
|       STORAGE_LOG(WARN, "out of memory", K(ret));
 | |
|     } else {
 | |
|       start_val->set_int(s_val);
 | |
|       end_val->set_int(e_val);
 | |
|       ObRowkey start_key(start_val, 1);
 | |
|       ObRowkey end_key(end_val, 1);
 | |
|       ObNewRange range;
 | |
|       range.table_id_ = 3003;
 | |
|       range.start_key_ = start_key;
 | |
|       range.end_key_ = end_key;
 | |
|       ret = param.key_ranges_.push_back(range);
 | |
|     }
 | |
|   } else {
 | |
|     ret = OB_INVALID_ARGUMENT;
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void check_get_range(const int64_t val, const ObExtStoreRowkey& rowkey)
 | |
| {
 | |
|   ObObj rk_val;
 | |
|   rk_val.set_int(val);
 | |
|   ObStoreRowkey rk(&rk_val, 1);
 | |
|   EXPECT_EQ(rk, rowkey.get_store_rowkey());
 | |
| }
 | |
| 
 | |
| void check_get_range(const int64_t val, ObBatch& batch)
 | |
| {
 | |
|   EXPECT_EQ(ObBatch::T_GET, batch.type_);
 | |
|   EXPECT_TRUE(NULL != batch.rowkey_);
 | |
|   check_get_range(val, *batch.rowkey_);
 | |
| }
 | |
| 
 | |
| void check_multi_get_range(ObIArray<int64_t>& rowkeys, ObBatch& batch)
 | |
| {
 | |
|   EXPECT_EQ(ObBatch::T_MULTI_GET, batch.type_);
 | |
|   EXPECT_TRUE(NULL != batch.rowkeys_);
 | |
|   EXPECT_EQ(rowkeys.count(), batch.rowkeys_->count());
 | |
|   for (int64_t i = 0; i < rowkeys.count(); ++i) {
 | |
|     check_get_range(rowkeys.at(i), batch.rowkeys_->at(i));
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool test_equal_store_range(const ObStoreRange& lhs, const ObStoreRange& rhs)
 | |
| {
 | |
|   return (rhs.get_table_id() == rhs.get_table_id()) && (lhs.get_start_key().simple_equal(rhs.get_start_key())) &&
 | |
|          (lhs.get_end_key().simple_equal(rhs.get_end_key())) &&
 | |
|          (lhs.get_border_flag().get_data() == rhs.get_border_flag().get_data());
 | |
| }
 | |
| 
 | |
| void check_scan_range(const int64_t s_val, const int64_t e_val, const ObExtStoreRange& single_range)
 | |
| {
 | |
|   if (e_val > s_val) {
 | |
|     ObObj start_val;
 | |
|     ObObj end_val;
 | |
|     start_val.set_int(s_val);
 | |
|     end_val.set_int(e_val);
 | |
|     ObStoreRowkey start_key(&start_val, 1);
 | |
|     ObStoreRowkey end_key(&end_val, 1);
 | |
|     ObStoreRange range;
 | |
|     range.set_table_id(3003);
 | |
|     range.set_start_key(start_key);
 | |
|     range.set_end_key(end_key);
 | |
|     STORAGE_LOG(INFO, "range", K(single_range), K(range));
 | |
|     EXPECT_TRUE(test_equal_store_range(single_range.get_range(), range));
 | |
|   } else {
 | |
|     BACKTRACE(INFO, true, "backtrace");
 | |
|     STORAGE_LOG(WARN, "wrong argument(s)", K(s_val), K(e_val));
 | |
|   }
 | |
| }
 | |
| 
 | |
| void check_scan_range(const int64_t s_val, const int64_t e_val, ObBatch& batch)
 | |
| {
 | |
|   ObObj start_val;
 | |
|   ObObj end_val;
 | |
|   start_val.set_int(s_val);
 | |
|   end_val.set_int(e_val);
 | |
|   ObStoreRowkey start_key(&start_val, 1);
 | |
|   ObStoreRowkey end_key(&end_val, 1);
 | |
|   ObStoreRange range;
 | |
|   range.set_table_id(3003);
 | |
|   range.set_start_key(start_key);
 | |
|   range.set_end_key(end_key);
 | |
|   EXPECT_EQ(ObBatch::T_SCAN, batch.type_);
 | |
|   EXPECT_TRUE(NULL != batch.range_);
 | |
|   EXPECT_TRUE(test_equal_store_range(batch.range_->get_range(), range));
 | |
| }
 | |
| 
 | |
| void check_multi_scan_range(const ObIArray<int64_t>& s_vals, const ObIArray<int64_t>& e_vals, ObBatch& batch)
 | |
| {
 | |
|   EXPECT_EQ(ObBatch::T_MULTI_SCAN, batch.type_);
 | |
|   ASSERT_TRUE(NULL != batch.ranges_);
 | |
|   EXPECT_EQ(s_vals.count(), batch.ranges_->count());
 | |
|   EXPECT_EQ(e_vals.count(), batch.ranges_->count());
 | |
|   for (int64_t i = 0; i < s_vals.count(); ++i) {
 | |
|     STORAGE_LOG(INFO, "", "s_val", s_vals.at(i), "e_val", e_vals.at(i));
 | |
|     if (s_vals.at(i) == e_vals.at(i)) {
 | |
|       check_get_range(s_vals.at(i), ObExtStoreRowkey(batch.ranges_->at(i).get_range().get_start_key()));
 | |
|     } else {
 | |
|       check_scan_range(s_vals.at(i), e_vals.at(i), batch.ranges_->at(i));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_empty_range)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ObIArray<ObOrderType>* column_orders;
 | |
|   int64_t rowkey_cnt = 1;
 | |
|   bool is_whole = false;
 | |
| 
 | |
|   column_orders = param.get_rowkey_column_orders();
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   EXPECT_EQ(ObBatch::T_SCAN, batch.type_);
 | |
|   EXPECT_EQ(OB_SUCCESS, batch.range_->get_range().is_whole_range(*column_orders, rowkey_cnt, is_whole));
 | |
|   EXPECT_TRUE(is_whole);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_get_range)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_get_range(1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| 
 | |
|   // test short path of single get
 | |
|   iter.reset();
 | |
|   param.is_get_ = true;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_get_range(1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_get_range_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_get_range(1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| 
 | |
|   // test short path of single get
 | |
|   iter.reset();
 | |
|   param.is_get_ = true;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_get_range(1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_scan_range(1, 9, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_scan_range(9, 1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_get_range)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(9, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ObSEArray<int64_t, 64> rowkeys;
 | |
|   rowkeys.push_back(1);
 | |
|   rowkeys.push_back(3);
 | |
|   rowkeys.push_back(5);
 | |
|   rowkeys.push_back(7);
 | |
|   rowkeys.push_back(9);
 | |
|   check_multi_get_range(rowkeys, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| 
 | |
|   // test short path of multi get
 | |
|   iter.reset();
 | |
|   param.is_get_ = true;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_get_range(rowkeys, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_get_unordered)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   param.scan_flag_.scan_order_ = ObQueryFlag::Forward;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(9, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ObSEArray<int64_t, 64> rowkeys;
 | |
|   rowkeys.push_back(1);
 | |
|   rowkeys.push_back(3);
 | |
|   rowkeys.push_back(5);
 | |
|   rowkeys.push_back(7);
 | |
|   rowkeys.push_back(9);
 | |
|   check_multi_get_range(rowkeys, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| 
 | |
|   // test short path of multi get
 | |
|   iter.reset();
 | |
|   param.is_get_ = true;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_get_range(rowkeys, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_get_range_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(9, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ObSEArray<int64_t, 64> rowkeys;
 | |
|   rowkeys.push_back(1);
 | |
|   rowkeys.push_back(3);
 | |
|   rowkeys.push_back(5);
 | |
|   rowkeys.push_back(7);
 | |
|   rowkeys.push_back(9);
 | |
|   check_multi_get_range(rowkeys, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| 
 | |
|   // test short path of multi get
 | |
|   iter.reset();
 | |
|   param.is_get_ = true;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_get_range(rowkeys, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_get_perf)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   ObBatch batch;
 | |
| 
 | |
|   const int64_t perf_count = 1000L * 1000L;
 | |
|   int64_t begin_time = 0;
 | |
|   int64_t end_time = 0;
 | |
|   int64_t cost_time = 0;
 | |
| 
 | |
|   // perf single get without is_get param
 | |
|   begin_time = ObTimeUtility::current_time();
 | |
|   for (int64_t i = 0; i < perf_count; ++i) {
 | |
|     iter.reset();
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|     check_get_range(1, batch);
 | |
|   }
 | |
|   end_time = ObTimeUtility::current_time();
 | |
|   cost_time = end_time - begin_time;
 | |
|   STORAGE_LOG(INFO, "perf single get without is_get", K(perf_count), K(cost_time));
 | |
| 
 | |
|   // perf single get with is_get param
 | |
|   param.is_get_ = true;
 | |
|   begin_time = ObTimeUtility::current_time();
 | |
|   for (int64_t i = 0; i < perf_count; ++i) {
 | |
|     iter.reset();
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|     check_get_range(1, batch);
 | |
|   }
 | |
|   end_time = ObTimeUtility::current_time();
 | |
|   cost_time = end_time - begin_time;
 | |
|   STORAGE_LOG(INFO, "perf single get with is_get", K(perf_count), K(cost_time));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_get_perf)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   param.scan_flag_.scan_order_ = ObQueryFlag::Forward;
 | |
|   ModulePageAllocator allocator;
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(9, allocator, param));
 | |
|   ObSEArray<int64_t, 64> rowkeys;
 | |
|   rowkeys.push_back(1);
 | |
|   rowkeys.push_back(3);
 | |
|   rowkeys.push_back(5);
 | |
|   rowkeys.push_back(7);
 | |
|   rowkeys.push_back(9);
 | |
| 
 | |
|   const int64_t perf_count = 200L * 1000L;
 | |
|   int64_t begin_time = 0;
 | |
|   int64_t end_time = 0;
 | |
|   int64_t cost_time = 0;
 | |
| 
 | |
|   // perf multi get without is_get param
 | |
|   begin_time = ObTimeUtility::current_time();
 | |
|   for (int64_t i = 0; i < perf_count; ++i) {
 | |
|     iter.reset();
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|     check_multi_get_range(rowkeys, batch);
 | |
|   }
 | |
|   end_time = ObTimeUtility::current_time();
 | |
|   cost_time = end_time - begin_time;
 | |
|   STORAGE_LOG(INFO, "perf multi get without is_get", K(perf_count), K(cost_time));
 | |
| 
 | |
|   // perf multi get with is_get param
 | |
|   param.is_get_ = true;
 | |
|   begin_time = ObTimeUtility::current_time();
 | |
|   for (int64_t i = 0; i < perf_count; ++i) {
 | |
|     iter.reset();
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|     EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|     check_multi_get_range(rowkeys, batch);
 | |
|   }
 | |
|   end_time = ObTimeUtility::current_time();
 | |
|   cost_time = end_time - begin_time;
 | |
|   STORAGE_LOG(INFO, "perf multi get with is_get", K(perf_count), K(cost_time));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_range_forward)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Forward, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(1);
 | |
|   s_vals.push_back(2);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(7);
 | |
|   s_vals.push_back(11);
 | |
|   e_vals.push_back(1);
 | |
|   e_vals.push_back(3);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(13);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
| }
 | |
| 
 | |
| // When stored in descending order, forward scan should get large value first
 | |
| TEST(ObRowFuseTest, test_multi_range_forward_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Forward, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(13);
 | |
|   s_vals.push_back(7);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(3);
 | |
|   s_vals.push_back(1);
 | |
|   e_vals.push_back(11);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(2);
 | |
|   e_vals.push_back(1);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_range_backward)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Reverse, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(11);
 | |
|   s_vals.push_back(7);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(2);
 | |
|   s_vals.push_back(1);
 | |
|   e_vals.push_back(13);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(3);
 | |
|   e_vals.push_back(1);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_range_backward_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Reverse, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(1);
 | |
|   s_vals.push_back(3);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(8);
 | |
|   s_vals.push_back(13);
 | |
|   e_vals.push_back(1);
 | |
|   e_vals.push_back(2);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(11);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_range_default)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(1);
 | |
|   s_vals.push_back(2);
 | |
|   s_vals.push_back(7);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(11);
 | |
|   e_vals.push_back(1);
 | |
|   e_vals.push_back(3);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(13);
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_range_default_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(1);
 | |
|   s_vals.push_back(3);
 | |
|   s_vals.push_back(7);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(13);
 | |
|   e_vals.push_back(1);
 | |
|   e_vals.push_back(2);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(11);
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_multi_range_keep_order)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(11, 13, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(6, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(2, 3, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::KeepOrder, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ObSEArray<int64_t, 64> s_vals;
 | |
|   ObSEArray<int64_t, 64> e_vals;
 | |
|   s_vals.push_back(1);
 | |
|   s_vals.push_back(13);
 | |
|   s_vals.push_back(7);
 | |
|   s_vals.push_back(5);
 | |
|   s_vals.push_back(6);
 | |
|   s_vals.push_back(3);
 | |
|   e_vals.push_back(1);
 | |
|   e_vals.push_back(11);
 | |
|   e_vals.push_back(7);
 | |
|   e_vals.push_back(5);
 | |
|   e_vals.push_back(6);
 | |
|   e_vals.push_back(2);
 | |
|   check_multi_scan_range(s_vals, e_vals, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range2)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Reverse, false, false, true, false, false, false);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_scan_range(1, 9, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range2_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Reverse, false, false, true, false, false, false);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_scan_range(9, 1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range3)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Forward, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_scan_range(1, 9, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range3_desc)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param(ObOrderType::DESC);
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Forward, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   check_scan_range(9, 1, batch);
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_single_scan_range4)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_scan_range(1, 9, allocator, param));
 | |
|   ObQueryFlag flag(ObQueryFlag::Forward, false, false, true, false, false, false);
 | |
|   param.scan_flag_ = flag;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
| }
 | |
| 
 | |
| TEST(ObRowFuseTest, test_get_range_array_idx)
 | |
| {
 | |
|   ObRangeIterator iter;
 | |
|   FakeTableScanParam param;
 | |
|   ModulePageAllocator allocator;
 | |
|   ObBatch batch;
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(1, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(3, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(5, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(7, allocator, param));
 | |
|   EXPECT_EQ(OB_SUCCESS, add_get_range(9, allocator, param));
 | |
|   param.range_array_pos_.push_back(0);
 | |
|   param.range_array_pos_.push_back(3);
 | |
|   param.range_array_pos_.push_back(4);
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   ASSERT_EQ(batch.type_, ObBatch::T_MULTI_GET);
 | |
|   ObSEArray<int64_t, 64> range_array_idx;
 | |
|   for (int64_t i = 0; i < 5; ++i) {
 | |
|     int64_t range_idx = batch.rowkeys_->at(i).get_range_array_idx();
 | |
|     ASSERT_EQ(OB_SUCCESS, range_array_idx.push_back(range_idx));
 | |
|   }
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| 
 | |
|   // check range_idx
 | |
|   EXPECT_EQ(range_array_idx[0], 0);
 | |
|   EXPECT_EQ(range_array_idx[1], 1);
 | |
|   EXPECT_EQ(range_array_idx[2], 1);
 | |
|   EXPECT_EQ(range_array_idx[3], 1);
 | |
|   EXPECT_EQ(range_array_idx[4], 2);
 | |
| 
 | |
|   // test short path of multi get
 | |
|   iter.reset();
 | |
|   param.is_get_ = true;
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.set_scan_param(param));
 | |
|   EXPECT_EQ(OB_SUCCESS, iter.get_next(batch));
 | |
|   for (int64_t i = 0; i < 5; ++i) {
 | |
|     int64_t range_idx = batch.rowkeys_->at(i).get_range_array_idx();
 | |
|     EXPECT_EQ(range_idx, range_array_idx.at(i));
 | |
|   }
 | |
|   EXPECT_EQ(OB_ITER_END, iter.get_next(batch));
 | |
| }
 | |
| 
 | |
| }  // namespace unittest
 | |
| }  // namespace oceanbase
 | |
| 
 | |
| int main(int argc, char** argv)
 | |
| {
 | |
|   system("rm -f test_range_iterator.log*");
 | |
|   OB_LOGGER.set_file_name("test_range_iterator.log", true, true);
 | |
|   OB_LOGGER.set_log_level("INFO");
 | |
|   STORAGE_LOG(INFO, "begin unittest: test_row_fuse");
 | |
|   ::testing::InitGoogleTest(&argc, argv);
 | |
|   return RUN_ALL_TESTS();
 | |
| }
 | 
