Fix incorrect accuracy when replacing nvl expr and disable simplify nvl expr in rollup

This commit is contained in:
xianyu-w
2023-05-09 06:12:11 +00:00
committed by ob-robot
parent b897e336aa
commit 0e16cc4545
5 changed files with 360 additions and 294 deletions

View File

@ -1282,6 +1282,7 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
LOG_WARN("stmt is NULL", K(stmt));
} else if (stmt->is_sel_del_upd()) {
ObNotNullContext not_null_ctx(*ctx_, stmt);
ObSEArray<ObRawExpr*, 4> ignore_exprs;
if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_WHERE))){
LOG_WARN("failed to generate not null context", K(ret));
}
@ -1291,6 +1292,7 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
} else if (OB_FAIL(inner_remove_dummy_nvl(stmt,
stmt->get_condition_exprs().at(i),
not_null_ctx,
ignore_exprs,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
} else if (OB_FAIL(not_null_ctx.add_filter(stmt->get_condition_exprs().at(i)))) {
@ -1298,26 +1300,33 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
}
}
/**
* Do not simplify expr in rollup.
* e.g.
* select nvl(NULL, a), a from t group by rollup(a, nvl(NULL, a));
* != select a, a from t group by rollup(a, a);
*/
if (OB_SUCC(ret) && stmt->is_select_stmt()) {
ObSelectStmt *sel_stmt = static_cast<ObSelectStmt *>(stmt);
not_null_ctx.reset();
if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_GROUPBY))){
LOG_WARN("failed to generate not null context", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < sel_stmt->get_group_expr_size(); ++i) {
if (OB_FAIL(inner_remove_dummy_nvl(stmt,
sel_stmt->get_group_exprs().at(i),
not_null_ctx,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
if (sel_stmt->has_rollup()) {
if (OB_FAIL(append(ignore_exprs, sel_stmt->get_group_exprs()))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_FAIL(append(ignore_exprs, sel_stmt->get_rollup_exprs()))) {
LOG_WARN("failed to append exprs", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < sel_stmt->get_rollup_expr_size(); ++i) {
if (OB_FAIL(inner_remove_dummy_nvl(stmt,
sel_stmt->get_rollup_exprs().at(i),
not_null_ctx,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
} else {
not_null_ctx.reset();
if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_GROUPBY))){
LOG_WARN("failed to generate not null context", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < sel_stmt->get_group_expr_size(); ++i) {
if (OB_FAIL(inner_remove_dummy_nvl(stmt,
sel_stmt->get_group_exprs().at(i),
not_null_ctx,
ignore_exprs,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
}
}
}
}
@ -1334,6 +1343,7 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
} else if (OB_FAIL(inner_remove_dummy_nvl(stmt,
sel_stmt->get_having_exprs().at(i),
not_null_ctx,
ignore_exprs,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
} else if (OB_FAIL(not_null_ctx.add_having_filter(sel_stmt->get_having_exprs().at(i)))) {
@ -1345,6 +1355,7 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
if (OB_FAIL(inner_remove_dummy_nvl(stmt,
sel_stmt->get_select_item(i).expr_,
not_null_ctx,
ignore_exprs,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
}
@ -1355,6 +1366,7 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
if (OB_FAIL(inner_remove_dummy_nvl(stmt,
stmt->get_order_item(i).expr_,
not_null_ctx,
ignore_exprs,
trans_happened))) {
LOG_WARN("failed to remove dummy nvl", K(ret));
}
@ -1366,6 +1378,7 @@ int ObTransformSimplifyExpr::remove_dummy_nvl(ObDMLStmt *stmt,
int ObTransformSimplifyExpr::inner_remove_dummy_nvl(ObDMLStmt *stmt,
ObRawExpr *&expr,
ObNotNullContext &not_null_ctx,
ObIArray<ObRawExpr *> &ignore_exprs,
bool &trans_happened)
{
int ret = OB_SUCCESS;
@ -1378,6 +1391,7 @@ int ObTransformSimplifyExpr::inner_remove_dummy_nvl(ObDMLStmt *stmt,
if (OB_FAIL(SMART_CALL(inner_remove_dummy_nvl(stmt,
expr->get_param_expr(i),
not_null_ctx,
ignore_exprs,
trans_happened)))){
LOG_WARN("failed to remove dummy nvl", K(ret));
}
@ -1386,7 +1400,9 @@ int ObTransformSimplifyExpr::inner_remove_dummy_nvl(ObDMLStmt *stmt,
if (OB_SUCC(ret)
&& (T_FUN_SYS_NVL == expr->get_expr_type()
|| T_FUN_SYS_IFNULL == expr->get_expr_type())) {
if (OB_FAIL(do_remove_dummy_nvl(stmt,
if (ObOptimizerUtil::find_item(ignore_exprs, expr)) {
// nvl expr is rollup expr, do nothing
} else if (OB_FAIL(do_remove_dummy_nvl(stmt,
expr,
not_null_ctx,
trans_happened))){
@ -1456,8 +1472,7 @@ int ObTransformSimplifyExpr::do_remove_dummy_nvl(ObDMLStmt *stmt,
}
}
if (OB_SUCC(ret) && new_expr != NULL) {
bool need_cast = expr->get_collation_level() != new_expr->get_collation_level();
if (need_cast && OB_FAIL(ObTransformUtils::add_cast_for_replace(
if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(
*ctx_->expr_factory_, expr, new_expr, ctx_->session_info_))) {
LOG_WARN("failed to add cast for replace", K(ret));
} else if (OB_ISNULL(new_expr)) {
@ -1488,9 +1503,10 @@ int ObTransformSimplifyExpr::convert_nvl_predicate(ObDMLStmt *stmt, bool &trans_
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt is NULL", K(stmt));
} else if (stmt->is_sel_del_upd()) {
ObSEArray<ObRawExpr*, 4> ignore_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_condition_size(); ++i) {
if (OB_FAIL(inner_convert_nvl_predicate(
stmt, stmt->get_condition_exprs().at(i), is_happened))) {
stmt, stmt->get_condition_exprs().at(i), ignore_exprs, is_happened))) {
LOG_WARN("failed to replace is null expr", K(ret));
} else {
trans_happened |= is_happened;
@ -1498,9 +1514,18 @@ int ObTransformSimplifyExpr::convert_nvl_predicate(ObDMLStmt *stmt, bool &trans_
}
if (OB_SUCC(ret) && stmt->is_select_stmt()) {
ObSelectStmt *sel_stmt = static_cast<ObSelectStmt *>(stmt);
if (sel_stmt->has_rollup()) {
if (OB_FAIL(append(ignore_exprs, sel_stmt->get_group_exprs()))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_FAIL(append(ignore_exprs, sel_stmt->get_rollup_exprs()))) {
LOG_WARN("failed to append exprs", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < sel_stmt->get_having_expr_size(); ++i) {
if (OB_FAIL(inner_convert_nvl_predicate(
sel_stmt, sel_stmt->get_having_exprs().at(i), is_happened))) {
if (OB_FAIL(inner_convert_nvl_predicate(sel_stmt,
sel_stmt->get_having_exprs().at(i),
ignore_exprs,
is_happened))) {
LOG_WARN("failed to replace is null expr", K(ret));
} else {
trans_happened |= is_happened;
@ -1513,6 +1538,7 @@ int ObTransformSimplifyExpr::convert_nvl_predicate(ObDMLStmt *stmt, bool &trans_
int ObTransformSimplifyExpr::inner_convert_nvl_predicate(ObDMLStmt *stmt,
ObRawExpr *&expr,
ObIArray<ObRawExpr *> &ignore_exprs,
bool &trans_happened)
{
int ret = OB_SUCCESS;
@ -1552,7 +1578,9 @@ int ObTransformSimplifyExpr::inner_convert_nvl_predicate(ObDMLStmt *stmt,
sibling_expr = child_0;
}
if (OB_SUCC(ret) && is_nvl_cmp_const){
if (OB_FAIL(do_convert_nvl_predicate(stmt,
if (ObOptimizerUtil::find_item(ignore_exprs, expr)) {
// nvl pred is rollup expr, do nothing
} else if (OB_FAIL(do_convert_nvl_predicate(stmt,
expr,
nvl_expr,
sibling_expr,
@ -1603,11 +1631,10 @@ int ObTransformSimplifyExpr::do_convert_nvl_predicate(ObDMLStmt *stmt,
if (OB_ISNULL(exp1) || OB_ISNULL(exp2)){
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(exp1), K(exp2));
} else if (nvl_expr->get_collation_level() != exp2->get_collation_level() &&
OB_FAIL(ObTransformUtils::add_cast_for_replace(*ctx_->expr_factory_,
nvl_expr,
exp2,
ctx_->session_info_))) {
} else if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(*ctx_->expr_factory_,
nvl_expr,
exp2,
ctx_->session_info_))) {
LOG_WARN("failed to add cast for replace", K(ret));
} else if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*(ctx_->expr_factory_),
ctx_->session_info_,
@ -1629,7 +1656,12 @@ int ObTransformSimplifyExpr::do_convert_nvl_predicate(ObDMLStmt *stmt,
// IF exp2 ~ exp3 ≡ FALSE, NVL(exp1, exp2) ~ exp3 -> exp1 is not null and exp1 ~ exp3
// IF exp2 ~ exp3 ≡ TRUE, NVL(exp1, exp2) ~ exp3 -> exp1 is null or exp1 ~ exp3
ObRawExpr *exp1_cmp_exp3 = NULL;
if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*(ctx_->expr_factory_),
if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(*ctx_->expr_factory_,
nvl_expr,
exp1,
ctx_->session_info_))) {
LOG_WARN("failed to add cast for replace", K(ret));
} else if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*(ctx_->expr_factory_),
ctx_->session_info_,
parent_expr->get_expr_type(),
exp1_cmp_exp3,