Files
oceanbase/src/sql/rewrite/ob_transform_groupby_pullup.h
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

190 lines
6.9 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_GROUPBY_PULLUP_H
#define OB_TRANSFORM_GROUPBY_PULLUP_H
#include "sql/rewrite/ob_transform_rule.h"
#include "sql/resolver/dml/ob_select_stmt.h"
#include "sql/optimizer/ob_log_join.h"
namespace oceanbase
{
namespace sql
{
/**
* @brief The ObTransformGroupByReplacement class
* References:
* [1] Including Group-By in Query Optimization
* [2] Eager Aggregation and Lazy Aggregation
*/
class ObTransformGroupByPullup : public ObTransformRule
{
public:
ObTransformGroupByPullup(ObTransformerCtx *ctx)
: ObTransformRule(ctx, TransMethod::POST_ORDER, T_MERGE_HINT)
{}
virtual ~ObTransformGroupByPullup() {}
virtual int construct_transform_hint(ObDMLStmt &stmt, void *trans_params) override;
virtual int transform_one_stmt(common::ObIArray<ObParentDMLStmt> &parent_stmts,
ObDMLStmt *&stmt,
bool &trans_happened) override;
protected:
virtual int adjust_transform_types(uint64_t &transform_types) override;
virtual int is_expected_plan(ObLogPlan *plan, void *check_ctx, bool &is_valid) override;
private:
struct PullupHelper {
PullupHelper():
parent_table_(NULL),
table_id_(OB_INVALID_ID),
not_null_column_table_id_(OB_INVALID_ID),
not_null_column_id_(OB_INVALID_ID),
need_check_null_propagate_(false),
need_check_having_(false),
need_merge_(false)
{}
virtual ~PullupHelper(){}
JoinedTable *parent_table_;
uint64_t table_id_;
uint64_t not_null_column_table_id_;
uint64_t not_null_column_id_;
//如果是在outer join的右侧或者full join的两侧,需要找到一个not_null_column备用;
bool need_check_null_propagate_;
//如果是outer join的右表或者是full join的child table
//不能有having condition
bool need_check_having_;
//是否是否有merge hint,强制group by pull up
//不考虑代价
bool need_merge_;
TO_STRING_KV(K_(parent_table),
K_(table_id),
K_(not_null_column_id),
K_(not_null_column_table_id),
K_(need_check_null_propagate),
K_(need_check_having),
K_(need_merge));
};
struct ObCostBasedPushDownCtx {
ObCostBasedPushDownCtx() {};
int64_t stmt_id_;
ObSqlBitSet<> new_table_relids_;
};
int check_groupby_validity(const ObSelectStmt &stmt, bool &is_valid);
int check_collation_validity(const ObDMLStmt &stmt, bool &is_valid);
///////////////////// transform group by pull up //////////////////////////////
int check_groupby_pullup_validity(ObDMLStmt *stmt,
ObIArray<PullupHelper> &valid_views);
int check_groupby_pullup_validity(ObDMLStmt *stmt,
TableItem *table,
PullupHelper &helper,
bool contain_inner_table,
ObSqlBitSet<> &ignore_tables,
ObIArray<PullupHelper> &valid_views,
bool &is_valid);
int check_on_conditions(ObDMLStmt &stmt,
ObSqlBitSet<> &ignore_tables);
int is_valid_group_stmt(ObSelectStmt *sub_stmt,
bool &is_valid_group);
int check_null_propagate(ObDMLStmt *parent_stmt,
ObSelectStmt* child_stmt,
PullupHelper &helper,
bool &is_valid);
int find_not_null_column(ObDMLStmt &parent_stmt,
ObSelectStmt &child_stmt,
PullupHelper &helper,
ObIArray<ObRawExpr *> &column_exprs,
ObRawExpr *&not_null_column);
int find_not_null_column_with_condition(ObDMLStmt &parent_stmt,
ObSelectStmt &child_stmt,
PullupHelper &helper,
ObIArray<ObRawExpr *> &column_exprs,
ObRawExpr *&not_null_column);
int find_null_propagate_column(ObRawExpr *condition,
ObIArray<ObRawExpr*> &columns,
ObRawExpr *&null_propagate_column,
bool &is_valid);
int do_groupby_pull_up(ObSelectStmt *stmt, PullupHelper &helper);
int get_trans_view(ObDMLStmt *stmt, ObSelectStmt *&view_stmt);
int wrap_case_when_if_necessary(ObSelectStmt &child_stmt,
PullupHelper &helper,
ObIArray<ObRawExpr *> &exprs);
/**
* @brief wrap_case_when
* 如果当前视图是left outer join的右表或者right outer join的左表
* 需要对null rejuect的new column expr包裹一层case when
* 需要寻找视图的非空列,如果null_reject_columns不为空,
* 直接拿第一个使用,否则需要在stmt中查找非空列,
* 也可以是试图内基表的pk,但不能是outer join的补null侧
*/
int wrap_case_when(ObSelectStmt &child_stmt,
ObRawExpr *not_null_column,
ObRawExpr *&expr);
int check_nl_operator(ObLogicalOperator *op,
ObCostBasedPushDownCtx *push_down_ctx,
bool &is_valid);
int has_group_by_op(ObLogicalOperator *op,
bool &bret);
int check_group_by_subset(ObRawExpr *expr, const ObIArray<ObRawExpr *> &group_exprs, bool &bret);
int check_hint_valid(const ObDMLStmt &stmt,
const ObSelectStmt &ref_query,
bool &is_valid);
virtual int need_transform(const common::ObIArray<ObParentDMLStmt> &parent_stmts,
const int64_t current_level,
const ObDMLStmt &stmt,
bool &need_trans) override;
private:
// help functions
int64_t get_count_sum_num(const ObIArray<ObRawExpr *> &exprs)
{
int64_t num = 0;
for (int64_t i = 0; i < exprs.count(); ++i) {
if (OB_ISNULL(exprs.at(i))) {
// do nothing
} else if (exprs.at(i)->get_expr_type() == T_FUN_SUM ||
exprs.at(i)->get_expr_type() == T_FUN_COUNT) {
++num;
}
}
return num;
}
};
}
}
#endif // OB_TRANSFORM_GROUPBY_REPLACEMENT_H