diff --git a/src/sql/optimizer/ob_del_upd_log_plan.cpp b/src/sql/optimizer/ob_del_upd_log_plan.cpp index 520d7a6f47..637566ac04 100644 --- a/src/sql/optimizer/ob_del_upd_log_plan.cpp +++ b/src/sql/optimizer/ob_del_upd_log_plan.cpp @@ -329,8 +329,12 @@ int ObDelUpdLogPlan::calculate_insert_table_location_and_sharding(ObTablePartiti &dml_table_infos.at(0)->part_ids_, insert_sharding, insert_table_part))) { - if (ret == OB_NO_PARTITION_FOR_GIVEN_VALUE && - (trigger_exist || (del_upd_stmt->is_insert_stmt() && static_cast(del_upd_stmt)->value_from_select()))) { + if (ret != OB_NO_PARTITION_FOR_GIVEN_VALUE) { + LOG_WARN("failed to calculate table location and sharding", K(ret)); + } else if (del_upd_stmt->is_merge_stmt()) { + insert_sharding = NULL; // get null insert sharding, use multi part merge into + ret = OB_SUCCESS; + } else if (trigger_exist || (del_upd_stmt->is_insert_stmt() && static_cast(del_upd_stmt)->value_from_select())) { ret = OB_SUCCESS; } else { LOG_WARN("failed to calculate table location and sharding", K(ret)); @@ -361,6 +365,7 @@ int ObDelUpdLogPlan::calculate_table_location_and_sharding(const ObDelUpdStmt &s table_partition_info = new(table_partition_info) ObTablePartitionInfo(allocator_); ObTableLocationType location_type = OB_TBL_LOCATION_UNINITIALIZED; ObAddr &server = get_optimizer_context().get_local_server_addr(); + table_partition_info->get_table_location().set_check_no_partiton(stmt.is_merge_stmt()); if (OB_FAIL(calculate_table_location(stmt, filters, table_id, diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index a61c448853..2406343f00 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -11882,21 +11882,42 @@ int ObLogPlan::collect_table_location(ObLogicalOperator *op) } else if (OB_FAIL(add_global_table_partition_info(table_partition_info))) { LOG_WARN("failed to add table partition info", K(ret)); } else { /*do nothing*/ } - } else if ((log_op_def::LOG_INSERT == op->get_type() || - log_op_def::LOG_MERGE == op->get_type()) && - !static_cast(op)->has_instead_of_trigger() && - static_cast(op)->is_insert_select()) { + } else if (log_op_def::LOG_INSERT == op->get_type() + && static_cast(op)->is_insert_select() + && !static_cast(op)->has_instead_of_trigger()) { ObLogInsert *insert_op = static_cast(op); ObTablePartitionInfo *table_partition_info = insert_op->get_table_partition_info(); if (OB_ISNULL(table_partition_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(table_partition_info), K(ret)); - } else if ((!insert_op->is_multi_part_dml() || - ObPhyPlanType::OB_PHY_PLAN_DISTRIBUTED == insert_op->get_phy_plan_type())) { + } else if (!insert_op->is_multi_part_dml() || + ObPhyPlanType::OB_PHY_PLAN_DISTRIBUTED == insert_op->get_phy_plan_type()) { if (OB_FAIL(add_global_table_partition_info(table_partition_info))) { LOG_WARN("failed to add table partition info", K(ret)); } else { /*do nothing*/ } } else { /*do nothing*/ } + } else if (log_op_def::LOG_MERGE == op->get_type() + && !static_cast(op)->has_instead_of_trigger()) { + ObLogDelUpd *dml_op = static_cast(op); + ObTablePartitionInfo *table_partition_info = dml_op->get_table_partition_info(); + const ObOptimizerContext &opt_ctx = get_optimizer_context(); + if (OB_ISNULL(table_partition_info) || OB_ISNULL(opt_ctx.get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(table_partition_info), K(opt_ctx.get_query_ctx()), K(ret)); + } else if (!dml_op->is_multi_part_dml()) { + /* for merge into view, additional table location for insert sharding need add + create table tp1(c1 int, c2 int, c3 int) partition by hash(c1) partitions 2; + create table tp2(c1 int, c2 int, c3 int) partition by hash(c1) partitions 2; + create or replace view v as select * from tp1 where c1 = 3; + merge into v v1 using (select * from tp2 where c1 = 2) t2 on (v1.c1 = t2.c1) + when matched then update set v1.c2 = t2.c1 + 100 + when not matched then insert values (t2.c1, t2.c2, t2.c3); + */ + table_partition_info->get_table_location().set_table_id(opt_ctx.get_query_ctx()->available_tb_id_ - 1); + if (OB_FAIL(add_global_table_partition_info(table_partition_info))) { + LOG_WARN("failed to add table partition info", K(ret)); + } + } else { /*do nothing*/ } } else { /*do nothing*/ } if (OB_SUCC(ret) && OB_FAIL(collect_location_related_info(*op))) { LOG_WARN("collect location related info failed", K(ret)); diff --git a/src/sql/optimizer/ob_table_location.cpp b/src/sql/optimizer/ob_table_location.cpp index f998177f7c..5d7aaacde7 100644 --- a/src/sql/optimizer/ob_table_location.cpp +++ b/src/sql/optimizer/ob_table_location.cpp @@ -725,6 +725,7 @@ int ObTableLocation::assign(const ObTableLocation &other) is_non_partition_optimized_ = other.is_non_partition_optimized_; tablet_id_ = other.tablet_id_; object_id_ = other.object_id_; + check_no_partiton_ = other.check_no_partiton_; if (OB_FAIL(loc_meta_.assign(other.loc_meta_))) { LOG_WARN("assign loc meta failed", K(ret), K(other.loc_meta_)); } @@ -852,6 +853,7 @@ void ObTableLocation::reset() is_non_partition_optimized_ = false; tablet_id_.reset(); object_id_ = OB_INVALID_ID; + check_no_partiton_ = false; } int ObTableLocation::init(share::schema::ObSchemaGetterGuard &schema_guard, const ObDMLStmt &stmt, @@ -1700,7 +1702,9 @@ int ObTableLocation::calculate_tablet_ids(ObExecContext &exec_ctx, if ( OB_SUCC(ret) && 0 == partition_ids.count() - && (stmt::T_INSERT == stmt_type_ || stmt::T_REPLACE == stmt_type_)) { + && (stmt::T_INSERT == stmt_type_ + || stmt::T_REPLACE == stmt_type_ + || check_no_partiton_)) { ret = OB_NO_PARTITION_FOR_GIVEN_VALUE; LOG_USER_WARN(OB_NO_PARTITION_FOR_GIVEN_VALUE); } @@ -4739,6 +4743,7 @@ OB_DEF_SERIALIZE(ObTableLocation) OB_UNIS_ENCODE(object_id_); OB_UNIS_ENCODE(related_list_); OB_UNIS_ENCODE(table_type_); + OB_UNIS_ENCODE(check_no_partiton_); return ret; } @@ -4816,6 +4821,7 @@ OB_DEF_SERIALIZE_SIZE(ObTableLocation) OB_UNIS_ADD_LEN(object_id_); OB_UNIS_ADD_LEN(related_list_); OB_UNIS_ADD_LEN(table_type_); + OB_UNIS_ADD_LEN(check_no_partiton_); return len; } @@ -4971,6 +4977,7 @@ OB_DEF_DESERIALIZE(ObTableLocation) OB_UNIS_DECODE(object_id_); OB_UNIS_DECODE(related_list_); OB_UNIS_DECODE(table_type_); + OB_UNIS_DECODE(check_no_partiton_); return ret; } diff --git a/src/sql/optimizer/ob_table_location.h b/src/sql/optimizer/ob_table_location.h index c68e392c80..04b8f1c2e7 100644 --- a/src/sql/optimizer/ob_table_location.h +++ b/src/sql/optimizer/ob_table_location.h @@ -497,7 +497,8 @@ public: is_non_partition_optimized_(false), tablet_id_(ObTabletID::INVALID_TABLET_ID), object_id_(OB_INVALID_ID), - related_list_(allocator_) + related_list_(allocator_), + check_no_partiton_(false) { } @@ -545,7 +546,8 @@ public: is_non_partition_optimized_(false), tablet_id_(ObTabletID::INVALID_TABLET_ID), object_id_(OB_INVALID_ID), - related_list_(allocator_) + related_list_(allocator_), + check_no_partiton_(false) { } virtual ~ObTableLocation() { reset(); } @@ -768,7 +770,10 @@ public: const bool is_dml_table = true); int calc_not_partitioned_table_ids(ObExecContext &exec_ctx); - + void set_check_no_partiton(const bool check) + { + check_no_partiton_ = check; + } TO_STRING_KV(K_(loc_meta), K_(part_projector), K_(has_dynamic_exec_param), @@ -1165,6 +1170,7 @@ private: ObTabletID tablet_id_; ObObjectID object_id_; common::ObList related_list_; + bool check_no_partiton_; }; }