From b7f99a68c07a610200a3fb438137035c70923df9 Mon Sep 17 00:00:00 2001 From: xianyu-w <707512433@qq.com> Date: Fri, 21 Jul 2023 12:42:30 +0000 Subject: [PATCH] Fix stmt compare bug --- src/sql/rewrite/ob_stmt_comparer.cpp | 118 +++++++++++++++++++- src/sql/rewrite/ob_stmt_comparer.h | 11 ++ src/sql/rewrite/ob_transform_temp_table.cpp | 2 +- 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/sql/rewrite/ob_stmt_comparer.cpp b/src/sql/rewrite/ob_stmt_comparer.cpp index 47812c00c1..96b554e88b 100644 --- a/src/sql/rewrite/ob_stmt_comparer.cpp +++ b/src/sql/rewrite/ob_stmt_comparer.cpp @@ -596,6 +596,29 @@ int ObStmtComparer::check_stmt_containment(const ObDMLStmt *first, } } + // check order by exprs + if (OB_SUCC(ret) && QueryRelation::QUERY_UNCOMPARABLE != relation) { + first_count = first->get_order_item_size(); + second_count = second->get_order_item_size(); + if (0 == first_count && 0 == second_count) { + map_info.is_order_equal_ = true; + } else if (OB_FAIL(compute_orderby_map(first_sel, + second_sel, + first_sel->get_order_items(), + second_sel->get_order_items(), + map_info, + map_info.order_map_, + match_count))) { + LOG_WARN("failed to compute order item map", K(ret)); + } else if (match_count == first_count && match_count == second_count) { + map_info.is_order_equal_ = true; + LOG_TRACE("succeed to check order item map", K(relation), K(map_info)); + } else { + // The Order Item relation does not afftect the query relation + LOG_TRACE("succeed to check order item map", K(relation), K(map_info)); + } + } + // check limit exprs if (OB_SUCC(ret) && QueryRelation::QUERY_UNCOMPARABLE != relation) { if (!first_sel->has_limit() && !second_sel->has_limit()) { @@ -738,6 +761,53 @@ int ObStmtComparer::compute_conditions_map(const ObDMLStmt *first, return ret; } +int ObStmtComparer::compute_orderby_map(const ObDMLStmt *first, + const ObDMLStmt *second, + const ObIArray &first_orders, + const ObIArray &second_orders, + ObStmtMapInfo &map_info, + ObIArray &order_map, + int64_t &match_count) +{ + int ret = OB_SUCCESS; + ObSqlBitSet<> matched_items; + ObStmtCompareContext context(first, second, map_info, &first->get_query_ctx()->calculable_items_); + match_count = 0; + if (OB_ISNULL(first) || OB_ISNULL(second) || OB_ISNULL(first->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(first), K(second), K(ret)); + } else if (OB_FAIL(order_map.prepare_allocate(first_orders.count()))) { + LOG_WARN("failed to preallocate array", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < first_orders.count(); ++i) { + bool is_match = false; + order_map.at(i) = OB_INVALID_ID; + for (int64_t j = 0; OB_SUCC(ret) && !is_match && j < second_orders.count(); ++j) { + if (matched_items.has_member(j)) { + // do nothing + } else if (first_orders.at(i).order_type_ != second_orders.at(i).order_type_) { + // do nothing + } else if (OB_FAIL(is_same_condition(first_orders.at(i).expr_, + second_orders.at(j).expr_, + context, + is_match))) { + LOG_WARN("failed to check is condition equal", K(ret)); + } else if (!is_match) { + // do nothing + } else if (OB_FAIL(append(map_info.equal_param_map_, context.equal_param_info_))) { + LOG_WARN("failed to append exprs", K(ret)); + } else if (OB_FAIL(matched_items.add_member(j))) { + LOG_WARN("failed to add member", K(ret)); + } else { + match_count++; + order_map.at(i) = j; + } + } + } + } + return ret; +} + int ObStmtComparer::is_same_condition(const ObRawExpr *left, const ObRawExpr *right, ObStmtCompareContext &context, @@ -1128,7 +1198,7 @@ int ObStmtComparer::compare_table_item(const ObDMLStmt *first, } else if (OB_FAIL(map_info.view_select_item_map_.at(first_table_index - 1).assign(ref_query_map_info.select_item_map_))) { LOG_WARN("failed to assign select item map", K(ret)); } else if (QueryRelation::QUERY_UNCOMPARABLE != relation) { - if (map_info.is_select_item_equal_ && QueryRelation::QUERY_EQUAL == relation) { + if (ref_query_map_info.is_select_item_equal_ && QueryRelation::QUERY_EQUAL == relation) { map_info.table_map_.at(first_table_index - 1) = second_table_index - 1; if (OB_FAIL(append(map_info.equal_param_map_, ref_query_map_info.equal_param_map_))) { LOG_WARN("failed to append equal param", K(ret)); @@ -1189,6 +1259,7 @@ int ObStmtComparer::compare_set_stmt(const ObSelectStmt *first, } } if (OB_SUCC(ret) && QueryRelation::QUERY_EQUAL == set_query_relation) { + map_info.is_select_item_equal_ = true; for (int64_t i = 0; OB_SUCC(ret) && QueryRelation::QUERY_EQUAL == set_query_relation && i < map_info.view_select_item_map_.count(); ++i) { const ObIArray &select_item_map = map_info.view_select_item_map_.at(i); @@ -1198,12 +1269,14 @@ int ObStmtComparer::compare_set_stmt(const ObSelectStmt *first, } } else if (map_info.select_item_map_.count() != select_item_map.count()) { set_query_relation = QueryRelation::QUERY_UNCOMPARABLE; + map_info.is_select_item_equal_ = false; } else { for (int64_t j = 0; OB_SUCC(ret) && QueryRelation::QUERY_EQUAL == set_query_relation && j < map_info.select_item_map_.count(); ++j) { if (map_info.select_item_map_.at(j) != select_item_map.at(j) || OB_INVALID_ID == map_info.select_item_map_.at(j)) { set_query_relation = QueryRelation::QUERY_UNCOMPARABLE; + map_info.is_select_item_equal_ = false; } } } @@ -1224,6 +1297,49 @@ int ObStmtComparer::compare_set_stmt(const ObSelectStmt *first, relation = QueryRelation::QUERY_LEFT_SUBSET; } } + // check order by exprs + if (OB_SUCC(ret) && QueryRelation::QUERY_UNCOMPARABLE != relation) { + int64_t first_count = first->get_order_item_size(); + int64_t second_count = second->get_order_item_size(); + int64_t match_count = 0; + if (0 == first_count && 0 == second_count) { + map_info.is_order_equal_ = true; + } else if (OB_FAIL(compute_orderby_map(first, + second, + first->get_order_items(), + second->get_order_items(), + map_info, + map_info.order_map_, + match_count))) { + LOG_WARN("failed to compute order item map", K(ret)); + } else if (match_count == first_count && match_count == second_count) { + map_info.is_order_equal_ = true; + LOG_TRACE("succeed to check order item map", K(relation), K(map_info)); + } else { + // The Order Item relation does not afftect the query relation + LOG_TRACE("succeed to check order item map", K(relation), K(map_info)); + } + } + + // check limit exprs + if (OB_SUCC(ret) && QueryRelation::QUERY_UNCOMPARABLE != relation) { + if (!first->has_limit() && !second->has_limit()) { + LOG_TRACE("succeed to check limit expr", K(relation), K(map_info)); + } else if (first->has_limit() && !second->has_limit() && + (relation == QueryRelation::QUERY_LEFT_SUBSET || + relation == QueryRelation::QUERY_EQUAL)) { + relation = QueryRelation::QUERY_LEFT_SUBSET; + LOG_TRACE("succeed to check limit expr", K(relation), K(map_info)); + } else if (!first->has_limit() && second->has_limit() && + (relation == QueryRelation::QUERY_RIGHT_SUBSET || + relation == QueryRelation::QUERY_EQUAL)) { + relation = QueryRelation::QUERY_RIGHT_SUBSET; + LOG_TRACE("succeed to check limit expr", K(relation), K(map_info)); + } else { + relation = QueryRelation::QUERY_UNCOMPARABLE; + LOG_TRACE("succeed to check limit expr", K(relation), K(map_info)); + } + } } return ret; } diff --git a/src/sql/rewrite/ob_stmt_comparer.h b/src/sql/rewrite/ob_stmt_comparer.h index 1c7d381a6d..ec0f96cfae 100644 --- a/src/sql/rewrite/ob_stmt_comparer.h +++ b/src/sql/rewrite/ob_stmt_comparer.h @@ -43,6 +43,7 @@ enum QueryRelation common::ObSEArray cond_map_; common::ObSEArray group_map_; common::ObSEArray having_map_; + common::ObSEArray order_map_; common::ObSEArray select_item_map_; bool is_table_equal_; bool is_from_equal_; @@ -50,6 +51,7 @@ enum QueryRelation bool is_cond_equal_; bool is_group_equal_; bool is_having_equal_; + bool is_order_equal_; bool is_select_item_equal_; bool is_distinct_equal_; @@ -62,6 +64,7 @@ enum QueryRelation is_cond_equal_(false), is_group_equal_(false), is_having_equal_(false), + is_order_equal_(false), is_select_item_equal_(false), is_distinct_equal_(false) {} @@ -228,6 +231,14 @@ public: ObIArray &condition_map, int64_t &match_count); + static int compute_orderby_map(const ObDMLStmt *first, + const ObDMLStmt *second, + const ObIArray &first_orders, + const ObIArray &second_orders, + ObStmtMapInfo &map_info, + ObIArray &order_map, + int64_t &match_count); + static int compute_from_items_map(const ObDMLStmt *first, const ObDMLStmt *second, ObStmtMapInfo &map_info, diff --git a/src/sql/rewrite/ob_transform_temp_table.cpp b/src/sql/rewrite/ob_transform_temp_table.cpp index db2a208dd0..d48531e76f 100644 --- a/src/sql/rewrite/ob_transform_temp_table.cpp +++ b/src/sql/rewrite/ob_transform_temp_table.cpp @@ -612,7 +612,7 @@ bool ObTransformTempTable::is_similar_stmt(ObSelectStmt& stmt, { bool bret = false; if (stmt.is_set_stmt()) { - bret = QueryRelation::QUERY_EQUAL == relation; + bret = QueryRelation::QUERY_EQUAL == relation && map_info.is_order_equal_;; } else if (stmt.get_table_size() < 2) { if (stmt.get_group_expr_size() > 0 || stmt.get_rollup_expr_size() > 0) {