 566e920620
			
		
	
	566e920620
	
	
	
		
			
			Co-authored-by: wangt1xiuyi <13547954130@163.com> Co-authored-by: yangqise7en <877793735@qq.com> Co-authored-by: Zach41 <zach_41@163.com>
		
			
				
	
	
		
			647 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			647 lines
		
	
	
		
			23 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 <gtest/gtest.h>
 | |
| 
 | |
| #define protected public
 | |
| #define private public
 | |
| 
 | |
| #include "lib/ob_define.h"
 | |
| #include "lib/time/ob_time_utility.h"
 | |
| #include "lib/container/ob_array.h"
 | |
| #include "common/ob_tablet_id.h"
 | |
| #include "common/ob_clock_generator.h"
 | |
| #include "common/object/ob_obj_type.h"
 | |
| #include "share/ob_ls_id.h"
 | |
| #include "share/ob_rpc_struct.h"
 | |
| #include "share/ob_storage_format.h"
 | |
| #include "share/ob_tenant_info_proxy.h"
 | |
| #include "share/schema/ob_table_param.h"
 | |
| #include "storage/mockcontainer/mock_ob_iterator.h"
 | |
| #include "mtlenv/mock_tenant_module_env.h"
 | |
| #include "storage/ls/ob_ls_tablet_service.h"
 | |
| #include "storage/tx/ob_trans_define.h"
 | |
| #include "storage/tx/ob_trans_service.h"
 | |
| #include "mock_ls_tablet_service.h"
 | |
| #include "mock_access_service.h"
 | |
| #include "init_basic_struct.h"
 | |
| 
 | |
| #undef private
 | |
| #undef protected
 | |
| 
 | |
| namespace oceanbase
 | |
