[CP] fix predicate move around cannot deduce implicit cast preds
This commit is contained in:
@ -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<ObRawExpr *> &target_exprs,
|
||||
ObIArray<ObRawExpr *> &general_preds,
|
||||
ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &lossless_cast_preds,
|
||||
ObIArray<ObRawExpr *> &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<const ObRawExpr *, 4> 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;
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ public:
|
||||
int deduce_general_predicates(ObTransformerCtx &ctx,
|
||||
ObIArray<ObRawExpr *> &target_exprs,
|
||||
ObIArray<ObRawExpr *> &other_preds,
|
||||
ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &lossless_preds,
|
||||
ObIArray<ObRawExpr *> &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();
|
||||
|
||||
@ -3064,6 +3064,7 @@ int ObTransformPredicateMoveAround::transform_predicates(
|
||||
ObSEArray<ObRawExpr *, 4> simple_preds;
|
||||
ObSEArray<ObRawExpr *, 4> general_preds;
|
||||
ObSEArray<ObRawExpr *, 4> aggr_bound_preds;
|
||||
ObSEArray<std::pair<ObRawExpr*, ObRawExpr*>, 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<ObRawExpr*, ObRawExpr*>(
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user