/** * 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 _OB_OPTIMIZER_UTIL_H #define _OB_OPTIMIZER_UTIL_H #include "lib/container/ob_array.h" #include "lib/allocator/ob_allocator.h" #include "sql/resolver/dml/ob_insert_stmt.h" #include "sql/resolver/dml/ob_select_stmt.h" #include "sql/resolver/expr/ob_raw_expr_util.h" #include "sql/optimizer/ob_fd_item.h" namespace oceanbase { namespace sql { enum PartitionRelation { NO_COMPATIBLE, COMPATIBLE_SMALL, COMPATIBLE_LARGE, COMPATIBLE_COMMON }; struct MergeKeyInfo { MergeKeyInfo(common::ObIAllocator &allocator, int64_t size) : need_sort_(false), order_needed_(true), prefix_pos_(0), map_array_(allocator, size), order_directions_(allocator, size), order_exprs_(allocator, size), order_items_(allocator, size) { } virtual ~MergeKeyInfo() {}; int assign(MergeKeyInfo &other); TO_STRING_KV(K_(need_sort), K_(order_needed), K_(prefix_pos), K_(map_array), K_(order_directions), K_(order_exprs), K_(order_items)); bool need_sort_; bool order_needed_; int64_t prefix_pos_; common::ObFixedArray map_array_; common::ObFixedArray order_directions_; common::ObFixedArray order_exprs_; common::ObFixedArray order_items_; }; struct ColumnItem; struct OrderItem; class ExprProducer; class ObOptimizerContext; class ObShardingInfo; class ObTablePartitionInfo; struct SubPlanInfo; class OptSelectivityCtx; class Path; class ObSharedExprResolver; class ObOptimizerUtil { public: static int is_prefix_ordering(const ObIArray &first, const ObIArray &second, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &first_is_prefix, bool &second_is_prefix); static int find_common_prefix_ordering(const ObIArray &left_side, const ObIArray &right_side, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &left_is_prefix, bool &right_is_prefix, const ObIArray *left_directions, const ObIArray *right_directions); static int is_const_or_equivalent_expr(const common::ObIArray &exprs, const EqualSets &equal_sets, const common::ObIArray &const_exprs, const common::ObIArray &exec_ref_exprs, const int64_t &pos, bool &is_const); static int is_const_or_equivalent_expr(const common::ObIArray &order_items, const EqualSets &equal_sets, const common::ObIArray &const_exprs, const common::ObIArray &exec_ref_exprs, const int64_t &pos, bool &is_const); static int prefix_subset_ids(const common::ObIArray &pre, const common::ObIArray &full, bool &is_prefix); static int prefix_subset_exprs(const common::ObIArray &exprs, const common::ObIArray &ordering, const EqualSets &equal_sets, const common::ObIArray &const_exprs, bool &is_covered, int64_t *match_count); static int prefix_subset_exprs(const ObIArray &exprs, const ObIArray &ordering, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_prefix); static int adjust_exprs_by_ordering(common::ObIArray &exprs, const common::ObIArray &ordering, const EqualSets &equal_sets, const common::ObIArray &const_exprs, const common::ObIArray &exec_ref_exprs, int64_t &prefix_count, bool &ordering_all_used, common::ObIArray &directions, common::ObIArray *match_map = NULL); // when there is no input ordering or interesting ordering, generate a stable ordering use this function static int generate_stable_ordering(common::ObIArray &exprs, ObIArray &directions); static int generate_stable_ordering(common::ObIArray &exprs, ObIArray &directions, ObBitSet<64> &used_expr_idxs, ObIArray &expr_map, ObIArray &adjusted_exprs, ObIArray &adjusted_directions); static bool stable_expr_cmp_func(std::pair l_pair, std::pair r_pair); static int cmp_expr(ObRawExpr *l_expr, ObRawExpr *r_expr, int64_t &res); static int adjust_exprs_by_mapping(const common::ObIArray &exprs, const common::ObIArray &match_map, common::ObIArray &adjusted_exprs); static bool is_same_ordering(const common::ObIArray &ordering1, const common::ObIArray &ordering2, const EqualSets &equal_sets); static bool in_same_equalset(const ObRawExpr *from, const ObRawExpr *to, const EqualSets &equal_sets); static bool is_expr_equivalent(const ObRawExpr *from, const ObRawExpr *to, const EqualSets &equal_sets); static bool is_exprs_equivalent(const common::ObIArray &from, const common::ObIArray &to, const EqualSets &equal_sets); static bool is_expr_equivalent(const ObRawExpr *from, const ObRawExpr *to); static int is_const_expr(const ObRawExpr* expr, const EqualSets &equal_sets, const common::ObIArray &const_exprs, const common::ObIArray &exec_ref_exprs, bool &is_const); static int is_const_expr_recursively(const ObRawExpr* expr, const common::ObIArray &exec_ref_exprs, bool &is_const); static int is_root_expr_const(const ObRawExpr* expr, const EqualSets &equal_sets, const common::ObIArray &const_exprs, const common::ObIArray &exec_ref_exprs, bool &is_const); static int is_const_expr(const ObRawExpr* expr, const EqualSets &equal_sets, const common::ObIArray &const_exprs, bool &is_const); static int get_non_const_expr_size(const ObIArray &exprs, const EqualSets &equal_sets, const common::ObIArray &const_exprs, const ObIArray &exec_ref_exprs, int64_t &number); static bool is_sub_expr(const ObRawExpr *sub_expr, const ObRawExpr *expr); static bool is_sub_expr(const ObRawExpr *sub_expr, const ObIArray &exprs); static bool is_sub_expr(const ObRawExpr *sub_expr, ObRawExpr *&expr, ObRawExpr **&addr_matched_expr); static bool is_point_based_sub_expr(const ObRawExpr *sub_expr, const ObRawExpr *expr); static bool overlap_exprs(const common::ObIArray &exprs1, const common::ObIArray &exprs2); static bool subset_exprs(const common::ObIArray &sub_exprs, const common::ObIArray &exprs, const EqualSets &equal_sets); static bool subset_exprs(const common::ObIArray &sub_exprs, const common::ObIArray &exprs); static int prefix_subset_exprs(const common::ObIArray &sub_exprs, const uint64_t subexpr_prefix_count, const common::ObIArray &exprs, const uint64_t expr_prefix_count, bool &is_subset); static int intersect_exprs(const ObIArray &first, const ObIArray &right, const EqualSets &equal_sets, ObIArray &result); static int intersect_exprs(const ObIArray &first, const ObIArray &right, ObIArray &result); static int except_exprs(const ObIArray &first, const ObIArray &right, ObIArray &result); static bool same_exprs(const common::ObIArray &src_exprs, const common::ObIArray &target_exprs, const EqualSets &equal_sets); static bool same_exprs(const common::ObIArray &src_exprs, const common::ObIArray &target_exprs); //for topk, non terminal expr with agg params need to be deep copied to prevent sum being replaced //with sum(sum) static int clone_expr_for_topk(ObRawExprFactory &expr_factory, ObRawExpr* src, ObRawExpr* &dst); template static void revert_items(common::ObIArray &items, const int64_t N); template static int remove_item(common::ObIArray &items, const T &item, bool *removed = NULL); template static int remove_item(common::ObIArray &items, const common::ObIArray &rm_items, bool *removed = NULL); /** * @brief find_item * 基于指针比较两个表达式是否相同。通常应用在以下两个场景中: * 1. 表达式生成过程。判断一个表达式是否在下层已经生成了 * 2. 比较 column, aggregation, query ref, winfunc 等表达式 * @param items * @param item * @param idx * @return */ template static bool find_item(const common::ObIArray &items, E item, int64_t *idx = NULL) { bool bret = false; for (int64_t i = 0; !bret && i < items.count(); ++i) { bret = (items.at(i) == item); if (NULL != idx && bret) { *idx = i; } } return bret; } template static int intersect(const ObIArray &first, const ObIArray &second, ObIArray &third); template static int intersect(const ObIArray> &sets, ObIArray &result); template static bool overlap(const ObIArray &first, const ObIArray &second); template static bool is_subset(const ObIArray &first, const ObIArray &second); /** * @brief find_equal_expr * 基于语义比较两个表达式是否相同。 * 先比较指针,后比较表达式结构,最后尝试利用 equal sets * 主要引用在改写或者计划生成中,判断一个谓词,一个排序/分组表达式是否重复 * @param exprs * @param expr * @return */ static bool find_equal_expr(const common::ObIArray &exprs, const ObRawExpr *expr) { int64_t idx = -1; return find_equal_expr(exprs, expr, idx); } static bool find_equal_expr(const common::ObIArray &exprs, const ObRawExpr *expr, int64_t &idx); static bool find_equal_expr(const common::ObIArray &exprs, const ObRawExpr *expr, const EqualSets &equal_sets) { int64_t dummy_index = -1; return find_equal_expr(exprs, expr, equal_sets, dummy_index); } static bool find_equal_expr(const common::ObIArray &exprs, const ObRawExpr *expr, const EqualSets &equal_sets, int64_t &idx); static int append_exprs_no_dup(ObIArray &dst, const ObIArray &src); static int find_stmt_expr_direction(const ObDMLStmt &stmt, const common::ObIArray &exprs, const EqualSets &equal_sets, common::ObIArray &directions); static int find_stmt_expr_direction(const ObDMLStmt &select_stmt, const ObRawExpr *expr, const EqualSets &equal_sets, ObOrderDirection &direction); static bool find_expr_direction(const common::ObIArray &exprs, const ObRawExpr *expr, const EqualSets &equal_sets, ObOrderDirection &direction); static uint64_t hash_expr(ObRawExpr *expr, uint64_t seed) { return expr == NULL ? seed : common::do_hash(*expr, seed); } template static uint64_t hash_exprs(uint64_t seed, const common::ObIArray &expr_array); static uint64_t hash_array(uint64_t seed, const common::ObIArray &data_array); /** * Check if the ctx contains the specified expr */ static bool find_expr(common::ObIArray *ctx, const ObRawExpr &expr); static bool find_expr(common::ObIArray *ctx, const ObRawExpr &expr, ExprProducer *&producer); static int classify_equal_conds(const common::ObIArray &conds, common::ObIArray &normal_conds, common::ObIArray &nullsafe_conds); static int get_equal_keys(const common::ObIArray &exprs, const ObRelIds &left_table_sets, common::ObIArray &left_keys, common::ObIArray &right_keys, common::ObIArray &null_safe_info); static bool find_exec_param(const common::ObIArray ¶ms, const ObExecParamRawExpr *ele); static ObRawExpr* find_exec_param(const common::ObIArray > ¶ms_, const int64_t param_num); static int64_t find_exec_param(const common::ObIArray > ¶ms, const ObRawExpr* expr); static int get_exec_ref_expr(const ObIArray &exec_params, ObIArray &ref_exprs); static int extract_equal_exec_params(const ObIArray &exprs, const ObIArray &my_params, ObIArray &left_keys, common::ObIArray &right_key, common::ObIArray &null_safe_info); static int generate_rowkey_exprs(const ObDMLStmt *stmt, ObOptimizerContext &opt_ctx, const uint64_t table_id, const uint64_t ref_table_id, common::ObIArray &keys, common::ObIArray &ordering); static int generate_rowkey_exprs(const ObDMLStmt* stmt, ObRawExprFactory &expr_factory, uint64_t table_id, const share::schema::ObTableSchema &index_table_schema, common::ObIArray &index_keys, common::ObIArray &index_ordering); static int build_range_columns(const ObDMLStmt *stmt, common::ObIArray &rowkeys, common::ObIArray &range_columns); ///for diff prefix filters and postfix filters enum ColCntType { INITED_VALUE = -4, //only const value TABLE_RELATED = -3, //has column not index_column and primary key INDEX_STORE_RELATED = -2, //has column not index column, but storing column MUL_INDEX_COL = -1, //has more than one index columns in expr not row.some case present not prefix filter }; static int get_subquery_id(const ObDMLStmt *upper_stmt, const ObSelectStmt *stmt, uint64_t &id); static int get_child_corresponding_exprs(const ObDMLStmt *upper_stmt, const ObSelectStmt *stmt, const common::ObIArray &exprs, common::ObIArray &corr_exprs); static int get_child_corresponding_exprs(const TableItem *table, const ObIArray &exprs, ObIArray &corr_exprs); static int is_table_on_null_side(const ObDMLStmt *stmt, uint64_t table_id, bool &is_on_null_side); static int is_table_on_null_side_recursively(const TableItem *table_item, uint64_t table_id, bool &found, bool &is_on_null_side); static int is_table_on_null_side_of_parent(const ObDMLStmt *stmt, uint64_t source_table_id, uint64_t target_table_id, bool &is_on_null_side); static int find_common_joined_table(JoinedTable *joined_table, uint64_t source_table_id, uint64_t target_table_id, JoinedTable *&target_joined_table); static int get_referenced_columns(const ObDMLStmt *stmt, const uint64_t table_id, const common::ObIArray &keys, common::ObIArray &columns); static int get_non_referenced_columns(const ObDMLStmt *stmt, const uint64_t table_id, const common::ObIArray &keys, common::ObIArray &columns); static int extract_parameterized_correlated_filters(const common::ObIArray &filters, common::ObIArray &correlated_filters, common::ObIArray &uncorrelated_filters); static int add_parameterized_expr(ObRawExpr *&target_expr, ObRawExpr *orig_expr, ObRawExpr *child_expr, int64_t child_idx); static int get_default_directions(const int64_t direction_num, ObIArray &directions); static int make_sort_keys(const ObIArray &candi_sort_keys, const ObIArray &need_sort_exprs, ObIArray &sort_keys); static int make_sort_keys(const ObIArray &candi_sort_exprs, const ObIArray &candi_directions, const ObIArray &need_sort_exprs, ObIArray &sort_keys); static int make_sort_keys(const common::ObIArray &sort_exprs, common::ObIArray &sort_keys); static int make_sort_keys(const common::ObIArray &sort_exprs, const ObOrderDirection direction, common::ObIArray &sort_keys); static int make_sort_keys(const common::ObIArray &sort_exprs, const common::ObIArray &sort_directions, common::ObIArray &sort_keys); static int split_expr_direction(const common::ObIArray &order_items, common::ObIArray &raw_exprs, common::ObIArray &directions); static int get_expr_and_types(const common::ObIArray &order_items, ObIArray &order_exprs, ObIArray &order_types); static int extract_column_ids(const ObRawExpr *expr, const uint64_t table_id, common::ObIArray &column_ids); static int is_const_expr(const ObRawExpr *expr, const common::ObIArray &conditions, bool &is_const); static int is_same_table( const ObIArray &exprs, uint64_t &table_id, bool &is_same); static int find_equal_set(const ObRawExpr* ordering, const EqualSets &equal_sets, common::ObIArray &found_sets); /** @brief 获取T_OP_ROW IN T_OP_ROW中对query_range范围产生影响的column * 最小的column_idx最为整体filter的column_idx,决定是否是前缀索引 * @param [in] column_ids 索引列 + primary key * @param [in] index_col_pos 索引列在range_columns中最大的pos * @param [in] table_id 访问表在stmt中的table_id * @param [in] l_expr, r_expr T_OP_ROW * @param [in/out] col_idxs记录影响query range的column * @param [out] is_table_filter 是否包含不在range columns中的列 */ static int extract_row_col_idx_for_in(const common::ObIArray &column_ids, const int64_t index_col_pos, const uint64_t table_id, const ObRawExpr &l_expr, const ObRawExpr &r_expr, common::ObBitSet<> &col_idxs, int64_t &min_col_idx, bool &is_table_filter); ///@brief 获取T_OP_ROW cmp T_OP_ROW中对query_range range范围产生影响的的column ///最小的column_idx最为整体filter的column_idx,决定是否是前缀索引 ///@param [in] column_ids 索引列 + primary key ///@param [in] index_col_pos 索引列在range_columns中最大的pos ///@param [in] table_id 访问表在stmt中的table_id ///@param [in] l_expr, r_expr T_OP_ROW ///@param [in/out] col_idxs记录影响query range的column ///@param [out] is_table_filter 是否包含不在range columns中的列 static int extract_row_col_idx(const common::ObIArray &column_ids, const int64_t index_col_pos, const uint64_t table_id, const ObRawExpr &l_expr, const ObRawExpr &r_expr, common::ObBitSet<> &col_idxs, int64_t &min_col_idx, bool &is_table_filter); ///@brief 获取filter中包含的column在column_ids中的column_idx. ///负值的column_idx意义见类ColCntType //@is_org_filter 输入的expr是否是原始的filter,而不是递归的expr static int extract_column_idx(const common::ObIArray &column_ids, const int64_t index_col_pos, const uint64_t table_id, const ObRawExpr *raw_expr, int64_t &col_idx, common::ObBitSet<> &col_idxs, const bool is_org_filter = false); static bool is_query_range_op(const ObItemType type); static int find_table_item(const TableItem *table_item, uint64_t table_id, bool &found); static int extract_column_ids(const ObRawExpr *expr, const uint64_t table_id, common::ObBitSet<> &column_ids); static int extract_column_ids(const common::ObIArray &exprs, const uint64_t table_id, common::ObIArray &column_ids); static int extract_column_ids(const common::ObIArray &exprs, const uint64_t table_id, common::ObBitSet<> &column_ids); static int check_equal_query_ranges(const common::ObIArray &ranges, const int64_t prefix_len, bool &all_prefix_single, bool &all_full_single); static int check_prefix_ranges_count(const common::ObIArray &ranges, int64_t &equal_prefix_count, int64_t &equal_prefix_null_count, int64_t &range_prefix_count, bool &contain_always_false); static int check_prefix_ranges_count(const common::ObIArray &ranges, int64_t &equal_prefix_count, int64_t &equal_prefix_null_count, int64_t &range_prefix_count); static int check_prefix_range_count(const common::ObNewRange* range, int64_t &equal_prefix_count, int64_t &range_prefix_count); static int check_equal_prefix_null_count(const common::ObNewRange *range, const int64_t equal_prefix_count, int64_t &equal_prefix_null_count); static bool same_partition_exprs(const common::ObIArray &l_exprs, const common::ObIArray &r_exprs, const EqualSets &equal_sets); static int classify_subquery_exprs(const ObIArray &exprs, ObIArray &subquery_exprs, ObIArray &non_subquery_exprs, const bool with_onetime = true); static int get_subquery_exprs(const ObIArray &exprs, ObIArray &subquery_exprs, const bool with_onetime = true); static int get_onetime_exprs(ObRawExpr* expr, ObIArray &onetime_exprs); static int get_query_ref_exprs(ObIArray &subquery_exprs, ObIArray &subqueries, ObIArray &nested_subqueries); static int get_nested_exprs(ObIArray &exprs, ObIArray &nested_exprs); static int classify_get_scan_ranges(const common::ObIArray &input_ranges, common::ObIArray &get_ranges, common::ObIArray &scan_ranges); static int is_exprs_unique(const ObIArray &ordering, const ObIArray &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &order_unique); static int is_exprs_unique(const ObIArray &ordering, const ObRelIds &all_tables, const ObIArray &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &order_unique); static int is_exprs_unique(const ObIArray &exprs, const ObRelIds &all_tables, const ObIArray &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_unique); static int is_exprs_unique(const ObIArray &exprs, const ObIArray &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_unique); static int is_exprs_unique(ObIArray &extend_exprs, ObRelIds &remain_tables, const ObIArray &fd_item_set, ObIArray &fd_set_parent_exprs, ObSqlBitSet<> &skip_fd, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_unique); static int get_fd_set_parent_exprs(const ObIArray &fd_item_set, ObIArray &fd_set_parent_exprs); /* * @param [in] fd_item * @param [in] equal_sets * @param [in/out] exprs, 分离 exprs 中包含在 fd_item child exprs 中的 expr 到 child_exprs 中 * @param [in/out] child_exprs * */ static int split_child_exprs(const ObFdItem *fd_item, const EqualSets &equal_sets, ObIArray &exprs, ObIArray &child_exprs); static int is_expr_is_determined(const ObIArray &exprs, const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObRawExpr *expr, bool &is_determined); static int is_exprs_contain_fd_parent(const ObIArray &exprs, const ObFdItem &fd_item, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_unique); static int add_fd_item_set_for_n21_join(ObFdItemFactory &fd_factory, ObIArray &target, const ObIArray &source, const ObIArray &join_exprs, const EqualSets &equal_sets, const ObRelIds &right_table_set); static int add_fd_item_set_for_n2n_join(ObFdItemFactory &fd_factory, ObIArray &target, const ObIArray &source); static int enhance_fd_item_set(const ObIArray &quals, ObIArray &candi_fd_item_set, ObIArray &fd_item_set, ObIArray ¬_null_columns); static int try_add_fd_item(const ObDMLStmt *stmt, ObFdItemFactory &fd_factory, const uint64_t table_id, ObRelIds &tables, const share::schema::ObTableSchema *index_schema, const ObIArray &quals, ObIArray ¬_null_columns, ObIArray &fd_item_set, ObIArray &candi_fd_item_set); static int convert_subplan_scan_equal_sets(ObIAllocator *allocator, ObRawExprFactory &expr_factory, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, const EqualSets &input_equal_sets, EqualSets &output_equal_sets); static int convert_subplan_scan_fd_item_sets(ObFdItemFactory &fd_factory, ObRawExprFactory &expr_factory, const EqualSets &equal_sets, const ObIArray &const_exprs, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, const ObFdItemSet &input_fd_item_sets, ObFdItemSet &output_fd_item_sets); static int convert_subplan_scan_fd_parent_exprs(ObRawExprFactory &expr_factory, const EqualSets &equal_sets, const ObIArray &const_exprs, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, const ObIArray &input_exprs, ObIArray &output_exprs); static int add_fd_item_set_for_left_join(ObFdItemFactory &fd_factory, const ObRelIds &right_tables, const ObIArray &right_join_exprs, const ObIArray &right_const_exprs, const EqualSets &right_equal_sets, const ObIArray &right_fd_item_sets, const ObIArray &all_left_join_exprs, const EqualSets &left_equal_sets, const ObIArray &left_fd_item_sets, const ObIArray &left_candi_fd_item_sets, ObIArray &fd_item_sets, ObIArray &candi_fd_item_sets); static int check_need_sort(const ObIArray &expected_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, bool &need_sort, int64_t &prefix_pos, const int64_t part_cnt, const bool check_part_only = false); static int check_need_sort(const ObIArray &expected_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, bool &need_sort, int64_t &prefix_pos); static int check_need_sort(const ObIArray &expected_order_exprs, const ObIArray *expected_order_directions, 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, bool &need_sort, int64_t &prefix_pos); static int check_need_sort(const ObIArray &expected_order_exprs, const ObIArray *expected_order_directions, 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, bool &need_sort, int64_t &prefix_pos, const int64_t part_cnt, const bool check_part_only = false); static int decide_sort_keys_for_merge_style_op(const ObDMLStmt *stmt, const EqualSets &stmt_equal_sets, 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, MergeKeyInfo *&interesting_key); static int create_interesting_merge_key(const ObDMLStmt *stmt, const ObIArray &merge_exprs, const EqualSets &equal_sets, MergeKeyInfo &merge_key); static int create_interesting_merge_key(const ObIArray &merge_exprs, const ObIArray &expect_key, const EqualSets &equal_sets, ObIArray &sort_exprs, ObIArray &directions, ObIArray &sort_map); static int flip_op_type(const ObItemType expr_type, ObItemType &rotated_expr_type); static int get_rownum_filter_info(ObRawExpr *rownum_expr, ObItemType &expr_type, ObRawExpr *&const_expr, bool &is_const_filter); static int convert_rownum_filter_as_offset(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, const ObItemType filter_type, ObRawExpr *const_expr, ObRawExpr *&offset_int_expr, ObRawExpr *zero_expr, bool &offset_is_not_neg, ObTransformerCtx *ctx); static int convert_rownum_filter_as_limit(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, const ObItemType filter_type, ObRawExpr *const_expr, ObRawExpr *&limit_int_expr); // used by //1. rownum <= num_expr => limit int_expr // int_expr = floor(num_expr) // rownum <= 2.4 => limit 2 // rownum <= 2 => limit 2 //2. rownum > num_expr => offset int_expr // rownum > 2.4 => offset 2 // rownum > 2 => offset 2 static int floor_number_as_limit_offset_value(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, ObRawExpr *num_expr, ObRawExpr *&int_expr); // used by //1. rownum < num_expr => limit int_expr // int_expr = ceill(num_expr) - 1 // rownum < 2.4 => limit 2 // rownum < 2 => limit 1 //2. rownum >= num_expr => offset int_expr // rownum >= 2.4 => offset 2 // rownum >= 2 => offset 1 static int ceil_number_as_limit_offset_value(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, ObRawExpr *num_expr, ObRawExpr *&int_expr); /** * @brief get_type_safe_join_exprs * 解析 join_quals,将等值连接条件分解成 left exprs 和 right exprs * 并且保证这些 exprs 在判断连接条件的时候不会有类型转换 * @return */ static int get_type_safe_join_exprs(const ObIArray &join_quals, const ObRelIds &left_tables, const ObRelIds &right_tables, ObIArray &left_exprs, ObIArray &right_exprs, ObIArray &all_left_exprs, ObIArray &all_right_exprs); /** * @brief split_or_qual_on_table * 从or谓词中分离出属于特定table的谓词并生成一个新的谓词 * 要求or谓词的每一个子谓词中都有属于该table的谓词 * @param new_expr 新生成的谓词,值为NULL表示无法从or谓词中分离属于table的谓词 */ static int split_or_qual_on_table(const ObDMLStmt *stmt, ObOptimizerContext &opt_ctx, const ObRelIds &table_ids, ObOpRawExpr &or_qual, ObOpRawExpr *&new_expr); static int check_push_down_expr(const ObRelIds &table_ids, ObOpRawExpr &or_qual, ObIArray > &sub_exprs, bool &all_contain); static int generate_push_down_expr(const ObDMLStmt *stmt, ObOptimizerContext &opt_ctx, ObIArray > &sub_exprs, ObOpRawExpr *&new_expr); static int simplify_exprs(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObIArray &candi_exprs, ObIArray &root_exprs); static int simplify_ordered_exprs(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObIArray &exec_ref_exprs, const ObIArray &candi_exprs, ObIArray &root_exprs); static int simplify_ordered_exprs(const ObFdItemSet &fd_item_set, const EqualSets &equal_sets, const ObIArray &const_exprs, const ObIArray &exec_ref_exprs, const ObIArray &candi_items, ObIArray &root_items); static int check_subquery_filter(const JoinedTable *table, bool &has); static bool has_equal_join_conditions(const ObIArray &join_conditions); static int get_subplan_const_column(const ObDMLStmt &parent_stmt, const uint64_t table_id, const ObSelectStmt &child_stmt, const ObIArray &exec_ref_exprs, ObIArray &output_exprs); /* * 以下函数主要用于把subplan scan中内层继承上来的属性(e.g.,ordering,unique set,partition key)转换成外层可以识别的属性 * 例子: select * from (select * from t1 where t1.a = t1.b order by t1.a) t2 order by t2.a, t2.b; * 内层ordering t1.a转换成外层可以识别的t2.a * 内存的equal set t1.a = t1.b转换成外层可以识别的t2.a = t2.b * * skip_invalid: true represents ignoring these that can not be converted(i.e., equal sets), * otherwise should return empty output exprs if some input expr can not be converted (i.e., unique sets) */ static int convert_subplan_scan_expr(ObRawExprFactory &expr_factory, const EqualSets &equal_sets, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, bool skip_invalid, const ObIArray &input_exprs, common::ObIArray &output_exprs); static int convert_subplan_scan_expr(ObRawExprCopier &copier, const EqualSets &equal_sets, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, ObRawExpr *input_expr, ObRawExpr *&output_expr); static int check_subplan_scan_expr_validity(const EqualSets &equal_sets, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, const ObRawExpr *input_expr, bool &is_valid); static int get_parent_stmt_expr(const EqualSets &equal_sets, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, const ObRawExpr *child_expr, ObRawExpr *&parent_expr); static int get_parent_stmt_exprs(const EqualSets &equal_sets, const uint64_t table_id, const ObDMLStmt &parent_stmt, const ObSelectStmt &child_stmt, const ObIArray &child_exprs, ObIArray &parent_exprs); static int compute_const_exprs(const ObIArray &condition_exprs, ObIArray &const_exprs); static int compute_const_exprs(ObRawExpr *cur_expr, ObRawExpr *&res_const_expr); static int compute_stmt_interesting_order(const ObIArray &ordering, const ObDMLStmt *stmt, const bool in_subplan_scan, EqualSets &equal_sets, const ObIArray &const_exprs, const bool is_parent_set_disinct, const int64_t check_scope, int64_t &match_info, int64_t &max_prefix_count); static int compute_stmt_interesting_order(const ObIArray &ordering, const ObDMLStmt *stmt, const bool in_subplan_scan, EqualSets &equal_sets, const ObIArray &const_exprs, const bool is_parent_set_distinct, const int64_t check_scope, int64_t &match_info); /** * 用来判断group by是否匹配序的前缀 * @ordering 待匹配的序 * @match_prefix_count 匹配序前缀长度 * @sort_match 是否是有效的匹配 */ static int is_group_by_match(const ObIArray &ordering, const ObSelectStmt *select_stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match); static int is_group_by_match(const ObIArray &ordering, const ObSelectStmt *select_stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &sort_match); /** * 判断win func的partition以及orderby是否匹配序的前缀 * @ordering 待匹配的序 * @match_prefix_count 匹配序前缀长度 * @sort_match 是否是有效的匹配 */ static int is_winfunc_match(const ObIArray &ordering, const ObSelectStmt *select_stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match, bool &sort_is_required); static int is_winfunc_match(const ObIArray &ordering, const ObSelectStmt *select_stmt, const ObWinFunRawExpr *win_expr, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match, bool &sort_is_required); // fast check, return a bool result static int is_winfunc_match(const ObIArray &ordering, const ObSelectStmt *select_stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_match); static int match_order_by_against_index(const ObIArray &expect_ordering, const ObIArray &input_ordering, const int64_t input_start_offset, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &full_covered, int64_t &match_count, bool check_direction = true); /** * 用来判断distinct的列或set的列是否匹配序前缀 * @ordering 待匹配的序 * @match_prefix_count 匹配序前缀长度 * @sort_match 是否是有效的匹配 */ static int is_set_or_distinct_match(const ObIArray &keys, const ObSelectStmt *select_stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match); static int is_distinct_match(const ObIArray &keys, const ObSelectStmt *stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match); static int is_set_match(const ObIArray &keys, const ObSelectStmt *stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match); /** * 用来判断order by的列能否匹配序的前缀 * @ordering 待匹配的序 * @match_prefix_count 匹配序前缀长度 * @sort_match 是否是有效的匹配 */ static int is_order_by_match(const ObIArray &ordering, const ObDMLStmt *stmt, const EqualSets &equal_sets, const ObIArray &const_exprs, int64_t &match_prefix_count, bool &sort_match); // fast check, return bool result static int is_order_by_match(const ObIArray &expect_ordering, const ObIArray &input_ordering, const EqualSets &equal_sets, const ObIArray &const_exprs, bool &is_match); static int is_lossless_column_cast(const ObRawExpr *expr, bool &is_lossless); static bool is_lossless_type_conv(const ObExprResType &child_type, const ObExprResType &dst_type); static int is_lossless_column_conv(const ObRawExpr *expr, bool &is_lossless); static int get_expr_without_lossless_cast(const ObRawExpr* ori_expr, const ObRawExpr*& expr); static int get_expr_without_lossless_cast(ObRawExpr* ori_expr, ObRawExpr*& expr); static int gen_set_target_list(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObSelectStmt &left_stmt, ObSelectStmt &right_stmt, ObSelectStmt *select_stmt, const bool is_mysql_recursive_union = false, ObIArray *rcte_col_name = NULL); static int gen_set_target_list(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObIArray &left_stmts, ObIArray &right_stmts, ObSelectStmt *select_stmt, const bool is_mysql_recursive_union = false, ObIArray *rcte_col_name = NULL); static int gen_set_target_list(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObSelectStmt *select_stmt); static int get_set_res_types(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObIArray &child_querys, ObIArray &res_types); static int try_add_cast_to_set_child_list(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, const bool is_distinct, ObIArray &left_stmts, ObIArray &right_stmts, ObIArray *res_types, const bool is_mysql_recursive_union = false, ObIArray *rcte_col_name = NULL); static int add_cast_to_set_list(ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObIArray &stmts, const ObExprResType &res_type, const int64_t idx); static int add_column_conv_to_set_list(ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObIArray &stmts, const ObExprResType &res_type, const int64_t idx, ObIArray *rcte_col_name); static int check_subquery_has_ref_assign_user_var(ObRawExpr *expr, bool &is_has); /** * @brief pushdown_filter_into_subquery * 条件下推到subquery内部,如果不能下推到subquery的where * 返回不能下推 * @param pushdown_quals 参数化后待下推的谓词 * @param candi_filters 能够下推的谓词 * @param remain_filters 未成功下推的谓词 * @param can_pushdown 能够下推谓词 */ static int pushdown_filter_into_subquery(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, ObOptimizerContext &opt_ctx, ObIArray &pushdown_filters, ObIArray &candi_filters, ObIArray &remain_filters, bool &can_pushdown, bool check_match_index = true); /** * @brief check_pushdown_filter * 检查哪些谓词可以下推到子查询的where * 谓词需要下推过win func和group by * @param pushdown_filters 待下推的谓词 * @param candi_filters 能够下推的谓词 * @param remain_filters 未成功下推的谓词 */ static int check_pushdown_filter(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, ObOptimizerContext &opt_ctx, ObIArray &pushdown_filters, ObIArray &candi_filters, ObIArray &remain_filters, bool check_match_index = true); static int remove_special_exprs(ObIArray &pushdown_filters, ObIArray &remain_filters); static int check_pushdown_filter_overlap_index(const ObDMLStmt &stmt, ObOptimizerContext &opt_ctx, ObIArray &pushdown_filters, ObIArray &candi_filters, ObIArray &remain_filters); /** * @brief check_pushdown_filter_for_set * 检查哪些谓词可以下推到子查询的where * 谓词需要下推过win func和group by * 如果parent stmt是set stmt,需要调用此函数 * @param pushdown_filters 待下推的谓词 * @param candi_filters 能够下推的谓词 * @param remain_filters 未成功下推的谓词 */ static int check_pushdown_filter_for_set(const ObSelectStmt &parent_stmt, const ObSelectStmt &subquery, ObIArray &common_exprs, ObIArray &pushdown_filters, ObIArray &candi_filters, ObIArray &remain_filters); static int check_pushdown_filter_for_subquery(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, ObOptimizerContext &opt_ctx, ObIArray &common_exprs, ObIArray &pushdown_filters, ObIArray &candi_filters, ObIArray &remain_filters, bool check_match_index = true); /** * @brief get_groupby_win_func_common_exprs * 获取group exprs与win func partition by exprs的交集 * @param common_exprs 交集表达式集合 * @param is_valid 是否有group 或 win func */ static int get_groupby_win_func_common_exprs(const ObSelectStmt &subquery, ObIArray &common_exprs, bool &is_valid); static int rename_pushdown_filter(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, int64_t table_id, ObSQLSessionInfo *session_info, ObRawExprFactory &expr_factory, ObIArray &candi_filters, ObIArray &rename_filters); static int rename_set_op_pushdown_filter(const ObSelectStmt &parent_stmt, const ObSelectStmt &subquery, ObSQLSessionInfo *session_info, ObRawExprFactory &expr_factory, ObIArray &candi_filters, ObIArray &rename_filters); static int rename_subquery_pushdown_filter(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, int64_t table_id, ObSQLSessionInfo *session_info, ObRawExprFactory &expr_factory, ObIArray &candi_filters, ObIArray &rename_filters); /** * @brief get_set_op_remain_filter * 收集set stmt左右子查询下推谓词后剩余在当前stmt的谓词 * @param child_pushdown_preds 单个子查询未下推的谓词 * @param output_pushdown_preds 剩余在set stmt中的谓词 * @param first_child 第一个分支 */ static int get_set_op_remain_filter(const ObSelectStmt &stmt, const ObIArray &child_pushdown_preds, ObIArray &output_pushdown_preds, const bool first_child); static int check_is_null_qual(const ParamStore *params, const ObDMLStmt *stmt, ObExecContext *exec_ctx, ObIAllocator &allocator, const ObRelIds &table_ids, const ObRawExpr* qual, bool &is_null_qual); static int check_expr_contain_subquery(const ObIArray &exprs, bool &has_subquery); static bool has_psedu_column(const ObRawExpr &expr); static bool has_hierarchical_expr(const ObRawExpr &expr); static int check_pushdown_filter_to_base_table(ObLogPlan &plan, const uint64_t table_id, const ObIArray &pushdown_filters, const ObIArray &restrict_infos, bool &can_pushdown); static int compute_ordering_relationship(const bool left_is_interesting, const bool right_is_interesting, const common::ObIArray &left_ordering, const common::ObIArray &right_ordering, const EqualSets &equal_sets, const common::ObIArray &condition_exprs, DominateRelation &relation); static int compute_sharding_relationship(const ObShardingInfo *left_strong_sharding, const ObIArray &left_weak_sharding, const ObShardingInfo *right_strong_sharding, const ObIArray &right_weak_sharding, const EqualSets &equal_sets, DominateRelation &relation); static int compute_sharding_relationship(const ObIArray &left_sharding, const ObIArray &right_sharding, const EqualSets &equal_sets, DominateRelation &relation); static int compute_sharding_relationship(const ObShardingInfo *left_sharding, const ObShardingInfo *right_sharding, const EqualSets &equal_sets, DominateRelation &relation); static int check_sharding_set_left_dominate(const ObIArray &left_sharding, const ObIArray &right_sharding, const EqualSets &equal_sets, bool &is_left_dominate); static int get_range_params(ObLogicalOperator *root, ObIArray &range_exprs, ObIArray &all_table_filters); static int check_basic_sharding_info(const ObAddr &local_addr, const ObIArray &child_ops, bool &is_basic); static int check_basic_sharding_info(const ObAddr &local_addr, const ObIArray &child_ops, bool &is_basic, bool &is_remote); static int check_basic_sharding_info(const ObAddr &local_server, const ObIArray &input_shardings, bool &is_basic); static int check_basic_sharding_info(const ObAddr &local_server, const ObIArray &input_shardings, bool &is_basic, bool &is_remote); static int compute_basic_sharding_info(const ObAddr &local_addr, const ObIArray &child_ops, ObIAllocator &allocator, ObShardingInfo *&result_sharding, int64_t &inherit_sharding_index); static int compute_basic_sharding_info(const ObAddr &local_addr, const ObIArray &input_shardings, ObIAllocator &allocator, ObShardingInfo *&result_sharding, int64_t &inherit_sharding_index); static int get_duplicate_table_replica(const ObCandiTableLoc &phy_table_loc, ObIArray &valid_addrs); static int compute_duplicate_table_sharding(const ObAddr &local_addr, const ObAddr &selected_addr, ObIAllocator &allocator, ObShardingInfo &src_sharding, ObIArray &valid_addrs, ObShardingInfo *&target_sharding); static int generate_duplicate_table_replicas(ObIAllocator &allocator, const ObCandiTableLoc *source_table_loc, ObIArray &valid_addrs, ObCandiTableLoc *&target_table_loc); static int64_t get_join_style_parallel(const int64_t left_parallel, const int64_t right_parallel, const DistAlgo join_dist_algo, const bool use_left = false); static bool is_left_need_exchange(const ObShardingInfo &sharding, const DistAlgo dist_algo); static bool is_right_need_exchange(const ObShardingInfo &sharding, const DistAlgo dist_algo); static ObPQDistributeMethod::Type get_left_dist_method(const ObShardingInfo &sharding, const DistAlgo dist_algo); static ObPQDistributeMethod::Type get_right_dist_method(const ObShardingInfo &sharding, const DistAlgo dist_algo); // aggregate partial results static int generate_pullup_aggr_expr(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, ObAggFunRawExpr *origin_aggr, ObAggFunRawExpr *&replaced_aggr); static int check_filter_before_indexback(const ObIArray &filter_exprs, const ObIArray &index_columns, ObIArray &filter_before_index_back); //generate expr and column item for column. // static int generate_rowkey_expr(ObDMLStmt *stmt, ObRawExprFactory &expr_factory, const uint64_t &table_id, const share::schema::ObColumnSchemaV2 &column_schema, ObColumnRefRawExpr *&rowkey, common::ObIArray *column_items = NULL); static int check_contain_ora_rowscn_expr(const ObRawExpr *expr, bool &contains); static int allocate_group_id_expr(ObLogPlan *log_plan, ObRawExpr *&group_id_expr); static int check_contribute_query_range(ObLogicalOperator *tsc, const ObIArray ¶ms, bool &is_valid); static int check_pushdown_range_cond(ObLogicalOperator *root, bool &cnt_pd_range_cond); static int check_exec_param_filter_exprs(const ObIArray &input_filters, bool &has_exec_param_filters); static int check_contain_batch_stmt_parameter(ObRawExpr* expr, bool &contain); static int expr_calculable_by_exprs(ObRawExpr *src_expr, const ObIArray &dst_exprs, const bool need_check_contain, const bool used_in_compare, bool &is_calculable); static int expr_calculable_by_exprs(ObRawExpr *src_expr, const ObIArray &dst_exprs, ObIArray &parent_exprs, const bool need_check_contain, const bool used_in_compare, bool &is_calculable); static int get_minset_of_exprs(const ObIArray &src_exprs, ObIArray &min_set); static int build_rel_ids_by_equal_set(const EqualSet &equal_set, ObRelIds &rel_ids); static int build_rel_ids_by_equal_sets(const EqualSets &equal_sets, ObIArray &rel_ids_array); static int find_expr_in_equal_sets(const EqualSets &equal_sets, const ObRawExpr *target_expr, int64_t &idx); static bool find_rel_ids(const ObIArray &rel_ids_array, const ObRelIds &target_ids, int64_t *idx = NULL); static int check_can_encode_sortkey(const common::ObIArray &order_keys, bool &can_sort_opt, ObLogPlan& plan, double card); static int extract_equal_join_conditions(const ObIArray &equal_join_conditions, const ObRelIds &left_tables, ObIArray &left_exprs, ObIArray &right_exprs); static int extract_pushdown_join_filter_quals(const ObIArray &left_quals, const ObIArray &right_quals, const ObSqlBitSet<> &right_tables, ObIArray &pushdown_left_quals, ObIArray &pushdown_right_quals); static int pushdown_join_filter_into_subquery(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, const ObIArray &pushdown_left_quals, const ObIArray &pushdown_right_quals, ObIArray &candi_left_quals, ObIArray &candi_right_quals, bool &can_pushdown); static int check_pushdown_join_filter_quals(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, const ObIArray &pushdown_left_quals, const ObIArray &pushdown_right_quals, ObIArray &candi_left_quals, ObIArray &candi_right_quals); static int check_pushdown_join_filter_for_subquery(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, ObIArray &common_exprs, const ObIArray &pushdown_left_quals, const ObIArray &pushdown_right_quals, ObIArray &candi_left_quals, ObIArray &candi_right_quals); static int check_pushdown_join_filter_for_set(const ObSelectStmt &parent_stmt, const ObSelectStmt &subquery, ObIArray &common_exprs, const ObIArray &pushdown_left_quals, const ObIArray &pushdown_right_quals, ObIArray &candi_left_quals, ObIArray &candi_right_quals); static int replace_gen_column(ObLogPlan *log_plan, ObRawExpr *part_expr, ObRawExpr *&new_part_expr); static int replace_column_with_select_for_partid(const ObInsertStmt *stmt, ObOptimizerContext &opt_ctx, ObRawExpr *&calc_part_id_expr); static int check_contain_my_exec_param(ObRawExpr* expr, const common::ObIArray & my_exec_params, bool &contain); static int generate_pseudo_trans_info_expr(ObOptimizerContext &opt_ctx, const common::ObString &table_name, ObOpPseudoColumnRawExpr *&expr); static int is_in_range_optimization_enabled(const ObGlobalHint &global_hint, ObSQLSessionInfo *session_info, bool &is_enabled); static int pushdown_and_rename_filter_into_subquery(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, int64_t table_id, ObOptimizerContext &opt_ctx, ObIArray &input_filters, ObIArray &push_filters, ObIArray &remain_filters, bool check_match_index = true); static int split_or_filter_into_subquery(const ObDMLStmt &parent_stmt, const ObSelectStmt &subquery, int64_t table_id, ObOptimizerContext &opt_ctx, ObRawExpr *filter, ObRawExpr *&push_filter, bool &can_pushdown_all, bool check_match_index = true); static int split_or_filter_into_subquery(ObIArray &parent_stmts, ObIArray &subqueries, ObIArray &table_ids, ObIArray*> &or_filter_params, ObOptimizerContext &opt_ctx, ObRawExpr *&push_filter, bool &can_pushdown_all, bool check_match_index = true); static bool find_superset(const ObRelIds &rel_ids, const ObIArray &single_table_ids); static int try_push_down_temp_table_filter(ObOptimizerContext &opt_ctx, ObSqlTempTableInfo &temp_table_info, ObRawExpr *&temp_table_filter, ObRawExpr *&where_filter); static int push_down_temp_table_filter(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, ObSqlTempTableInfo &temp_table_info, ObRawExpr *&temp_table_filter, ObSelectStmt *temp_table_query = NULL); static int check_is_static_false_expr(ObOptimizerContext &opt_ctx, ObRawExpr &expr, bool &is_static_false); static int check_ancestor_node_support_skip_scan(ObLogicalOperator* op, bool &can_use_batch_nlj); private: //disallow construct ObOptimizerUtil(); ~ObOptimizerUtil(); }; template void ObOptimizerUtil::revert_items(common::ObIArray &items, const int64_t N) { for (int64_t i = items.count(); i > N && i > 0; --i) { items.pop_back(); } } template int ObOptimizerUtil::remove_item(common::ObIArray &items, const T &item, bool *removed)// default null { int ret = common::OB_SUCCESS; int64_t N = items.count(); common::ObArray new_arr; bool tmp_removed = false; for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) { const T &v = items.at(i); if (v == item) { tmp_removed = true; } else if (OB_FAIL(new_arr.push_back(items.at(i)))) { SQL_OPT_LOG(WARN, "failed to push back expr to array", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(items.assign(new_arr))) { SQL_OPT_LOG(WARN, "failed to reset exprs array", K(ret)); } else if (NULL != removed) { *removed = tmp_removed; } } return ret; } template int ObOptimizerUtil::remove_item(common::ObIArray &items, const common::ObIArray &rm_items, bool *removed)// default null) { int ret = common::OB_SUCCESS; int64_t N = items.count(); common::ObArray new_arr; bool tmp_removed = false; for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) { if (!find_item(rm_items, items.at(i))) { if (OB_FAIL(new_arr.push_back(items.at(i)))) { SQL_OPT_LOG(WARN, "failed to push back expr to array", K(ret)); } } else { tmp_removed = true; } } if (OB_SUCC(ret)) { if (OB_FAIL(items.assign(new_arr))) { SQL_OPT_LOG(WARN, "failed to reset exprs array", K(ret)); } else if (NULL != removed) { *removed = tmp_removed; } } return ret; } template int ObOptimizerUtil::intersect(const ObIArray &first, const ObIArray &second, ObIArray &third) { int ret = common::OB_SUCCESS; int64_t N = first.count(); common::ObSEArray new_arr; for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) { if (find_item(second, first.at(i))) { if (OB_FAIL(new_arr.push_back(first.at(i)))) { SQL_OPT_LOG(WARN, "failed to push back item to array", K(ret)); } } } if (OB_SUCC(ret)) { if (OB_FAIL(third.assign(new_arr))) { SQL_OPT_LOG(WARN, "failed to assign item array", K(ret)); } } return ret; } /** * @brief intersect, to reduce the assign cost when computing many sets' overlap. * @param sets the element sets to calculate the overlap. * @param result the result of the overlap * @return */ template int ObOptimizerUtil::intersect(const ObIArray> &sets, ObIArray &result) { int ret = common::OB_SUCCESS; int64_t N = sets.count(); if (N == 0) { result.reset(); } else { common::ObSEArray , 2> intersection; if (OB_FAIL(intersection.prepare_allocate(2))) { SQL_OPT_LOG(WARN, "failed to pre allocate array", K(ret)); } else { bool cur = 0; if (OB_FAIL(intersection.at(cur^1).assign(sets.at(0)))) { SQL_OPT_LOG(WARN, "failed to assign item array", K(ret)); } for (int64_t i = 1; OB_SUCC(ret) && intersection.at(cur^1).count() > 0 && i < N; ++i, cur^=1) { for (int64_t j =0; OB_SUCC(ret) && j < sets.at(i).count(); j++) { if (find_item(intersection.at(cur^1), sets.at(i).at(j))) { if (OB_FAIL(intersection.at(cur).push_back(sets.at(i).at(j)))) { SQL_OPT_LOG(WARN, "failed to push back item to array", K(ret)); } } } } if (OB_SUCC(ret)){ if (OB_FAIL(result.assign(intersection.at(cur^1)))) { SQL_OPT_LOG(WARN, "failed to assign item array", K(ret)); } } } } return ret; } template bool ObOptimizerUtil::overlap(const ObIArray &first, const ObIArray &second) { bool b_ret = false; int64_t N = first.count(); for (int64_t i = 0; !b_ret && i < N; ++i) { if (find_item(second, first.at(i))) { b_ret = true; } } return b_ret; } template bool ObOptimizerUtil::is_subset(const ObIArray &first, const ObIArray &second) { bool b_ret = true; int64_t N = first.count(); for (int64_t i = 0; b_ret && i < N; ++i) { if (!find_item(second, first.at(i))) { b_ret = false; } } return b_ret; } template uint64_t ObOptimizerUtil::hash_exprs(uint64_t seed, const ObIArray &expr_array) { uint64_t hash_value = seed; int64_t N = expr_array.count(); for (int64_t i = 0; i < N; ++i) { hash_value = hash_expr(expr_array.at(i), hash_value); } return hash_value; } #define HASH_ARRAY(items, seed) \ do { \ int64_t N = (items).count(); \ for (int64_t i = 0; i < N; i++) { \ (seed) = do_hash((items).at(i), (seed)); \ } \ } while(0); #define HASH_PTR_ARRAY(items, seed) \ do { \ int64_t N = (items).count(); \ for (int64_t i = 0; i < N; i++) { \ if (NULL != (items).at(i)) { \ (seed) = do_hash(*((items).at(i)), (seed)); \ } \ } \ } while(0); } } #endif