Files
oceanbase/src/sql/optimizer/ob_merge_log_plan.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

572 lines
28 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.
*/
#define USING_LOG_PREFIX SQL_OPT
#include "sql/resolver/dml/ob_merge_stmt.h"
#include "sql/optimizer/ob_log_merge.h"
#include "sql/optimizer/ob_merge_log_plan.h"
#include "sql/optimizer/ob_log_operator_factory.h"
#include "sql/optimizer/ob_log_plan_factory.h"
#include "sql/optimizer/ob_select_log_plan.h"
#include "sql/optimizer/ob_log_expr_values.h"
#include "sql/optimizer/ob_log_append.h"
#include "sql/rewrite/ob_transform_utils.h"
using namespace oceanbase;
using namespace sql;
using namespace oceanbase::common;
using namespace oceanbase::sql::log_op_def;
int ObMergeLogPlan::generate_raw_plan()
{
int ret = OB_SUCCESS;
ObLogicalOperator* best_plan = NULL;
if (OB_FAIL(generate_plan_tree())) {
LOG_WARN("fail to generate plan tree", K(ret));
} else if (OB_FAIL(allocate_merge_subquery())) {
LOG_WARN("failed to allocate merge subquery", K(ret));
} else if (OB_FAIL(get_current_best_plan(best_plan))) {
LOG_WARN("failed to get best plan", K(ret));
} else if (OB_FAIL(allocate_merge_operator_as_top(best_plan))) {
LOG_WARN("fail to allocate merge operator", K(ret));
} else if (OB_FAIL(set_final_plan_root(best_plan))) {
LOG_WARN("failed to use final plan", K(ret));
} else { /*do nothing*/
}
return ret;
}
int ObMergeLogPlan::generate_plan()
{
int ret = OB_SUCCESS;
ObLogicalOperator* best_plan = NULL;
ObMergeStmt* merge_stmt = NULL;
if (OB_FAIL(generate_raw_plan())) {
LOG_WARN("failed to generate raw plan", K(ret));
} else if (OB_ISNULL(best_plan = get_plan_root()) || OB_ISNULL(stmt_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", KP(stmt_), KP(best_plan), K(ret));
} else if (OB_FAIL(best_plan->adjust_parent_child_relationship())) {
LOG_WARN("failed to adjust parent-child relationship", K(ret));
} else {
ObLogMerge* merge_op = static_cast<ObLogMerge*>(best_plan);
// init multi table assign info
merge_stmt = static_cast<ObMergeStmt*>(const_cast<ObDMLStmt*>(stmt_));
const ObTablesAssignments& table_assign = merge_stmt->get_tables_assignments();
ObIArray<TableColumns>& table_columns = merge_stmt->get_all_table_columns();
CK(table_columns.count() == 1);
CK(OB_NOT_NULL(optimizer_context_.get_session_info()));
if (OB_SUCC(ret) && OB_LIKELY(table_assign.count() == 1)) {
ObIArray<IndexDMLInfo>& index_infos = table_columns.at(0).index_dml_infos_;
for (int64_t i = 0; OB_SUCC(ret) && i < index_infos.count(); i++) {
if (OB_FAIL(index_infos.at(i).init_assignment_info(table_assign.at(0).assignments_))) {
LOG_WARN("init index assignment info failed", K(ret));
} else if (optimizer_context_.get_session_info()->use_static_typing_engine()) {
if (OB_FAIL(index_infos.at(i).add_spk_assignment_info(optimizer_context_.get_expr_factory()))) {
LOG_WARN("fail to add spk assignment info", K(ret));
}
}
}
}
}
if (OB_FAIL(ret)) {
// do nothing
} else if (OB_FAIL(plan_traverse_loop(ALLOC_LINK,
ALLOC_EXCH,
ALLOC_GI,
ADJUST_SORT_OPERATOR,
PX_PIPE_BLOCKING,
PX_RESCAN,
RE_CALC_OP_COST,
ALLOC_MONITORING_DUMP,
OPERATOR_NUMBERING,
EXCHANGE_NUMBERING,
ALLOC_EXPR,
PROJECT_PRUNING,
ALLOC_DUMMY_OUTPUT,
CG_PREPARE,
GEN_SIGNATURE,
GEN_LOCATION_CONSTRAINT,
GEN_LINK_STMT))) {
LOG_WARN("fail to travers logical plan", K(ret));
} else if (location_type_ != ObPhyPlanType::OB_PHY_PLAN_UNCERTAIN) {
location_type_ = phy_plan_type_;
}
if (OB_SUCC(ret)) {
if (OB_FAIL(calc_plan_resource())) {
LOG_WARN("fail calc plan resource", K(ret));
}
}
return ret;
}
int ObMergeLogPlan::allocate_merge_subquery()
{
int ret = OB_SUCCESS;
ObRawExpr* null_expr = NULL;
ObRawExpr* matched_expr = NULL;
bool update_has_subquery = false;
bool insert_has_subquery = false;
ObSEArray<ObRawExpr*, 8> condition_subquery_exprs;
ObSEArray<ObRawExpr*, 8> target_subquery_exprs;
ObSEArray<ObRawExpr*, 8> delete_subquery_exprs;
ObMergeStmt* merge_stmt = static_cast<ObMergeStmt*>(const_cast<ObDMLStmt*>(stmt_));
if (OB_ISNULL(merge_stmt) || OB_ISNULL(optimizer_context_.get_session_info())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(merge_stmt), K(optimizer_context_.get_session_info()), K(ret));
} else if (merge_stmt->get_subquery_exprs().empty()) {
/*do nothing*/
} else if (OB_FAIL(ObRawExprUtils::build_null_expr(get_optimizer_context().get_expr_factory(), null_expr))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(
get_optimizer_context().get_expr_factory(), merge_stmt->get_match_condition_exprs(), matched_expr))) {
LOG_WARN("failed to build matched expr", K(ret));
} else if (OB_ISNULL(null_expr) || OB_ISNULL(matched_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null expr", K(null_expr), K(matched_expr), K(ret));
} else if (OB_FAIL(get_update_insert_condition_subquery(
matched_expr, null_expr, update_has_subquery, insert_has_subquery, condition_subquery_exprs))) {
LOG_WARN("failed to allocate update insert condition subquery", K(ret));
} else if (OB_FAIL(get_update_insert_target_subquery(
matched_expr, null_expr, update_has_subquery, insert_has_subquery, target_subquery_exprs))) {
LOG_WARN("failed to allocate update insert target subquery", K(ret));
} else if (OB_FAIL(
get_delete_condition_subquery(matched_expr, null_expr, update_has_subquery, delete_subquery_exprs))) {
LOG_WARN("failed to allocate delete condition subquery", K(ret));
} else if (OB_FAIL(merge_stmt->formalize_stmt_expr_reference())) {
LOG_WARN("failed to formalize stmt expr reference", K(ret));
} else if (!condition_subquery_exprs.empty() &&
OB_FAIL(candi_allocate_subplan_filter(condition_subquery_exprs, false))) {
LOG_WARN("failed to allocate subplan filter", K(ret));
} else if (OB_FAIL(find_and_replace_onetime_expr_with_param(get_onetime_exprs(), target_subquery_exprs))) {
LOG_WARN("failed to find and replace onetime expr", K(ret));
} else if (!target_subquery_exprs.empty() && OB_FAIL(candi_allocate_subplan_filter(target_subquery_exprs, false))) {
LOG_WARN("failed to allocate subplan filter", K(ret));
} else if (OB_FAIL(find_and_replace_onetime_expr_with_param(get_onetime_exprs(), delete_subquery_exprs))) {
LOG_WARN("failed to find and replace onetime expr", K(ret));
} else if (!delete_subquery_exprs.empty() && OB_FAIL(candi_allocate_subplan_filter(delete_subquery_exprs, false))) {
LOG_WARN("failed to allocate subplan filter", K(ret));
} else { /*do nothing*/
}
return ret;
}
int ObMergeLogPlan::get_update_insert_condition_subquery(ObRawExpr* matched_expr, ObRawExpr* null_expr,
bool& update_has_subquery, bool& insert_has_subquery, ObIArray<ObRawExpr*>& new_subquery_exprs)
{
int ret = OB_SUCCESS;
ObMergeStmt* merge_stmt = static_cast<ObMergeStmt*>(const_cast<ObDMLStmt*>(stmt_));
update_has_subquery = false;
insert_has_subquery = false;
if (OB_ISNULL(merge_stmt) || OB_ISNULL(get_optimizer_context().get_session_info())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(merge_stmt), K(ret));
} else if (OB_FAIL(ObOptimizerUtil::check_expr_contain_subquery(
merge_stmt->get_update_condition_exprs(), NULL, update_has_subquery))) {
LOG_WARN("failed to check whether expr contain subquery", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::check_expr_contain_subquery(
merge_stmt->get_insert_condition_exprs(), NULL, insert_has_subquery))) {
LOG_WARN("failed to check whether expr contain subquery", K(ret));
} else if (update_has_subquery && OB_FAIL(generate_merge_conditions_subquery(
matched_expr, null_expr, true, merge_stmt->get_update_condition_exprs()))) {
LOG_WARN("failed to generate condition subquery", K(ret));
} else if (insert_has_subquery && OB_FAIL(generate_merge_conditions_subquery(
matched_expr, null_expr, false, merge_stmt->get_insert_condition_exprs()))) {
LOG_WARN("failed to generate condition subquery", K(ret));
} else if (update_has_subquery && OB_FAIL(append(new_subquery_exprs, merge_stmt->get_update_condition_exprs()))) {
LOG_WARN("failed to append subquery exprs", K(ret));
} else if (insert_has_subquery && OB_FAIL(append(new_subquery_exprs, merge_stmt->get_insert_condition_exprs()))) {
LOG_WARN("failed to append subquery exprs", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < new_subquery_exprs.count(); i++) {
ObRawExpr* raw_expr = NULL;
if (OB_ISNULL(raw_expr = new_subquery_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(raw_expr->formalize(optimizer_context_.get_session_info()))) {
LOG_WARN("failed to formalize case expr", K(ret));
} else if (OB_FAIL(raw_expr->pull_relation_id_and_levels(merge_stmt->get_current_level()))) {
LOG_WARN("failed to pull relation id and levels", K(ret));
} else { /*do nothing*/
}
}
}
return ret;
}
int ObMergeLogPlan::get_update_insert_target_subquery(ObRawExpr* matched_expr, ObRawExpr* null_expr,
bool update_has_subquery, bool insert_has_subquery, ObIArray<ObRawExpr*>& new_subquery_exprs)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 8> temp_exprs;
ObSEArray<ObRawExpr*, 8> assign_exprs;
ObSEArray<ObRawExpr*, 8> update_subquery_exprs;
ObSEArray<ObRawExpr*, 8> insert_values_subquery_exprs;
ObMergeStmt* merge_stmt = static_cast<ObMergeStmt*>(const_cast<ObDMLStmt*>(stmt_));
if (OB_ISNULL(merge_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(merge_stmt->get_tables_assignments_exprs(assign_exprs))) {
LOG_WARN("failed to get table assignment exprs", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::get_subquery_exprs(assign_exprs, update_subquery_exprs))) {
LOG_WARN("failed to get subquery exprs", K(ret));
} else if (OB_FAIL(
ObOptimizerUtil::get_subquery_exprs(merge_stmt->get_value_vectors(), insert_values_subquery_exprs))) {
LOG_WARN("failed to get subquery exprs", K(ret));
} else {
if (!update_subquery_exprs.empty()) {
ObRawExpr* update_matched_expr = NULL;
if (merge_stmt->get_update_condition_exprs().empty()) {
update_matched_expr = matched_expr;
} else if (update_has_subquery) {
if (OB_UNLIKELY(1 != merge_stmt->get_update_condition_exprs().count()) ||
OB_ISNULL(merge_stmt->get_update_condition_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret));
} else {
update_matched_expr = merge_stmt->get_update_condition_exprs().at(0);
}
} else if (OB_FAIL(append(temp_exprs, merge_stmt->get_match_condition_exprs()) ||
OB_FAIL(append(temp_exprs, merge_stmt->get_update_condition_exprs())))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(
get_optimizer_context().get_expr_factory(), temp_exprs, update_matched_expr))) {
LOG_WARN("failed to build and expr", K(ret));
} else if (OB_ISNULL(update_matched_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else { /*do nothing*/
}
for (int64_t i = 0; OB_SUCC(ret) && i < update_subquery_exprs.count(); i++) {
ObRawExpr* raw_expr = NULL;
ObRawExpr* case_when_expr = NULL;
if (OB_ISNULL(raw_expr = update_subquery_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(get_optimizer_context().get_expr_factory(),
update_matched_expr,
raw_expr,
null_expr,
case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_ISNULL(case_when_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(new_subquery_exprs.push_back(case_when_expr))) {
LOG_WARN("failed to push back case when expr", K(ret));
} else { /*do nothing*/
}
}
}
if (OB_SUCC(ret) && !insert_values_subquery_exprs.empty()) {
ObRawExpr* insert_matched_expr = NULL;
ObRawExpr* condition_expr = NULL;
if (merge_stmt->get_insert_condition_exprs().empty()) {
insert_matched_expr = matched_expr;
} else if (insert_has_subquery) {
if (OB_UNLIKELY(1 != merge_stmt->get_insert_condition_exprs().count()) ||
OB_ISNULL(merge_stmt->get_insert_condition_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
insert_matched_expr = merge_stmt->get_insert_condition_exprs().at(0);
}
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(get_optimizer_context().get_expr_factory(),
merge_stmt->get_insert_condition_exprs(),
condition_expr))) {
LOG_WARN("failed to build and expr", K(ret));
} else if (OB_ISNULL(condition_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(get_optimizer_context().get_expr_factory(),
matched_expr,
null_expr,
condition_expr,
insert_matched_expr))) {
LOG_WARN("failed to build and expr", K(ret));
} else if (OB_ISNULL(insert_matched_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else { /*do nothing*/
}
for (int64_t i = 0; OB_SUCC(ret) && i < insert_values_subquery_exprs.count(); i++) {
ObRawExpr* raw_expr = NULL;
ObRawExpr* case_when_expr = NULL;
if (OB_ISNULL(raw_expr = insert_values_subquery_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (merge_stmt->get_insert_condition_exprs().empty() &&
OB_FAIL(ObRawExprUtils::build_case_when_expr(get_optimizer_context().get_expr_factory(),
insert_matched_expr,
null_expr,
raw_expr,
case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (!merge_stmt->get_insert_condition_exprs().empty() &&
OB_FAIL(ObRawExprUtils::build_case_when_expr(get_optimizer_context().get_expr_factory(),
insert_matched_expr,
raw_expr,
null_expr,
case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_ISNULL(case_when_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(new_subquery_exprs.push_back(case_when_expr))) {
LOG_WARN("failed to push back subquery exprs", K(ret));
} else { /*do nothing*/
}
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < new_subquery_exprs.count(); i++) {
ObRawExpr* raw_expr = NULL;
if (OB_ISNULL(raw_expr = new_subquery_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(raw_expr->formalize(optimizer_context_.get_session_info()))) {
LOG_WARN("failed to formalize case expr", K(ret));
} else if (OB_FAIL(raw_expr->pull_relation_id_and_levels(merge_stmt->get_current_level()))) {
LOG_WARN("failed to pull relation id and levels", K(ret));
} else { /*do nothing*/
}
}
if (OB_SUCC(ret) && !new_subquery_exprs.empty()) {
ObSEArray<ObRawExpr*, 8> old_subquery_exprs;
if (OB_FAIL(append(old_subquery_exprs, update_subquery_exprs)) ||
OB_FAIL(append(old_subquery_exprs, insert_values_subquery_exprs))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_UNLIKELY(old_subquery_exprs.count() != new_subquery_exprs.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected array count", K(old_subquery_exprs.count()), K(new_subquery_exprs.count()), K(ret));
} else if (OB_FAIL(merge_stmt->replace_inner_stmt_expr(old_subquery_exprs, new_subquery_exprs))) {
LOG_WARN("failed to replace merge stmt", K(ret));
} else { /*do nothing*/
}
}
}
return ret;
}
int ObMergeLogPlan::get_delete_condition_subquery(
ObRawExpr* matched_expr, ObRawExpr* null_expr, bool update_has_subquery, ObIArray<ObRawExpr*>& new_subquery_exprs)
{
int ret = OB_SUCCESS;
bool delete_has_subquery = false;
ObMergeStmt* merge_stmt = static_cast<ObMergeStmt*>(const_cast<ObDMLStmt*>(stmt_));
if (OB_ISNULL(merge_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::check_expr_contain_subquery(
merge_stmt->get_delete_condition_exprs(), NULL, delete_has_subquery))) {
LOG_WARN("failed to check whether expr contain subquery", K(ret));
} else if (!delete_has_subquery) {
/*do nothing*/
} else {
ObSqlBitSet<> check_table_set;
ObSEArray<ObRawExpr*, 8> temp_exprs;
ObSEArray<ObDMLStmt*, 2> ignore_stmts;
ObRawExpr* delete_matched_expr = NULL;
ObSEArray<ObRawExpr*, 8> delete_column_exprs;
if (OB_FAIL(check_table_set.add_member(merge_stmt->get_table_bit_index(merge_stmt->get_target_table_id())))) {
LOG_WARN("failed to add table set", K(ret));
} else if (OB_FAIL(ObTransformUtils::extract_column_exprs(merge_stmt->get_delete_condition_exprs(),
merge_stmt->get_current_level(),
check_table_set,
ignore_stmts,
delete_column_exprs))) {
LOG_WARN("failed to extract column exprs", K(ret));
} else if (delete_column_exprs.empty()) {
/*do nothing*/
} else {
ObSEArray<ObRawExpr*, 8> old_exprs;
ObSEArray<ObRawExpr*, 8> new_exprs;
ObSEArray<ObQueryRefRawExpr*, 8> temp_subquery_exprs;
ObTablesAssignments& assignments = merge_stmt->get_table_assignments();
for (int64_t i = 0; OB_SUCC(ret) && i < assignments.count(); i++) {
ObAssignments& table_assigns = assignments.at(i).assignments_;
for (int64_t j = 0; OB_SUCC(ret) && j < table_assigns.count(); j++) {
if (OB_ISNULL(table_assigns.at(j).column_expr_) || OB_ISNULL(table_assigns.at(j).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (!ObOptimizerUtil::find_item(delete_column_exprs, table_assigns.at(j).column_expr_)) {
/*do nothing*/
} else if (table_assigns.at(j).expr_->has_flag(CNT_SUB_QUERY)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("not support replace column expr with subquery expr", K(ret));
} else if (OB_FAIL(old_exprs.push_back(table_assigns.at(j).column_expr_)) ||
OB_FAIL(new_exprs.push_back(table_assigns.at(j).expr_))) {
LOG_WARN("failed to push back exprs", K(ret));
} else { /*do nothing*/
}
}
}
if (OB_FAIL(ret)) {
/*do nothing*/
} else if (OB_FAIL(ObTransformUtils::extract_query_ref_expr(
merge_stmt->get_delete_condition_exprs(), temp_subquery_exprs))) {
LOG_WARN("failed to extract query ref exprs", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < merge_stmt->get_delete_condition_exprs().count(); i++) {
if (OB_FAIL(ObTransformUtils::replace_expr(
old_exprs, new_exprs, merge_stmt->get_delete_condition_exprs().at(i)))) {
LOG_WARN("failed to replace expr", K(ret));
} else { /*do nothing*/
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < temp_subquery_exprs.count(); i++) {
ObSelectStmt* ref_stmt = NULL;
if (OB_ISNULL(temp_subquery_exprs.at(i)) || OB_ISNULL(ref_stmt = temp_subquery_exprs.at(i)->get_ref_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(temp_subquery_exprs.at(i)), K(ref_stmt), K(ret));
} else if (OB_FAIL(ref_stmt->replace_inner_stmt_expr(old_exprs, new_exprs))) {
LOG_WARN("failed to replace stmt expr", K(ret));
} else { /*do nothing*/
}
}
}
}
if (OB_FAIL(ret)) {
/*do nothing*/
} else if (merge_stmt->get_update_condition_exprs().empty()) {
delete_matched_expr = matched_expr;
} else if (update_has_subquery) {
if (OB_UNLIKELY(1 != merge_stmt->get_update_condition_exprs().count()) ||
OB_ISNULL(merge_stmt->get_update_condition_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret));
} else {
delete_matched_expr = merge_stmt->get_update_condition_exprs().at(0);
}
} else if (OB_FAIL(append(temp_exprs, merge_stmt->get_match_condition_exprs()) ||
OB_FAIL(append(temp_exprs, merge_stmt->get_update_condition_exprs())))) {
LOG_WARN("failed to push back exprs", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(
get_optimizer_context().get_expr_factory(), temp_exprs, delete_matched_expr))) {
LOG_WARN("failed to build matched expr", K(ret));
} else if (OB_ISNULL(delete_matched_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else { /*do nothing*/
}
if (OB_FAIL(ret)) {
/*do nothing*/
} else if (OB_FAIL(generate_merge_conditions_subquery(
delete_matched_expr, null_expr, true, merge_stmt->get_delete_condition_exprs()))) {
LOG_WARN("failed to generate merge conditions", K(ret));
} else if (OB_FAIL(append(new_subquery_exprs, merge_stmt->get_delete_condition_exprs()))) {
LOG_WARN("failed to append new exprs", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < new_subquery_exprs.count(); i++) {
ObRawExpr* raw_expr = NULL;
if (OB_ISNULL(raw_expr = new_subquery_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(raw_expr->formalize(optimizer_context_.get_session_info()))) {
LOG_WARN("failed to formalize case expr", K(ret));
} else if (OB_FAIL(raw_expr->pull_relation_id_and_levels(merge_stmt->get_current_level()))) {
LOG_WARN("failed to pull relation id and levels", K(ret));
} else { /*do nothing*/
}
}
}
}
return ret;
}
int ObMergeLogPlan::allocate_merge_operator_as_top(ObLogicalOperator*& top)
{
int ret = OB_SUCCESS;
ObLogMerge* merge_op = NULL;
ObMergeStmt* merge_stmt = static_cast<ObMergeStmt*>(const_cast<ObDMLStmt*>(stmt_));
if (OB_ISNULL(merge_stmt) || OB_ISNULL(top)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(merge_stmt), K(top), K(ret));
} else if (OB_ISNULL(merge_op = static_cast<ObLogMerge*>(get_log_op_factory().allocate(*this, LOG_MERGE)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to allocate MERGE operator", K(ret));
} else if (OB_FAIL(set_autoinc_params(merge_stmt->get_autoinc_params()))) {
LOG_WARN("failed to set auto-increment params", K(ret));
} else if (merge_stmt->has_sequence() && OB_FAIL(allocate_sequence_as_top(top))) {
LOG_WARN("failed to allocate sequence as top", K(ret));
} else if (OB_FAIL(append(merge_op->get_output_exprs(), merge_stmt->get_column_conv_functions()))) {
LOG_WARN("failed to append exprs", K(ret));
} else {
merge_op->set_column_convert_exprs(&merge_stmt->get_column_conv_functions());
merge_op->set_all_table_columns(&merge_stmt->get_all_table_columns());
merge_op->set_match_condition(&merge_stmt->get_match_condition_exprs());
merge_op->set_update_condition(&merge_stmt->get_update_condition_exprs());
merge_op->set_delete_condition(&merge_stmt->get_delete_condition_exprs());
merge_op->set_insert_condition(&merge_stmt->get_insert_condition_exprs());
merge_op->set_rowkey_exprs(&merge_stmt->get_rowkey_exprs());
merge_op->set_value_vector(&merge_stmt->get_value_vectors());
merge_op->set_primary_key_ids(&merge_stmt->get_primary_key_ids());
merge_op->set_tables_assignments(&merge_stmt->get_tables_assignments());
merge_op->set_all_table_columns(&(merge_stmt->get_all_table_columns()));
merge_op->set_check_constraint_exprs(&(merge_stmt->get_check_constraint_exprs()));
merge_op->set_child(ObLogicalOperator::first_child, top);
merge_op->set_cost(top->get_card() * UPDATE_ONE_ROW_COST);
merge_op->set_card(top->get_card());
top = merge_op;
}
return ret;
}
int ObMergeLogPlan::generate_merge_conditions_subquery(
ObRawExpr* matched_expr, ObRawExpr* null_expr, bool is_matched, ObIArray<ObRawExpr*>& condition_exprs)
{
int ret = OB_SUCCESS;
ObRawExpr* case_when_expr = NULL;
ObRawExpr* case_param_expr = NULL;
ObSEArray<ObRawExpr*, 8> subquery_exprs;
ObSEArray<ObRawExpr*, 8> non_subquery_exprs;
if (OB_ISNULL(matched_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::classify_subquery_exprs(condition_exprs, subquery_exprs, non_subquery_exprs))) {
LOG_WARN("failed to classify subquery exprs", K(ret));
} else if (subquery_exprs.empty()) {
/*do nothing*/
} else if (OB_FAIL(append(non_subquery_exprs, subquery_exprs))) {
LOG_WARN("failed to append subquery exprs", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(
get_optimizer_context().get_expr_factory(), non_subquery_exprs, case_param_expr))) {
LOG_WARN("failed to build matched expr", K(ret));
} else if (OB_ISNULL(case_param_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (is_matched && OB_FAIL(ObRawExprUtils::build_case_when_expr(get_optimizer_context().get_expr_factory(),
matched_expr,
case_param_expr,
null_expr,
case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (!is_matched && OB_FAIL(ObRawExprUtils::build_case_when_expr(get_optimizer_context().get_expr_factory(),
matched_expr,
null_expr,
case_param_expr,
case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_ISNULL(case_when_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
condition_exprs.reuse();
if (OB_FAIL(condition_exprs.push_back(case_when_expr))) {
LOG_WARN("failed to push back expr", K(ret));
} else { /*do nothing*/
}
}
return ret;
}