From f6f344d2cae4016de35d1a2f2745c4afb7ad6df3 Mon Sep 17 00:00:00 2001 From: zzg19950727 <1071026277@qq.com> Date: Fri, 24 Feb 2023 13:52:25 +0000 Subject: [PATCH] fix pushdown filter into set stmt bug --- src/sql/optimizer/ob_optimizer_util.cpp | 91 +++++++++++----------- src/sql/resolver/expr/ob_raw_expr_util.cpp | 23 ++++++ src/sql/resolver/expr/ob_raw_expr_util.h | 2 + src/sql/rewrite/ob_transform_utils.cpp | 33 ++++++++ src/sql/rewrite/ob_transform_utils.h | 4 + 5 files changed, 108 insertions(+), 45 deletions(-) diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index facc4694e6..88dad7faff 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -6402,57 +6402,58 @@ int ObOptimizerUtil::check_pushdown_filter_for_set(const ObSelectStmt &parent_st ObIArray &remain_filters) { int ret = OB_SUCCESS; - ObSEArray child_select_list; - ObSEArray parent_select_list; - if (OB_FAIL(subquery.get_select_exprs(child_select_list))) { - LOG_WARN("get child stmt select exprs failed", K(ret)); - } else if (OB_FAIL(parent_stmt.get_select_exprs(parent_select_list))) { - LOG_WARN("get parent stmt select exprs failed", K(ret)); - } else if (child_select_list.count() != parent_select_list.count()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("child stmt select exprs size is incorrect", K(child_select_list.count()), - K(parent_select_list.count()), K(ret)); - } + ObSEArray view_column_exprs; + ObSEArray set_op_exprs; + ObSEArray select_exprs; for (int64_t i = 0; OB_SUCC(ret) && i < pushdown_filters.count(); ++i) { - ObSEArray view_column_exprs; - ObRawExpr *expr = pushdown_filters.at(i); - if (OB_ISNULL(expr)) { + ObRawExpr *pred = NULL; + bool is_simple_expr = true; + bool pushed = false; + set_op_exprs.reuse(); + select_exprs.reuse(); + view_column_exprs.reuse(); + if (OB_ISNULL(pred = pushdown_filters.at(i))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect null expr", K(ret)); - } else if (OB_FAIL(ObTransformUtils::replace_expr(parent_select_list, - child_select_list, - expr))) { - SQL_LOG(WARN, "failed to replace expr", K(ret)); - } else if (OB_FAIL(expr->extract_info())) { - LOG_WARN("failed to extract info", K(ret), K(*expr)); - } else if (expr->has_flag(CNT_WINDOW_FUNC) || - expr->has_flag(CNT_AGG) || - expr->has_flag(CNT_SUB_QUERY) || - expr->has_flag(CNT_ONETIME)) { - ret = remain_filters.push_back(expr); - } else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(expr, view_column_exprs))) { - LOG_WARN("failed to extract column exprs", K(ret)); - } else if (!common_exprs.empty() && - !subset_exprs(view_column_exprs, common_exprs)) { - //common_exprs为空,说明既没有windown func,也没有group by - ret = remain_filters.push_back(expr); - } else if (OB_FAIL(candi_filters.push_back(expr))) { - LOG_WARN("failed to push back predicate", K(ret)); + LOG_WARN("predicate is null", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::extract_set_op_exprs(pred, set_op_exprs))) { + LOG_WARN("failed to extract set op exprs", K(ret)); + } else if (OB_FAIL(ObTransformUtils::convert_set_op_expr_to_select_expr(set_op_exprs, + subquery, + select_exprs))) { + LOG_WARN("failed to convert set op exprs to select exprs", K(ret)); + } else if (set_op_exprs.count() != select_exprs.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect set op expr count", K(ret)); + } + for (int64_t j = 0; OB_SUCC(ret) && is_simple_expr && j < select_exprs.count(); ++j) { + ObRawExpr *expr = select_exprs.at(j); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null expr", K(ret)); + } else if (expr->has_flag(CNT_WINDOW_FUNC) || + expr->has_flag(CNT_AGG) || + expr->has_flag(CNT_SUB_QUERY) || + expr->has_flag(CNT_ONETIME)) { + is_simple_expr = false; + } else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(expr, view_column_exprs))) { + LOG_WARN("failed to extract column exprs", K(ret)); + } } if (OB_FAIL(ret)) { - } else if (OB_FAIL(ObTransformUtils::replace_expr(child_select_list, - parent_select_list, - expr))) { - SQL_LOG(WARN, "failed to replace expr", K(ret)); - } else if (OB_FAIL(expr->extract_info())) { - LOG_WARN("failed to extract info", K(ret), K(*expr)); + } else if (!is_simple_expr) { + //can not push down + } else if (!common_exprs.empty() && + !subset_exprs(view_column_exprs, common_exprs)) { + //common_exprs为空,说明既没有windown func,也没有group by + } else if (OB_FAIL(candi_filters.push_back(pred))) { + LOG_WARN("failed to push back predicate", K(ret)); } else { - pushdown_filters.at(i) = expr; + pushed = true; + } + if (OB_SUCC(ret) && !pushed && + OB_FAIL(remain_filters.push_back(pred))) { + LOG_WARN("failed to push back expr", K(ret)); } - } - if (OB_SUCC(ret)) { - LOG_TRACE("success to check_pushdown_filter_for_set", K(pushdown_filters), K(candi_filters), - K(remain_filters)); } return ret; } diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index 9c0f0eb800..8685d649c6 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -3105,6 +3105,29 @@ bool ObRawExprUtils::is_all_column_exprs(const common::ObIArray &exp return is_all_column; } +int ObRawExprUtils::extract_set_op_exprs(const ObRawExpr *raw_expr, + common::ObIArray &set_op_exprs) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(raw_expr)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid raw expr", K(ret), K(raw_expr)); + } else if (raw_expr->is_set_op_expr()) { + if (OB_FAIL(add_var_to_array_no_dup(set_op_exprs, const_cast(raw_expr)))) { + LOG_WARN("failed to append expr", K(ret)); + } + } else { + int64_t N = raw_expr->get_param_count(); + for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) { + if (OB_FAIL(SMART_CALL(extract_set_op_exprs(raw_expr->get_param_expr(i), + set_op_exprs)))) { + LOG_WARN("failed to extract set op exprs", K(ret)); + } + } + } + return ret; +} + int ObRawExprUtils::extract_column_exprs(const ObRawExpr *raw_expr, ObIArray &column_exprs, bool need_pseudo_column) diff --git a/src/sql/resolver/expr/ob_raw_expr_util.h b/src/sql/resolver/expr/ob_raw_expr_util.h index 60a5637648..708ce1a0b7 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.h +++ b/src/sql/resolver/expr/ob_raw_expr_util.h @@ -370,6 +370,8 @@ public: const ObIArray *except_exprs = NULL); static bool is_all_column_exprs(const common::ObIArray &exprs); + static int extract_set_op_exprs(const ObRawExpr *raw_expr, + common::ObIArray &set_op_exprs); /// extract column exprs from the raw expr static int extract_column_exprs(const ObRawExpr *raw_expr, common::ObIArray &column_exprs, diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 420acb48a1..d0755f1f2f 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -8414,6 +8414,39 @@ int ObTransformUtils::convert_column_expr_to_select_expr(const common::ObIArray< return ret; } +int ObTransformUtils::convert_set_op_expr_to_select_expr(const common::ObIArray &set_op_exprs, + const ObSelectStmt &inner_stmt, + common::ObIArray &select_exprs) +{ + int ret = OB_SUCCESS; + ObRawExpr *outer_expr = NULL; + ObRawExpr *inner_expr = NULL; + ObSetOpRawExpr *set_op_expr = NULL; + for (int64_t i = 0; OB_SUCC(ret) && i < set_op_exprs.count(); i++) { + int64_t pos = OB_INVALID_ID; + if (OB_ISNULL(outer_expr = set_op_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_UNLIKELY(!outer_expr->is_set_op_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected expr type", K(ret)); + } else if (FALSE_IT(set_op_expr = static_cast(outer_expr))) { + /*do nothing*/ + } else if (FALSE_IT(pos = set_op_expr->get_idx())) { + /*do nothing*/ + } else if (OB_UNLIKELY(pos < 0 || pos >= inner_stmt.get_select_item_size())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid array pos", K(pos), K(inner_stmt.get_select_item_size()), K(ret)); + } else if (OB_ISNULL(inner_expr = inner_stmt.get_select_item(pos).expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(select_exprs.push_back(inner_expr))) { + LOG_WARN("failed to push back expr", K(ret)); + } else { /*do nothing*/ } + } + return ret; +} + int ObTransformUtils::convert_select_expr_to_column_expr(const common::ObIArray &select_exprs, const ObSelectStmt &inner_stmt, ObDMLStmt &outer_stmt, diff --git a/src/sql/rewrite/ob_transform_utils.h b/src/sql/rewrite/ob_transform_utils.h index a81d6ab49a..3464e81c6c 100644 --- a/src/sql/rewrite/ob_transform_utils.h +++ b/src/sql/rewrite/ob_transform_utils.h @@ -1229,6 +1229,10 @@ public: const ObSelectStmt &inner_stmt, common::ObIArray &select_exprs); + static int convert_set_op_expr_to_select_expr(const common::ObIArray &set_op_exprs, + const ObSelectStmt &inner_stmt, + common::ObIArray &select_exprs); + /** * @brief convert_select_expr_to_column_expr * 将视图的select expr转换为outer stmt对应的column expr