/** * 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. */ #ifndef OCEANBASE_SQL_OPTIMIZER_OB_LOGICAL_PLAN_TREE_H #define OCEANBASE_SQL_OPTIMIZER_OB_LOGICAL_PLAN_TREE_H 1 #include "lib/container/ob_array.h" #include "sql/resolver/dml/ob_select_stmt.h" #include "sql/optimizer/ob_log_plan.h" #include "sql/optimizer/ob_sharding_info.h" namespace oceanbase { namespace sql { class ObJoinOrder; class AccessPath; struct JoinInfo; class Path; class JoinPath; class ObLogGroupBy; class ObLogSet; class ObLogWindowFunction; struct MergeKeyInfo; struct IndexDMLInfo; /** * Logical Plan for 'select' statement */ class ObSelectLogPlan : public ObLogPlan { friend class ::test::ObLogPlanTest_ob_explain_test_Test; public: ObSelectLogPlan(ObOptimizerContext &ctx, const ObSelectStmt *select_stmt); virtual ~ObSelectLogPlan(); // @brief GENERATE the raw PLAN tree which have not traversed int allocate_link_scan_as_top(ObLogicalOperator *&old_top); const ObSelectStmt *get_stmt() const override { return reinterpret_cast(stmt_); } int perform_late_materialization(ObSelectStmt *stmt, ObLogicalOperator *&op); protected: virtual int generate_normal_raw_plan() override; virtual int generate_dblink_raw_plan() override; private: // @brief Allocate a hash group by on top of a plan tree // ObLogicalOperator * candi_allocate_hash_group_by(); // @brief Allocate a merge group by on top of a plan tree // ObLogicalOperator * candi_allocate_merge_group_by(ObIArray &ordering); // @brief Allocate GROUP BY on top of plan candidates int candi_allocate_group_by(); // @brief Get all the group by exprs, rollup exprs and their directions. int get_groupby_rollup_exprs(const ObLogicalOperator *op, common::ObIArray &reduce_exprs, common::ObIArray &group_by_exprs, common::ObIArray &rollup_exprs, common::ObIArray &group_directions, common::ObIArray &rollup_directions); int candi_allocate_normal_group_by(const ObIArray &reduce_exprs, const ObIArray &group_by_exprs, const ObIArray &group_directions, const ObIArray &rollup_exprs, const ObIArray &rollup_directions, const ObIArray &having_exprs, const ObIArray &agg_items, const bool is_from_povit); int get_valid_aggr_algo(const ObIArray &group_by_exprs, const GroupingOpHelper &groupby_helper, const bool ignore_hint, bool &use_hash_valid, bool &use_merge_valid, bool &part_sort_valid, bool &normal_sort_valid); int update_part_sort_method(bool &part_sort_valid, bool &normal_sort_valid); int candi_allocate_normal_group_by(const ObIArray &reduce_exprs, const ObIArray &group_by_exprs, const ObIArray &group_directions, const ObIArray &rollup_exprs, const ObIArray &rollup_directions, const ObIArray &having_exprs, const ObIArray &aggr_items, const bool is_from_povit, GroupingOpHelper &groupby_helper, const bool ignore_hint, ObIArray &groupby_plans); int candi_allocate_three_stage_group_by(const ObIArray &reduce_exprs, const ObIArray &group_by_exprs, const ObIArray &group_directions, const ObIArray &rollup_exprs, const ObIArray &rollup_directions, const ObIArray &aggr_items, const ObIArray &having_exprs, const bool is_from_povit, GroupingOpHelper &groupby_helper, ObIArray &groupby_plans); int create_hash_group_plan(const ObIArray &reduce_exprs, const ObIArray &group_by_exprs, const ObIArray &rollup_exprs, const ObIArray &aggr_items, const ObIArray &having_exprs, const bool is_from_povit, GroupingOpHelper &groupby_helper, ObLogicalOperator *&top); int allocate_topk_for_hash_group_plan(ObLogicalOperator *&top); int allocate_topk_sort_as_top(ObLogicalOperator *&top, const ObIArray &sort_keys, ObRawExpr *limit_expr, ObRawExpr *offset_expr, int64_t minimum_row_count, int64_t topk_precision); int clone_sort_keys_for_topk(const ObIArray &sort_keys_, ObIArray &topk_sort_keys); int allocate_topk_as_top(ObLogicalOperator *&top, ObRawExpr *topk_limit_count, ObRawExpr *topk_limit_offset, int64_t minimum_row_count, int64_t topk_precision); int should_create_rollup_pushdown_plan(ObLogicalOperator *top, const ObIArray &reduce_exprs, const ObIArray &rollup_exprs, GroupingOpHelper &groupby_helper, bool &is_needed); int create_rollup_pushdown_plan(const ObIArray &group_by_exprs, const ObIArray &rollup_exprs, const ObIArray &aggr_items, const ObIArray &having_exprs, GroupingOpHelper &groupby_helper, ObLogicalOperator *&top); int create_merge_group_plan(const ObIArray &reduce_exprs, const ObIArray &group_by_exprs, const ObIArray &group_directions, const ObIArray &rollup_exprs, const ObIArray &rollup_directions, const ObIArray &aggr_items, const ObIArray &having_exprs, const bool is_from_povit, GroupingOpHelper &groupby_helper, CandidatePlan &candidate_plan, ObIArray &candidate_plans, bool part_sort_valid, bool normal_sort_valid, bool can_ignore_merge = false); int generate_merge_group_sort_keys(ObLogicalOperator *top, const ObIArray &group_by_exprs, const ObIArray &group_directions, const ObIArray &rollup_exprs, const ObIArray &rollup_directions, ObIArray &sort_exprs, ObIArray &sort_directions); int allocate_topk_for_merge_group_plan(ObLogicalOperator *&top); // @brief Allocate DISTINCT by on top of plan candidates int candi_allocate_distinct(); // @brief Get all the distinct exprs int get_distinct_exprs(const ObLogicalOperator *top, common::ObIArray &reduce_exprs, common::ObIArray &distinct_exprs); int create_hash_distinct_plan(ObLogicalOperator *&top, GroupingOpHelper &distinct_helper, ObIArray &reduce_exprs, ObIArray &distinct_exprs); int create_merge_distinct_plan(ObLogicalOperator *&top, GroupingOpHelper &distinct_helper, ObIArray &reduce_exprs, ObIArray &distinct_exprs, ObIArray &directions, bool &is_plan_valid, bool can_ignore_merge_plan = false); int allocate_distinct_as_top(ObLogicalOperator *&top, const AggregateAlgo algo, const ObIArray &distinct_exprs, const double total_ndv, const bool is_partition_wise = false, const bool is_pushed_down = false, const bool is_partition_gi = false); /** * @brief GENERATE the PLAN tree FOR "SET" operator (UNION/INTERSECT/EXCEPT) * Warning: * @param void * @retval OB_SUCCESS execute success * @retval otherwise, failed to generate the logical plan */ int generate_raw_plan_for_set(); int candi_allocate_set(const ObIArray &child_plans); int update_set_sharding_info(const ObIArray &child_plans); int candi_allocate_union_all(const ObIArray &child_plans); int generate_union_all_plans(const ObIArray &child_plans, const bool ignore_hint, ObIArray &all_plans); int create_union_all_plan(const ObIArray &child_plans, const bool ignore_hint, ObLogicalOperator *&top); int check_if_union_all_match_partition_wise(const ObIArray &child_ops, bool &is_partition_wise); int check_if_union_all_match_set_partition_wise(const ObIArray &child_ops, bool &is_match_set_pw); int check_sharding_inherit_from_access_all(ObLogicalOperator* op, bool &is_inherit_from_access_all); int check_if_union_all_match_extended_partition_wise(const ObIArray &child_ops, bool &is_match_ext_pw); int get_largest_sharding_child(const ObIArray &child_ops, const int64_t candi_pos, ObLogicalOperator *&largest_op); int allocate_union_all_as_top(const ObIArray &child_plans, DistAlgo dist_set_method, ObLogicalOperator *&top); int allocate_set_distinct_as_top(ObLogicalOperator *&top); int candi_allocate_recursive_union_all(const ObIArray &child_plans); int create_recursive_union_all_plan(ObIArray &left_best_plans, ObIArray &right_best_plans, const ObIArray &order_items, const bool ignore_hint, ObIArray &all_plans); int create_recursive_union_all_plan(ObLogicalOperator *left_child, ObLogicalOperator *right_child, const ObIArray &candi_order_items, const bool ignore_hint, ObLogicalOperator *&top); int allocate_recursive_union_all_as_top(ObLogicalOperator *left_child, ObLogicalOperator *right_child, DistAlgo dist_set_method, ObLogicalOperator *&top); int candi_allocate_distinct_set(const ObIArray &child_plans); int get_allowed_branch_order(const bool ignore_hint, const ObSelectStmt::SetOperator set_op, bool &no_swap, bool &swap); /** * @brief create_hash_set * create hash-based set operation * @return */ int generate_hash_set_plans(const EqualSets &equal_sets, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, const ObIArray &left_best_plans, const ObIArray &right_best_plans, const bool ignore_hint, ObIArray &hash_set_plans); int inner_generate_hash_set_plans(const EqualSets &equal_sets, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, const ObIArray &left_best_plans, const ObIArray &right_best_plans, const bool ignore_hint, ObIArray &hash_set_plans); int create_hash_set_plan(const EqualSets &equal_sets, ObLogicalOperator *left_child, ObLogicalOperator *right_child, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, DistAlgo dist_set_method, CandidatePlan &hash_plan); int compute_set_exchange_info(const EqualSets &equal_sets, ObLogicalOperator &left_child, ObLogicalOperator &right_child, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, DistAlgo set_method, ObExchangeInfo &left_exch_info, ObExchangeInfo &right_exch_info); int compute_set_hash_hash_sharding(const EqualSets &equal_sets, const ObIArray &left_keys, const ObIArray &right_keys, ObShardingInfo *&sharding); int generate_merge_set_plans(const EqualSets &equal_sets, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, ObIArray> &left_candidate_list, ObIArray> &right_candidate_list, const bool ignore_hint, const bool no_hash_plans, ObIArray &merge_set_plans); int inner_generate_merge_set_plans(const EqualSets &equal_sets, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObIArray &left_merge_keys, const ObSelectStmt::SetOperator set_op, ObIArray &left_candidates, ObIArray &right_candidates, const bool ignore_hint, const bool can_ignore_merge_plan, const bool no_hash_plans, ObIArray &merge_set_plans); int get_minimal_cost_set_plan(const int64_t in_parallel, const ObLogicalOperator &left_child, const MergeKeyInfo &left_merge_key, const ObIArray &right_set_exprs, const ObIArray &right_candi, const DistAlgo set_dist_algo, ObIArray &best_order_items, ObLogicalOperator *&best_plan, bool &best_need_sort, int64_t &best_prefix_pos, const bool can_ignore_merge_plan); int decide_merge_set_sort_key(const ObIArray &set_order_items, const ObIArray &input_ordering, const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObIArray &exec_ref_exprs, const bool is_at_most_one_row, const ObIArray &merge_exprs, const ObIArray &default_directions, MergeKeyInfo &merge_key); int convert_set_order_item(const ObDMLStmt *stmt, const ObIArray &select_exprs, ObIArray &order_items); int create_merge_set_key(const ObIArray &set_order_items, const ObIArray &merge_exprs, const EqualSets &equal_sets, MergeKeyInfo &merge_key); /** * @brief create_merge_set * create merge-based set operation * @return */ int create_merge_set_plan(const EqualSets &equal_sets, ObLogicalOperator *left_child, ObLogicalOperator *right_child, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, const DistAlgo dist_set_method, const ObIArray &order_directions, const ObIArray &map_array, const ObIArray &left_sort_keys, const bool left_need_sort, const int64_t left_prefix_pos, const ObIArray &right_sort_keys, const bool right_need_sort, const int64_t right_prefix_pos, CandidatePlan &merge_plan); int allocate_distinct_set_as_top(ObLogicalOperator *left_child, ObLogicalOperator *right_child, SetAlgo set_method, DistAlgo dist_set_method, ObLogicalOperator *&top, const ObIArray *order_directions = NULL, const ObIArray *map_array = NULL); int get_distributed_set_methods(const EqualSets &equal_sets, const ObIArray &left_set_keys, const ObIArray &right_set_keys, const ObSelectStmt::SetOperator set_op, const SetAlgo set_method, ObLogicalOperator &left_child, ObLogicalOperator &right_child, const bool ignore_hint, int64_t &set_dist_methods); bool is_set_partition_wise_valid(const ObLogicalOperator &left_plan, const ObLogicalOperator &right_plan); bool is_set_repart_valid(const ObLogicalOperator &left_plan, const ObLogicalOperator &right_plan, const DistAlgo dist_algo); int check_if_set_match_repart(const EqualSets &equal_sets, const ObIArray &src_join_keys, const ObIArray &target_join_keys, const ObLogicalOperator &target_child, bool &is_match_repart); int check_if_set_match_rehash(const EqualSets &equal_sets, const ObIArray &src_join_keys, const ObIArray &target_join_keys, const ObLogicalOperator &target_child, bool &is_match_single_side_hash); /** * @brief generate_subquery_plan * generate sub query plan * @return */ int generate_child_plan_for_set(const ObDMLStmt *sub_stmt, ObSelectLogPlan *&sub_plan, ObIArray &pushdown_filters, const uint64_t child_offset, const bool is_set_distinct, ObSelectLogPlan *nonrecursive_plan); /** * @brief GENERATE the PLAN tree FOR PLAIN SELECT stmt * Warning: * @param void * @retval OB_SUCCESS execute success * @retval otherwise, failed to generate the logical plan */ int generate_raw_plan_for_plain_select(); /** * @brief GENERATE the PLAN tree FOR select EXPR from dual * Warning: * @param void * @retval OB_SUCCESS execute success * @retval otherwise, failed to generate the logical plan */ int generate_raw_plan_for_expr_values(); /** * @brief GENERATE the PLAN TOP FOR select stmt * Warning: * @param void * @retval OB_SUCCESS execute success * @retval otherwise, failed to generate the top operators of plan tree */ int allocate_plan_top(); /** * 处理select子句里的子查询,生成SubPlan * @param * @return */ // int process_subplan(); int candi_allocate_subplan_filter_for_select_item(common::ObIArray &order_items); struct WinFuncOpHelper { WinFuncOpHelper(const ObIArray &all_win_func_exprs, const ObWindowDistHint *win_dist_hint, const bool explicit_hint, const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const double card, const bool is_at_most_one_row, const ObIArray &qualify_filters) : all_win_func_exprs_(all_win_func_exprs), win_dist_hint_(win_dist_hint), explicit_hint_(explicit_hint), fd_item_set_(fd_item_set), equal_sets_(equal_sets), const_exprs_(const_exprs), card_(card), is_at_most_one_row_(is_at_most_one_row), win_dist_method_(WinDistAlgo::WIN_DIST_INVALID), force_normal_sort_(false), force_hash_sort_(false), force_no_pushdown_(false), force_pushdown_(false), part_cnt_(false), win_op_idx_(false), wf_aggr_status_expr_(NULL), need_qualify_filter_(false), qualify_filters_(qualify_filters), enable_topn_(false), topn_const_(NULL), is_fetch_with_ties_(false), origin_sort_card_(0.0) { } virtual ~WinFuncOpHelper() {} // is const during allocate multi window function op const ObIArray &all_win_func_exprs_; // original ordered window functions from stmt const ObWindowDistHint *win_dist_hint_; const bool explicit_hint_; const ObFdItemSet &fd_item_set_; const EqualSets &equal_sets_; const ObIArray &const_exprs_; const double card_; const bool is_at_most_one_row_; // attribute for single window function op WinDistAlgo win_dist_method_; bool force_normal_sort_; bool force_hash_sort_; bool force_no_pushdown_; // hint force pushdown, at least pushdown one window function bool force_pushdown_; // hint force pushdown, at least pushdown one window function int64_t part_cnt_; int64_t win_op_idx_; ObOpPseudoColumnRawExpr *wf_aggr_status_expr_; ObArray partition_exprs_; ObArray ordered_win_func_exprs_; ObArray sort_key_ndvs_; ObArray> pby_oby_prefixes_; ObArray sort_keys_; //if true, add winfunc filters to winfunc operator bool need_qualify_filter_; const ObIArray &qualify_filters_; //if true, only generate partition topn plans. if false, only generate no partition topn plans. bool enable_topn_; ObRawExpr* topn_const_; bool is_fetch_with_ties_; double origin_sort_card_; TO_STRING_KV(K_(win_dist_method), K_(win_op_idx), K_(force_normal_sort), K_(force_hash_sort), K_(force_no_pushdown), K_(force_pushdown), K_(partition_exprs), K_(part_cnt), K_(ordered_win_func_exprs), K_(win_dist_hint), K_(explicit_hint), K_(enable_topn), K_(topn_const), K_(is_fetch_with_ties), K_(qualify_filters)); }; private: int decide_sort_keys_for_runion(const common::ObIArray &order_items, common::ObIArray &new_order_items); int init_merge_set_structure(common::ObIAllocator &allocator, const common::ObIArray &plans, const common::ObIArray &select_exprs, common::ObIArray &merge_keys, const bool can_ignore_merge_plan); int candi_allocate_window_function(); int candi_allocate_window_function_with_hint(const ObIArray &win_func_exprs, const ObIArray &qualify_filters, common::ObIArray &total_plans); int candi_allocate_window_function(const ObIArray &win_func_exprs, const ObIArray &qualify_filters, ObIArray &total_plans); int create_one_window_function(CandidatePlan &candidate_plan, const WinFuncOpHelper &win_func_helper, ObIArray &all_plans); int create_none_dist_win_func(ObLogicalOperator *top, const WinFuncOpHelper &win_func_helper, const int64_t need_sort, const int64_t prefix_pos, const int64_t part_cnt, ObIArray &all_plans); int create_range_list_dist_win_func(ObLogicalOperator *top, const WinFuncOpHelper &win_func_helper, const int64_t part_cnt, ObIArray &all_plans); int get_range_dist_keys(const WinFuncOpHelper &win_func_helper, const ObWinFunRawExpr *win_func, ObIArray &range_dist_keys, int64_t &pby_prefix); int get_range_list_win_func_exchange_info(const WinDistAlgo dist_method, const ObIArray &range_dist_keys, ObExchangeInfo &exch_info, ObRawExpr *&random_expr); int set_exchange_random_expr(ObLogicalOperator *top, ObRawExpr *random_expr); int create_hash_dist_win_func(ObLogicalOperator *top, const WinFuncOpHelper &win_func_helper, const int64_t need_sort, const int64_t prefix_pos, const int64_t part_cnt, ObIArray &all_plans); int create_normal_hash_dist_win_func(ObLogicalOperator *&top, const ObIArray &win_func_exprs, const ObIArray &partition_exprs, const ObIArray &sort_keys, const int64_t need_sort, const int64_t prefix_pos, OrderItem *hash_sortkey, ObRawExpr *topn_const, bool is_fetch_with_ties, const ObIArray *qualify_filters, double origin_sort_card); int create_pushdown_hash_dist_win_func(ObLogicalOperator *&top, const ObIArray &win_func_exprs, const ObIArray &sort_keys, const ObIArray &pushdown_info, ObOpPseudoColumnRawExpr *wf_aggr_status_expr, const int64_t need_sort, const int64_t prefix_pos, OrderItem *hash_sortkey, const ObIArray *qualify_filters); int check_is_win_func_hint_valid(const ObIArray &all_win_exprs, const ObWindowDistHint *hint, bool &is_valid); int init_win_func_helper_with_hint(const ObIArray &candi_plans, ObIArray &remaining_exprs, WinFuncOpHelper &win_func_helper, bool &is_valid); int calc_win_func_helper_with_hint(const ObLogicalOperator *op, WinFuncOpHelper &win_func_helper, bool &is_valid); int check_win_dist_method_valid(const WinFuncOpHelper &win_func_helper, bool &is_valid); int generate_window_functions_plan(WinFuncOpHelper &win_func_helper, ObIArray &status_exprs, ObIArray &total_plans, CandidatePlan &orig_candidate_plan); int check_win_func_need_sort(const ObLogicalOperator &top, const WinFuncOpHelper &win_func_helper, bool &need_sort, int64_t &prefix_pos, int64_t &part_cnt); int prepare_next_group_win_funcs(const bool distributed, const ObIArray &op_ordering, const int64_t dop, WinFuncOpHelper &win_func_helper, ObIArray &remaining_exprs, ObIArray &ordered_win_func_exprs, ObIArray> &pby_oby_prefixes, ObIArray &split, ObIArray &methods); int init_win_func_helper(const ObIArray &ordered_win_func_exprs, const ObIArray> &pby_oby_prefixes, const ObIArray &split, const ObIArray &methods, const int64_t splict_idx, ObIArray &status_exprs, bool is_last_group, WinFuncOpHelper &win_func_helper); int get_next_group_window_exprs(const ObIArray &op_ordering, WinFuncOpHelper &win_func_helper, ObIArray &remaining_exprs, ObIArray ¤t_exprs); int gen_win_func_sort_keys(const ObIArray &input_ordering, WinFuncOpHelper &win_func_helper, bool &is_valid); int classify_window_exprs(const WinFuncOpHelper &win_func_helper, const ObIArray &input_ordering, const ObIArray &remaining_exprs, ObIArray &no_need_sort_exprs, ObIArray &no_need_order_exprs, ObIArray &rest_win_func_exprs, ObIArray &best_sort_keys, ObIArray &possible_sort_keys); int calc_ndvs_and_pby_oby_prefix(const ObIArray &win_func_exprs, WinFuncOpHelper &win_func_helper, ObIArray> &pby_oby_prefixes); int check_win_func_pushdown(const int64_t dop, const WinFuncOpHelper &win_func_helper, ObIArray &pushdown_info); // Split adjusted window function (`sort_win_func_exprs()` called) into groups such that each // group hash same distribute method. // // @param distributed // @param win_func_exprs window functions to split, must adjusted by `sort_win_func_exprs()` // @param sort_key_ndvs // @param pby_oby_prefixes // @param[out] split split result which stores the %window_exprs array end positions // @param[out] methods window distribute method for each split array int split_win_funcs_by_dist_method(const bool distributed, const common::ObIArray &win_func_exprs, const ObIArray &sort_key_ndvs, const ObIArray> &pby_oby_prefixes, const int64_t dop, const double card, const ObWindowDistHint *hint, const int64_t win_op_idx, common::ObIArray &split, common::ObIArray &methods); // Generate sort keys for window function // @param[out] order_item generated sort keys // @param[out] pby_prefix set the prefix count of %order_item for partition by exprs if not NULL // @return int get_sort_keys_for_window_function(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObWinFunRawExpr *win_expr, const ObIArray &ordering, const ObIArray &winfunc_exprs, ObIArray &order_items, int64_t *pby_prefix = NULL); int get_win_func_pby_oby_sort_prefix(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObWinFunRawExpr *win_expr, const ObIArray &ordering, int64_t &pby_prefix, int64_t &pby_oby_prefix); // Get the PBY, PBY + OBY prefix count of %ordering // e.g.: // sum(v) over (partition by a, b order by b, c) // %ordering should start with [a, b, c] or [b, a, c] // %pby_prefix will be 2 // %pby_oby_prefix will b 3 int get_winfunc_pby_oby_sort_prefix(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObWinFunRawExpr *win_expr, const ObIArray &ordering, int64_t &pby_prefix, int64_t &pby_oby_prefix); int calc_partition_count(WinFuncOpHelper &win_func_helper); /** * @brief set_default_sort_directions * 确定窗口函数partition表达式的排序方向 */ int set_default_sort_directions(const ObIArray &winfunc_entries, const ObIArray &part_exprs, const EqualSets &equal_sets, ObIArray &directions); /** * @brief allocate_window_function_group * 为一组窗口函数表达式分配 ObLogWindowFunction 算子 */ int create_merge_window_function_plan(ObLogicalOperator *&top, const ObIArray &winfunc_exprs, const ObRawExpr *limit_expr, const ObIArray &sort_keys, const ObIArray &partition_exprs, WinDistAlgo dist_method, const bool is_pushdown, ObOpPseudoColumnRawExpr *wf_aggr_status_expr, const ObIArray &pushdown_info, bool need_sort, int64_t prefix_pos, int64_t part_cnt); //init topn_filter,topn_const and is_fetch_with_ties flag int init_wf_topn_option(WinFuncOpHelper &win_func_helper, bool wf_topn_hint); int create_hash_window_function_plan(ObLogicalOperator *&top, const ObIArray &adjusted_winfunc_exprs, const ObIArray &qualify_filter_exprs, const ObRawExpr *limit_expr, const ObIArray &sort_keys, const ObIArray &partition_exprs, const OrderItem &hash_sortkey, const bool is_pushdown, ObOpPseudoColumnRawExpr *wf_aggr_status_expr, const ObIArray &pushdown_info); int sort_window_functions(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObIArray &winfunc_exprs, ObIArray &adjusted_winfunc_exprs, bool &ordering_changed); int match_window_function_parallel(const ObIArray &win_exprs, bool &can_parallel); int check_wf_range_dist_supported(ObWinFunRawExpr *win_expr, bool &supported); int check_wf_pushdown_supported(ObWinFunRawExpr *win_expr, bool &supported); int check_wf_part_topn_supported(const common::ObIArray &winfunc_exprs, const ObIArray &partition_exprs, bool &can_wf_topn); int get_pushdown_window_function_exchange_info(const ObIArray &win_exprs, ObLogicalOperator *op, ObExchangeInfo &exch_info); int extract_window_function_partition_exprs(WinFuncOpHelper &winfunc_helper); int allocate_window_function_as_top(const WinDistAlgo dist_algo, const ObIArray &win_exprs, const bool match_parallel, const bool is_partition_wise, const bool use_hash_sort, const bool use_topn_sort, const ObIArray &sort_keys, ObLogicalOperator *&top, const ObIArray *qualify_filters, double origin_sort_card); int allocate_window_function_as_top(const WinDistAlgo dist_algo, const ObIArray &win_exprs, const bool match_parallel, const bool is_partition_wise, const bool use_hash_sort, const bool use_topn_sort, const int32_t role_type, const ObIArray &sort_keys, const int64_t range_dist_keys_cnt, const int64_t range_dist_pby_prefix, ObLogicalOperator *&top, const ObIArray *qualify_filters, double origin_sort_card, ObOpPseudoColumnRawExpr *wf_aggr_status_expr = NULL, const ObIArray *pushdown_info = NULL); int candi_allocate_late_materialization(); int get_late_materialization_operator(ObLogicalOperator *top, ObLogSort *&sort_op, ObLogTableScan *&table_scan); int adjust_late_materialization_structure(ObSelectStmt *stmt, ObLogicalOperator *join, ObLogTableScan *index_scan, ObLogTableScan *table_scan, TableItem *table_item); int convert_project_columns(ObSelectStmt *stmt, ObIRawExprCopier &expr_copier, uint64_t table_id, TableItem *project_table_item, ObIArray &index_columns); int adjust_late_materialization_stmt_structure(ObSelectStmt *stmt, ObLogTableScan *index_scan, ObLogTableScan *table_scan, TableItem *table_item); int adjust_late_materialization_plan_structure(ObLogicalOperator *join, ObLogTableScan *index_scan, ObLogTableScan *table_scan); int generate_late_materialization_info(ObSelectStmt *stmt, ObLogTableScan *index_scan, ObLogTableScan *&table_get, TableItem *&table_item); int generate_late_materialization_table_get(ObLogTableScan *index_scan, TableItem *table_item, uint64_t table_id, ObLogTableScan *&table_get); int generate_late_materialization_table_item(ObSelectStmt *stmt, uint64_t old_table_id, uint64_t new_table_id, TableItem *&new_table_item); int allocate_late_materialization_join_as_top(ObLogicalOperator *left_child, ObLogicalOperator *right_child, ObLogicalOperator *&join_path); int if_plan_need_late_materialization(ObLogicalOperator *top, ObLogTableScan *&index_scan, double &late_mater_cost, bool &need); int if_index_back_plan_need_late_materialization(ObLogSort *child_sort, ObLogTableScan *table_scan, ObIArray &used_column_ids, bool &need); int if_column_store_plan_need_late_materialization(ObLogSort *child_sort, ObLogTableScan *table_scan, ObIArray &used_column_ids, bool &need); int adjust_est_info_for_index_back_plan(ObLogTableScan *table_scan, ObIArray &used_column_ids); int adjust_est_cost_info_for_column_store_plan(ObLogTableScan *table_scan, ObIArray &used_column_ids); int if_stmt_need_late_materialization(bool &need); int candi_allocate_unpivot(); int allocate_unpivot_as_top(ObLogicalOperator *&old_top); int init_selectivity_metas_for_set(ObSelectLogPlan *sub_plan, const uint64_t child_offset); int inner_create_merge_group_plan(const ObIArray &reduce_exprs, const ObIArray &group_by_exprs, const ObIArray &group_directions, const ObIArray &rollup_exprs, const ObIArray &rollup_directions, const ObIArray &aggr_items, const ObIArray &having_exprs, const bool is_from_povit, GroupingOpHelper &groupby_helper, ObLogicalOperator *&top, bool use_part_sort, bool can_ignore_merge = false); int check_external_table_scan(ObSelectStmt *stmt, bool &has_external_table); int contain_enum_set_rowkeys(const ObLogTableScan &table_scan, bool &contain); DISALLOW_COPY_AND_ASSIGN(ObSelectLogPlan); }; }//end of namespace sql }//end of namespace oceanbase #endif // _OB_LOGICAL_PLAN_TREE_H