diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index f55b818563..7207f2af74 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -6421,6 +6421,35 @@ int ObRawExprUtils::build_const_bool_expr(ObRawExprFactory *expr_factory, ObRawE return ret; } +int ObRawExprUtils::build_ora_decode_expr(ObRawExprFactory *expr_factory, + const ObSQLSessionInfo &session_info, + ObRawExpr *&expr, + ObIArray ¶ms_exprs) +{ + int ret = OB_SUCCESS; + expr = NULL; + ObSysFunRawExpr *ora_decode = NULL; + if (OB_ISNULL(expr_factory) || params_exprs.count() < 3) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected params", K(ret), KP(expr_factory), K(params_exprs.count())); + } else if (OB_FAIL(expr_factory->create_raw_expr(T_FUN_SYS_ORA_DECODE, ora_decode))) { + LOG_WARN("failed to create raw expr", K(ret)); + } else if (OB_ISNULL(ora_decode)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("new expr is NULL", K(ret), KP(ora_decode)); + } else if (OB_FAIL(append(ora_decode->get_param_exprs(), params_exprs))) { + LOG_WARN("failed to append into ora_decode param exprs", K(ret)); + } else { + ora_decode->set_func_name(ObString::make_string(N_ORA_DECODE)); + if (OB_FAIL(ora_decode->formalize(&session_info))) { + LOG_WARN("failed to formalize ora_decode", K(ret)); + } else { + expr = ora_decode; + } + } + return ret; +} + int ObRawExprUtils::check_composite_cast(ObRawExpr *&expr, ObSchemaChecker &schema_checker) { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/expr/ob_raw_expr_util.h b/src/sql/resolver/expr/ob_raw_expr_util.h index 6547392806..7af1d52e73 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.h +++ b/src/sql/resolver/expr/ob_raw_expr_util.h @@ -738,6 +738,10 @@ public: ObItemType type, ObRawExpr *param_expr, ObRawExpr *&exists_expr); + static int build_ora_decode_expr(ObRawExprFactory *expr_factory, + const ObSQLSessionInfo &session_info, + ObRawExpr *&expr, + ObIArray ¶m_exprs); template static bool find_expr(const common::ObIArray &exprs, const ObRawExpr* expr); template diff --git a/src/sql/rewrite/ob_transform_simplify_expr.cpp b/src/sql/rewrite/ob_transform_simplify_expr.cpp index 48cfae4c07..f367222e0c 100644 --- a/src/sql/rewrite/ob_transform_simplify_expr.cpp +++ b/src/sql/rewrite/ob_transform_simplify_expr.cpp @@ -76,6 +76,15 @@ int ObTransformSimplifyExpr::transform_one_stmt(common::ObIArray old_exprs; + ObSEArray new_exprs; + ObSEArray relation_exprs; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is NULL", K(stmt)); + } else if (OB_FAIL(stmt->get_relation_exprs(relation_exprs))) { + LOG_WARN("failed to get stmt's relation exprs"); + } + for (int64_t i = 0; OB_SUCC(ret) && i < relation_exprs.count(); ++i) { + if (OB_FAIL(inner_remove_ora_decode(relation_exprs.at(i), old_exprs, new_exprs))) { + LOG_WARN("failed to inner remove ora decode"); + } + } + if (OB_SUCC(ret) && !old_exprs.empty()) { + if (OB_FAIL(stmt->replace_relation_exprs(old_exprs, new_exprs))) { + LOG_WARN("select_stmt replace inner stmt expr failed", K(ret)); + } else { + trans_happened = true; + } + } + return ret; +} + +int ObTransformSimplifyExpr::inner_remove_ora_decode(ObRawExpr *&expr, + ObIArray &old_exprs, + ObIArray &new_exprs) +{ + int ret = OB_SUCCESS; + ObRawExpr *new_expr = NULL; + if (OB_ISNULL(expr)){ + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), KP(expr)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) { + if (OB_FAIL(SMART_CALL(inner_remove_ora_decode(expr->get_param_expr(i), + old_exprs, + new_exprs)))) { + LOG_WARN("failed to do remove ora_decode", K(ret)); + } + } + } + if (OB_SUCC(ret) && T_FUN_SYS_ORA_DECODE == expr->get_expr_type()) { + if (ObOptimizerUtil::find_item(old_exprs, expr)) { + } else if (OB_FAIL(try_remove_ora_decode(expr, new_expr))){ + LOG_WARN("failed to do remove ora_decode", K(ret)); + } else if (NULL == new_expr) { + } else if (OB_FAIL(old_exprs.push_back(expr))) { + LOG_WARN("failed to push back into old_exprs", K(ret)); + } else if (OB_FAIL(new_exprs.push_back(new_expr))) { + LOG_WARN("failed to push back into new_exprs", K(ret)); + } + } + return ret; +} + +/* + decode(com_expr, search_expr0, result_expr0, search_expr1, result_expr1 ... search_exprN, result_exprN, default) +*/ +int ObTransformSimplifyExpr::check_remove_ora_decode_valid(ObRawExpr *&expr, + int64_t &result_idx, + bool &is_valid) { + int ret = OB_SUCCESS; + is_valid = false; + int64_t param_num = 0; + int64_t const_search_num = 0; + ObRawExpr *com_expr = NULL; + bool is_all_const = true; + if (OB_ISNULL(expr) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->session_info_) || + OB_ISNULL(ctx_->expr_factory_) || (OB_ISNULL(ctx_->allocator_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), KP(expr), KP(ctx_)); + } else if (T_FUN_SYS_ORA_DECODE != expr->get_expr_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected type expr", K(ret), K(expr->get_expr_type())); + } else if (expr->is_const_expr()) { + is_valid = false; /* no need to replace */ + } else if (FALSE_IT(param_num = expr->get_param_count())) { + } else if (OB_UNLIKELY(param_num < 3)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected param numm", K(ret), K(param_num)); + } else if (OB_ISNULL(com_expr = expr->get_param_expr(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (com_expr->is_static_scalar_const_expr()) { + const bool has_default = (param_num - 1) % 2; + const int64_t search_num = (param_num - 1) / 2; + for (int64_t i = 0; OB_SUCC(ret) && is_all_const && i < search_num; ++i) { + ObRawExpr *search_expr = NULL; + int64_t search_idx = 2 * i + 1; + if (OB_ISNULL(search_expr = expr->get_param_expr(search_idx))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(search_idx)); + } else if (!search_expr->is_static_scalar_const_expr()) { + is_all_const = false; + const_search_num = i; + } else { /* search_expr is valid, continue */ } + } + if (OB_SUCC(ret) && is_all_const) { + const_search_num = search_num; + } + } + if (OB_SUCC(ret) && const_search_num > 0) { + ObSEArray param_exprs; + ObConstRawExpr *int_expr = NULL; + ObRawExpr *decode_expr = NULL; + ObObj decode_obj; + int64_t result = 0; + bool calc_happened = false; + bool is_oracle = lib::is_oracle_mode(); + if (OB_FAIL(param_exprs.push_back(com_expr))) { + LOG_WARN("failed to push back into param_exprs", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i <= const_search_num; ++i) { + int64_t param_idx = 2 * i + 1; + if (i < const_search_num && OB_FAIL(param_exprs.push_back(expr->get_param_expr(param_idx)))) { + LOG_WARN("failed to push back into search_exprs", K(ret)); + } else if (is_oracle) { + number::ObNumber num; + if (OB_FAIL(num.from(static_cast(i), *ctx_->allocator_))) { + LOG_WARN("failed to cast int64 to num"); + } else if (OB_FAIL(ObRawExprUtils::build_const_number_expr(*ctx_->expr_factory_, + ObNumberType, num, int_expr))) { + LOG_WARN("failed to build const expr", K(ret)); + } + } else if (!is_oracle && ObRawExprUtils::build_const_int_expr(*ctx_->expr_factory_, + ObIntType, i, int_expr)) { + LOG_WARN("failed to build const expr", K(ret)); + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(int_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("build unexpected NULL expr", K(ret), KP(int_expr)); + } else if (OB_FAIL(param_exprs.push_back(int_expr))) { + LOG_WARN("failed to push back into result_exprs", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObRawExprUtils::build_ora_decode_expr(ctx_->expr_factory_, + *ctx_->session_info_, + decode_expr, + param_exprs))) { + LOG_WARN("failed to build ora_decode expr", K(ret)); + } else if (ObTransformUtils::calc_const_expr_result(decode_expr, ctx_, decode_obj, calc_happened)) { + LOG_WARN("failed to calc const expr result", K(ret), K(*decode_expr)); + } else if (!calc_happened) { + is_valid = false; + } else if (OB_UNLIKELY(!decode_obj.is_numeric_type())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to calc const expr result", K(ret), K(is_valid), K(decode_obj)); + } else if (decode_obj.is_number() && OB_FAIL(decode_obj.get_number().cast_to_int64(result))) { + LOG_WARN("failed to cast to int64", K(ret)); + } else if (decode_obj.is_integer_type()) { + result = decode_obj.get_int(); + } + if (OB_SUCC(ret) && calc_happened) { + bool is_default = result == const_search_num; + if (!is_all_const && is_default) { + is_valid = false; + } else { + result_idx = is_default ? 2 * result + 1 : 2 * result + 2; + if (OB_UNLIKELY(result_idx < 0) || OB_UNLIKELY(result_idx >= param_exprs.count()) || + OB_UNLIKELY(result_idx > param_num)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected result", K(ret), K(result_idx)); + } else if (OB_FAIL(ObTransformUtils::add_equal_expr_value_constraint(ctx_, decode_expr, + param_exprs.at(result_idx)))) { + LOG_WARN("failed to add equal expr value constraint", K(ret)); + } else { + is_valid = true; + } + } + } + } /* else is_valid = false, then return */ + return ret; +} + +int ObTransformSimplifyExpr::try_remove_ora_decode(ObRawExpr *&expr, + ObRawExpr *&new_expr) +{ + int ret = OB_SUCCESS; + bool is_valid = false; + int64_t result_idx = 0; + ObRawExpr *null_expr = NULL; + new_expr = NULL; + if (OB_ISNULL(expr) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->expr_factory_) || + OB_ISNULL(ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), KP(expr), KP(ctx_)); + } else if (OB_FAIL(check_remove_ora_decode_valid(expr, result_idx, is_valid))) { + LOG_WARN("failed to check remove ora_decode", K(ret)); + } else if (is_valid) { + if (result_idx < expr->get_param_count()) { + new_expr = expr->get_param_expr(result_idx); + } else if (OB_FAIL(ObRawExprUtils::build_null_expr(*ctx_->expr_factory_, null_expr))) { + LOG_WARN("failed to build null expr", K(ret)); + } else if (OB_ISNULL(null_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), KP(null_expr)); + } else if (OB_FAIL(null_expr->formalize(ctx_->session_info_))) { + LOG_WARN("failed to formalize result expr", K(ret), K(null_expr)); + } else { + new_expr = null_expr; /* using default null */ + } + if (OB_SUCC(ret) && OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(*ctx_->expr_factory_, + expr, new_expr, ctx_->session_info_))) { + LOG_WARN("try add cast expr above failed", K(ret)); + } + } + return ret; } \ No newline at end of file diff --git a/src/sql/rewrite/ob_transform_simplify_expr.h b/src/sql/rewrite/ob_transform_simplify_expr.h index 7bcff018e7..664bd6bf25 100644 --- a/src/sql/rewrite/ob_transform_simplify_expr.h +++ b/src/sql/rewrite/ob_transform_simplify_expr.h @@ -159,6 +159,12 @@ private: int remove_false_true(common::ObIArray &exprs, bool &trans_happened); int is_valid_remove_false_true(ObRawExpr *expr, bool &is_valid); int remove_false_true(ObRawExpr *expr, ObRawExpr *&ret_expr, bool &trans_happened); + int remove_ora_decode(ObDMLStmt *stmt, bool &trans_happened); + int inner_remove_ora_decode(ObRawExpr *&expr, + ObIArray &old_exprs, + ObIArray &new_exprs); + int check_remove_ora_decode_valid(ObRawExpr *&expr, int64_t &result_idx, bool &is_valid); + int try_remove_ora_decode(ObRawExpr *&expr, ObRawExpr *&new_expr); }; } diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index b2707d8104..a765f7259a 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -10291,6 +10291,26 @@ int ObTransformUtils::add_neg_or_pos_constraint(ObTransformerCtx *trans_ctx, return ret; } +int ObTransformUtils::add_equal_expr_value_constraint(ObTransformerCtx *trans_ctx, + ObRawExpr *left, + ObRawExpr *right) +{ + int ret = OB_SUCCESS; + ObRawExpr *equal_expr = NULL; + if (OB_ISNULL(trans_ctx) || OB_ISNULL(left) || (OB_ISNULL(right)) || + OB_ISNULL(trans_ctx->expr_factory_) || OB_ISNULL(trans_ctx->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected NULL ptr", K(ret), KP(trans_ctx), KP(left), KP(right)); + } else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(*trans_ctx->expr_factory_, T_OP_EQ, + left, right, equal_expr))) { + LOG_WARN("failed to build common binary_op_expr"); + } else if (OB_FAIL(equal_expr->formalize(trans_ctx->session_info_))) { + LOG_WARN("failed to formalize expr", K(ret)); + } else if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(trans_ctx, equal_expr, true))) { + LOG_WARN("failed to add param bool constraint", K(ret)); + } + return ret; +} int ObTransformUtils::add_param_bool_constraint(ObTransformerCtx *ctx, ObRawExpr *bool_expr, const bool is_true, diff --git a/src/sql/rewrite/ob_transform_utils.h b/src/sql/rewrite/ob_transform_utils.h index 3935f2dd47..35cd1727d3 100644 --- a/src/sql/rewrite/ob_transform_utils.h +++ b/src/sql/rewrite/ob_transform_utils.h @@ -1420,8 +1420,11 @@ public: static bool check_objparam_abs_equal(const ObObjParam &obj1, const ObObjParam &obj2); static int add_neg_or_pos_constraint(ObTransformerCtx *trans_ctx, - ObRawExpr *expr, - bool is_negative = false); + ObRawExpr *expr, + bool is_negative = false); + static int add_equal_expr_value_constraint(ObTransformerCtx *trans_ctx, + ObRawExpr *left, + ObRawExpr *right); static bool check_objparam_negative(const ObObjParam &obj1); static int add_param_bool_constraint(ObTransformerCtx *ctx, ObRawExpr *bool_expr, @@ -1432,7 +1435,6 @@ public: bool need_query_compare, ObTransformerCtx *tran_ctx, bool in_add_expr); - static int add_constraint_for_groupby_expr(ObTransformerCtx *trans_ctx, ObSelectStmt *select_stmt, ObRawExpr* groupby_expr, ObRawExpr* old_expr); static int add_param_not_null_constraint(ObIArray &constraints, ObIArray ¬_null_exprs);