From 4fb42a22e87392d032cd9c42039350204b5ed999 Mon Sep 17 00:00:00 2001 From: 2149 <260391947@qq.com> Date: Thu, 17 Aug 2023 10:43:35 +0000 Subject: [PATCH] Fix subquery coalesce bug --- .../ob_transform_subquery_coalesce.cpp | 53 ++++++++++++++++++- .../rewrite/ob_transform_subquery_coalesce.h | 5 ++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/sql/rewrite/ob_transform_subquery_coalesce.cpp b/src/sql/rewrite/ob_transform_subquery_coalesce.cpp index cc751f7366..8e686363cc 100644 --- a/src/sql/rewrite/ob_transform_subquery_coalesce.cpp +++ b/src/sql/rewrite/ob_transform_subquery_coalesce.cpp @@ -91,7 +91,7 @@ int ObTransformSubqueryCoalesce::transform_one_stmt(common::ObIArrayequal_param_constraints_, cost_based_equal_infos))) { @@ -401,6 +401,7 @@ int ObTransformSubqueryCoalesce::coalesce_same_any_all_exprs(ObDMLStmt *stmt, is_happened = false; bool force_trans = false; bool force_no_trans = false; + bool is_select_same = false; if (OB_ISNULL(stmt) || OB_ISNULL(ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret), K(stmt), K(ctx_)); @@ -441,6 +442,13 @@ int ObTransformSubqueryCoalesce::coalesce_same_any_all_exprs(ObDMLStmt *stmt, LOG_WARN("failed to check stmt containment", K(ret)); } else if (!map_info.is_select_item_equal_) { OPT_TRACE("stmts have different select items, can not coalesce"); + } else if (OB_FAIL(check_select_items_same(first_query_ref->get_ref_stmt(), + second_query_ref->get_ref_stmt(), + map_info, + is_select_same))) { + LOG_WARN("check select items failed", K(ret)); + } else if (!is_select_same) { + OPT_TRACE("The order of select items in two stmts is different, can not coalesce"); } else if (relation == QUERY_LEFT_SUBSET || relation == QUERY_EQUAL) { remove_index = (type == T_ANY ? j : i); OPT_TRACE("right query contain left query, will coalesce suqbeury"); @@ -746,6 +754,7 @@ int ObTransformSubqueryCoalesce::compare_any_all_subqueries(ObDMLStmt *stmt, ObQueryRefRawExpr* first_query_ref = get_any_all_query_expr(param.any_expr_); ObRawExpr* second_left_expr = get_any_all_left_hand_expr(param.all_expr_); ObQueryRefRawExpr* second_query_ref = get_any_all_query_expr(param.all_expr_); + bool is_select_same = false; OPT_TRACE("try to coalesce any/all subquery:"); OPT_TRACE("any expr:", param.any_expr_); OPT_TRACE("all expr:", param.all_expr_); @@ -774,6 +783,15 @@ int ObTransformSubqueryCoalesce::compare_any_all_subqueries(ObDMLStmt *stmt, param.map_info_, relation))) { LOG_WARN("failed to check stmt containment", K(ret)); + } else if (!param.map_info_.is_select_item_equal_) { + OPT_TRACE("stmts have different select items, can not coalesce"); + } else if (OB_FAIL(check_select_items_same(first_query_ref->get_ref_stmt(), + second_query_ref->get_ref_stmt(), + param.map_info_, + is_select_same))) { + LOG_WARN("check select items failed", K(ret)); + } else if (!is_select_same) { + OPT_TRACE("The order of select items in two stmts is different, can not coalesce"); } else if (relation == QueryRelation::QUERY_RIGHT_SUBSET || relation == QueryRelation::QUERY_EQUAL) { has_false_conds = true; @@ -2635,3 +2653,36 @@ int ObTransformSubqueryCoalesce::sort_coalesce_stmts(Ob2DArray } return ret; } + +int ObTransformSubqueryCoalesce::check_select_items_same(const ObDMLStmt *first, + const ObDMLStmt *second, + ObStmtMapInfo &map_info, + bool &is_same) +{ + int ret = OB_SUCCESS; + is_same = true; + if (OB_ISNULL(first) || OB_ISNULL(second)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), KP(first), KP(second)); + } else if (first->is_select_stmt() && second->is_select_stmt()) { + const ObSelectStmt *first_sel = static_cast(first); + const ObSelectStmt *second_sel = static_cast(second); + ObStmtCompareContext context(first, second, map_info, &first->get_query_ctx()->calculable_items_); + if (first_sel->get_select_item_size() != second_sel->get_select_item_size()) { + is_same = false; + } + for (int64_t i = 0; OB_SUCC(ret) && is_same && i < first_sel->get_select_item_size(); ++i) { + ObRawExpr *first_expr = first_sel->get_select_item(i).expr_; + ObRawExpr *second_expr = second_sel->get_select_item(i).expr_; + if (OB_ISNULL(first_expr) || OB_ISNULL(second_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), KP(first_expr), KP(second_expr)); + } else if (!first_expr->same_as(*second_expr, &context)) { + is_same = false; + } + } + } else { + //do nothing + } + return ret; +} diff --git a/src/sql/rewrite/ob_transform_subquery_coalesce.h b/src/sql/rewrite/ob_transform_subquery_coalesce.h index ce9fd434eb..fab9573817 100644 --- a/src/sql/rewrite/ob_transform_subquery_coalesce.h +++ b/src/sql/rewrite/ob_transform_subquery_coalesce.h @@ -237,6 +237,11 @@ private: int sort_coalesce_stmts(Ob2DArray &coalesce_stmts); + int check_select_items_same(const ObDMLStmt *first, + const ObDMLStmt *second, + ObStmtMapInfo &map_info, + bool &is_same); + private: ObQueryRefRawExpr * get_exists_query_expr(ObRawExpr *expr);