diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index 4cf481daac..fbf1345623 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -4102,22 +4102,35 @@ int ObOptimizerUtil::convert_rownum_filter_as_offset(ObRawExprFactory &expr_fact ObSQLSessionInfo *session_info, const ObItemType filter_type, ObRawExpr *const_expr, - ObRawExpr *&offset_int_expr) + ObRawExpr *&offset_int_expr, + ObRawExpr *zero_expr, + bool &offset_is_not_neg, + ObTransformerCtx *ctx) { int ret = OB_SUCCESS; - if (OB_ISNULL(const_expr) || OB_ISNULL(session_info) + if (OB_ISNULL(const_expr) || OB_ISNULL(session_info) || OB_ISNULL(ctx) || OB_ISNULL(zero_expr) || OB_UNLIKELY(filter_type != T_OP_GE && filter_type != T_OP_GT) || OB_UNLIKELY(!const_expr->get_result_type().is_integer_type() && !const_expr->get_result_type().is_number())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(const_expr), K(session_info), K(filter_type)); } else if (T_OP_GT == filter_type) { - if (OB_FAIL(floor_number_as_limit_offset_value(expr_factory, session_info, + if (OB_FAIL(ObTransformUtils::compare_const_expr_result(ctx, const_expr, T_OP_GE, + 0, offset_is_not_neg))) { + LOG_WARN("offset value is negative calc failed", K(ret)); + } else if (!offset_is_not_neg) { + offset_int_expr = zero_expr; + } else if (OB_FAIL(floor_number_as_limit_offset_value(expr_factory, session_info, const_expr, offset_int_expr))) { LOG_WARN("failed to floor number as offset value", K(ret)); } } else if (T_OP_GE == filter_type) { - if (OB_FAIL(ceil_number_as_limit_offset_value(expr_factory, session_info, + if (OB_FAIL(ObTransformUtils::compare_const_expr_result(ctx, const_expr, T_OP_GE, + 0, offset_is_not_neg))) { + LOG_WARN("offset value is negative calc failed", K(ret)); + } else if (!offset_is_not_neg) { + offset_int_expr = zero_expr; + } else if (OB_FAIL(ceil_number_as_limit_offset_value(expr_factory, session_info, const_expr, offset_int_expr))) { LOG_WARN("failed to ceil number as offset value", K(ret)); } diff --git a/src/sql/optimizer/ob_optimizer_util.h b/src/sql/optimizer/ob_optimizer_util.h index 8878e41230..97e9a318d3 100644 --- a/src/sql/optimizer/ob_optimizer_util.h +++ b/src/sql/optimizer/ob_optimizer_util.h @@ -776,7 +776,10 @@ public: ObSQLSessionInfo *session_info, const ObItemType filter_type, ObRawExpr *const_expr, - ObRawExpr *&offset_int_expr); + ObRawExpr *&offset_int_expr, + ObRawExpr *zero_expr, + bool &offset_is_not_neg, + ObTransformerCtx *ctx); static int convert_rownum_filter_as_limit(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, diff --git a/src/sql/rewrite/ob_transform_pre_process.cpp b/src/sql/rewrite/ob_transform_pre_process.cpp index 915310b696..3f6787a753 100644 --- a/src/sql/rewrite/ob_transform_pre_process.cpp +++ b/src/sql/rewrite/ob_transform_pre_process.cpp @@ -5987,27 +5987,74 @@ int ObTransformPreProcess::try_transform_generated_rownum_as_limit_offset(ObDMLS ObRawExpr* minus_cmp_expr = NULL; ObSEArray params; bool is_not_neg = false; + bool is_null = false; + bool is_not_null = false; + ObNotNullContext not_null_ctx(*ctx_, upper_stmt); if (OB_FAIL(ret) || (limit_cond == NULL && offset_cond == NULL)) { + } else if (!lib::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx_->expr_factory_, + ObIntType, + 0, + zero_expr))) { + LOG_WARN("create zero expr failed", K(ret)); + } else if (!lib::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx_->expr_factory_, + ObIntType, + 1, + one_expr))) { + LOG_WARN("create one expr failed", K(ret)); + } else if (lib::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_const_number_expr(*ctx_->expr_factory_, + ObNumberType, + ObNumber::get_zero(), + zero_expr))) { + LOG_WARN("create zero expr failed", K(ret)); + } else if (lib::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_const_number_expr(*ctx_->expr_factory_, + ObNumberType, + ObNumber::get_positive_one(), + one_expr))) { + LOG_WARN("create one expr failed", K(ret)); + } else if (limit_value != NULL && OB_FAIL(ObTransformUtils::is_const_expr_not_null(not_null_ctx, limit_value, is_not_null, is_null))) { + LOG_WARN("check value is null failed", K(ret)); + } else if (limit_value != NULL && !is_not_null && !is_null) { + //not calculable + } else if (offset_value != NULL && !is_null && + OB_FAIL(ObTransformUtils::is_const_expr_not_null(not_null_ctx, offset_value, is_not_null, is_null))) { + LOG_WARN("check value is null failed", K(ret)); + } else if (offset_value != NULL && !is_not_null && !is_null) { + //not calculable } else if (NULL != limit_cond && OB_FAIL(ObOptimizerUtil::remove_item(upper_conds, limit_cond))) { LOG_WARN("failed to remove expr", K(ret)); } else if (NULL != offset_cond && OB_FAIL(ObOptimizerUtil::remove_item(upper_conds, offset_cond))) { LOG_WARN("failed to remove expr", K(ret)); + } else if (is_null) { + limit_expr = zero_expr; + offset_expr = NULL; + ObRawExpr *and_expr = NULL; + ObRawExpr *tmp_is_not_expr = NULL; + ObSEArray not_null_exprs; + if (limit_value != NULL && (OB_FAIL(ObRawExprUtils::build_is_not_null_expr(*ctx_->expr_factory_, + limit_value, + true /*is_not_null*/, + tmp_is_not_expr)) || + OB_FAIL(not_null_exprs.push_back(tmp_is_not_expr)))) { + LOG_WARN("push back failed", K(ret)); + } else if (offset_value != NULL && (OB_FAIL(ObRawExprUtils::build_is_not_null_expr(*ctx_->expr_factory_, + offset_value, + true /*is_not_null*/, + tmp_is_not_expr)) || + OB_FAIL(not_null_exprs.push_back(tmp_is_not_expr)))) { + LOG_WARN("push back failed", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::build_and_expr(*ctx_->expr_factory_, not_null_exprs, and_expr))) { + LOG_WARN("build and expr failed", K(ret)); + } else if (OB_FAIL(and_expr->formalize(ctx_->session_info_))) { + LOG_WARN("formalize failed", K(ret)); + } else if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, and_expr, false))) { + LOG_WARN("add cons failed", K(ret)); + } } else if (is_eq_cond) { if (OB_FAIL(transform_generated_rownum_eq_cond(limit_value, limit_expr, offset_expr))) { LOG_WARN("show limit expr", K(ret), K(limit_expr), K(offset_expr)); } - } else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx_->expr_factory_, - ObIntType, - 0, - zero_expr))) { - LOG_WARN("create zero expr failed", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx_->expr_factory_, - ObIntType, - 1, - one_expr))) { - LOG_WARN("create zero expr failed", K(ret)); } else if (NULL != limit_value && (OB_FAIL(ObOptimizerUtil::convert_rownum_filter_as_limit(*ctx_->expr_factory_, ctx_->session_info_, @@ -6016,20 +6063,19 @@ int ObTransformPreProcess::try_transform_generated_rownum_as_limit_offset(ObDMLS init_limit_expr)))) { //int > 0 LOG_WARN("failed to create limit expr from rownum", K(ret)); } else if (NULL != offset_value && - (OB_FAIL(ObOptimizerUtil::convert_rownum_filter_as_offset(*ctx_->expr_factory_, + OB_FAIL(ObOptimizerUtil::convert_rownum_filter_as_offset(*ctx_->expr_factory_, ctx_->session_info_, offset_cmp_type, offset_value, - init_offset_expr)))) { + init_offset_expr, + zero_expr, + offset_is_not_neg, + ctx_))) { LOG_WARN("failed tp conver rownum as filter", K(ret)); } else if (NULL != limit_value && OB_FAIL(ObTransformUtils::compare_const_expr_result(ctx_, init_limit_expr, T_OP_GE, 1, limit_is_not_neg))) { LOG_WARN("check is not neg false", K(ret)); - } else if (NULL != offset_value && OB_FAIL(ObTransformUtils::compare_const_expr_result(ctx_, init_offset_expr, - T_OP_GE, 0, - offset_is_not_neg))) { - LOG_WARN("check is not neg false", K(ret)); } else if (NULL != limit_value && OB_FAIL(ObRawExprUtils::create_double_op_expr(*ctx_->expr_factory_, ctx_->session_info_, T_OP_GE, @@ -6041,41 +6087,24 @@ int ObTransformPreProcess::try_transform_generated_rownum_as_limit_offset(ObDMLS ctx_->session_info_, T_OP_GE, offset_cmp_expr, - init_offset_expr, + offset_value, zero_expr))) { LOG_WARN("create expr failed", K(ret)); - } else if (NULL != limit_value && OB_FAIL(params.push_back(limit_cmp_expr))) { - LOG_WARN("push back failed", K(ret)); - } else if (NULL != offset_value && OB_FAIL(params.push_back(offset_cmp_expr))) { - LOG_WARN("check is not neg false", K(ret)); - } else if (offset_value == NULL) { + } else if (offset_value == NULL && limit_value != NULL) { if (limit_is_not_neg) { limit_expr = init_limit_expr; - if (params.count() > 0) { - ObRawExpr *and_expr = NULL; - if (OB_FAIL(ObRawExprUtils::build_and_expr(*ctx_->expr_factory_, params, and_expr))) { - LOG_WARN("build and expr failed", K(ret)); - } else if (OB_FAIL(and_expr->formalize(ctx_->session_info_))) { - LOG_WARN("formalize failed", K(ret)); - } else if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, and_expr, true))) { - LOG_WARN("add cons failed", K(ret)); - } - } } else { limit_expr = zero_expr; - if (params.count() > 0) { - ObRawExpr *and_expr = NULL; - if (OB_FAIL(ObRawExprUtils::build_and_expr(*ctx_->expr_factory_, params, and_expr))) { - LOG_WARN("build and expr failed", K(ret)); - } else if (OB_FAIL(and_expr->formalize(ctx_->session_info_))) { - LOG_WARN("formalize failed", K(ret)); - } else if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, and_expr, false))) { - LOG_WARN("add cons failed", K(ret)); - } - } } - } else if (limit_value == NULL) { + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, limit_cmp_expr, limit_is_not_neg))) { + LOG_WARN("add cons failed", K(ret)); + } + } else if (limit_value == NULL && offset_value != NULL) { offset_expr = init_offset_expr; + if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, offset_cmp_expr, offset_is_not_neg))) { + LOG_WARN("add cons failed", K(ret)); + } } else if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*ctx_->expr_factory_, ctx_->session_info_, T_OP_MINUS, minus_expr, @@ -6092,13 +6121,14 @@ int ObTransformPreProcess::try_transform_generated_rownum_as_limit_offset(ObDMLS minus_expr, one_expr))) { LOG_WARN("create expr failed", K(ret)); - } else if (OB_FAIL(params.push_back(minus_cmp_expr))) { + } else if (OB_FAIL(params.push_back(minus_cmp_expr)) || OB_FAIL(params.push_back(limit_cmp_expr))) { LOG_WARN("push back failed", K(ret)); - } else if (!offset_is_not_neg || !minus_is_not_neg) { + } else if (!minus_is_not_neg || !limit_is_not_neg) { limit_expr = zero_expr; offset_expr = NULL; - - if (params.count() > 0) { + if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, offset_cmp_expr, offset_is_not_neg))) { + LOG_WARN("add cons failed", K(ret)); + } else if (params.count() > 0) { ObRawExpr *and_expr = NULL; if (OB_FAIL(ObRawExprUtils::build_and_expr(*ctx_->expr_factory_, params, and_expr))) { LOG_WARN("build and expr failed", K(ret)); @@ -6111,7 +6141,9 @@ int ObTransformPreProcess::try_transform_generated_rownum_as_limit_offset(ObDMLS } else { limit_expr = minus_expr; offset_expr = init_offset_expr; - if (params.count() > 0) { + if (OB_FAIL(ObTransformUtils::add_param_bool_constraint(ctx_, offset_cmp_expr, offset_is_not_neg))) { + LOG_WARN("add cons failed", K(ret)); + } else if (params.count() > 0) { ObRawExpr *and_expr = NULL; if (OB_FAIL(ObRawExprUtils::build_and_expr(*ctx_->expr_factory_, params, and_expr))) { LOG_WARN("build and expr failed", K(ret)); diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 98e60acfbe..62795b7d99 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -1902,7 +1902,8 @@ int ObTransformUtils::is_expr_not_null(ObNotNullContext &ctx, } else if (is_not_null) { // do nothing } else if (expr->is_static_scalar_const_expr()) { - if (OB_FAIL(is_const_expr_not_null(ctx, expr, is_not_null))) { + bool is_null = false; + if (OB_FAIL(is_const_expr_not_null(ctx, expr, is_not_null, is_null))) { LOG_WARN("failed to check calculable expr not null", K(ret)); } else if (is_not_null && !expr->is_const_raw_expr() && NULL != constraints && @@ -1954,12 +1955,14 @@ int ObTransformUtils::is_expr_not_null(ObNotNullContext &ctx, int ObTransformUtils::is_const_expr_not_null(ObNotNullContext &ctx, const ObRawExpr *expr, - bool &is_not_null) + bool &is_not_null, + bool &is_null) { int ret = OB_SUCCESS; ObObj result; bool got_result = false; is_not_null = false; + is_null = false; if (OB_ISNULL(expr) || !expr->is_static_scalar_const_expr()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret), K(expr)); @@ -1986,8 +1989,10 @@ int ObTransformUtils::is_const_expr_not_null(ObNotNullContext &ctx, if (OB_SUCC(ret) && got_result) { if (result.is_null() || (lib::is_oracle_mode() && result.is_null_oracle())) { is_not_null = false; + is_null = true; } else { is_not_null = true; + is_null = false; } } return ret; @@ -7980,26 +7985,6 @@ int ObTransformUtils::merge_limit_as_zero(ObTransformerCtx &ctx, is_valid = true; } } - if (OB_FAIL(ret)) {//to create constraint - } else if (view_offset == NULL) { - } else if (OB_FAIL(compare_const_expr_result(&ctx, view_offset, T_OP_GE, 0, is_not_neg))) { - LOG_WARN("failed to get_expr_int_value", K(ret)); - } else { - ObRawExpr *cmp_expr = NULL; - if (zero_expr == NULL && OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx.expr_factory_, - ObIntType, - 0, - zero_expr))) { - LOG_WARN("create expr failed", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*ctx.expr_factory_, ctx.session_info_, T_OP_GE, cmp_expr, - view_offset, zero_expr))) { - LOG_WARN("create_double_op_expr_failed", K(ret)); - } else if (OB_FAIL(params.push_back(cmp_expr))) { - LOG_WARN("push back failed", K(ret)); - } else if (!is_not_neg) { - is_valid = true; - } - } if (OB_FAIL(ret)) { } else if (upper_limit == NULL) { } else if (OB_FAIL(compare_const_expr_result(&ctx, upper_limit, T_OP_GE, 1, is_not_neg))) { @@ -8020,27 +8005,6 @@ int ObTransformUtils::merge_limit_as_zero(ObTransformerCtx &ctx, is_valid = true; } } - if (OB_FAIL(ret)) { - } else if (upper_offset == NULL) { - } else if (OB_FAIL(compare_const_expr_result(&ctx, upper_offset, T_OP_GE, 0, is_not_neg))) { - LOG_WARN("failed to get_expr_int_value", K(ret)); - } else { - ObRawExpr *cmp_expr = NULL; - if (zero_expr == NULL && OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx.expr_factory_, - ObIntType, - 0, - zero_expr))) { - LOG_WARN("create expr failed", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*ctx.expr_factory_, ctx.session_info_, T_OP_GE, cmp_expr, - upper_offset, zero_expr))) { - LOG_WARN("create_double_op_expr_failed", K(ret)); - } else if (OB_FAIL(params.push_back(cmp_expr))) { - LOG_WARN("push back failed", K(ret)); - } else if (!is_not_neg) { - is_valid = true; - } - } - if (OB_FAIL(ret) || view_limit == NULL || upper_offset == NULL) { //do nothing @@ -8070,11 +8034,12 @@ int ObTransformUtils::merge_limit_as_zero(ObTransformerCtx &ctx, ObRawExpr *and_expr = NULL; if (OB_FAIL(ret)) { + } else if (params.count() == 0) { + //do nothing } else if (OB_FAIL(ObRawExprUtils::build_and_expr(*(ctx.expr_factory_), params, and_expr))) { LOG_WARN("build and expr failed", K(ret)); } else if (OB_FAIL(and_expr->formalize(ctx.session_info_))) { LOG_WARN("formalize expr failed", K(ret)); - } else if (is_valid) { if (OB_FAIL(add_param_bool_constraint(&ctx, and_expr, false))) { LOG_WARN("build cons failed", K(ret)); @@ -8212,9 +8177,40 @@ int ObTransformUtils::merge_limit_offset(ObTransformerCtx *ctx, upper_offset))) { LOG_WARN("create double op expr", K(ret)); } - if (OB_FAIL(ret) || upper_limit == NULL || calc_limit_expr == NULL) { - //do nothing - } else { + if (OB_FAIL(ret)) { + } else if ( upper_limit == NULL && calc_limit_expr != NULL) { + limit_expr = calc_limit_expr; + bool is_true = false; + ObRawExpr *cmp_expr = NULL; + ObConstRawExpr *zero_expr = NULL; + + if (!lib::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, + ObIntType, + 0, + zero_expr))) { + LOG_WARN("create zero expr failed", K(ret)); + } else if (lib::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_const_number_expr(*ctx->expr_factory_, + ObNumberType, + ObNumber::get_zero(), + zero_expr))) { + LOG_WARN("create zero expr failed", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::create_double_op_expr(*ctx->expr_factory_, ctx->session_info_, + T_OP_GE, cmp_expr, calc_limit_expr, zero_expr))) { + LOG_WARN("create double op expr failed", K(ret)); + } else if (OB_FAIL(compare_const_expr_result(ctx, *calc_limit_expr, T_OP_GE, *zero_expr, is_true))) { + LOG_WARN("compare const expr is failed", K(ret)); + } else if (is_true) { + limit_expr = calc_limit_expr; + if (OB_FAIL(add_param_bool_constraint(ctx, cmp_expr, true))) { + LOG_WARN("add cons failed", K(ret)); + } + } else { + limit_expr = zero_expr; + if (OB_FAIL(add_param_bool_constraint(ctx, cmp_expr, false))) { + LOG_WARN("add cons failed", K(ret)); + } + } + } else if ( upper_limit != NULL && calc_limit_expr != NULL) { bool is_true = false; ObRawExpr *cmp_expr = NULL; if (OB_FAIL(compare_const_expr_result(ctx, *upper_limit, T_OP_LE, *calc_limit_expr, is_true))) { diff --git a/src/sql/rewrite/ob_transform_utils.h b/src/sql/rewrite/ob_transform_utils.h index 3c5d49c6ca..4ab961d42a 100644 --- a/src/sql/rewrite/ob_transform_utils.h +++ b/src/sql/rewrite/ob_transform_utils.h @@ -443,7 +443,8 @@ public: static int is_const_expr_not_null(ObNotNullContext &ctx, const ObRawExpr *expr, - bool &is_not_null); + bool &is_not_null, + bool &is_null); static int is_general_expr_not_null(ObNotNullContext &ctx, const ObRawExpr *expr, @@ -1201,7 +1202,6 @@ public: ObRawExpr *upper_offset, ObRawExpr *&limit_expr, ObRawExpr *&offset_expr); - static int compare_const_expr_result(ObTransformerCtx *ctx, ObRawExpr *expr, ObItemType op_type,