Fix core at cost-based rewrite in temp table query
This commit is contained in:
@ -124,7 +124,8 @@ int ObSqlTempTableInfo::collect_specified_temp_table(ObIAllocator &allocator,
|
||||
ObSelectStmt *specified_query,
|
||||
const ObIArray<ObDMLStmt *> &upper_stmts,
|
||||
const ObIArray<TableItem *> &table_items,
|
||||
ObSqlTempTableInfo &temp_table_info)
|
||||
ObSqlTempTableInfo &temp_table_info,
|
||||
bool &all_has_filter)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
temp_table_info.reset();
|
||||
@ -134,7 +135,8 @@ int ObSqlTempTableInfo::collect_specified_temp_table(ObIAllocator &allocator,
|
||||
LOG_WARN("unexpected param", K(specified_query), K(upper_stmts), K(table_items));;
|
||||
} else {
|
||||
temp_table_info.table_query_ = specified_query;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < upper_stmts.count(); i ++) {
|
||||
all_has_filter = upper_stmts.count() > 0;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && all_has_filter && i < upper_stmts.count(); i ++) {
|
||||
TableItem *table = table_items.at(i);
|
||||
ObDMLStmt *stmt = upper_stmts.at(i);
|
||||
if (OB_ISNULL(stmt) || OB_ISNULL(table) ||
|
||||
@ -152,6 +154,8 @@ int ObSqlTempTableInfo::collect_specified_temp_table(ObIAllocator &allocator,
|
||||
LOG_WARN("failed to collect temp table info", K(ret));
|
||||
} else if (OB_FAIL(temp_table_info.table_infos_.push_back(table_info))) {
|
||||
LOG_WARN("failed to push back table info", K(ret));
|
||||
} else {
|
||||
all_has_filter &= !table_info.table_filters_.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +110,8 @@ public:
|
||||
ObSelectStmt *specified_query,
|
||||
const ObIArray<ObDMLStmt *> &upper_stmts,
|
||||
const ObIArray<TableItem *> &table_items,
|
||||
ObSqlTempTableInfo &temp_table_info);
|
||||
ObSqlTempTableInfo &temp_table_info,
|
||||
bool &all_has_filter);
|
||||
static int collect_temp_table_filters(ObDMLStmt *stmt,
|
||||
TableItem *table,
|
||||
ObIArray<ObRawExpr*> &table_filters,
|
||||
|
||||
@ -90,8 +90,7 @@ int ObOptimizer::optimize(ObDMLStmt &stmt, ObLogPlan *&logical_plan)
|
||||
|
||||
int ObOptimizer::get_optimization_cost(ObDMLStmt &stmt,
|
||||
ObLogPlan *&plan,
|
||||
double &cost,
|
||||
ObDMLStmt::TempTableInfo *current_temp_table_)
|
||||
double &cost)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
cost = 0.0;
|
||||
@ -107,30 +106,6 @@ int ObOptimizer::get_optimization_cost(ObDMLStmt &stmt,
|
||||
LOG_WARN("failed to init env info", K(ret));
|
||||
} else if (OB_FAIL(generate_plan_for_temp_table(stmt))) {
|
||||
LOG_WARN("failed to generate plan for temp table", K(ret));
|
||||
} else if (NULL != current_temp_table_) {
|
||||
ObSqlTempTableInfo temp_table_info;
|
||||
ObRawExpr *temp_table_nonwhere_filter = NULL;
|
||||
ObRawExpr *temp_table_where_filter = NULL;
|
||||
if (OB_UNLIKELY(!stmt.is_select_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("temp table query should be select stmt", K(stmt));
|
||||
} else if (OB_FAIL(ObSqlTempTableInfo::collect_specified_temp_table(ctx_.get_allocator(),
|
||||
current_temp_table_->temp_table_query_,
|
||||
current_temp_table_->upper_stmts_,
|
||||
current_temp_table_->table_items_,
|
||||
temp_table_info))) {
|
||||
LOG_WARN("failed to collect_specified_temp_table", K(ret));
|
||||
} else if (OB_FAIL(try_push_down_temp_table_filter(temp_table_info,
|
||||
temp_table_nonwhere_filter,
|
||||
temp_table_where_filter,
|
||||
static_cast<ObSelectStmt *>(&stmt)))) {
|
||||
LOG_WARN("failed to push down filter for temp table", K(ret));
|
||||
} else if (NULL != temp_table_where_filter &&
|
||||
OB_FAIL(plan->get_pushdown_filters().push_back(temp_table_where_filter))) {
|
||||
LOG_WARN("failed to push down filter", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(plan->generate_raw_plan())) {
|
||||
LOG_WARN("failed to perform optimization", K(ret));
|
||||
} else {
|
||||
@ -231,8 +206,14 @@ int ObOptimizer::generate_plan_for_temp_table(ObDMLStmt &stmt)
|
||||
} else {
|
||||
OPT_TRACE_TITLE("begin generate plan for temp table ", temp_table_info->table_name_);
|
||||
}
|
||||
/**
|
||||
* In table scan op, filters are calculated before `limit`.
|
||||
* So, we can not push filter into temp table which contain `limit`.
|
||||
*/
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_FAIL(try_push_down_temp_table_filter(*temp_table_info,
|
||||
} else if (!ref_query->has_limit() &&
|
||||
OB_FAIL(ObOptimizerUtil::try_push_down_temp_table_filter(ctx_,
|
||||
*temp_table_info,
|
||||
temp_table_nonwhere_filter,
|
||||
temp_table_where_filter))) {
|
||||
LOG_WARN("failed to push down filter for temp table", K(ret));
|
||||
@ -246,10 +227,15 @@ int ObOptimizer::generate_plan_for_temp_table(ObDMLStmt &stmt)
|
||||
} else if (OB_ISNULL(temp_op)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (NULL != temp_table_nonwhere_filter &&
|
||||
OB_FAIL(temp_op->get_filter_exprs().push_back(temp_table_nonwhere_filter))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else {
|
||||
if (NULL != temp_table_nonwhere_filter) {
|
||||
ObSEArray<ObRawExpr *, 1> expr_array;
|
||||
if (OB_FAIL(expr_array.push_back(temp_table_nonwhere_filter))) {
|
||||
LOG_WARN("failed to push back");
|
||||
} else if (OB_FAIL(temp_plan->candi_allocate_filter(expr_array))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
}
|
||||
temp_table_info->table_plan_ = temp_op;
|
||||
OPT_TRACE_TITLE("end generate plan for temp table ", temp_table_info->table_name_);
|
||||
}
|
||||
@ -258,137 +244,6 @@ int ObOptimizer::generate_plan_for_temp_table(ObDMLStmt &stmt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* If every appearance of cte is accompanied by some filter,
|
||||
* We can combine these filters to reduce the data materialized by cte.
|
||||
* We try to push these filters to where condition.
|
||||
* If all filters can be push to where condition, nonwhere_filter will be NULL.
|
||||
* Otherwise, we might have both where_filter and nonwhere_filter.
|
||||
* e.g.
|
||||
* with cte as (select a,count(*) as cnt from t1 group by a)
|
||||
* select * from cte where a = 1 and cnt = 1 union all select * from cte where a = 2 and cnt = 2;
|
||||
* nonwhere_filter : (a = 1 and cnt = 1) or (a = 2 and cnt = 2)
|
||||
* where_filter : (a = 1) or (a = 2)
|
||||
*/
|
||||
int ObOptimizer::try_push_down_temp_table_filter(ObSqlTempTableInfo &info,
|
||||
ObRawExpr *&nonwhere_filter,
|
||||
ObRawExpr *&where_filter,
|
||||
ObSelectStmt *temp_table_query)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool have_filter = true;
|
||||
nonwhere_filter = NULL;
|
||||
where_filter = NULL;
|
||||
ObSEArray<ObIArray<ObRawExpr *> *, 4> temp_table_filters;
|
||||
ObSEArray<const ObDMLStmt *, 4> parent_stmts;
|
||||
ObSEArray<const ObSelectStmt *, 4> subqueries;
|
||||
ObSEArray<int64_t, 4> table_ids;
|
||||
temp_table_query = (temp_table_query == NULL) ? info.table_query_ : temp_table_query;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && have_filter && i < info.table_infos_.count(); ++i) {
|
||||
TableItem *table = info.table_infos_.at(i).table_item_;
|
||||
ObDMLStmt *stmt = info.table_infos_.at(i).upper_stmt_;
|
||||
if (OB_ISNULL(table) || OB_ISNULL(stmt)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret));
|
||||
} else if (info.table_infos_.at(i).table_filters_.empty()) {
|
||||
have_filter = false;
|
||||
} else if (OB_FAIL(temp_table_filters.push_back(&info.table_infos_.at(i).table_filters_))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else if (OB_FAIL(parent_stmts.push_back(stmt))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else if (OB_FAIL(subqueries.push_back(temp_table_query))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else if (OB_FAIL(table_ids.push_back(table->table_id_))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && have_filter) {
|
||||
OPT_TRACE("pushdown filter into temp table:", info.table_query_);
|
||||
bool can_push_all = false;
|
||||
if (OB_FAIL(ObOptimizerUtil::split_or_filter_into_subquery(parent_stmts,
|
||||
subqueries,
|
||||
table_ids,
|
||||
temp_table_filters,
|
||||
ctx_,
|
||||
where_filter,
|
||||
can_push_all,
|
||||
/*check_match_index = */false))) {
|
||||
LOG_WARN("failed to split filter", K(ret));
|
||||
} else if (can_push_all) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(push_down_temp_table_filter(info, nonwhere_filter))) {
|
||||
LOG_WARN("failed to push down remain temp table filter", K(ret));
|
||||
}
|
||||
if (NULL != where_filter) {
|
||||
OPT_TRACE("succeed to pushdown filter to where:", where_filter);
|
||||
}
|
||||
if (NULL != nonwhere_filter) {
|
||||
OPT_TRACE("succeed to pushdown filter into the top of temp table:", nonwhere_filter);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizer::push_down_temp_table_filter(ObSqlTempTableInfo &info,
|
||||
ObRawExpr *&temp_table_filter)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExprFactory &expr_factory = ctx_.get_expr_factory();
|
||||
ObSQLSessionInfo *session_info = NULL;
|
||||
temp_table_filter = NULL;
|
||||
ObSEArray<ObRawExpr *, 8> and_exprs;
|
||||
ObRawExpr *or_expr = NULL;
|
||||
bool have_temp_table_filter = true;
|
||||
if (OB_ISNULL(session_info = ctx_.get_session_info()) ||
|
||||
OB_ISNULL(info.table_query_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null param", K(session_info), K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && have_temp_table_filter && i < info.table_infos_.count(); ++i) {
|
||||
have_temp_table_filter &= !info.table_infos_.at(i).table_filters_.empty();
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && have_temp_table_filter && i < info.table_infos_.count(); ++i) {
|
||||
ObDMLStmt *upper_stmt = info.table_infos_.at(i).upper_stmt_;
|
||||
TableItem *table = info.table_infos_.at(i).table_item_;
|
||||
ObIArray<ObRawExpr *> &table_filters = info.table_infos_.at(i).table_filters_;
|
||||
ObSEArray<ObRawExpr *, 8> rename_exprs;
|
||||
ObRawExpr *and_expr = NULL;
|
||||
if (table_filters.empty() || OB_ISNULL(upper_stmt) ||
|
||||
OB_ISNULL(table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null table info", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::rename_pushdown_filter(*upper_stmt,
|
||||
*info.table_query_,
|
||||
table->table_id_,
|
||||
session_info,
|
||||
expr_factory,
|
||||
table_filters,
|
||||
rename_exprs))) {
|
||||
LOG_WARN("failed to rename push down preds", K(ret));
|
||||
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(expr_factory,
|
||||
rename_exprs,
|
||||
and_expr))) {
|
||||
LOG_WARN("failed to build and expr", K(ret));
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_FAIL(and_exprs.push_back(and_expr))) {
|
||||
LOG_WARN("failed to push back expr", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret) || !have_temp_table_filter) {
|
||||
} else if (OB_FAIL(ObRawExprUtils::build_or_exprs(expr_factory,
|
||||
and_exprs,
|
||||
or_expr))) {
|
||||
LOG_WARN("failed to build or expr", K(ret));
|
||||
} else if (OB_FAIL(or_expr->formalize(session_info))) {
|
||||
LOG_WARN("failed to formalize expr", K(ret));
|
||||
} else if (OB_FAIL(or_expr->pull_relation_id())) {
|
||||
LOG_WARN("failed to pull relation id and levels", K(ret));
|
||||
} else {
|
||||
temp_table_filter = or_expr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObOptimizer::exists_temp_table(const ObIArray<ObSqlTempTableInfo*> &temp_table_infos,
|
||||
const ObSelectStmt *table_query) const
|
||||
{
|
||||
|
||||
@ -182,8 +182,7 @@ namespace sql
|
||||
virtual int optimize(ObDMLStmt &stmt, ObLogPlan *&plan);
|
||||
virtual int get_optimization_cost(ObDMLStmt &stmt,
|
||||
ObLogPlan *&plan,
|
||||
double &cost,
|
||||
ObDMLStmt::TempTableInfo *current_temp_table_);
|
||||
double &cost);
|
||||
virtual int get_cte_optimization_cost(ObDMLStmt &root_stmt,
|
||||
ObSelectStmt *cte_query,
|
||||
ObIArray<ObSelectStmt *> &stmts,
|
||||
@ -224,13 +223,6 @@ namespace sql
|
||||
int check_force_default_stat();
|
||||
int calc_link_stmt_count(const ObDMLStmt &stmt, int64_t &count);
|
||||
|
||||
int try_push_down_temp_table_filter(ObSqlTempTableInfo &temp_table_info,
|
||||
ObRawExpr *&temp_table_filter,
|
||||
ObRawExpr *&where_filter,
|
||||
ObSelectStmt *temp_table_query = NULL);
|
||||
int push_down_temp_table_filter(ObSqlTempTableInfo &temp_table_info,
|
||||
ObRawExpr *&temp_table_filter);
|
||||
|
||||
private:
|
||||
ObOptimizerContext &ctx_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ObOptimizer);
|
||||
|
||||
@ -8923,7 +8923,7 @@ int ObOptimizerUtil::split_or_filter_into_subquery(const ObDMLStmt &parent_stmt,
|
||||
check_match_index))) {
|
||||
LOG_WARN("failed to split or fitler", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < or_filter_params.count(); i ++) {
|
||||
for (int64_t i = 0; i < or_filter_params.count(); i ++) {
|
||||
if (OB_NOT_NULL(or_filter_params.at(i))) {
|
||||
or_filter_params.at(i)->~ObIArray();
|
||||
}
|
||||
@ -9025,6 +9025,140 @@ int ObOptimizerUtil::split_or_filter_into_subquery(ObIArray<const ObDMLStmt *> &
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* If every appearance of cte is accompanied by some filter,
|
||||
* We can combine these filters to reduce the data materialized by cte.
|
||||
* We try to push these filters to where condition.
|
||||
* If all filters can be push to where condition, nonwhere_filter will be NULL.
|
||||
* Otherwise, we might have both where_filter and nonwhere_filter.
|
||||
* e.g.
|
||||
* with cte as (select a,count(*) as cnt from t1 group by a)
|
||||
* select * from cte where a = 1 and cnt = 1 union all select * from cte where a = 2 and cnt = 2;
|
||||
* nonwhere_filter : (a = 1 and cnt = 1) or (a = 2 and cnt = 2)
|
||||
* where_filter : (a = 1) or (a = 2)
|
||||
*/
|
||||
int ObOptimizerUtil::try_push_down_temp_table_filter(ObOptimizerContext &opt_ctx,
|
||||
ObSqlTempTableInfo &info,
|
||||
ObRawExpr *&nonwhere_filter,
|
||||
ObRawExpr *&where_filter)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool have_filter = true;
|
||||
nonwhere_filter = NULL;
|
||||
where_filter = NULL;
|
||||
ObSEArray<ObIArray<ObRawExpr *> *, 4> temp_table_filters;
|
||||
ObSEArray<const ObDMLStmt *, 4> parent_stmts;
|
||||
ObSEArray<const ObSelectStmt *, 4> subqueries;
|
||||
ObSEArray<int64_t, 4> table_ids;
|
||||
ObSelectStmt *temp_table_query = info.table_query_;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && have_filter && i < info.table_infos_.count(); ++i) {
|
||||
TableItem *table = info.table_infos_.at(i).table_item_;
|
||||
ObDMLStmt *stmt = info.table_infos_.at(i).upper_stmt_;
|
||||
if (OB_ISNULL(table) || OB_ISNULL(stmt)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret));
|
||||
} else if (info.table_infos_.at(i).table_filters_.empty()) {
|
||||
have_filter = false;
|
||||
} else if (OB_FAIL(temp_table_filters.push_back(&info.table_infos_.at(i).table_filters_))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else if (OB_FAIL(parent_stmts.push_back(stmt))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else if (OB_FAIL(subqueries.push_back(temp_table_query))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else if (OB_FAIL(table_ids.push_back(table->table_id_))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && have_filter) {
|
||||
OPT_TRACE("pushdown filter into temp table:", info.table_query_);
|
||||
bool can_push_all = false;
|
||||
if (OB_FAIL(ObOptimizerUtil::split_or_filter_into_subquery(parent_stmts,
|
||||
subqueries,
|
||||
table_ids,
|
||||
temp_table_filters,
|
||||
opt_ctx,
|
||||
where_filter,
|
||||
can_push_all,
|
||||
/*check_match_index = */false))) {
|
||||
LOG_WARN("failed to split filter", K(ret));
|
||||
} else if (can_push_all) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(push_down_temp_table_filter(opt_ctx.get_expr_factory(), opt_ctx.get_session_info(),
|
||||
info, nonwhere_filter))) {
|
||||
LOG_WARN("failed to push down remain temp table filter", K(ret));
|
||||
}
|
||||
if (NULL != where_filter) {
|
||||
OPT_TRACE("succeed to pushdown filter to where:", where_filter);
|
||||
}
|
||||
if (NULL != nonwhere_filter) {
|
||||
OPT_TRACE("succeed to pushdown filter into the top of temp table:", nonwhere_filter);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObOptimizerUtil::push_down_temp_table_filter(ObRawExprFactory &expr_factory,
|
||||
ObSQLSessionInfo *session_info,
|
||||
ObSqlTempTableInfo &info,
|
||||
ObRawExpr *&temp_table_filter,
|
||||
ObSelectStmt *temp_table_query)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
temp_table_filter = NULL;
|
||||
ObSEArray<ObRawExpr *, 8> and_exprs;
|
||||
ObRawExpr *or_expr = NULL;
|
||||
bool have_temp_table_filter = true;
|
||||
temp_table_query = (NULL == temp_table_query) ? info.table_query_ : temp_table_query;
|
||||
if (OB_ISNULL(temp_table_query)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null param", K(info), K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && have_temp_table_filter && i < info.table_infos_.count(); ++i) {
|
||||
have_temp_table_filter &= !info.table_infos_.at(i).table_filters_.empty();
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && have_temp_table_filter && i < info.table_infos_.count(); ++i) {
|
||||
ObDMLStmt *upper_stmt = info.table_infos_.at(i).upper_stmt_;
|
||||
TableItem *table = info.table_infos_.at(i).table_item_;
|
||||
ObIArray<ObRawExpr *> &table_filters = info.table_infos_.at(i).table_filters_;
|
||||
ObSEArray<ObRawExpr *, 8> rename_exprs;
|
||||
ObRawExpr *and_expr = NULL;
|
||||
if (table_filters.empty() || OB_ISNULL(upper_stmt) ||
|
||||
OB_ISNULL(table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null table info", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::rename_pushdown_filter(*upper_stmt,
|
||||
*temp_table_query,
|
||||
table->table_id_,
|
||||
session_info,
|
||||
expr_factory,
|
||||
table_filters,
|
||||
rename_exprs))) {
|
||||
LOG_WARN("failed to rename push down preds", K(ret));
|
||||
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(expr_factory,
|
||||
rename_exprs,
|
||||
and_expr))) {
|
||||
LOG_WARN("failed to build and expr", K(ret));
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_FAIL(and_exprs.push_back(and_expr))) {
|
||||
LOG_WARN("failed to push back expr", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret) || !have_temp_table_filter) {
|
||||
} else if (OB_FAIL(ObRawExprUtils::build_or_exprs(expr_factory,
|
||||
and_exprs,
|
||||
or_expr))) {
|
||||
LOG_WARN("failed to build or expr", K(ret));
|
||||
} else if (OB_FAIL(or_expr->formalize(session_info))) {
|
||||
LOG_WARN("failed to formalize expr", K(ret));
|
||||
} else if (OB_FAIL(or_expr->pull_relation_id())) {
|
||||
LOG_WARN("failed to pull relation id and levels", K(ret));
|
||||
} else {
|
||||
temp_table_filter = or_expr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObOptimizerUtil::find_superset(const ObRelIds &rel_ids,
|
||||
const ObIArray<ObRelIds> &single_table_ids)
|
||||
{
|
||||
|
||||
@ -1497,6 +1497,16 @@ public:
|
||||
|
||||
static bool find_superset(const ObRelIds &rel_ids,
|
||||
const ObIArray<ObRelIds> &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);
|
||||
private:
|
||||
//disallow construct
|
||||
ObOptimizerUtil();
|
||||
|
||||
@ -412,7 +412,7 @@ int ObTransformRule::evaluate_cost(common::ObIArray<ObParentDMLStmt> &parent_stm
|
||||
//optctx.set_only_ds_basic_stat(true);
|
||||
ObOptimizer optimizer(optctx);
|
||||
ObLogPlan *plan = NULL;
|
||||
if (OB_FAIL(optimizer.get_optimization_cost(*root_stmt, plan, plan_cost, current_temp_table_))) {
|
||||
if (OB_FAIL(optimizer.get_optimization_cost(*root_stmt, plan, plan_cost))) {
|
||||
LOG_WARN("failed to get optimization cost", K(ret));
|
||||
} else if (NULL == check_ctx) {
|
||||
// do nothing
|
||||
@ -435,6 +435,82 @@ int ObTransformRule::evaluate_cost(common::ObIArray<ObParentDMLStmt> &parent_stm
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObTransformRule::prepare_root_stmt_with_temp_table_filter(ObDMLStmt &root_stmt, ObDMLStmt *&root_stmt_with_filter)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSqlTempTableInfo temp_table_info;
|
||||
ObRawExpr *temp_table_filter = NULL;
|
||||
ObSelectStmt *sel_root_stmt = static_cast<ObSelectStmt *>(&root_stmt);
|
||||
bool have_temp_table_filter = false;
|
||||
if (NULL == current_temp_table_) {
|
||||
root_stmt_with_filter = &root_stmt;
|
||||
} else if (OB_UNLIKELY(!root_stmt.is_select_stmt()) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->allocator_) ||
|
||||
OB_ISNULL(ctx_->stmt_factory_) || OB_ISNULL(ctx_->session_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected params", K(root_stmt));
|
||||
} else if (OB_FAIL(ObSqlTempTableInfo::collect_specified_temp_table(*ctx_->allocator_,
|
||||
current_temp_table_->temp_table_query_,
|
||||
current_temp_table_->upper_stmts_,
|
||||
current_temp_table_->table_items_,
|
||||
temp_table_info,
|
||||
have_temp_table_filter))) {
|
||||
LOG_WARN("failed to collect_specified_temp_table", K(ret));
|
||||
} else if (have_temp_table_filter) {
|
||||
TableItem *new_table_item = NULL;
|
||||
ObSEArray<ObRawExpr *, 8> column_exprs;
|
||||
root_stmt_with_filter = NULL;
|
||||
ObSelectStmt *sel_stmt_with_filter = NULL;
|
||||
if (OB_FAIL(ctx_->stmt_factory_->create_stmt(sel_stmt_with_filter))) {
|
||||
LOG_WARN("failed to create stmt", K(ret));
|
||||
} else if (OB_ISNULL(sel_stmt_with_filter)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FALSE_IT(sel_stmt_with_filter->set_query_ctx(sel_root_stmt->get_query_ctx()))) {
|
||||
} else if (OB_FAIL(sel_stmt_with_filter->adjust_statement_id(ctx_->allocator_,
|
||||
ctx_->src_qb_name_,
|
||||
ctx_->src_hash_val_))) {
|
||||
LOG_WARN("failed to adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::add_new_table_item(ctx_, sel_stmt_with_filter, sel_root_stmt, new_table_item))) {
|
||||
LOG_WARN("failed to add new table item", K(ret));
|
||||
} else if (OB_ISNULL(new_table_item)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(sel_stmt_with_filter->add_from_item(new_table_item->table_id_, false))) {
|
||||
LOG_WARN("failed to add from item", K(ret));
|
||||
} else if (OB_FAIL(sel_stmt_with_filter->rebuild_tables_hash())) {
|
||||
LOG_WARN("failed to rebuid table hash", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::create_columns_for_view(ctx_,
|
||||
*new_table_item,
|
||||
sel_stmt_with_filter,
|
||||
column_exprs))) {
|
||||
LOG_WARN("failed to create column items", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::create_select_item(*ctx_->allocator_,
|
||||
column_exprs,
|
||||
sel_stmt_with_filter))) {
|
||||
LOG_WARN("failed to create select item", K(ret));
|
||||
} else if (OB_FAIL(sel_stmt_with_filter->formalize_stmt(ctx_->session_info_))) {
|
||||
LOG_WARN("failed to formalize stmt", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::push_down_temp_table_filter(*ctx_->expr_factory_,
|
||||
ctx_->session_info_,
|
||||
temp_table_info,
|
||||
temp_table_filter,
|
||||
sel_stmt_with_filter))) {
|
||||
LOG_WARN("failed to push down filter for temp table", K(ret));
|
||||
} else if (OB_ISNULL(temp_table_filter)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("filter is null", K(temp_table_info));
|
||||
} else if (OB_FAIL(sel_stmt_with_filter->add_condition_expr(temp_table_filter))) {
|
||||
LOG_WARN("failed to add condition expr", K(ret));
|
||||
} else {
|
||||
root_stmt_with_filter = sel_stmt_with_filter;
|
||||
}
|
||||
} else {
|
||||
root_stmt_with_filter = &root_stmt;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformRule::prepare_eval_cost_stmt(common::ObIArray<ObParentDMLStmt> &parent_stmts,
|
||||
ObDMLStmt &stmt,
|
||||
ObDMLStmt *&copied_stmt,
|
||||
@ -444,6 +520,7 @@ int ObTransformRule::prepare_eval_cost_stmt(common::ObIArray<ObParentDMLStmt> &p
|
||||
ObSEArray<ObSelectStmt*, 2> old_temp_table_stmts;
|
||||
ObSEArray<ObSelectStmt*, 2> new_temp_table_stmts;
|
||||
ObDMLStmt *root_stmt = NULL;
|
||||
ObDMLStmt *root_stmt_with_filter = NULL;
|
||||
ObDMLStmt *copied_trans_stmt = NULL;
|
||||
ObString cur_qb_name;
|
||||
ObDMLStmt *orig_stmt = NULL;
|
||||
@ -453,8 +530,10 @@ int ObTransformRule::prepare_eval_cost_stmt(common::ObIArray<ObParentDMLStmt> &p
|
||||
LOG_WARN("params are invalid", K(ret), K(ctx_), K(stmt.get_query_ctx()));
|
||||
} else if (OB_FAIL(adjust_transformed_stmt(parent_stmts, &stmt, orig_stmt, root_stmt))) {
|
||||
LOG_WARN("failed to adjust transformed stmt", K(ret));
|
||||
} else if (OB_FAIL(prepare_root_stmt_with_temp_table_filter(*root_stmt, root_stmt_with_filter))) {
|
||||
LOG_WARN("failed to prepare root stmt with temp table filter", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_, *ctx_->expr_factory_,
|
||||
root_stmt, copied_stmt))) {
|
||||
root_stmt_with_filter, copied_stmt))) {
|
||||
LOG_WARN("failed to deep copy stmt", K(ret));
|
||||
} else if (OB_FAIL(deep_copy_temp_table(*copied_stmt,
|
||||
*ctx_->stmt_factory_,
|
||||
|
||||
@ -420,6 +420,8 @@ private:
|
||||
ObDMLStmt *&copied_stmt,
|
||||
bool is_trans_stmt);
|
||||
|
||||
int prepare_root_stmt_with_temp_table_filter(ObDMLStmt &root_stmt, ObDMLStmt *&root_stmt_with_filter);
|
||||
|
||||
virtual int is_expected_plan(ObLogPlan *plan,
|
||||
void *check_ctx,
|
||||
bool is_trans_plan,
|
||||
|
||||
Reference in New Issue
Block a user