diff --git a/src/sql/rewrite/ob_predicate_deduce.cpp b/src/sql/rewrite/ob_predicate_deduce.cpp index 893ef1cd4d..1c8226c656 100644 --- a/src/sql/rewrite/ob_predicate_deduce.cpp +++ b/src/sql/rewrite/ob_predicate_deduce.cpp @@ -528,6 +528,7 @@ int ObPredicateDeduce::check_type_safe(int64_t first, int64_t second, bool &type int ObPredicateDeduce::deduce_general_predicates(ObTransformerCtx &ctx, ObIArray &target_exprs, ObIArray &general_preds, + ObIArray> &lossless_cast_preds, ObIArray &result) { int ret = OB_SUCCESS; @@ -562,6 +563,51 @@ int ObPredicateDeduce::deduce_general_predicates(ObTransformerCtx &ctx, } } } + for (int64_t i = 0; OB_SUCC(ret) && i < lossless_cast_preds.count(); ++i) { + ObRawExpr *cast_expr = NULL; + ObRawExpr *pred = NULL; + const ObRawExpr *column_expr = NULL; + int64_t param_idx = -1; + if (OB_ISNULL(cast_expr = lossless_cast_preds.at(i).first) || + OB_ISNULL(pred = lossless_cast_preds.at(i).second)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::get_real_expr_without_cast(cast_expr, column_expr))) { + LOG_WARN("fail to get real expr", K(ret), K(cast_expr)); + } else if (!ObOptimizerUtil::find_item(input_exprs_, column_expr, ¶m_idx)) { + // do nothing + } else { + ObSEArray equal_exprs; + for (int64_t j = 0; OB_SUCC(ret) && j < N; ++j) { + const ObRawExpr *expr = input_exprs_.at(j); + if (!has(graph_, param_idx, j, EQ) || j == param_idx) { + // do nothing + } else if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("input expr is null", K(ret)); + } else if (!expr->is_column_ref_expr()) { + // do nothing + } else if (OB_FAIL(equal_exprs.push_back(expr))) { + LOG_WARN("failed to push back exprs"); + } + } + for (int64_t j = 0; OB_SUCC(ret) && j < equal_exprs.count(); ++j) { + ObRawExpr *new_pred = NULL; + ObRawExprCopier copier(*ctx.expr_factory_); + if (OB_FAIL(copier.add_replaced_expr(cast_expr, equal_exprs.at(j)))) { + LOG_WARN("failed to add replaced expr", K(ret)); + } else if (OB_FAIL(copier.copy_on_replace(pred, new_pred))) { + LOG_WARN("failed to copy expr node", K(ret)); + } else if (OB_FAIL(new_pred->formalize(ctx.session_info_))) { + LOG_WARN("failed to formalize expr", K(ret)); + } else if (OB_FAIL(new_pred->pull_relation_id())) { + LOG_WARN("failed to pull relation id and levels", K(ret)); + } else if (OB_FAIL(result.push_back(new_pred))) { + LOG_WARN("failed to push back new pred", K(ret)); + } + } + } + } return ret; } @@ -977,3 +1023,48 @@ bool ObPredicateDeduce::has_raw_const_equal_condition(int64_t param_idx) } return has_const_condition; } + +int ObPredicateDeduce::check_lossless_cast_table_filter(ObRawExpr *expr, + ObRawExpr *&cast_expr, + bool &is_valid) +{ + int ret = OB_SUCCESS; + ObRawExpr *left_expr = NULL; + ObRawExpr *right_expr = NULL; + cast_expr = NULL; + is_valid = true; + ObRawExpr *check_expr = NULL; + if (OB_ISNULL(expr) || + OB_UNLIKELY(expr->get_param_count() != 2) || + OB_ISNULL(left_expr = expr->get_param_expr(0)) || + OB_ISNULL(right_expr = expr->get_param_expr(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(expr), K(left_expr), K(right_expr)); + } else if (expr->get_expr_type() != T_OP_EQ) { + is_valid = false; + } else if (left_expr->is_const_expr()) { + check_expr = right_expr; + } else if (right_expr->is_const_expr()) { + check_expr = left_expr; + } else { + is_valid = false; + } + if (OB_SUCC(ret) && is_valid) { + const ObRawExpr *column_expr = NULL; + bool is_lossless = false; + if (check_expr->get_expr_type() != T_FUN_SYS_CAST) { + is_valid = false; + } else if (OB_FAIL(ObRawExprUtils::get_real_expr_without_cast(check_expr, column_expr))) { + LOG_WARN("failed to get real expr without cast", K(ret)); + } else if (!column_expr->is_column_ref_expr()) { + is_valid = false; + } else if (OB_FAIL(ObOptimizerUtil::is_lossless_column_cast(check_expr, is_lossless))) { + LOG_WARN("failed to check expr is lossless column cast", K(ret)); + } else if (!is_lossless) { + is_valid = false; + } else { + cast_expr = check_expr; + } + } + return ret; +} diff --git a/src/sql/rewrite/ob_predicate_deduce.h b/src/sql/rewrite/ob_predicate_deduce.h index 5378ab37ba..6bf6c8f9b2 100644 --- a/src/sql/rewrite/ob_predicate_deduce.h +++ b/src/sql/rewrite/ob_predicate_deduce.h @@ -42,6 +42,7 @@ public: int deduce_general_predicates(ObTransformerCtx &ctx, ObIArray &target_exprs, ObIArray &other_preds, + ObIArray> &lossless_preds, ObIArray &result); int deduce_aggr_bound_predicates(ObTransformerCtx &ctx, @@ -82,6 +83,9 @@ public: expr.has_flag(CNT_DYNAMIC_USER_VARIABLE); } + static int check_lossless_cast_table_filter(ObRawExpr *expr, + ObRawExpr *&cast_expr, + bool &is_valid); private: int init(); diff --git a/src/sql/rewrite/ob_transform_predicate_move_around.cpp b/src/sql/rewrite/ob_transform_predicate_move_around.cpp index c850c95e87..10ce83a7e7 100644 --- a/src/sql/rewrite/ob_transform_predicate_move_around.cpp +++ b/src/sql/rewrite/ob_transform_predicate_move_around.cpp @@ -3064,6 +3064,7 @@ int ObTransformPredicateMoveAround::transform_predicates( ObSEArray simple_preds; ObSEArray general_preds; ObSEArray aggr_bound_preds; + ObSEArray, 4> lossless_cast_preds; ObSqlBitSet<> visited; if (OB_ISNULL(ctx_)) { ret = OB_ERR_UNEXPECTED; @@ -3074,8 +3075,18 @@ int ObTransformPredicateMoveAround::transform_predicates( if (OB_FAIL(ObPredicateDeduce::check_deduce_validity(input_preds.at(i), is_valid))) { LOG_WARN("failed to check condition validity", K(ret)); } else if (is_valid) { + ObRawExpr *cast_expr = NULL; if (OB_FAIL(valid_preds.push_back(input_preds.at(i)))) { LOG_WARN("failed to push back predicates for deduce", K(ret)); + } else if (OB_FAIL(ObPredicateDeduce::check_lossless_cast_table_filter(input_preds.at(i), + cast_expr, + is_valid))) { + LOG_WARN("failed to check lossless cast table filter", K(ret)); + } else if (!is_valid) { + // do nothing + } else if (OB_FAIL(lossless_cast_preds.push_back(std::pair( + cast_expr, input_preds.at(i))))) { + LOG_WARN("failed to push back preds", K(ret)); } } else if (OB_FAIL(other_preds.push_back(input_preds.at(i)))) { LOG_WARN("failed to push back complex predicates", K(ret)); @@ -3098,7 +3109,8 @@ int ObTransformPredicateMoveAround::transform_predicates( if (OB_FAIL(deducer.deduce_simple_predicates(*ctx_, simple_preds))) { LOG_WARN("failed to deduce predicates for target", K(ret)); } else if (OB_FAIL(deducer.deduce_general_predicates( - *ctx_, target_exprs, other_preds, general_preds))) { + *ctx_, target_exprs, other_preds, + lossless_cast_preds, general_preds))) { LOG_WARN("failed to deduce special predicates", K(ret)); } else if (!is_pullup) { // do nothing