/** * 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_opt_est_sel.h" #include "sql/optimizer/ob_fd_item.h" namespace oceanbase { namespace common { class ObExprCtx; } namespace sql { enum PartitionRelation { NO_COMPATIBLE, COMPATIBLE_SMALL, COMPATIBLE_LARGE, COMPATIBLE_COMMON }; struct MergeKeyInfo { MergeKeyInfo(common::ObIAllocator& allocator, int64_t size) : need_sort_(false), map_array_(allocator, size), order_directions_(allocator, size), order_exprs_(allocator, size), order_items_(allocator, size) {} virtual ~MergeKeyInfo(){}; TO_STRING_KV(K_(need_sort), K_(map_array), K_(order_directions), K_(order_exprs), K_(order_items)); bool need_sort_; 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 ObOptimizerUtil { public: static int is_prefix_ordering(const common::ObIArray& pre, const common::ObIArray& full, const EqualSets& equal_sets, const common::ObIArray& const_exprs, bool& is_prefix); static int is_prefix_ordering(const common::ObIArray& pre, const common::ObIArray& full, const EqualSets& equal_sets, const common::ObIArray& const_exprs, bool& is_prefix, const common::ObIArray* pre_directions = NULL); static int is_prefix_ordering(const common::ObIArray& pre, const common::ObIArray& full, const EqualSets& equal_sets, const common::ObIArray& const_exprs, bool& is_prefix, const common::ObIArray* right_directions = NULL); // find common prefix ordering static int find_common_prefix_ordering(const common::ObIArray& left_side, const common::ObIArray& right_side, const EqualSets& equal_sets, const common::ObIArray& const_exprs, int64_t& left_match_count, int64_t& right_match_count, const common::ObIArray* right_directions = NULL); // find common prefix ordering static int find_common_prefix_ordering(const common::ObIArray& left_side, const common::ObIArray& right_side, const EqualSets& equal_sets, const common::ObIArray& const_exprs, int64_t& left_match_count, int64_t& right_match_count); static int is_const_or_equivalent_expr(const common::ObIArray& exprs, const EqualSets& equal_sets, const common::ObIArray& const_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 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 adjust_exprs_by_ordering(common::ObIArray& exprs, const common::ObIArray& ordering, const EqualSets& equal_sets, const common::ObIArray& const_exprs, bool& ordering_used, common::ObIArray& directions, common::ObIArray* match_map = NULL); 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 is_expr_equivalent(const ObRawExpr* from, const ObRawExpr* to, const EqualSets& equal_sets); 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, int64_t& number); static int extract_target_level_query_ref_expr(ObIArray& exprs, const int64_t level, const ObIArray& ignore_exprs, ObIArray& subqueries); static int extract_target_level_query_ref_expr(ObIArray& exprs, const int64_t level, const ObIArray& ignore_exprs, ObIArray& subqueries); static int extract_target_level_query_ref_expr(ObRawExpr* expr, const int64_t level, const ObIArray& ignore_exprs, ObIArray& subqueries); 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); 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 bool subset_exprs(const common::ObIArray& sort_keys, const common::ObIArray& exprs2, const EqualSets& equal_sets); static int intersect_exprs(ObIArray& first, ObIArray& right, ObIArray& result); static int except_exprs(ObIArray& first, ObIArray& right, ObIArray& result); static int copy_exprs( ObRawExprFactory& expr_factory, const common::ObIArray& src, common::ObIArray& dst); // for topk, non terminal expr with agg params need to be deep copyed to prevent sum being replaced // with sum(sum) static int clone_expr_for_topk(ObRawExprFactory& expr_factory, ObRawExpr* src, ObRawExpr*& dst); static int copy_sort_keys(const common::ObIArray& src, common::ObIArray& dst); static int copy_sort_keys(const common::ObIArray& src, common::ObIArray& dst); static int copy_sort_keys(const common::ObIArray& src, const common::ObIArray& directions, common::ObIArray& dst); 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); 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 bool overlap(const ObIArray& first, const ObIArray& second); template static bool is_subset(const ObIArray& first, const ObIArray& second); static bool find_equal_expr(const common::ObIArray& exprs, const ObRawExpr* expr) { int64_t dummy_index = -1; EqualSets dummy_sets; return find_equal_expr(exprs, expr, dummy_sets, dummy_index); } static bool find_equal_expr(const common::ObIArray& exprs, const ObRawExpr* expr, int64_t& idx) { EqualSets dummy_sets; return find_equal_expr(exprs, expr, dummy_sets, 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 bool find_equal_expr( const common::ObIArray& exprs, const ObRawExpr* expr, ObExprParamCheckContext& context) { int64_t dummy_index = -1; return find_equal_expr(exprs, expr, context, dummy_index); } static bool find_equal_expr( const common::ObIArray& exprs, const ObRawExpr* expr, ObExprParamCheckContext& context, int64_t& idx); 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); static ObRawExpr* find_exec_param( const common::ObIArray>& params_, const int64_t param_num); static int64_t find_exec_param(const common::ObIArray>& params, const ObRawExpr* expr); static ObRawExpr* find_param_expr(const common::ObIArray& exprs, const int64_t param_num); static int extract_equal_exec_params(const common::ObIArray& exprs, const common::ObIArray>& params, common::ObIArray& left_key, common::ObIArray& right_key); /** * extract all params from the input expr * @param expr * @param params * @return */ static int extract_params(ObRawExpr* expr, common::ObIArray& params); static int extract_params(common::ObIArray& exprs, common::ObIArray& params); static int add_col_ids_to_set(const common::ObIArray& exprs, common::ObBitSet<>& bitset); static int add_col_ids_to_set(const ObRawExpr* expr, common::ObBitSet<>& bitset, bool check_single_col = false, bool restrict_table_id = false, uint64_t target_table_id = common::OB_INVALID_ID); static int check_if_column_ids_covered(const common::ObIArray& exprs, const common::ObBitSet<>& colset, bool restrict_table_id, uint64_t target_table_id, common::ObIArray& result); static int check_if_column_ids_covered(const ObRawExpr* expr, const common::ObBitSet<>& colset, bool restrict_table_id, uint64_t target_table_id, bool& result); static int generate_rowkey_column_items(ObDMLStmt* stmt, ObRawExprFactory& expr_factory, uint64_t table_id, const share::schema::ObTableSchema& index_table_schema, common::ObIArray& index_columns); static int generate_rowkey_exprs(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(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 generate_column_exprs(ObDMLStmt* stmt, ObOptimizerContext& opt_ctx, const uint64_t table_id, const uint64_t ref_table_id, const ObIArray& column_ids, ObIArray& column_exprs); static int build_range_columns( const ObDMLStmt* stmt, common::ObIArray& rowkeys, common::ObIArray& range_columns); static int check_filter_before_indexback(uint64_t index_id, share::schema::ObSchemaGetterGuard* schema_guard, const common::ObIArray& filters, bool restrict_table_id, uint64_t target_table_id, common::ObIArray& filter_before_ib); // 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); /// 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 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 is_contain_nl_params( const common::ObIArray& filters, const int64_t max_param_num, bool& is_contain); static int extract_parameterized_correlated_filters(const common::ObIArray& filters, const int64_t max_param_num, 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 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, 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 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 bool is_const_expr(const ObRawExpr* expr, const int64_t stmt_level = -1); 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); 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); 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); 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); static int get_subquery_exprs(const ObIArray& exprs, ObIArray& subquery_exprs); static int check_is_onetime_expr(const ObIArray>& onetime_exprs, ObRawExpr* expr, ObDMLStmt* stmt, bool& is_onetime_expr); static int classify_get_scan_ranges(const common::ObIArray& input_ranges, common::ObIAllocator& allocator, common::ObIArray& get_ranges, common::ObIArray& scan_ranges, const share::schema::ObTableSchema* table_schema = NULL, const bool should_trans_rowid = false); 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); static int split_child_exprs(const ObFdItem* fd_item, const EqualSets& equal_sets, ObIArray& exprs, ObIArray& child_exprs); 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& not_null_columns); static int try_add_fd_item(ObDMLStmt* stmt, ObFdItemFactory& fd_factory, const uint64_t table_id, ObRelIds& tables, const share::schema::ObTableSchema* index_schema, const ObIArray& quals, ObIArray& not_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, 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 uint64_t table_id, ObDMLStmt& parent_stmt, const ObSelectStmt& child_stmt, const ObFdItemSet& input_fd_item_sets, ObFdItemSet& output_fd_item_sets); 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 bool is_at_most_one_row, bool& need_sort); 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 bool is_at_most_one_row, bool& need_sort); static int decide_sort_keys_for_merge_style_op(const ObIArray& input_ordering, const ObFdItemSet& fd_item_set, const EqualSets& equal_sets, const ObIArray& const_exprs, const bool is_at_most_one_row, const ObIArray& merge_exprs, const ObIArray& merge_directions, MergeKeyInfo& merge_key); 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*& rownum, 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); 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); 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); 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, ObIArray& root_exprs, const ObIArray& candi_exprs); static int simplify_ordered_exprs(const ObFdItemSet& fd_item_set, const EqualSets& equal_sets, const ObIArray& const_exprs, ObIArray& root_exprs, const ObIArray& candi_exprs); static int simplify_ordered_exprs(const ObFdItemSet& fd_item_set, const EqualSets& equal_sets, const ObIArray& const_exprs, ObIArray& root_items, const ObIArray& candi_items); static int remove_equal_exprs( const EqualSets& equal_sets, const ObIArray& target_exprs, ObIArray& exprs); static int check_subquery_filter(const JoinedTable* table, bool& has); static bool has_equal_join_conditions(const ObIArray& join_conditions); static int convert_subplan_scan_expr(ObRawExprFactory& expr_factory, const EqualSets& equal_sets, const uint64_t table_id, ObDMLStmt& parent_stmt, const ObSelectStmt& child_stmt, bool skip_invalid, const ObIArray& input_exprs, common::ObIArray& output_exprs); static int convert_subplan_scan_expr(ObRawExprFactory& expr_factory, const EqualSets& equal_sets, const uint64_t table_id, ObDMLStmt& parent_stmt, const ObSelectStmt& child_stmt, const ObRawExpr* input_expr, ObRawExpr*& output_expr); static int replace_subplan_scan_expr(const EqualSets& equal_sets, const uint64_t table_id, ObDMLStmt& parent_stmt, const ObSelectStmt& child_stmt, ObRawExpr*& expr); static int check_subplan_scan_expr_validity(const EqualSets& equal_sets, const uint64_t table_id, 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, ObDMLStmt& parent_stmt, const ObSelectStmt& child_stmt, const ObRawExpr* child_expr, ObRawExpr*& parent_expr); static int compute_const_exprs( const ObIArray& condition_exprs, const int64_t stmt_level, ObIArray& const_exprs); static int compute_const_exprs(const ObIArray& condition_exprs, ObIArray& const_exprs) { return compute_const_exprs(condition_exprs, -1, const_exprs); } 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 int64_t check_scope, int64_t& match_info, int64_t* max_prefix_count_ptr = NULL); 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_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); 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); 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); 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); static int is_lossless_column_cast(const ObRawExpr* expr, bool& is_lossless); 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 to_left_type = false); 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 to_left_type = false); 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 to_left_type = false); 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 check_subquery_has_ref_assign_user_var(ObRawExpr* expr, bool& is_has); static bool is_param_expr_correspond_subquey( const ObConstRawExpr& const_expr, ObIArray>& onetime_exprs); static int pushdown_filter_into_subquery(ObDMLStmt& parent_stmt, ObSelectStmt& subquery, ObOptimizerContext& opt_ctx, ObIArray& pushdown_filters, ObIArray& candi_filters, ObIArray& remain_filters, bool& can_pushdown); static int check_pushdown_filter(ObDMLStmt& parent_stmt, ObSelectStmt& subquery, ObOptimizerContext& opt_ctx, ObIArray& pushdown_filters, ObIArray& candi_filters, ObIArray& remain_filters); static int check_pushdown_filter_overlap_index(ObDMLStmt& stmt, ObOptimizerContext& opt_ctx, ObIArray& pushdown_filters, ObIArray& candi_filters, ObIArray& remain_filters); static int check_pushdown_filter_for_set(ObSelectStmt& parent_stmt, ObSelectStmt& subquery, ObIArray& common_exprs, ObIArray& pushdown_filters, ObIArray& candi_filters, ObIArray& remain_filters); static int check_pushdown_filter_for_subquery(ObSelectStmt& parent_stmt, ObSelectStmt& subquery, ObOptimizerContext& opt_ctx, ObIArray& common_exprs, ObIArray& pushdown_filters, ObIArray& candi_filters, ObIArray& remain_filters); static int get_groupby_win_func_common_exprs( 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); 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 ObEstSelInfo& est_sel_info, const ObRelIds& table_ids, const ObRawExpr* qual, bool& is_null_qual); static int check_expr_contain_subquery(const ObIArray& exprs, const ObIArray>* onetime_exprs, bool& has_subquery); static int check_expr_contain_subquery( const ObRawExpr* expr, const ObIArray>* onetime_exprs, bool& has_subquery); static int check_expr_contain_sharable_subquery(ObRawExpr* expr, int32_t stmt_level, const ObIArray>& onetime_exprs, const bool ignore_root, bool& contains); 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); private: // disallow construct ObOptimizerUtil(); ~ObOptimizerUtil(); }; 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; } 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); } // namespace sql } // namespace oceanbase #endif