diff --git a/src/objit/include/objit/common/ob_item_type.h b/src/objit/include/objit/common/ob_item_type.h index c7258fc737..c8ea1863dd 100755 --- a/src/objit/include/objit/common/ob_item_type.h +++ b/src/objit/include/objit/common/ob_item_type.h @@ -1897,7 +1897,10 @@ typedef enum ObItemType T_NO_WIN_MAGIC, T_PULLUP_EXPR, T_NO_PULLUP_EXPR, - + T_AGGR_FIRST_UNNEST, + T_NO_AGGR_FIRST_UNNEST, + T_JOIN_FIRST_UNNEST, + T_NO_JOIN_FIRST_UNNEST, T_INTERVAL_LITERAL, //T_INTERVAL_YM_LITERAL, //T_INTERVAL_DS_LITERAL, diff --git a/src/sql/parser/sql_parser_mysql_mode.l b/src/sql/parser/sql_parser_mysql_mode.l index 9e96cf16d3..3c76997883 100755 --- a/src/sql/parser/sql_parser_mysql_mode.l +++ b/src/sql/parser/sql_parser_mysql_mode.l @@ -1100,6 +1100,10 @@ Timestamp{whitespace}?\"[^\"]*\" { NO_WIN_MAGIC { return NO_WIN_MAGIC; } PULLUP_EXPR { return PULLUP_EXPR; } NO_PULLUP_EXPR { return NO_PULLUP_EXPR; } +AGGR_FIRST_UNNEST { return AGGR_FIRST_UNNEST; } +NO_AGGR_FIRST_UNNEST { return NO_AGGR_FIRST_UNNEST; } +JOIN_FIRST_UNNEST { return JOIN_FIRST_UNNEST; } +NO_JOIN_FIRST_UNNEST { return NO_JOIN_FIRST_UNNEST; } OPT_PARAM { return OPT_PARAM; } OB_DDL_SCHEMA_VERSION { return OB_DDL_SCHEMA_VERSION; } DYNAMIC_SAMPLING { return DYNAMIC_SAMPLING; } diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index cdfd9de8a6..1e0b729a75 100755 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -165,7 +165,7 @@ NO_SIMPLIFY_LIMIT SIMPLIFY_SUBQUERY NO_SIMPLIFY_SUBQUERY FAST_MINMAX NO_FAST_MIN PROJECT_PRUNE NO_PROJECT_PRUNE SIMPLIFY_SET NO_SIMPLIFY_SET OUTER_TO_INNER NO_OUTER_TO_INNER COALESCE_SQ NO_COALESCE_SQ COUNT_TO_EXISTS NO_COUNT_TO_EXISTS LEFT_TO_ANTI NO_LEFT_TO_ANTI ELIMINATE_JOIN NO_ELIMINATE_JOIN PUSH_LIMIT NO_PUSH_LIMIT PULLUP_EXPR NO_PULLUP_EXPR -WIN_MAGIC NO_WIN_MAGIC +WIN_MAGIC NO_WIN_MAGIC AGGR_FIRST_UNNEST NO_AGGR_FIRST_UNNEST JOIN_FIRST_UNNEST NO_JOIN_FIRST_UNNEST // optimize hint INDEX_HINT FULL_HINT NO_INDEX_HINT USE_DAS_HINT NO_USE_DAS_HINT INDEX_SS_HINT INDEX_SS_ASC_HINT INDEX_SS_DESC_HINT @@ -9238,6 +9238,22 @@ NO_REWRITE opt_qb_name { malloc_non_terminal_node($$, result->malloc_pool_, T_NO_PULLUP_EXPR, 1, $2); } +| AGGR_FIRST_UNNEST opt_qb_name +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_AGGR_FIRST_UNNEST, 1, $2); +} +| NO_AGGR_FIRST_UNNEST opt_qb_name +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_NO_AGGR_FIRST_UNNEST, 1, $2); +} +| JOIN_FIRST_UNNEST opt_qb_name +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_JOIN_FIRST_UNNEST, 1, $2); +} +| NO_JOIN_FIRST_UNNEST opt_qb_name +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_NO_JOIN_FIRST_UNNEST, 1, $2); +} ; multi_qb_name_list: diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index e652d97c77..64a45986f1 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -12698,7 +12698,11 @@ int ObDMLResolver::resolve_transform_hint(const ParseNode &hint_node, case T_NO_PUSH_LIMIT: case T_NO_REWRITE: case T_PULLUP_EXPR: - case T_NO_PULLUP_EXPR: { + case T_NO_PULLUP_EXPR: + case T_AGGR_FIRST_UNNEST: + case T_NO_AGGR_FIRST_UNNEST: + case T_JOIN_FIRST_UNNEST: + case T_NO_JOIN_FIRST_UNNEST: { if (OB_FAIL(resolve_normal_transform_hint(hint_node, trans_hint))) { LOG_WARN("failed to resolve hint with qb name param.", K(ret)); } diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index d2fc0630b4..330fc6fc88 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -873,6 +873,8 @@ ObItemType ObHint::get_hint_type(ObItemType type) case T_NO_PRED_DEDUCE: return T_PRED_DEDUCE; case T_NO_PUSH_PRED_CTE: return T_PUSH_PRED_CTE; case T_NO_PULLUP_EXPR : return T_PULLUP_EXPR; + case T_NO_AGGR_FIRST_UNNEST: return T_AGGR_FIRST_UNNEST; + case T_NO_JOIN_FIRST_UNNEST: return T_JOIN_FIRST_UNNEST; // optimize hint case T_NO_USE_DAS_HINT: return T_USE_DAS_HINT; @@ -927,7 +929,9 @@ const char* ObHint::get_hint_name(ObItemType type, bool is_enable_hint /* defaul case T_ELIMINATE_JOIN : return is_enable_hint ? "ELIMINATE_JOIN" : "NO_ELIMINATE_JOIN"; case T_WIN_MAGIC : return is_enable_hint ? "WIN_MAGIC" : "NO_WIN_MAGIC"; case T_PUSH_LIMIT : return is_enable_hint ? "PUSH_LIMIT" : "NO_PUSH_LIMIT"; - case T_PULLUP_EXPR : return is_enable_hint ? "PULLUP_EXPR" : "NO_PULLUP_EXPR"; + case T_PULLUP_EXPR : return is_enable_hint ? "PULLUP_EXPR" : "NO_PULLUP_EXPR"; + case T_AGGR_FIRST_UNNEST: return is_enable_hint ? "AGGR_FIRST_UNNEST" : "NO_AGGR_FIRST_UNNEST"; + case T_JOIN_FIRST_UNNEST: return is_enable_hint ? "JOIN_FIRST_UNNEST" : "NO_JOIN_FIRST_UNNEST"; // optimize hint case T_INDEX_HINT: return "INDEX"; case T_FULL_HINT: return "FULL"; diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index 8178e0ddbe..c4486db347 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -435,6 +435,8 @@ public: bool is_view_merge_hint() const { return HINT_VIEW_MERGE == hint_class_; } bool is_pred_deduce_hint() const { return T_PRED_DEDUCE == hint_type_; } bool is_unnest_hint() const { return T_UNNEST == hint_type_; } + bool is_aggr_first_unnest_hint() const { return T_AGGR_FIRST_UNNEST == hint_type_; } + bool is_join_first_unnest_hint() const { return T_JOIN_FIRST_UNNEST == hint_type_; } bool is_coalesce_sq_hint() const { return HINT_COALESCE_SQ == hint_class_; } bool is_materialize_hint() const { return HINT_MATERIALIZE == hint_class_; } bool is_semi_to_inner_hint() const { return HINT_SEMI_TO_INNER == hint_class_; } diff --git a/src/sql/resolver/dml/ob_sql_hint.h b/src/sql/resolver/dml/ob_sql_hint.h index 7c225c1928..bb92a954f0 100644 --- a/src/sql/resolver/dml/ob_sql_hint.h +++ b/src/sql/resolver/dml/ob_sql_hint.h @@ -458,7 +458,7 @@ struct ObLogPlanHint bool pushdown_distinct() const { return has_enable_hint(T_DISTINCT_PUSHDOWN); } bool no_pushdown_distinct() const { return has_disable_hint(T_DISTINCT_PUSHDOWN); } bool use_distributed_dml() const { return has_enable_hint(T_USE_DISTRIBUTED_DML); } - bool no_use_distributed_dml() const { return has_disable_hint(T_NO_USE_DISTRIBUTED_DML); } + bool no_use_distributed_dml() const { return has_disable_hint(T_USE_DISTRIBUTED_DML); } const ObWindowDistHint *get_window_dist() const; diff --git a/src/sql/rewrite/ob_transform_aggr_subquery.cpp b/src/sql/rewrite/ob_transform_aggr_subquery.cpp index eb2c070cea..280485e207 100644 --- a/src/sql/rewrite/ob_transform_aggr_subquery.cpp +++ b/src/sql/rewrite/ob_transform_aggr_subquery.cpp @@ -96,33 +96,6 @@ int ObTransformAggrSubquery::transform_one_stmt(common::ObIArray &parent_stmts, - ObDMLStmt *&stmt, - bool &trans_happened) -{ - int ret = OB_SUCCESS; - UNUSED(parent_stmts); - trans_happened = false; - bool is_happened = false; - trans_stmt_infos_.reset(); - join_first_happened_ = false; - do { - is_happened = false; - if (OB_FAIL(do_transform(stmt, is_happened))) { - LOG_WARN("failed to transform one stmt", K(ret)); - } else if (is_happened) { - ++ctx_->trans_list_loc_; - trans_happened = true; - LOG_TRACE("succeed to do aggr subquery with outline", K(ctx_->src_qb_name_)); - } - } while (OB_SUCC(ret) && is_happened); - - if (OB_SUCC(ret) && trans_happened && OB_FAIL(add_transform_hint(*stmt, &trans_stmt_infos_))) { - LOG_WARN("failed to add transform hint", K(ret)); - } - return ret; -} - int ObTransformAggrSubquery::check_hint_status(const ObDMLStmt &stmt, bool &need_trans) { int ret = OB_SUCCESS; @@ -135,7 +108,8 @@ int ObTransformAggrSubquery::check_hint_status(const ObDMLStmt &stmt, bool &need } else if (!query_hint->has_outline_data()) { need_trans = true; } else if (NULL == (cur_trans_hint = query_hint->get_outline_trans_hint(ctx_->trans_list_loc_)) || - !cur_trans_hint->is_unnest_hint()) { + !(cur_trans_hint->is_aggr_first_unnest_hint() || + cur_trans_hint->is_join_first_unnest_hint())) { /*do nothing*/ } else { ObQueryRefRawExpr* subquery_expr = nullptr; @@ -145,9 +119,15 @@ int ObTransformAggrSubquery::check_hint_status(const ObDMLStmt &stmt, bool &need OB_ISNULL(select_stmt = subquery_expr->get_ref_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(subquery_expr), K(select_stmt)); - } else { - need_trans = query_hint->is_valid_outline_transform(ctx_->trans_list_loc_, - get_hint(select_stmt->get_stmt_hint())); + } else if (query_hint->is_valid_outline_transform(ctx_->trans_list_loc_, + get_sub_unnest_hint(*select_stmt, AGGR_FIRST))) { + need_trans = true; + } else if (query_hint->is_valid_outline_transform(ctx_->trans_list_loc_, + get_sub_unnest_hint(*select_stmt, JOIN_FIRST))) { + need_trans = true; + } else if (query_hint->is_valid_outline_transform(ctx_->trans_list_loc_, + select_stmt->get_stmt_hint().get_normal_hint(T_UNNEST))) { + need_trans = true; } } } @@ -170,7 +150,9 @@ int ObTransformAggrSubquery::construct_transform_hint(ObDMLStmt &stmt, void *tra ObTransHint *hint = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < trans_stmt_infos->count(); ++i) { TransStmtInfo& info = trans_stmt_infos->at(i); - if (OB_FAIL(ObQueryHint::create_hint(ctx_->allocator_, T_UNNEST, hint))) { + if (OB_FAIL(ObQueryHint::create_hint(ctx_->allocator_, + get_unnest_strategy(info.pullup_strategy_), + hint))) { LOG_WARN("failed to create hint", K(ret)); } else if (OB_FAIL(ctx_->add_src_hash_val(info.qb_name_))) { LOG_WARN("failed to add src hash val", K(ret)); @@ -209,9 +191,6 @@ int ObTransformAggrSubquery::transform_with_aggregation_first(ObDMLStmt *&stmt, for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) { if (OB_FAIL(do_aggr_first_transform(stmt, exprs.at(i), trans_happened))) { LOG_WARN("failed to transform one expr", K(ret)); - } else if (trans_happened && query_hint->has_outline_data()) { - // transform one subquery at one time if with outline - break; } } return ret; @@ -331,14 +310,10 @@ int ObTransformAggrSubquery::do_aggr_first_transform(ObDMLStmt *&stmt, LOG_WARN("failed to transform subquery", K(ret)); } else if (OB_FAIL(transform_upper_stmt(*stmt, trans_param))) { LOG_WARN("failed to transform upper stmt", K(ret)); - } else if (OB_FAIL(add_trans_stmt_info(*subquery))) { + } else if (OB_FAIL(add_trans_stmt_info(*subquery, AGGR_FIRST))) { LOG_WARN("failed add trans stmt info", K(ret)); } else { trans_happened = true; - if (query_hint->has_outline_data()) { - // transform one subquery at one time if with outline - break; - } } } return ret; @@ -373,7 +348,10 @@ int ObTransformAggrSubquery::gather_transform_params(ObDMLStmt &stmt, if (ObOptimizerUtil::find_item(no_rewrite_exprs_, child_expr)) { LOG_TRACE("subquery in select expr and can use index"); OPT_TRACE("subquery in select expr and can use index, no need transfrom"); - } else if (OB_FAIL(check_hint_allowed_unnest(stmt, *subquery, hint_allowed))) { + } else if (OB_FAIL(check_hint_allowed_unnest(stmt, *subquery, + ctx_->trans_list_loc_ + transform_params.count(), + pullup_strategy, + hint_allowed))) { LOG_WARN("failed to check hint allowed unnest", K(ret)); } else if (!hint_allowed) { OPT_TRACE("hint reject transform"); @@ -1200,9 +1178,6 @@ int ObTransformAggrSubquery::transform_with_join_first(ObDMLStmt *&stmt, join_first_happened_ = true; if (OB_FAIL(add_constraints_for_limit(param))) { LOG_WARN("add constraints failed", K(ret)); - } else if (query_hint->has_outline_data()) { - // transform one subquery at one time if with outline - break; } } } @@ -1762,7 +1737,7 @@ int ObTransformAggrSubquery::do_join_first_transform(ObSelectStmt &select_stmt, LOG_WARN("failed to formalize stmt", K(ret)); } else if (OB_FAIL(rebuild_conditon(select_stmt, *subquery))) { LOG_WARN("failed to rebuild condition", K(ret)); - } else if (OB_FAIL(add_trans_stmt_info(*subquery))) { + } else if (OB_FAIL(add_trans_stmt_info(*subquery, JOIN_FIRST))) { LOG_WARN("failed to add trans stmt info", K(ret)); } } @@ -2449,7 +2424,9 @@ int ObTransformAggrSubquery::extract_no_rewrite_expr(ObRawExpr *expr) if (OB_ISNULL(subquery)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); - } else if (subquery->get_stmt_hint().has_enable_hint(T_UNNEST)) { + } else if (subquery->get_stmt_hint().has_enable_hint(T_UNNEST) || + subquery->get_stmt_hint().has_enable_hint(T_AGGR_FIRST_UNNEST) || + subquery->get_stmt_hint().has_enable_hint(T_JOIN_FIRST_UNNEST)) { //do nothing } else if (OB_FAIL(ObTransformUtils::check_subquery_match_index(ctx_, static_cast(expr), @@ -2470,50 +2447,94 @@ int ObTransformAggrSubquery::extract_no_rewrite_expr(ObRawExpr *expr) } return ret; } +ObHint* ObTransformAggrSubquery::get_sub_unnest_hint(ObSelectStmt &subquery, + int64_t pullup_strategy) +{ + ObHint *myhint = NULL; + if (aggr_first(pullup_strategy)) { + myhint = subquery.get_stmt_hint().get_normal_hint(T_AGGR_FIRST_UNNEST); + } else if (join_first(pullup_strategy)) { + myhint = subquery.get_stmt_hint().get_normal_hint(T_JOIN_FIRST_UNNEST); + } + return myhint; +} +ObItemType ObTransformAggrSubquery::get_unnest_strategy(int64_t pullup_strategy) { + ObItemType hint = T_INVALID; + if (aggr_first(pullup_strategy)) { + hint = T_AGGR_FIRST_UNNEST; + } else if (join_first(pullup_strategy)) { + hint = T_JOIN_FIRST_UNNEST; + } + return hint; +} int ObTransformAggrSubquery::check_hint_allowed_unnest(ObDMLStmt &stmt, - ObSelectStmt &subquery, - bool &allowed) + ObSelectStmt &subquery, + const int64_t hint_loc, + const int64_t pullup_strategy, + bool &allowed) { int ret = OB_SUCCESS; allowed = true; - const ObQueryHint *query_hint = NULL; - const ObHint *myhint = get_hint(subquery.get_stmt_hint()); - bool is_enable = (NULL != myhint && myhint->is_enable_hint()); - bool is_disable = (NULL != myhint && myhint->is_disable_hint()); + const ObQueryHint *query_hint = stmt.get_stmt_hint().query_hint_; + const ObHint *unnest_hint = subquery.get_stmt_hint().get_normal_hint(T_UNNEST); + const ObHint *subhint = get_sub_unnest_hint(subquery, pullup_strategy); + bool is_enable = false; + bool is_disable = false; + bool is_unnest_enable = false; + bool is_unnest_disable = false; + if (NULL != unnest_hint) { + is_unnest_enable = unnest_hint->is_enable_hint(); + is_unnest_disable = unnest_hint->is_disable_hint(); + } + if (NULL != subhint) { + is_enable = subhint->is_enable_hint(); + is_disable = subhint->is_disable_hint(); + } const ObHint *no_rewrite1 = stmt.get_stmt_hint().get_no_rewrite_hint(); const ObHint *no_rewrite2 = subquery.get_stmt_hint().get_no_rewrite_hint(); - if (OB_ISNULL(ctx_) || OB_ISNULL(query_hint = stmt.get_stmt_hint().query_hint_)) { + if (OB_ISNULL(ctx_) || OB_ISNULL(query_hint)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(ctx_), K(query_hint)); } else if (query_hint->has_outline_data()) { // outline data allowed merge - allowed = query_hint->is_valid_outline_transform(ctx_->trans_list_loc_, myhint); - } else if (is_enable) { - allowed = true; - } else if (NULL != no_rewrite1 || NULL != no_rewrite2 || is_disable) { - // add disable transform hint here - allowed = false; - if (OB_FAIL(ctx_->add_used_trans_hint(no_rewrite1))) { - LOG_WARN("failed to add used trans hint", K(ret)); - } else if (OB_FAIL(ctx_->add_used_trans_hint(no_rewrite2))) { - LOG_WARN("failed to add used trans hint", K(ret)); - } else if (is_disable && OB_FAIL(ctx_->add_used_trans_hint(myhint))) { - LOG_WARN("failed to add used trans hint", K(ret)); - } + allowed = query_hint->is_valid_outline_transform(hint_loc, subhint); + } else { + if (is_enable || (!is_disable && is_unnest_enable)) { + // enable hint + allowed = true; + } else if (NULL != no_rewrite1 || NULL != no_rewrite2 || is_disable || is_unnest_disable) { + // add disable transform hint here + allowed = false; + if (OB_FAIL(ctx_->add_used_trans_hint(no_rewrite1))) { + LOG_WARN("failed to add used trans hint", K(ret)); + } else if (OB_FAIL(ctx_->add_used_trans_hint(no_rewrite2))) { + LOG_WARN("failed to add used trans hint", K(ret)); + } else if (is_disable && OB_FAIL(ctx_->add_used_trans_hint(subhint))) { + LOG_WARN("failed to add used trans hint", K(ret)); + } else if (is_unnest_disable && OB_FAIL(ctx_->add_used_trans_hint(unnest_hint))) { + LOG_WARN("failed to add used trans hint", K(ret)); + } + } else { /* default enable */ } } return ret; } -int ObTransformAggrSubquery::add_trans_stmt_info(ObSelectStmt &subquery) +int ObTransformAggrSubquery::add_trans_stmt_info(ObSelectStmt &subquery, int64_t flag) { int ret = OB_SUCCESS; TransStmtInfo info; - info.unnest_ = get_hint(subquery.get_stmt_hint()); + info.pullup_strategy_ = flag; + info.unnest_ = get_sub_unnest_hint(subquery, flag); + if (NULL == info.unnest_) { + info.unnest_ = get_hint(subquery.get_stmt_hint()); + } if (OB_FAIL(subquery.get_qb_name(info.qb_name_))) { LOG_WARN("failed to get qb name", K(ret)); } else if (OB_FAIL(trans_stmt_infos_.push_back(info))) { LOG_WARN("failed to push back trans stmt info", K(ret), K(info)); + } else { + ctx_->trans_list_loc_++; } return ret; } diff --git a/src/sql/rewrite/ob_transform_aggr_subquery.h b/src/sql/rewrite/ob_transform_aggr_subquery.h index 66b105eb9d..cd239317b3 100644 --- a/src/sql/rewrite/ob_transform_aggr_subquery.h +++ b/src/sql/rewrite/ob_transform_aggr_subquery.h @@ -44,9 +44,6 @@ public: bool &trans_happened) override; protected: virtual int check_hint_status(const ObDMLStmt &stmt, bool &need_trans) override; - virtual int transform_one_stmt_with_outline(common::ObIArray &parent_stmts, - ObDMLStmt *&stmt, - bool &trans_happened) override; virtual int construct_transform_hint(ObDMLStmt &stmt, void *trans_params) override; private: @@ -96,16 +93,18 @@ private: struct TransStmtInfo { TransStmtInfo() - : qb_name_(), unnest_(nullptr) {} + : qb_name_(), unnest_(nullptr), pullup_strategy_(AGGR_FIRST) {} int assign(const TransStmtInfo& other) { qb_name_ = other.qb_name_; unnest_ = other.unnest_; + pullup_strategy_ = other.pullup_strategy_; return common::OB_SUCCESS; } - TO_STRING_KV(K_(qb_name), KPC_(unnest)); + TO_STRING_KV(K_(qb_name), KPC_(unnest), K_(pullup_strategy)); common::ObString qb_name_; const ObHint *unnest_; + int64_t pullup_strategy_; }; int do_transform(ObDMLStmt *&stmt, bool &trans_happened); @@ -269,16 +268,19 @@ private: int transform_with_aggr_first_for_having(ObDMLStmt *&stmt, bool &trans_happened); int check_hint_allowed_unnest(ObDMLStmt &stmt, ObSelectStmt &subquery, + const int64_t hint_loc, + const int64_t pullup_strategy, bool &allowed); - int add_trans_stmt_info(ObSelectStmt &subquery); + int add_trans_stmt_info(ObSelectStmt &subquery, int64_t flag); int check_limit_validity(ObSelectStmt &subquery, bool &add_limit_constraints, int64_t &limit_value, bool &is_valid); int add_constraints_for_limit(TransformParam ¶m); - int convert_limit_as_aggr(ObSelectStmt *subquery, - TransformParam &trans_param); + int convert_limit_as_aggr(ObSelectStmt *subquery, TransformParam &trans_param); + ObHint* get_sub_unnest_hint(ObSelectStmt &subquery, int64_t pullup_strategy); + ObItemType get_unnest_strategy(int64_t pullup_strategy); private: common::ObSEArray no_rewrite_exprs_; common::ObSEArray trans_stmt_infos_; diff --git a/src/sql/rewrite/ob_transform_groupby_pushdown.cpp b/src/sql/rewrite/ob_transform_groupby_pushdown.cpp index 38f4ee8e5d..89c85564b5 100644 --- a/src/sql/rewrite/ob_transform_groupby_pushdown.cpp +++ b/src/sql/rewrite/ob_transform_groupby_pushdown.cpp @@ -1559,17 +1559,10 @@ int ObTransformGroupByPushdown::construct_transform_hint(ObDMLStmt &stmt, void * hint->set_qb_name(ctx_->src_qb_name_); for (int64_t i = 0; OB_SUCC(ret) && i < transed_tables->count(); ++i) { ObSEArray single_or_joined_hint_table; - for (int64_t j = 0; OB_SUCC(ret) && j < transed_tables->at(i).count(); ++j) { - TableItem *table = transed_tables->at(i).at(j); - if (OB_ISNULL(table)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(single_or_joined_hint_table.push_back(ObTableInHint(table->qb_name_, - table->database_name_, table->get_object_name())))) { - LOG_WARN("failed to push back hint table", K(ret)); - } - } - if (OB_SUCC(ret) && OB_FAIL(hint->get_tb_name_list().push_back(single_or_joined_hint_table))) { + if (OB_FAIL(ObTransformUtils::get_sorted_table_hint(transed_tables->at(i), + single_or_joined_hint_table))) { + LOG_WARN("failed to get table hint", K(ret)); + } else if (OB_FAIL(hint->get_tb_name_list().push_back(single_or_joined_hint_table))) { LOG_WARN("failed to push back table name list", K(ret)); } } diff --git a/src/sql/rewrite/ob_transform_join_elimination.cpp b/src/sql/rewrite/ob_transform_join_elimination.cpp index 73a97c127d..9a686c12fe 100644 --- a/src/sql/rewrite/ob_transform_join_elimination.cpp +++ b/src/sql/rewrite/ob_transform_join_elimination.cpp @@ -88,17 +88,10 @@ int ObTransformJoinElimination::construct_transform_hint(ObDMLStmt &stmt, void * hint->set_qb_name(ctx_->src_qb_name_); for (int64_t i = 0; OB_SUCC(ret) && i < eliminated_tables->count(); ++i) { ObSEArray single_or_joined_hint_table; - for (int64_t j = 0; OB_SUCC(ret) && j < eliminated_tables->at(i).count(); ++j) { - TableItem *table = eliminated_tables->at(i).at(j); - if (OB_ISNULL(table)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(single_or_joined_hint_table.push_back(ObTableInHint(table->qb_name_, - table->database_name_, table->get_object_name())))) { - LOG_WARN("failed to push back hint table", K(ret)); - } - } - if (OB_SUCC(ret) && OB_FAIL(hint->get_tb_name_list().push_back(single_or_joined_hint_table))) { + if (OB_FAIL(ObTransformUtils::get_sorted_table_hint(eliminated_tables->at(i), + single_or_joined_hint_table))) { + LOG_WARN("failed to get table hint", K(ret)); + } else if (OB_FAIL(hint->get_tb_name_list().push_back(single_or_joined_hint_table))) { LOG_WARN("failed to push back table name list", K(ret)); } } @@ -1241,11 +1234,8 @@ int ObTransformJoinElimination::left_join_can_be_eliminated(ObDMLStmt *stmt, LOG_WARN("failed to calc const or calculable expr", K(ret)); } else if (got_result) { can_be_eliminated = value.is_false(); - // add constraints - if (condition->is_static_const_expr()) { - if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, condition, false))) { - LOG_WARN("failed to add param bool constraint", K(ret)); - } + if (can_be_eliminated && OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, condition, false))) { + LOG_WARN("failed to add param bool constraint", K(ret)); } } } diff --git a/src/sql/rewrite/ob_transform_left_join_to_anti.cpp b/src/sql/rewrite/ob_transform_left_join_to_anti.cpp index bd3ecad468..beb99baccc 100644 --- a/src/sql/rewrite/ob_transform_left_join_to_anti.cpp +++ b/src/sql/rewrite/ob_transform_left_join_to_anti.cpp @@ -86,17 +86,10 @@ int ObTransformLeftJoinToAnti::construct_transform_hint(ObDMLStmt &stmt, void *t hint->set_qb_name(ctx_->src_qb_name_); for (int64_t i = 0; OB_SUCC(ret) && i < trans_tables->count(); ++i) { ObSEArray single_or_joined_hint_table; - for (int64_t j = 0; OB_SUCC(ret) && j < trans_tables->at(i).count(); ++j) { - TableItem *table = trans_tables->at(i).at(j); - if (OB_ISNULL(table)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(single_or_joined_hint_table.push_back(ObTableInHint(table->qb_name_, - table->database_name_, table->get_object_name())))) { - LOG_WARN("failed to push back hint table", K(ret)); - } - } - if (OB_SUCC(ret) && OB_FAIL(hint->get_tb_name_list().push_back(single_or_joined_hint_table))) { + if (OB_FAIL(ObTransformUtils::get_sorted_table_hint(trans_tables->at(i), + single_or_joined_hint_table))) { + LOG_WARN("failed to get table hint", K(ret)); + } else if (OB_FAIL(hint->get_tb_name_list().push_back(single_or_joined_hint_table))) { LOG_WARN("failed to push back table name list", K(ret)); } } diff --git a/src/sql/rewrite/ob_transform_rule.h b/src/sql/rewrite/ob_transform_rule.h index 12c22e8876..7c72560129 100644 --- a/src/sql/rewrite/ob_transform_rule.h +++ b/src/sql/rewrite/ob_transform_rule.h @@ -431,7 +431,8 @@ private: { return TEMP_TABLE_OPTIMIZATION == transformer_type_ // move trans loc in transform rule || POST_PROCESS == transformer_type_ // need not move trans loc - || PRE_PROCESS == transformer_type_; // need not move trans loc + || PRE_PROCESS == transformer_type_ // need not move trans loc + || AGGR_SUBQUERY == transformer_type_; // move trans loc in transform rule } bool skip_adjust_qb_name() const // qb name adjust by transform rule diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 28758cabb2..5b435e885e 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -12041,6 +12041,32 @@ int ObTransformUtils::construct_trans_tables(const ObDMLStmt *stmt, return ret; } +int ObTransformUtils::get_sorted_table_hint(ObSEArray &tables, + ObIArray &table_hints) { + int ret = OB_SUCCESS; + if (tables.count() > 1) { + auto cmp_func = [](TableItem* a, TableItem* b) { + if (OB_ISNULL(a) || OB_ISNULL(b)) { + return false; + } else { + return a->table_id_ > b->table_id_; + } + }; + std::sort(tables.begin(), tables.end(), cmp_func); + } + for (int64_t i = 0; OB_SUCC(ret) && i < tables.count(); ++i) { + TableItem *table = tables.at(i); + if (OB_ISNULL(table)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(table_hints.push_back( + ObTableInHint(table->qb_name_, table->database_name_, table->get_object_name())))) { + LOG_WARN("failed to push back hint table", K(ret)); + } + } + return ret; +} + int ObTransformUtils::construct_trans_table(const ObDMLStmt *stmt, const TableItem *table, ObIArray &trans_tables) diff --git a/src/sql/rewrite/ob_transform_utils.h b/src/sql/rewrite/ob_transform_utils.h index e9ed48f2c2..d4995e9753 100644 --- a/src/sql/rewrite/ob_transform_utils.h +++ b/src/sql/rewrite/ob_transform_utils.h @@ -1777,6 +1777,8 @@ public: ObRawExpr *expr, ObIArray &exprs, bool &trans_happened); + // used to stable outline + static int get_sorted_table_hint(ObSEArray &tables, ObIArray &table_hints); private: static int inner_get_lazy_left_join(ObDMLStmt *stmt, TableItem *table,