[CP] rewrite ora_decode which has const result to const result.
This commit is contained in:
@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user