From 5fb975ae7c1b3ec030b5dac06b651e9c2ea8b9cd Mon Sep 17 00:00:00 2001 From: obdev Date: Thu, 20 Jul 2023 02:54:11 +0000 Subject: [PATCH] fix semi to inner bug for view from dual --- src/sql/resolver/dml/ob_select_stmt.h | 2 +- src/sql/rewrite/ob_stmt_comparer.cpp | 2 +- src/sql/rewrite/ob_transform_min_max.cpp | 2 +- .../rewrite/ob_transform_semi_to_inner.cpp | 56 +++++++++++++++++++ src/sql/rewrite/ob_transform_semi_to_inner.h | 2 + 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/sql/resolver/dml/ob_select_stmt.h b/src/sql/resolver/dml/ob_select_stmt.h index b9099ea208..74445c7792 100644 --- a/src/sql/resolver/dml/ob_select_stmt.h +++ b/src/sql/resolver/dml/ob_select_stmt.h @@ -408,7 +408,7 @@ public: get_aggr_item_size() > 0; } inline bool has_hierarchical_query() const { return is_hierarchical_query_ ; } - inline bool has_recusive_cte() const { return is_recursive_cte_; } + inline bool has_recursive_cte() const { return is_recursive_cte_; } void set_order_siblings(bool is_order_siblings) { is_order_siblings_ = is_order_siblings; } bool is_order_siblings() const { return is_order_siblings_; } void set_hierarchical_query(bool is_hierarchical_query) { is_hierarchical_query_ = is_hierarchical_query; } diff --git a/src/sql/rewrite/ob_stmt_comparer.cpp b/src/sql/rewrite/ob_stmt_comparer.cpp index e3f2372f33..47812c00c1 100644 --- a/src/sql/rewrite/ob_stmt_comparer.cpp +++ b/src/sql/rewrite/ob_stmt_comparer.cpp @@ -397,7 +397,7 @@ int ObStmtComparer::check_stmt_containment(const ObDMLStmt *first, /*do nothing*/ } else if (FALSE_IT(second_sel = const_cast(static_cast(second)))) { /*do nothing*/ - } else if (first_sel->has_recusive_cte() || second_sel->has_recusive_cte() || + } else if (first_sel->has_recursive_cte() || second_sel->has_recursive_cte() || first_sel->has_hierarchical_query() || second_sel->has_hierarchical_query() || first_sel->is_contains_assignment() || second_sel->is_contains_assignment()) { /*do nothing*/ diff --git a/src/sql/rewrite/ob_transform_min_max.cpp b/src/sql/rewrite/ob_transform_min_max.cpp index 6535bf9290..dbc56e0421 100644 --- a/src/sql/rewrite/ob_transform_min_max.cpp +++ b/src/sql/rewrite/ob_transform_min_max.cpp @@ -86,7 +86,7 @@ int ObTransformMinMax::check_transform_validity(ObSelectStmt *select_stmt, if (OB_ISNULL(select_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(select_stmt)); - } else if (select_stmt->has_recusive_cte() || select_stmt->has_hierarchical_query()) { + } else if (select_stmt->has_recursive_cte() || select_stmt->has_hierarchical_query()) { OPT_TRACE("stmt has recusive cte or hierarchical query"); } else if (select_stmt->get_from_item_size() != 1 || select_stmt->get_from_item(0).is_joined_ || diff --git a/src/sql/rewrite/ob_transform_semi_to_inner.cpp b/src/sql/rewrite/ob_transform_semi_to_inner.cpp index 502aec74c1..87bf43354a 100644 --- a/src/sql/rewrite/ob_transform_semi_to_inner.cpp +++ b/src/sql/rewrite/ob_transform_semi_to_inner.cpp @@ -606,6 +606,16 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, ctx.is_multi_join_cond_ = is_multi_join_cond; need_check_cost = true; is_valid = true; + // when right table is from "dual", ban cost checking for adding distinct + bool query_from_dual = false; + ObSelectStmt *right_table_ref_query = NULL; + if (OB_ISNULL(right_table_ref_query = right_table->ref_query_)) { + // do nothing + } else if (OB_FAIL(check_query_from_dual(right_table_ref_query, query_from_dual))) { + LOG_WARN("failed to check union all dual form", K(ret)); + } else if (query_from_dual) { + need_check_cost = false; + } } else if (cmp_join_conds_count == 1 && other_conds_count == 0 && can_add_deduplication) { // TO_AGGR_INNER : for cases when there is one and only one compare-join-condition is_valid = true; @@ -640,6 +650,52 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, return ret; } +int ObTransformSemiToInner::check_query_from_dual(ObSelectStmt *stmt, bool& query_from_dual/*=false*/) { + int ret = OB_SUCCESS; + ObSEArray child_stmts; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(stmt)); + } else if (OB_FAIL(stmt->get_child_stmts(child_stmts))) { + LOG_WARN("failed to get child stmts"); + } else if (stmt->get_table_items().count() == 0 && child_stmts.count() == 0) { + query_from_dual = true; + } else { + bool temp_flag = true; + // check table items + for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_table_items().count() && temp_flag; i++) { + TableItem *table_item = stmt->get_table_items().at(i); + if (OB_ISNULL(table_item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(table_item)); + } else if (!(table_item->is_temp_table() || table_item->is_generated_table())) { + temp_flag = false; + } else if (table_item->is_temp_table()) { + // stmt referenced in temp table need to be checked + ObSelectStmt *temp_stmt = NULL; + if (OB_ISNULL(temp_stmt = table_item->ref_query_)) { + LOG_WARN("unexpected null", K(ret), K(temp_stmt)); + } else if (temp_stmt->has_recursive_cte()) { + temp_flag = false; + } else if (OB_FAIL(child_stmts.push_back(table_item->ref_query_))) { + LOG_WARN("failed to push back stmt"); + } + } + } + // check stmts + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count() && temp_flag; i++) { + ObSelectStmt *child_stmt = child_stmts.at(i); + temp_flag = false; + if (OB_FAIL(SMART_CALL(check_query_from_dual(child_stmt, temp_flag)))) { + LOG_WARN("failed to check query from dual"); + } + } + query_from_dual = temp_flag; + } + return ret; +} + + /** * @brief collect_unique_property_of_from_items * try to construct a unique column group based on unique column of each from item diff --git a/src/sql/rewrite/ob_transform_semi_to_inner.h b/src/sql/rewrite/ob_transform_semi_to_inner.h index eb6049f3ea..2eec4baa52 100644 --- a/src/sql/rewrite/ob_transform_semi_to_inner.h +++ b/src/sql/rewrite/ob_transform_semi_to_inner.h @@ -127,6 +127,8 @@ private: bool& need_check_cost, TransformParam& trans_param); + int check_query_from_dual(ObSelectStmt *stmt, bool& query_from_dual); + int collect_unique_property_of_from_items(ObTransformerCtx* ctx, ObDMLStmt* stmt, ObIArray>& unique_column_group);