diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index a4df82504e..353d09cd62 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -4639,6 +4639,7 @@ int ObOptimizerUtil::generate_push_down_expr(const ObDMLStmt *stmt, { int ret = OB_SUCCESS; new_expr = NULL; + ObSEArray new_expr_params; ObRawExprFactory &expr_factory = opt_ctx.get_expr_factory(); const ObSQLSessionInfo *session_info = opt_ctx.get_session_info(); if (OB_ISNULL(session_info) || OB_ISNULL(stmt)) { @@ -4653,37 +4654,48 @@ int ObOptimizerUtil::generate_push_down_expr(const ObDMLStmt *stmt, for (int64_t i = 0; OB_SUCC(ret) && i < sub_exprs.count(); ++i) { ObIArray &cur_exprs = sub_exprs.at(i); const int64_t N = cur_exprs.count(); - // 在原or expr的子expr上只有一个expr符合条件,直接加入到or expr中即可 if (1 == N) { - if (OB_FAIL(new_expr->add_param_expr(cur_exprs.at(0)))) { - LOG_WARN("failed to add param expr", K(ret)); + if (OB_FAIL(new_expr_params.push_back(cur_exprs.at(0)))) { + LOG_WARN("failed to push back param expr", K(ret)); } } else { + ObOpRawExpr *new_param_expr = NULL; // 在原or expr的子expr上有多个expr符合条件,需要生成一个新的and expr - ObOpRawExpr *new_and_expr = NULL; - if (OB_FAIL(expr_factory.create_raw_expr(T_OP_AND, new_and_expr))) { + if (OB_FAIL(expr_factory.create_raw_expr(T_OP_AND, new_param_expr))) { LOG_WARN("failed to create and expr", K(ret)); - } else if (OB_ISNULL(new_and_expr)) { + } else if (OB_ISNULL(new_param_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("create expr get null", K(ret)); - } - for (int64_t j = 0; OB_SUCC(ret) && j < N; ++j) { - if (OB_FAIL(new_and_expr->add_param_expr(cur_exprs.at(j)))) { - LOG_WARN("failed to add param expr", K(ret)); - } - } - if (OB_FAIL(ret)) { - /* do nothing */ - } else if (OB_FAIL(new_and_expr->formalize(session_info))) { + } else if (OB_FAIL(new_param_expr->get_param_exprs().assign(cur_exprs))) { + LOG_WARN("failed to assign param exprs", K(ret)); + } else if (OB_FAIL(new_param_expr->formalize(session_info))) { LOG_WARN("failed to formalize and expr", K(ret)); - } else if (OB_FAIL(new_and_expr->pull_relation_id())) { + } else if (OB_FAIL(new_param_expr->pull_relation_id())) { LOG_WARN("failed to pull relation id and levels", K(ret)); - } else if (OB_FAIL(new_expr->add_param_expr(new_and_expr))) { - LOG_WARN("failed to add param expr", K(ret)); + } else if (OB_FAIL(new_expr_params.push_back(new_param_expr))) { + LOG_WARN("failed to push back param expr", K(ret)); } } } } + if (OB_SUCC(ret)) { + //split expr may result T_OP_ROW shared + ObSEArray new_or_exprs; + ObRawExprCopier copier(expr_factory); + ReplaceExprByType replacer(T_OP_ROW); + if (OB_FAIL(copier.copy_on_replace(new_expr_params, + new_or_exprs, + &replacer))) { + LOG_WARN("failed to copy on replace start with exprs", K(ret)); + } else if (OB_UNLIKELY(new_expr_params.count() != new_or_exprs.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(new_expr_params.count()), K(new_or_exprs.count())); + } else if (OB_FAIL(new_expr_params.assign(new_or_exprs))) { + LOG_WARN("failed to assign assign results", K(ret)); + } else if (OB_FAIL(new_expr->get_param_exprs().assign(new_expr_params))) { + LOG_WARN("failed to assign param exprs", K(ret)); + } + } if (OB_FAIL(ret)) { /* do nothing */ } else if (OB_FAIL(new_expr->formalize(session_info))) { diff --git a/src/sql/resolver/expr/ob_raw_expr_copier.h b/src/sql/resolver/expr/ob_raw_expr_copier.h index 48d0a18d9a..11cc1779a8 100644 --- a/src/sql/resolver/expr/ob_raw_expr_copier.h +++ b/src/sql/resolver/expr/ob_raw_expr_copier.h @@ -219,6 +219,43 @@ int ObRawExprCopier::add_skipped_expr(const ObIArray &targets, bool include return ret; } +/** + * ReplaceExprByType is used to generate new expr when contain some special type node + * as following case, when we need to copy a medium expr: T_OP_ROW, need to deep copy parents + * expr:(c1,c2)!=(1,2) + * ReplaceExprByType(T_OP_ROW) + * old expr:(c1,c2)!=(1,2) new expr:(c1,c2)!=(1,2) + * T_OP_NE T_OP_NE(new) + * T_OP_ROW T_OP_ROW (new)T_OP_ROW T_OP_ROW(new) + * c1 c2 const(1) const(2) (old)c1 (old)c2 (old)const(1) const(2)(old) + */ +class ReplaceExprByType : public ObIRawExprReplacer +{ +public: + ReplaceExprByType(ObItemType expr_type) : expr_type_(expr_type) {} + virtual int generate_new_expr(ObRawExprFactory &expr_factory, + ObRawExpr *old_expr, + ObRawExpr *&new_expr) + { + int ret = OB_SUCCESS; + if (OB_ISNULL(old_expr)) { + ret = OB_ERR_UNEXPECTED; + SQL_RESV_LOG(WARN, "old expr is null", K(ret)); + } else if (old_expr->get_expr_type() == expr_type_) { + if (OB_FAIL(ObRawExprCopier::copy_expr_node(expr_factory, + old_expr, + new_expr))) { + SQL_RESV_LOG(WARN, "failed to copy calc urowid expr", K(ret)); + } else if (OB_ISNULL(new_expr)) { + ret = OB_ERR_UNEXPECTED; + SQL_RESV_LOG(WARN, "failed to build new calc rowid expr", K(ret)); + } + } + return ret; + } + ObItemType expr_type_; +}; + } } diff --git a/src/sql/rewrite/ob_transform_predicate_move_around.cpp b/src/sql/rewrite/ob_transform_predicate_move_around.cpp index a498a8bee2..3a4d713589 100644 --- a/src/sql/rewrite/ob_transform_predicate_move_around.cpp +++ b/src/sql/rewrite/ob_transform_predicate_move_around.cpp @@ -2523,6 +2523,22 @@ int ObTransformPredicateMoveAround::inner_split_or_having_expr(ObSelectStmt &stm LOG_WARN("failed to push back expr", K(ret)); } } + if (OB_SUCC(ret)) { + //split expr may result T_OP_ROW shared + ObSEArray new_or_exprs; + ObRawExprCopier copier(*expr_factory); + ReplaceExprByType replacer(T_OP_ROW); + if (OB_FAIL(copier.copy_on_replace(or_exprs, + new_or_exprs, + &replacer))) { + LOG_WARN("failed to copy on replace start with exprs", K(ret)); + } else if (OB_UNLIKELY(or_exprs.count() != new_or_exprs.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(or_exprs.count()), K(new_or_exprs.count())); + } else if (OB_FAIL(or_exprs.assign(new_or_exprs))) { + LOG_WARN("failed to assign assign results", K(ret)); + } + } if (OB_SUCC(ret)) { if (OB_FAIL(ObRawExprUtils::build_or_exprs(*expr_factory, or_exprs, new_expr))) { LOG_WARN("failed to build or expr", K(ret));