diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index 1addcad617..dcdb57a1c8 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -3245,6 +3245,21 @@ int ObRawExprUtils::extract_set_op_exprs(const ObRawExpr *raw_expr, return ret; } +int ObRawExprUtils::extract_set_op_exprs(const ObIArray &exprs, + common::ObIArray &set_op_exprs) +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) { + if (OB_ISNULL(exprs.at(i))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("Expr is NULL", K(ret), K(i)); + } else if (OB_FAIL(extract_set_op_exprs(exprs.at(i), set_op_exprs))) { + LOG_WARN("Failed to extract column 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 aec0b62066..9ab6de82c3 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.h +++ b/src/sql/resolver/expr/ob_raw_expr_util.h @@ -372,6 +372,8 @@ public: 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); + static int extract_set_op_exprs(const ObIArray &exprs, + 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_query_push_down.cpp b/src/sql/rewrite/ob_transform_query_push_down.cpp index e666108b49..024fb455de 100644 --- a/src/sql/rewrite/ob_transform_query_push_down.cpp +++ b/src/sql/rewrite/ob_transform_query_push_down.cpp @@ -414,6 +414,12 @@ int ObTransformQueryPushDown::is_select_item_same(ObSelectStmt *select_stmt, if (column_count == view_stmt->get_select_item_size()) { /*do nothing*/ //if outer output is const expr, then inner output must be const expr, eg:select 1 from (select 2 from t1) + } else if (OB_FAIL(check_set_op_expr_reference(select_stmt, view_stmt, + select_offset, is_same))) { + LOG_WARN("failed to check select item reference", K(ret)); + } else if (!is_same) { + // view stmt is set stmt and outer output not contain all set op exprs in relation exprs of view + // eg: select 1, c1 from (select 2 c1, 3 c2 from t1 union all select 4, 5 from t2 order by union[2]) v } else if (const_select_items.count() == select_stmt->get_select_item_size()) { for (int64_t i = 0; OB_SUCC(ret) && is_same && i < view_stmt->get_select_item_size(); ++i) { ObRawExpr *select_expr = NULL; @@ -440,6 +446,49 @@ int ObTransformQueryPushDown::is_select_item_same(ObSelectStmt *select_stmt, return ret; } +int ObTransformQueryPushDown::check_set_op_expr_reference(ObSelectStmt *select_stmt, + ObSelectStmt *view_stmt, + ObIArray &select_offset, + bool &is_valid) +{ + int ret = OB_SUCCESS; + is_valid = true; + if (OB_ISNULL(select_stmt)|| OB_ISNULL(view_stmt)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("stmt is NULL", K(select_stmt), K(view_stmt), K(ret)); + } else if (!view_stmt->is_set_stmt()) { + // do nothing + } else { + ObSEArray relation_exprs; + ObSEArray set_op_exprs; + ObBitSet<> selected_set_op_idx; + ObStmtExprGetter visitor; + visitor.set_relation_scope(); + visitor.remove_scope(SCOPE_SELECT); + if (OB_FAIL(view_stmt->get_relation_exprs(relation_exprs, visitor))) { + LOG_WARN("failed to get relation exprs", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::extract_set_op_exprs(relation_exprs, + set_op_exprs))) { + LOG_WARN("failed to extract column ids", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < select_offset.count(); ++i) { + if (select_offset.at(i) != -1) { + selected_set_op_idx.add_member(select_offset.at(i)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < set_op_exprs.count(); ++i) { + ObSetOpRawExpr *expr = static_cast(set_op_exprs.at(i)); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null expr", K(ret), KPC(set_op_exprs.at(i))); + } else if (!selected_set_op_idx.has_member(expr->get_idx())) { + is_valid = false; + } + } + } + return ret; +} + /*@brief check_rownum_push_down检查含有rownum能否被下压 * 1.外层存在rownum时 * 如果外层存在rownum,内层是非spj时算子基本都不支持下压,如: diff --git a/src/sql/rewrite/ob_transform_query_push_down.h b/src/sql/rewrite/ob_transform_query_push_down.h index 22391c00cb..914c00a839 100644 --- a/src/sql/rewrite/ob_transform_query_push_down.h +++ b/src/sql/rewrite/ob_transform_query_push_down.h @@ -74,6 +74,10 @@ private: bool &is_same, common::ObIArray &select_offset, common::ObIArray &const_select_items); + int check_set_op_expr_reference(ObSelectStmt *select_stmt, + ObSelectStmt *view_stmt, + common::ObIArray &select_offset, + bool &is_contain); int do_transform(ObSelectStmt *select_stmt, ObSelectStmt *view_stmt, bool need_distinct,