| {
 | |
| namespace storage
 | |
| {
 | |
| class TestTxCallback : public transaction::ObITxCallback
 | |
| {
 | |
| public:
 | |
|   TestTxCallback() : committed_(false) {}
 | |
| public:
 | |
|   virtual void callback(int ret) override { UNUSED(ret); committed_ = true; }
 | |
|   bool wait() { return !committed_; }
 | |
| private:
 | |
|   bool committed_;
 | |
| };
 | |
| 
 | |
| class TestDmlCommon
 | |
| {
 | |
| public:
 | |
|   static int create_ls(
 | |
|       const uint64_t tenant_id,
 | |
|       const share::ObLSID &ls_id,
 | |
|       ObLSHandle &ls_handle);
 | |
|   static int create_data_tablet(
 | |
|       const uint64_t tenant_id,
 | |
|       const share::ObLSID &ls_id,
 | |
|       const common::ObTabletID &tablet_id);
 | |
|   static int create_data_and_index_tablets(
 | |
|       const uint64_t tenant_id,
 | |
|       const share::ObLSID &ls_id,
 | |
|       const common::ObTabletID &data_tablet_id,
 | |
|       const common::ObIArray<common::ObTabletID> &index_tablet_id_array);
 | |
|   static int mock_ls_tablet_service(
 | |
|       const share::ObLSID &ls_id,
 | |
|       ObLSTabletService *&tablet_service);
 | |
|   static void delete_mocked_ls_tablet_service(ObLSTabletService *tablet_service);
 | |
|   static int mock_access_service(
 | |
|       ObLSTabletService *tablet_service,
 | |
|       MockObAccessService *&access_service);
 | |
|   static void delete_mocked_access_service(ObAccessService *access_service);
 | |
| 
 | |
|   static int build_table_param(
 | |
|       const ObTableSchema &table_schema,
 | |
|       const ObIArray<uint64_t> &output_column_ids,
 | |
|       share::schema::ObTableParam &table_param);
 | |
|   static int build_table_scan_param(
 | |
|       const uint64_t tenant_id,
 | |
|       ObTxReadSnapshot &read_snapshot,
 | |
|       const share::schema::ObTableParam &table_param,
 | |
|       ObTableScanParam &scan_param);
 | |
|   static int build_table_scan_param(
 | |
|       const uint64_t tenant_id,
 | |
|       ObTransID &tx_id,
 | |
|       const share::schema::ObTableParam &table_param,
 | |
|       ObTableScanParam &scan_param);
 | |
|   static int build_table_scan_param_base_(
 | |
|       const uint64_t tenant_id,
 | |
|       const share::schema::ObTableParam &table_param,
 | |
|       bool read_latest,
 | |
|       ObTableScanParam &scan_param);
 | |
|   static void build_data_table_schema(
 | |
|       const uint64_t tenant_id,
 | |
|       share::schema::ObTableSchema &table_schema);
 | |
|   static void build_index_table_schema(
 | |
|       const uint64_t tenant_id,
 | |
|       share::schema::ObTableSchema &table_schema);
 | |
|   static int build_tx_desc(const uint64_t tenant_id, ObTxDesc *&tx_desc);
 | |
|   static void build_tx_param(ObTxParam &tx_param);
 | |
|   static void release_tx_desc(ObTxDesc &tx_desc);
 | |
|   static int insert_data_to_tablet();
 | |
| protected:
 | |
|   static int build_pure_data_tablet_arg(
 | |
|       const uint64_t tenant_id,
 | |
|       const share::ObLSID &ls_id,
 | |
|       const common::ObTabletID &data_tablet_id,
 | |
|       obrpc::ObBatchCreateTabletArg &arg);
 | |
|   static int build_mixed_tablets_arg(
 | |
|       const uint64_t tenant_id,
 | |
|       const share::ObLSID &ls_id,
 | |
|       const common::ObTabletID &data_tablet_id,
 | |
|       const common::ObIArray<common::ObTabletID> &index_tablet_id_array,
 | |
|       obrpc::ObBatchCreateTabletArg &arg);
 | |
| public:
 | |
|   static const uint64_t TX_EXPIRE_TIME_US = 120 * 1000 * 1000; // 120s
 | |
|   static const int64_t TEST_LS_ID = 2;
 | |
|   static const uint64_t TEST_DATA_TABLE_ID = 50;
 | |
|   static const uint64_t TEST_INDEX_TABLE_ID = 51;
 | |
|   static constexpr const char *data_row_str =
 | |
|       "bigint  bigint   bigint  var         var        dml          \n"
 | |
|       "1       62       20      Houston     Rockets    T_DML_INSERT \n"
 | |
|       "2       65       17      SanAntonio  Spurs      T_DML_INSERT \n"
 | |
|       "3       58       24      Dallas      Mavericks  T_DML_INSERT \n"
 | |
|       "4       51       31      LosAngeles  Lakers     T_DML_INSERT \n"
 | |
|       "5       57       25      Phoenix     Suns       T_DML_INSERT \n"
 | |
|       "6       32       50      NewJersey   Nets       T_DML_INSERT \n"
 | |
|       "7       44       38      Miami       Heats      T_DML_INSERT \n"
 | |
|       "8       21       61      Chicago     Bulls      T_DML_INSERT \n"
 | |
|       "9       47       35      Cleveland   Cavaliers  T_DML_INSERT \n"
 | |
|       "10      59       23      Detroit     Pistons    T_DML_INSERT \n"
 | |
|       "11      40       42      Utah        Jazz       T_DML_INSERT \n"
 | |
|       "12      50       32      Boston      Celtics    T_DML_INSERT \n";
 | |
| };
 | |
| 
 | |
| int TestDmlCommon::create_ls(
 | |
|     const uint64_t tenant_id,
 | |
|     const share::ObLSID &ls_id,
 | |
|     ObLSHandle &ls_handle)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   ObLSService *ls_svr = MTL(ObLSService*);
 | |
|   bool b_exist = false;
 | |
|   ObLS *ls = nullptr;
 | |
|   obrpc::ObCreateLSArg create_ls_arg;
 | |
| 
 | |
|   if (OB_FAIL(gen_create_ls_arg(tenant_id, ls_id, create_ls_arg))) {
 | |
|     STORAGE_LOG(WARN, "failed to build create ls arg", K(ret), K(tenant_id), K(ls_id));
 | |
|   } else if (OB_FAIL(ls_svr->create_ls(create_ls_arg))) {
 | |
|     STORAGE_LOG(WARN, "failed to create ls", K(create_ls_arg));
 | |
|   } else if (OB_FAIL(ls_svr->check_ls_exist(ls_id, b_exist))) {
 | |
|     STORAGE_LOG(WARN, "failed to check ls exist", K(ls_id));
 | |
|   } else if (!b_exist) {
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|     STORAGE_LOG(WARN, "unexpected error, ls does not exist", K(ret), K(ls_id));
 | |
|   } else if (OB_FAIL(ls_svr->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD))) {
 | |
|     STORAGE_LOG(WARN, "failed to get ls", K(ls_id));
 | |
|   } else if (OB_ISNULL(ls = ls_handle.get_ls())) {
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|     STORAGE_LOG(WARN, "ls is null", K(ret), K(ls_handle));
 | |
|   }
 | |
| 
 | |
|   // set member list
 | |
|   if (OB_SUCC(ret)) {
 | |
|     ObMemberList member_list;
 | |
|     const int64_t paxos_replica_num = 1;
 | |
|     (void) member_list.add_server(MockTenantModuleEnv::get_instance().self_addr_);
 | |
|     GlobalLearnerList learner_list;
 | |
|     if (OB_FAIL(ls->set_initial_member_list(member_list, paxos_replica_num, learner_list))) {
 | |
|       STORAGE_LOG(WARN, "failed to set initial member list", K(ret),
 | |
|           K(member_list), K(paxos_replica_num));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // check leader
 | |
|   STORAGE_LOG(INFO, "check leader");
 | |
|   ObRole role;
 | |
|   for (int i = 0; OB_SUCC(ret) && i < 15; i++) {
 | |
|     int64_t proposal_id = 0;
 | |
|     if (OB_FAIL(ls->get_log_handler()->get_role(role, proposal_id))) {
 | |
|       STORAGE_LOG(WARN, "failed to get role", K(ret));
 | |
|     } else if (role == ObRole::LEADER) {
 | |
|       break;
 | |
|     }
 | |
|     ::sleep(1);
 | |
|   }
 | |
| 
 | |
|   if (OB_FAIL(ret)) {
 | |
|   } else if (OB_UNLIKELY(ObRole::LEADER != role)) {
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|     STORAGE_LOG(WARN, "unexpected error, role is not leader", K(ret), K(role));
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::create_data_tablet(
 | |
|     const uint64_t tenant_id,
 | |
|     const share::ObLSID &ls_id,
 | |
|     const common::ObTabletID &tablet_id)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   ObLSHandle ls_handle;
 | |
|   obrpc::ObBatchCreateTabletArg arg;
 | |
| 
 | |
|   if (OB_FAIL(create_ls(tenant_id, ls_id, ls_handle))) {
 | |
|     STORAGE_LOG(WARN, "failed to create ls", K(ret), K(tenant_id), K(ls_id));
 | |
|   } else if (OB_FAIL(build_pure_data_tablet_arg(tenant_id, ls_id, tablet_id, arg))) {
 | |
|     STORAGE_LOG(WARN, "failed to build pure data tablet arg", K(ret),
 | |
|         K(tenant_id), K(ls_id), K(tablet_id));
 | |
|   } else {
 | |
|     ret = OB_NOT_SUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::create_data_and_index_tablets(
 | |
|     const uint64_t tenant_id,
 | |
|     const share::ObLSID &ls_id,
 | |
|     const common::ObTabletID &data_tablet_id,
 | |
|     const common::ObIArray<common::ObTabletID> &index_tablet_id_array)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   ObLSHandle ls_handle;
 | |
|   obrpc::ObBatchCreateTabletArg arg;
 | |
| 
 | |
|   if (OB_FAIL(create_ls(tenant_id, ls_id, ls_handle))) {
 | |
|     STORAGE_LOG(WARN, "failed to create ls", K(ret), K(tenant_id), K(ls_id));
 | |
|   } else if (OB_FAIL(build_mixed_tablets_arg(tenant_id, ls_id,
 | |
|       data_tablet_id, index_tablet_id_array, arg))) {
 | |
|     STORAGE_LOG(WARN, "failed to build pure data tablet arg", K(ret),
 | |
|         K(tenant_id), K(ls_id), K(data_tablet_id), K(index_tablet_id_array));
 | |
|   } else {
 | |
|     ret = OB_NOT_SUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::mock_ls_tablet_service(
 | |
|     const share::ObLSID &ls_id,
 | |
|     ObLSTabletService *&tablet_service)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   ObLSHandle ls_handle;
 | |
|   ObLSService *ls_svr = MTL(ObLSService*);
 | |
|   ObLS *ls = nullptr;
 | |
| 
 | |
|   if (OB_FAIL(ls_svr->get_ls(ls_id, ls_handle, ObLSGetMod::STORAGE_MOD))) {
 | |
|     STORAGE_LOG(WARN, "failed to get ls", K(ret), K(ls_id));
 | |
|   } else if (OB_ISNULL(ls = ls_handle.get_ls())) {
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|     STORAGE_LOG(WARN, "ls is null", K(ret), K(ls));
 | |
|   } else {
 | |
|     ObLSTabletService &svc = ls->ls_tablet_svr_;
 | |
|     MockInsertRowsLSTabletService *mock_svc = OB_NEW(MockInsertRowsLSTabletService, ObModIds::TEST);
 | |
|     ObArray<common::ObTabletID> tablet_ids;
 | |
|     ObLSTabletService::GetAllTabletIDOperator get_all_tablet_id_op(tablet_ids);
 | |
|     if (OB_ISNULL(mock_svc)) {
 | |
|       ret = OB_ALLOCATE_MEMORY_FAILED;
 | |
|       STORAGE_LOG(WARN, "failed to alloc memory", K(ret));
 | |
|     } else if (OB_FAIL(svc.tablet_id_set_.foreach(get_all_tablet_id_op))) {
 | |
|       STORAGE_LOG(WARN, "fail to get all tablet ids from set", K(ret));
 | |
|     } else {
 | |
|       mock_svc->ls_ = svc.ls_;
 | |
|       // ignore ObTxDataMemtableMgr and ObTxCtxMemtableMgr
 | |
| 
 | |
|       // copy hash set
 | |
|       for (int64_t i = 0; OB_SUCC(ret) && i < tablet_ids.count(); ++i) {
 | |
|         const common::ObTabletID &tablet_id = tablet_ids.at(i);
 | |
|         if (mock_svc->tablet_id_set_.set(tablet_id)) {
 | |
|           STORAGE_LOG(WARN, "failed to insert tablet id", K(tablet_id));
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       // ignore ObBucketLock
 | |
|       mock_svc->is_inited_ = svc.is_inited_;
 | |
|     }
 | |
| 
 | |
|     if (OB_SUCC(ret)) {
 | |
|       tablet_service = mock_svc;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void TestDmlCommon::delete_mocked_ls_tablet_service(ObLSTabletService *tablet_service)
 | |
| {
 | |
|   MockInsertRowsLSTabletService *svc = static_cast<MockInsertRowsLSTabletService*>(tablet_service);
 | |
|   OB_DELETE(MockInsertRowsLSTabletService, ObModIds::TEST, svc);
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::mock_access_service(
 | |
|     ObLSTabletService *tablet_service,
 | |
|     MockObAccessService *&access_service)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   MockObAccessService *mock_svc = OB_NEW(MockObAccessService, ObModIds::TEST);
 | |
| 
 | |
|   if (OB_ISNULL(tablet_service)) {
 | |
|     ret = OB_INVALID_ARGUMENT;
 | |
|     STORAGE_LOG(WARN, "invalid args", K(ret), K(tablet_service));
 | |
|   } else if (OB_ISNULL(mock_svc)) {
 | |
|     ret = OB_ALLOCATE_MEMORY_FAILED;
 | |
|     STORAGE_LOG(WARN, "failed to alloc memory", K(ret));
 | |
|   } else {
 | |
|     ObAccessService *svc = MTL(ObAccessService*);
 | |
|     // do copy
 | |
|     mock_svc->is_inited_ = svc->is_inited_;
 | |
|     mock_svc->tenant_id_ = svc->tenant_id_;
 | |
|     mock_svc->ls_svr_ = svc->ls_svr_;
 | |
|     mock_svc->tablet_service_ = tablet_service;
 | |
| 
 | |
|     access_service = mock_svc;
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void TestDmlCommon::delete_mocked_access_service(ObAccessService *access_service)
 | |
| {
 | |
|   MockObAccessService *svc = static_cast<MockObAccessService*>(access_service);
 | |
|   OB_DELETE(MockObAccessService, ObModIds::TEST, svc);
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::build_table_param(
 | |
|     const ObTableSchema &table_schema,
 | |
|     const ObIArray<uint64_t> &output_column_ids,
 | |
|     share::schema::ObTableParam &table_param)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   //use table schema as index schema
 | |
|   if (OB_UNLIKELY(!table_schema.is_valid())) {
 | |
|     ret = OB_INVALID_ARGUMENT;
 | |
|     STORAGE_LOG(WARN, "invalid args", K(ret), K(table_schema));
 | |
|   } else if (OB_FAIL(table_param.convert(table_schema, output_column_ids, 0 /* disable enable_column_store */))) {
 | |
|     STORAGE_LOG(WARN, "failed to convert to table param", K(ret), K(table_schema), K(output_column_ids));
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| /* table_scan read_latest of transaction: tx_id */
 | |
| int TestDmlCommon::build_table_scan_param(
 | |
|     const uint64_t tenant_id,
 | |
|     ObTransID &tx_id,
 | |
|     const share::schema::ObTableParam &table_param,
 | |
|     ObTableScanParam &scan_param)
 | |
| {
 | |
|   int ret = build_table_scan_param_base_(tenant_id, table_param, true, scan_param);
 | |
|   if (OB_SUCC(ret)) {
 | |
|     scan_param.tx_id_ = tx_id;
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| /* table_scan read_by_snapshot */
 | |
| int TestDmlCommon::build_table_scan_param(
 | |
|     const uint64_t tenant_id,
 | |
|     ObTxReadSnapshot &read_snapshot,
 | |
|     const share::schema::ObTableParam &table_param,
 | |
|     ObTableScanParam &scan_param)
 | |
| {
 | |
|   int ret = build_table_scan_param_base_(tenant_id, table_param, false, scan_param);
 | |
|   if (OB_SUCC(ret)) {
 | |
|     scan_param.snapshot_ = read_snapshot;
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::build_table_scan_param_base_(
 | |
|     const uint64_t tenant_id,
 | |
|     const share::schema::ObTableParam &table_param,
 | |
|     bool read_latest,
 | |
|     ObTableScanParam &scan_param)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   int64_t expire_time = ObTimeUtility::current_time() + TX_EXPIRE_TIME_US;
 | |
|   const uint64_t table_id = TEST_DATA_TABLE_ID;
 | |
| 
 | |
|   scan_param.column_ids_.push_back(OB_APP_MIN_COLUMN_ID + 0); // pk
 | |
|   scan_param.column_ids_.push_back(OB_APP_MIN_COLUMN_ID + 1); // c1
 | |
|   scan_param.column_ids_.push_back(OB_APP_MIN_COLUMN_ID + 2); // c2
 | |
|   scan_param.column_ids_.push_back(OB_APP_MIN_COLUMN_ID + 3); // c3
 | |
|   scan_param.column_ids_.push_back(OB_APP_MIN_COLUMN_ID + 4); // c4
 | |
| 
 | |
|   scan_param.ls_id_ = TestDmlCommon::TEST_LS_ID;
 | |
|   scan_param.tablet_id_ = TEST_DATA_TABLE_ID;
 | |
| 
 | |
|   scan_param.table_param_ = &table_param;
 | |
|   scan_param.index_id_ = table_id; // table id
 | |
|   scan_param.is_get_ = false;
 | |
|   scan_param.timeout_ = expire_time;
 | |
| 
 | |
|   ObQueryFlag query_flag(ObQueryFlag::Forward, // scan_order
 | |
|                          false, // daily_merge
 | |
|                          false, // optimize
 | |
|                          false, // sys scan
 | |
|                          false, // full_row
 | |
|                          false, // index_back
 | |
|                          false, // query_stat
 | |
|                          ObQueryFlag::MysqlMode, // sql_mode
 | |
|                          read_latest // read_latest
 | |
|                         );
 | |
|   scan_param.scan_flag_.flag_ = query_flag.flag_;
 | |
| 
 | |
|   scan_param.reserved_cell_count_ = 5;
 | |
|   scan_param.allocator_ = &CURRENT_CONTEXT->get_arena_allocator();
 | |
|   scan_param.for_update_ = false;
 | |
|   scan_param.for_update_wait_timeout_ = expire_time;
 | |
|   scan_param.sql_mode_ = SMO_DEFAULT;
 | |
|   scan_param.scan_allocator_ = &CURRENT_CONTEXT->get_arena_allocator();
 | |
|   scan_param.frozen_version_ = -1;
 | |
|   scan_param.force_refresh_lc_ = false;
 | |
|   scan_param.output_exprs_ = nullptr;
 | |
|   scan_param.aggregate_exprs_ = nullptr;
 | |
|   scan_param.op_ = nullptr;
 | |
|   scan_param.row2exprs_projector_ = nullptr;
 | |
|   scan_param.schema_version_ = share::OB_CORE_SCHEMA_VERSION + 1;
 | |
|   scan_param.tenant_schema_version_ = share::OB_CORE_SCHEMA_VERSION + 1;
 | |
|   scan_param.limit_param_.limit_ = -1;
 | |
|   scan_param.limit_param_.offset_ = 0;
 | |
|   scan_param.need_scn_ = false;
 | |
|   scan_param.pd_storage_flag_ = false;
 | |
|   scan_param.fb_snapshot_.reset();
 | |
| 
 | |
|   ObNewRange range;
 | |
|   range.table_id_ = table_id;
 | |
|   range.start_key_.set_min_row();
 | |
|   range.end_key_.set_max_row();
 | |
|   scan_param.key_ranges_.push_back(range);
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void TestDmlCommon::build_data_table_schema(
 | |
|     const uint64_t tenant_id,
 | |
|     share::schema::ObTableSchema &table_schema)
 | |
| {
 | |
|   const uint64_t table_id = TEST_DATA_TABLE_ID;
 | |
|   const int64_t micro_block_size = 16 * 1024;
 | |
| 
 | |
|   table_schema.reset();
 | |
|   table_schema.set_table_name("test_dml_common");
 | |
|   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_schema_version(share::OB_CORE_SCHEMA_VERSION + 1);
 | |
|   table_schema.set_rowkey_column_num(1);
 | |
|   table_schema.set_max_used_column_id(ObObjType::ObExtendType - 1);
 | |
|   table_schema.set_block_size(micro_block_size);
 | |
|   table_schema.set_compress_func_name("none");
 | |
|   table_schema.set_row_store_type(ObRowStoreType::ENCODING_ROW_STORE);
 | |
|   table_schema.set_storage_format_version(ObStorageFormatVersion::OB_STORAGE_FORMAT_VERSION_V4);
 | |
| 
 | |
| #define ADD_COLUMN(column_id, column_name, data_type, collation_type, is_row_key) \
 | |
|   { \
 | |
|     ObColumnSchemaV2 column; \
 | |
|     column.set_tenant_id(tenant_id); \
 | |
|     column.set_column_id(column_id); \
 | |
|     column.set_column_name(column_name); \
 | |
|     column.set_data_type(data_type); \
 | |
|     column.set_collation_type(collation_type); \
 | |
|     if (is_row_key) { \
 | |
|       column.set_rowkey_position(1); \
 | |
|     } \
 | |
|     table_schema.add_column(column); \
 | |
|   }
 | |
| 
 | |
|   // table schema
 | |
|   // a(bigint)  b(bigint)  c(bigint)  d(varchar)  e(varchar)
 | |
|   ADD_COLUMN(OB_APP_MIN_COLUMN_ID + 0, "a", ObIntType, CS_TYPE_UTF8MB4_GENERAL_CI, true);
 | |
|   ADD_COLUMN(OB_APP_MIN_COLUMN_ID + 1, "b", ObIntType, CS_TYPE_UTF8MB4_GENERAL_CI, false);
 | |
|   ADD_COLUMN(OB_APP_MIN_COLUMN_ID + 2, "c", ObIntType, CS_TYPE_UTF8MB4_GENERAL_CI, false);
 | |
|   ADD_COLUMN(OB_APP_MIN_COLUMN_ID + 3, "d", ObVarcharType, CS_TYPE_UTF8MB4_BIN, false);
 | |
|   ADD_COLUMN(OB_APP_MIN_COLUMN_ID + 4, "e", ObVarcharType, CS_TYPE_UTF8MB4_BIN, false);
 | |
| #undef ADD_COLUMN
 | |
| }
 | |
| 
 | |
| void TestDmlCommon::build_index_table_schema(
 | |
|     const uint64_t tenant_id,
 | |
|     share::schema::ObTableSchema &table_schema)
 | |
| {
 | |
|   const uint64_t data_table_id = TEST_DATA_TABLE_ID;
 | |
|   const uint64_t index_table_id = TEST_INDEX_TABLE_ID;
 | |
|   const int64_t micro_block_size = 16 * 1024;
 | |
| 
 | |
|   table_schema.reset();
 | |
|   table_schema.set_table_name("test_dml_common_index");
 | |
|   table_schema.set_tenant_id(tenant_id);
 | |
|   table_schema.set_tablegroup_id(1);
 | |
|   table_schema.set_database_id(1);
 | |
|   table_schema.set_data_table_id(data_table_id);
 | |
|   table_schema.set_table_id(index_table_id);
 | |
|   table_schema.set_index_type(ObIndexType::INDEX_TYPE_NORMAL_LOCAL);
 | |
|   table_schema.set_rowkey_column_num(1);
 | |
|   table_schema.set_max_used_column_id(ObObjType::ObExtendType - 1);
 | |
|   table_schema.set_block_size(micro_block_size);
 | |
|   table_schema.set_row_store_type(ObRowStoreType::ENCODING_ROW_STORE);
 | |
|   table_schema.set_storage_format_version(ObStorageFormatVersion::OB_STORAGE_FORMAT_VERSION_V4);
 | |
| 
 | |
|   // add index column: a
 | |
|   {
 | |
|     ObColumnSchemaV2 column;
 | |
|     column.set_tenant_id(tenant_id);
 | |
|     column.set_column_id(OB_APP_MIN_COLUMN_ID);
 | |
|     column.set_column_name("index_a");
 | |
|     column.set_data_type(ObIntType);
 | |
|     column.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
 | |
|     column.set_rowkey_position(1);
 | |
|     table_schema.add_column(column);
 | |
|   }
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::build_tx_desc(const uint64_t tenant_id, ObTxDesc *&tx_desc)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   transaction::ObTransService *tx_service = MTL(transaction::ObTransService*);
 | |
|   if (OB_FAIL(tx_service->acquire_tx(tx_desc, 100))) {
 | |
|     STORAGE_LOG(WARN, "failed to acquire tx", K(ret));
 | |
|   } else {
 | |
|     STORAGE_LOG(INFO, "acquired tx desc", KPC(tx_desc));
 | |
|   }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void TestDmlCommon::build_tx_param(ObTxParam &tx_param)
 | |
| {
 | |
|   tx_param.access_mode_ = transaction::ObTxAccessMode::RW;
 | |
|   tx_param.isolation_ = transaction::ObTxIsolationLevel::RC;
 | |
|   tx_param.cluster_id_ = 1221;
 | |
|   tx_param.timeout_us_ = TX_EXPIRE_TIME_US;
 | |
|   STORAGE_LOG(INFO, "build tx param", K(tx_param));
 | |
| }
 | |
| 
 | |
| void TestDmlCommon::release_tx_desc(ObTxDesc &tx_desc)
 | |
| {
 | |
|   transaction::ObTransService *tx_service = MTL(transaction::ObTransService*);
 | |
|   tx_service->release_tx(tx_desc);
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::build_pure_data_tablet_arg(
 | |
|     const uint64_t tenant_id,
 | |
|     const share::ObLSID &ls_id,
 | |
|     const common::ObTabletID &data_tablet_id,
 | |
|     obrpc::ObBatchCreateTabletArg &arg)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   ObCreateTabletInfo tablet_info;
 | |
|   ObArray<common::ObTabletID> tablet_id_array;
 | |
|   ObArray<int64_t> tablet_schema_index_array;
 | |
|   share::schema::ObTableSchema table_schema;
 | |
|   build_data_table_schema(tenant_id, table_schema);
 | |
| 
 | |
|   arg.reset();
 | |
|   if (OB_FAIL(tablet_id_array.push_back(data_tablet_id))) {
 | |
|     STORAGE_LOG(WARN, "failed to push tablet id into array", K(ret), K(data_tablet_id));
 | |
|   } else if (OB_FAIL(tablet_schema_index_array.push_back(0))) {
 | |
|     STORAGE_LOG(WARN, "failed to push index into array", K(ret));
 | |
|   } else if (OB_FAIL(tablet_info.init(tablet_id_array, data_tablet_id, tablet_schema_index_array, lib::Worker::CompatMode::MYSQL, false))) {
 | |
|     STORAGE_LOG(WARN, "failed to init tablet info", K(ret), K(tablet_id_array),
 | |
|         K(data_tablet_id), K(tablet_schema_index_array));
 | |
|   } else if (OB_FAIL(arg.init_create_tablet(ls_id, share::SCN::min_scn(), false/*need_check_tablet_cnt*/))) {
 | |
|     STORAGE_LOG(WARN, "failed to init create tablet", K(ret), K(tenant_id), K(ls_id));
 | |
|   } else if (OB_FAIL(arg.table_schemas_.push_back(table_schema))) {
 | |
|     STORAGE_LOG(WARN, "failed to push back table schema", K(ret), K(table_schema));
 | |
|   } else if (OB_FAIL(arg.tablets_.push_back(tablet_info))) {
 | |
|     STORAGE_LOG(WARN, "failed to push back tablet info", K(ret), K(tablet_info));
 | |
|   }
 | |
| 
 | |
|   if (OB_FAIL(ret)) {
 | |
|     arg.reset();
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int TestDmlCommon::build_mixed_tablets_arg(
 | |
|     const uint64_t tenant_id,
 | |
|     const share::ObLSID &ls_id,
 | |
|     const common::ObTabletID &data_tablet_id,
 | |
|     const common::ObIArray<common::ObTabletID> &index_tablet_id_array,
 | |
|     obrpc::ObBatchCreateTabletArg &arg)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   ObCreateTabletInfo tablet_info;
 | |
|   ObArray<common::ObTabletID> tablet_id_array;
 | |
|   ObArray<int64_t> tablet_schema_index_array;
 | |
|   share::schema::ObTableSchema data_table_schema;
 | |
|   share::schema::ObTableSchema index_table_schema;
 | |
|   build_data_table_schema(tenant_id, data_table_schema);
 | |
|   build_index_table_schema(tenant_id, index_table_schema);
 | |
| 
 | |
|   arg.reset();
 | |
|   if (OB_FAIL(tablet_id_array.push_back(data_tablet_id))) {
 | |
|     STORAGE_LOG(WARN, "failed to push tablet id into array", K(ret), K(data_tablet_id));
 | |
|   } else {
 | |
|     for (int64_t i = 0; OB_SUCC(ret) && i < index_tablet_id_array.count(); ++i) {
 | |
|       const common::ObTabletID &index_tablet_id = index_tablet_id_array.at(i);
 | |
|       if (OB_FAIL(tablet_id_array.push_back(index_tablet_id))) {
 | |
|         STORAGE_LOG(WARN, "failed to push back index tablet id", K(ret), K(index_tablet_id));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OB_FAIL(ret)) {
 | |
|   } else if (OB_FAIL(tablet_schema_index_array.push_back(0))) {
 | |
|     STORAGE_LOG(WARN, "failed to push index into array", K(ret));
 | |
|   } else if (OB_FAIL(tablet_schema_index_array.push_back(1))) {
 | |
|     STORAGE_LOG(WARN, "failed to push index into array", K(ret));
 | |
|   } else if (OB_FAIL(tablet_info.init(tablet_id_array, data_tablet_id, tablet_schema_index_array, lib::Worker::CompatMode::MYSQL, false))) {
 | |
|     STORAGE_LOG(WARN, "failed to init tablet info", K(ret), K(tablet_id_array),
 | |
|         K(data_tablet_id), K(tablet_schema_index_array));
 | |
|   } else if (OB_FAIL(arg.init_create_tablet(ls_id, share::SCN::min_scn(), false/*need_check_tablet_cnt*/))) {
 | |
|     STORAGE_LOG(WARN, "failed to init create tablet", K(ret), K(tenant_id), K(ls_id));
 | |
|   } else if (OB_FAIL(arg.table_schemas_.push_back(data_table_schema))) {
 | |
|     STORAGE_LOG(WARN, "failed to push back data table schema", K(ret), K(data_table_schema));
 | |
|   } else if (OB_FAIL(arg.table_schemas_.push_back(index_table_schema))) {
 | |
|     STORAGE_LOG(WARN, "failed to push back index table schema", K(ret), K(index_table_schema));
 | |
|   } else if (OB_FAIL(arg.tablets_.push_back(tablet_info))) {
 | |
|     STORAGE_LOG(WARN, "failed to push back tablet info", K(ret), K(tablet_info));
 | |
|   }
 | |
| 
 | |
|   if (OB_FAIL(ret)) {
 | |
|     arg.reset();
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| } // namespace storage
 | |
| } // namespace oceanbase
 |