[CP] rewrite ora_decode which has const result to const result.

This commit is contained in:
jingtaoye35
2023-06-06 07:48:24 +00:00
committed by ob-robot
parent 82b923c9db
commit b9dc170c63
6 changed files with 287 additions and 3 deletions

View File

@ -76,6 +76,15 @@ int ObTransformSimplifyExpr::transform_one_stmt(common::ObIArray<ObParentDMLStmt
LOG_TRACE("succeed to remove dummy exprs", K(is_happened));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(remove_ora_decode(stmt, is_happened))) {
LOG_WARN("failed to remove ora_decode", K(ret));
} else {
trans_happened |= is_happened;
OPT_TRACE("remove ora_decode", is_happened);
LOG_TRACE("succeed to remove decode", K(is_happened));
}
}
if (OB_SUCC(ret)){
if (OB_FAIL(convert_nvl_predicate(stmt, is_happened))){
LOG_WARN("failed to convert nvl predicate", K(ret));
@ -2362,4 +2371,218 @@ int ObTransformSimplifyExpr::remove_false_true(ObRawExpr *expr,
}
}
return ret;
}
int ObTransformSimplifyExpr::remove_ora_decode(ObDMLStmt *stmt, bool &trans_happened)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr *, 2> old_exprs;
ObSEArray<ObRawExpr *, 2> new_exprs;
ObSEArray<ObRawExpr *, 16> 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<ObRawExpr *> &old_exprs,
ObIArray<ObRawExpr *> &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<ObRawExpr *, 3> 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<int64_t>(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;
}