Files
oceanbase/src/sql/rewrite/ob_transform_simplify_subquery.h

232 lines
10 KiB
C++

/**
* 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_TRANSFORM_SIMPILFY_SUBQUERY_H
#define OB_TRANSFORM_SIMPILFY_SUBQUERY_H
#include "sql/rewrite/ob_transform_rule.h"
#include "sql/rewrite/ob_transform_utils.h"
namespace oceanbase {
namespace sql {
class ObTransformSimplifySubquery : public ObTransformRule
{
public:
ObTransformSimplifySubquery(ObTransformerCtx *ctx)
: ObTransformRule(ctx, TransMethod::POST_ORDER, T_SIMPLIFY_SUBQUERY)
{}
virtual ~ObTransformSimplifySubquery() {}
virtual int transform_one_stmt(common::ObIArray<ObParentDMLStmt> &parent_stmts,
ObDMLStmt *&stmt,
bool &trans_happened) override;
private:
int transform_subquery_as_expr(ObDMLStmt *stmt, bool &trans_happened);
int try_trans_subquery_in_expr(ObDMLStmt *stmt,
ObRawExpr *&expr,
bool &trans_happened);
int do_trans_subquery_as_expr(ObDMLStmt *stmt,
ObRawExpr *&expr,
bool &trans_happened);
int is_subquery_to_expr_valid(const ObSelectStmt *stmt,
bool &is_valid);
int transform_not_expr(ObDMLStmt *stmt, bool &trans_happened);
int do_transform_not_expr(ObRawExpr *&expr, bool &trans_happened);
int remove_redundant_select(ObDMLStmt *&stmt, bool &trans_happened);
int try_remove_redundant_select(ObSelectStmt &stmt, ObSelectStmt *&new_stmt);
int check_subquery_valid(ObSelectStmt &stmt, bool &is_valid);
int push_down_outer_join_condition(ObDMLStmt *stmt, bool &trans_happened);
int push_down_outer_join_condition(ObDMLStmt *stmt,
TableItem *join_table,
bool &trans_happened);
int try_push_down_outer_join_conds(ObDMLStmt *stmt,
JoinedTable *join_table,
bool &trans_happened);
ObItemType get_opposite_expr_type(ObItemType item_type);
int add_limit_for_exists_subquery(ObDMLStmt *stmt,bool &trans_happened);
int recursive_add_limit_for_exists_expr(ObRawExpr *expr, bool &trans_happened);
/**
* @brief transform_any_all
* 遍历stmt中不同部分中的表达式,并尝试对其改写
*/
int transform_any_all(ObDMLStmt *stmt, bool &trans_happened);
/**
* @brief try_trans_any_all
* 尝试对表达式 expr 本身或者它的参数表达式进行改写
*/
int try_transform_any_all(ObDMLStmt *stmt, ObRawExpr *&expr, bool &trans_happened);
/**
* @brief do_trans_any_all
* 判断一个表达式是否可以进行改写,如果可以那么进行改写
*/
int do_transform_any_all(ObDMLStmt *stmt, ObRawExpr *&expr, bool &trans_happened);
int check_any_all_as_min_max(ObRawExpr *expr, bool &is_valid);
int transform_any_all_as_min_max(ObDMLStmt *stmt, ObRawExpr *expr, bool &trans_happened);
int do_transform_any_all_as_min_max(ObSelectStmt *sel_stmt, const ObItemType aggr_type,
bool is_with_all, bool &trans_happened);
/**
* @brief ObTransformAnyAll::eliminate_any_all_for_scalar_query
* 如果 subquery 返回的记录数量为0或者1,那么 any 可以消除
* 如果 subquery 返回记录数量为1,那么 all 可以消除
* rel.c > all 空集 与 rel.c > 空集 语义不相同
*/
int eliminate_any_all_before_subquery(ObDMLStmt *stmt, ObRawExpr *&expr, bool &trans_happened);
/**
* @brief is_any_all_removeable
* 判断一个subquery compare 表达式的 any/all flag是否可以移除
*/
int check_any_all_removeable(ObRawExpr *expr, bool &can_be_removed);
/**
* @brief clear_any_all_flag
* 将一个 subquery compare 表达式 expr 替换为相应的 common compare 表达式
*/
int clear_any_all_flag(ObDMLStmt *stmt, ObRawExpr *&expr, ObQueryRefRawExpr *query_ref);
ObItemType get_aggr_type(ObItemType op_type, bool is_with_all);
ObItemType query_cmp_to_value_cmp(const ObItemType cmp_type);
int transform_exists_query(ObDMLStmt *stmt, bool &trans_happened);
int try_eliminate_subquery(ObDMLStmt *stmt, ObRawExpr *&expr, bool &trans_happened);
/**
* Simplify subuqery in exists, any, all (subq)
* 1. Eliminate subquery if possible
* 2. Eliminate select list to const 1
* 3. Eliminate group by
*/
int recursive_eliminate_subquery(ObDMLStmt *stmt, ObRawExpr *&expr,
bool &trans_happened);
int eliminate_subquery(ObDMLStmt *stmt,
ObRawExpr *&expr,
bool &trans_happened);
/**
* 当[not] exists(subq)满足以下所有条件时,subquery可以被消除
* 1. 当前stmt不是set stmt
* 2. 当前stmt不包含having或group by
* 3. stmt包含聚集函数
*/
static bool is_subquery_not_empty(const ObSelectStmt &stmt);
int subquery_can_be_eliminated_in_exists(const ObItemType op_type,
const ObSelectStmt *stmt,
bool &can_be_eliminated) const;
/**
* 当[not] exists(subq)满足以下所有条件时,select list可替换为1
* 1. 当前stmt不是set stmt
* 2. distinct和limit不同时存在
*/
int select_items_can_be_simplified(const ObItemType op_type,
const ObSelectStmt *stmt,
bool &can_be_simplified) const;
/**
* 当[not] exists(subq)满足以下所有条件时,可消除group by子句:
* 1. 当前stmt不是set stmt
* 2. 没有having子句
* 3. 没有limit子句
*/
int groupby_can_be_eliminated_in_exists(const ObItemType op_type,
const ObSelectStmt *stmt,
bool &can_be_eliminated) const;
/**
* 当Any/all/in(subq)满足以下所有条件时,可消除group by子句:
* 1. 当前stmt不是set stmt
* 2. 没有having子句
* 3. 没有limit子句
* 4. 无聚集函数(select item中)
* 5. 非常量select item列,全部包含在group exprs中
*/
int groupby_can_be_eliminated_in_any_all(const ObSelectStmt *stmt, bool &can_be_eliminated) const;
int eliminate_subquery_in_exists(ObDMLStmt *stmt,
ObRawExpr *&expr,
bool &trans_happened);
int simplify_select_items(ObDMLStmt *stmt,
const ObItemType op_type,
ObSelectStmt *subquery,
bool parent_is_set_query,
bool &trans_happened);
int eliminate_groupby_in_exists(ObDMLStmt *stmt,
const ObItemType op_type,
ObSelectStmt *&subquery,
bool &trans_happened);
int eliminate_groupby_distinct_in_any_all(ObRawExpr *expr, bool &trans_happened);
int eliminate_groupby_in_any_all(ObSelectStmt *&stmt, bool &trans_happened);
int eliminate_distinct_in_any_all(ObSelectStmt *subquery,bool &trans_happened);
int check_need_add_limit(ObSelectStmt *subquery, bool &need_add_limit);
int check_limit(const ObItemType op_type,
const ObSelectStmt *subquery,
bool &has_limit) const;
int need_add_limit_constraint(const ObItemType op_type,
const ObSelectStmt *subquery,
bool &add_limit_constraint) const;
int check_const_select(const ObSelectStmt &stmt, bool &is_const_select) const;
int get_push_down_conditions(ObDMLStmt *stmt,
JoinedTable *join_table,
ObIArray<ObRawExpr *> &join_conds,
ObIArray<ObRawExpr *> &push_down_conds);
int try_trans_any_all_as_exists(ObDMLStmt *stmt,
ObRawExpr *&expr,
ObNotNullContext *not_null_ctx,
bool is_bool_expr,
bool &trans_happened);
int do_trans_any_all_as_exists(ObRawExpr *&expr,
ObNotNullContext *not_null_ctx,
bool &trans_happened);
int check_can_trans_as_exists(ObRawExpr* expr, bool is_bool_expr, bool &is_valid);
int check_stmt_can_trans_as_exists(ObSelectStmt *stmt,
bool is_correlated,
bool &match_index,
bool &is_valid);
int query_cmp_to_exists_value_cmp(ObItemType type, bool is_with_all, ObItemType& new_type);
int add_limit_for_any_all_subquery(ObRawExpr *stmt,bool &trans_happened);
int prepare_trans_any_all_as_exists(ObQueryRefRawExpr* expr, ObSelectStmt *&trans_stmt);
int transform_any_all_as_exists(ObDMLStmt *stmt, bool &trans_happened);
int transform_any_all_as_exists_joined_table(ObDMLStmt* stmt,
TableItem *table,
bool &trans_happened);
int try_trans_any_all_as_exists(ObDMLStmt *stmt,
ObIArray<ObRawExpr* > &exprs,
ObNotNullContext *not_null_cxt,
bool is_bool_expr,
bool &trans_happened);
int empty_table_subquery_can_be_eliminated_in_exists(ObRawExpr *expr,
bool &is_valid);
int do_trans_empty_table_subquery_as_expr(ObRawExpr *&expr,
bool &trans_happened);
};
}
}
#endif // OB_TRANSFORM_SIMPILFY_SUBQUERY_H