diff --git a/src/pl/pl_cache/ob_pl_cache.cpp b/src/pl/pl_cache/ob_pl_cache.cpp index 6a083d1a53..67ec3d9797 100644 --- a/src/pl/pl_cache/ob_pl_cache.cpp +++ b/src/pl/pl_cache/ob_pl_cache.cpp @@ -967,10 +967,10 @@ int ObPLObjectValue::match_param_info(const ObPlParamInfo ¶m_info, LOG_WARN("fail to match complex type info", K(ret), K(param), K(param_info)); } LOG_DEBUG("ext match param info", K(data_type), K(param_info), K(is_same), K(ret)); - } else if (param_info.is_oracle_empty_string_ && !param.is_null()) { //Plain strings do not match the scheme of the empty string + } else if (param_info.is_oracle_null_value_ && !param.is_null()) { is_same = false; - } else if (ObSQLUtils::is_oracle_empty_string(param) - &&!param_info.is_oracle_empty_string_) { //Empty strings do not match the scheme of ordinary strings + } else if (ObSQLUtils::is_oracle_null_with_normal_type(param) + &&!param_info.is_oracle_null_value_) { //Typed nulls can only match plans with the same type of nulls. is_same = false; } else if (param_info.flag_.is_boolean_ != param.is_boolean()) { //bool type not match int type is_same = false; diff --git a/src/pl/pl_cache/ob_pl_cache_object.cpp b/src/pl/pl_cache/ob_pl_cache_object.cpp index 68a299907d..e08a5c64e6 100644 --- a/src/pl/pl_cache/ob_pl_cache_object.cpp +++ b/src/pl/pl_cache/ob_pl_cache_object.cpp @@ -26,7 +26,7 @@ OB_SERIALIZE_MEMBER(ObPlParamInfo, scale_, type_, ext_real_type_, - is_oracle_empty_string_, + is_oracle_null_value_, // FARM COMPAT WHITELIST col_type_, pl_type_, udt_id_); @@ -54,8 +54,8 @@ int ObPLCacheObject::set_params_info(const ParamStore ¶ms, bool is_anonymous param_info.flag_ = params.at(i).get_param_flag(); param_info.type_ = params.at(i).get_param_meta().get_type(); param_info.col_type_ = params.at(i).get_collation_type(); - if (sql::ObSQLUtils::is_oracle_empty_string(params.at(i))) { - param_info.is_oracle_empty_string_ = true; + if (sql::ObSQLUtils::is_oracle_null_with_normal_type(params.at(i))) { + param_info.is_oracle_null_value_ = true; } if (params.at(i).get_param_meta().get_type() != params.at(i).get_type()) { LOG_TRACE("differ in set_params_info", diff --git a/src/pl/pl_cache/ob_pl_cache_object.h b/src/pl/pl_cache/ob_pl_cache_object.h index c03f1d8166..98970d0764 100644 --- a/src/pl/pl_cache/ob_pl_cache_object.h +++ b/src/pl/pl_cache/ob_pl_cache_object.h @@ -48,7 +48,7 @@ struct ObPlParamInfo : public sql::ObParamInfo K_(scale), K_(type), K_(ext_real_type), - K_(is_oracle_empty_string), + K_(is_oracle_null_value), K_(col_type), K_(pl_type), K_(udt_id)); diff --git a/src/sql/ob_sql_utils.cpp b/src/sql/ob_sql_utils.cpp index 4fcc9217b4..be2bb564c5 100644 --- a/src/sql/ob_sql_utils.cpp +++ b/src/sql/ob_sql_utils.cpp @@ -4770,6 +4770,11 @@ bool ObSQLUtils::is_oracle_empty_string(const ObObjParam ¶m) || ObNCharType == param.get_param_meta().get_type())); } +bool ObSQLUtils::is_oracle_null_with_normal_type(const ObObjParam ¶m) +{ + return (param.is_null() && param.get_param_meta().get_type() != ObNullType); +} + bool ObSQLUtils::is_one_part_table_can_skip_part_calc(const ObTableSchema &schema) { bool can_skip = false; @@ -4933,54 +4938,68 @@ int ObPreCalcExprConstraint::assign(const ObPreCalcExprConstraint &other, common return ret; } -int ObPreCalcExprConstraint::check_is_match(const ObObjParam &obj_param, bool &is_match) const +int ObPreCalcExprConstraint::check_is_match(ObDatumObjParam &datum_param, + ObExecContext &exec_ctx, + bool &is_match) const { int ret = OB_SUCCESS; - switch (expect_result_) { - case PRE_CALC_RESULT_NULL: - is_match = obj_param.is_null(); - break; - case PRE_CALC_RESULT_NOT_NULL: - is_match = !obj_param.is_null(); - break; - case PRE_CALC_RESULT_TRUE: - is_match = obj_param.get_bool(); - break; - case PRE_CALC_RESULT_FALSE: - is_match = !obj_param.get_bool(); - break; - case PRE_CALC_PRECISE: - case PRE_CALC_NOT_PRECISE: { - //default escape - //@todu JueHui: make escape value can be parameterized - char escape = '\\'; - bool is_precise = false; - bool expect_precise = PRE_CALC_PRECISE == expect_result_; - if (OB_FAIL(ObQueryRange::is_precise_like_range(obj_param, escape, is_precise))) { - LOG_WARN("failed to check precise constraint.", K(ret)); - } else { - is_match = is_precise == expect_precise; + ObObjParam obj_param; + ObDatum &datum = datum_param.datum_; + bool is_udt_type = false; + bool is_udt_null = false; + if (OB_FAIL(datum_param.to_objparam(obj_param, &exec_ctx.get_allocator()))) { + LOG_WARN("failed to obj param", K(ret)); + } else if (OB_FALSE_IT(is_udt_type = lib::is_oracle_mode() && obj_param.get_param_meta().is_ext())) { + } else if (is_udt_type && OB_FAIL(pl::ObPLDataType::datum_is_null(&datum, is_udt_type, is_udt_null))) { + LOG_WARN("check complex value is null not support"); + } else { + bool is_udt_type = lib::is_oracle_mode() && obj_param.get_param_meta().is_ext(); + switch (expect_result_) { + case PRE_CALC_RESULT_NULL: + is_match = is_udt_type ? is_udt_null : obj_param.is_null(); + break; + case PRE_CALC_RESULT_NOT_NULL: + is_match = is_udt_type ? !is_udt_null : !obj_param.is_null(); + break; + case PRE_CALC_RESULT_TRUE: + is_match = obj_param.get_bool(); + break; + case PRE_CALC_RESULT_FALSE: + is_match = !obj_param.get_bool(); + break; + case PRE_CALC_PRECISE: + case PRE_CALC_NOT_PRECISE: { + //default escape + //@todu JueHui: make escape value can be parameterized + char escape = '\\'; + bool is_precise = false; + bool expect_precise = PRE_CALC_PRECISE == expect_result_; + if (OB_FAIL(ObQueryRange::is_precise_like_range(obj_param, escape, is_precise))) { + LOG_WARN("failed to check precise constraint.", K(ret)); + } else { + is_match = is_precise == expect_precise; + } + break; + } + case PRE_CALC_RESULT_NO_WILDCARD: { + ObString pattern_val = obj_param.get_string(); + if (obj_param.is_lob()) { + is_match = false; + } else if (!pattern_val.empty()) { + is_match = OB_ISNULL(pattern_val.find('%')) && + OB_ISNULL(pattern_val.find('_')) && + OB_ISNULL(pattern_val.find('\\')); + } else { + is_match = true; + } } break; - } - case PRE_CALC_RESULT_NO_WILDCARD: { - ObString pattern_val = obj_param.get_string(); - if (obj_param.is_lob()) { - is_match = false; - } else if (!pattern_val.empty()) { - is_match = OB_ISNULL(pattern_val.find('%')) && - OB_ISNULL(pattern_val.find('_')) && - OB_ISNULL(pattern_val.find('\\')); - } else { - is_match = true; - } - } - break; - default: - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expect res type", K_(expect_result), K(ret)); - break; - } // switch end + default: + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expect res type", K_(expect_result), K(ret)); + break; + } // switch end + } return ret; } @@ -5001,10 +5020,15 @@ int ObRowidConstraint::assign(const ObPreCalcExprConstraint &other, common::ObIA return ret; } -int ObRowidConstraint::check_is_match(const ObObjParam &obj_param, bool &is_match) const +int ObRowidConstraint::check_is_match(ObDatumObjParam &datum_param, + ObExecContext &exec_ctx, + bool &is_match) const { int ret = OB_SUCCESS; - if (OB_UNLIKELY(!obj_param.is_urowid())) { + ObObjParam obj_param; + if (OB_FAIL(datum_param.to_objparam(obj_param, &exec_ctx.get_allocator()))) { + LOG_WARN("failed to obj param", K(ret)); + } else if (OB_UNLIKELY(!obj_param.is_urowid())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected rowid param", K(obj_param), K(ret)); } else { diff --git a/src/sql/ob_sql_utils.h b/src/sql/ob_sql_utils.h index 0a82289471..d97b3d2532 100644 --- a/src/sql/ob_sql_utils.h +++ b/src/sql/ob_sql_utils.h @@ -602,6 +602,7 @@ public: ObString &out); //检查参数是否为Oracle模式下的'' static bool is_oracle_empty_string(const common::ObObjParam ¶m); + static bool is_oracle_null_with_normal_type(const common::ObObjParam ¶m); static int convert_sql_text_from_schema_for_resolve(common::ObIAllocator &allocator, const common::ObDataTypeCastParams &dtc_params, ObString &sql_text, @@ -1224,7 +1225,9 @@ struct ObPreCalcExprConstraint : public common::ObDLinkBase rowid_type_array_; }; diff --git a/src/sql/plan_cache/ob_cache_object.cpp b/src/sql/plan_cache/ob_cache_object.cpp index 66652d48fc..caefbe66bb 100644 --- a/src/sql/plan_cache/ob_cache_object.cpp +++ b/src/sql/plan_cache/ob_cache_object.cpp @@ -36,7 +36,7 @@ void ObParamInfo::reset() scale_ = 0; type_ = common::ObNullType; ext_real_type_ = common::ObNullType; - is_oracle_empty_string_ = false; + is_oracle_null_value_ = false; col_type_ = common::CS_TYPE_INVALID; precision_ = PRECISION_UNKNOWN_YET; } @@ -46,7 +46,7 @@ OB_SERIALIZE_MEMBER(ObParamInfo, scale_, type_, ext_real_type_, - is_oracle_empty_string_, + is_oracle_null_value_, // FARM COMPAT WHITELIST col_type_, precision_); @@ -79,8 +79,8 @@ int ObPlanCacheObject::set_params_info(const ParamStore ¶ms) param_info.flag_ = params.at(i).get_param_flag(); param_info.type_ = params.at(i).get_param_meta().get_type(); param_info.col_type_ = params.at(i).get_collation_type(); - if (ObSQLUtils::is_oracle_empty_string(params.at(i))) { - param_info.is_oracle_empty_string_ = true; + if (ObSQLUtils::is_oracle_null_with_normal_type(params.at(i))) { + param_info.is_oracle_null_value_ = true; } if (params.at(i).get_param_meta().get_type() != params.at(i).get_type()) { LOG_TRACE("differ in set_params_info", @@ -176,11 +176,8 @@ int ObPlanCacheObject::check_pre_calc_cons(const bool is_ignore_stmt, is_match = false; ret = OB_SUCCESS; } else { - ObObjParam obj_param; for (int64_t i = 0; OB_SUCC(ret) && is_match && i < datum_params.count(); ++i) { - if (OB_FAIL(datum_params.at(i).to_objparam(obj_param, &exec_ctx.get_allocator()))) { - LOG_WARN("failed to obj param", K(ret)); - } else if (OB_FAIL(pre_calc_con.check_is_match(obj_param, is_match))) { + if (OB_FAIL(pre_calc_con.check_is_match(datum_params.at(i), exec_ctx, is_match))) { LOG_WARN("failed to check is match", K(ret)); } // else end } // for end diff --git a/src/sql/plan_cache/ob_cache_object.h b/src/sql/plan_cache/ob_cache_object.h index 1f462cbc8b..d9820b5234 100644 --- a/src/sql/plan_cache/ob_cache_object.h +++ b/src/sql/plan_cache/ob_cache_object.h @@ -107,7 +107,7 @@ struct ObParamInfo : scale_(0), type_(common::ObNullType), ext_real_type_(common::ObNullType), - is_oracle_empty_string_(false), + is_oracle_null_value_(false), col_type_(common::CS_TYPE_INVALID), precision_(PRECISION_UNKNOWN_YET) {} @@ -118,7 +118,7 @@ struct ObParamInfo K_(scale), K_(type), K_(ext_real_type), - K_(is_oracle_empty_string), + K_(is_oracle_null_value), K_(col_type), K_(precision)); @@ -128,8 +128,8 @@ struct ObParamInfo common::ObScale scale_; common::ObObjType type_; common::ObObjType ext_real_type_; // use as high 4 bytes of udt id if type is sql udt - //处理Oracle模式空串在plan_cache中的匹配 - bool is_oracle_empty_string_; + //处理 Oracle 模式带类型 null 值在 plan_cache 中的匹配 + bool is_oracle_null_value_; common::ObCollationType col_type_; common::ObPrecision precision_; diff --git a/src/sql/plan_cache/ob_plan_set.cpp b/src/sql/plan_cache/ob_plan_set.cpp index 14daa0340a..fa12f2124b 100644 --- a/src/sql/plan_cache/ob_plan_set.cpp +++ b/src/sql/plan_cache/ob_plan_set.cpp @@ -275,10 +275,10 @@ int ObPlanSet::match_param_info(const ObParamInfo ¶m_info, LOG_TRACE("ext match param info", K(data_type), K(param_info), K(is_same), K(ret)); } LOG_DEBUG("ext match param info", K(data_type), K(param_info), K(is_same), K(ret)); - } else if (param_info.is_oracle_empty_string_ && !param.is_null()) { //普通字符串不匹配空串的计划 + } else if (param_info.is_oracle_null_value_ && !param.is_null()) { is_same = false; - } else if (ObSQLUtils::is_oracle_empty_string(param) - &&!param_info.is_oracle_empty_string_) { //空串不匹配普通字符串的计划 + } else if (ObSQLUtils::is_oracle_null_with_normal_type(param) + &&!param_info.is_oracle_null_value_) { //Typed nulls can only match plans with the same type of nulls. is_same = false; } else if (param_info.flag_.is_boolean_ != param.is_boolean()) { //bool type not match int type is_same = false; diff --git a/src/sql/rewrite/ob_transform_const_propagate.cpp b/src/sql/rewrite/ob_transform_const_propagate.cpp index 4edf9a034e..aeefb8da65 100644 --- a/src/sql/rewrite/ob_transform_const_propagate.cpp +++ b/src/sql/rewrite/ob_transform_const_propagate.cpp @@ -813,7 +813,7 @@ int ObTransformConstPropagate::collect_equal_pair_from_pullup(ObDMLStmt *stmt, got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or caculable expr", K(ret)); - } else if (got_result && (result.is_null() + } else if (got_result && !result.is_ext() && (result.is_null() || (lib::is_oracle_mode() && result.is_null_oracle()))) { is_valid = true; if (!equal_info.const_expr_ -> is_const_raw_expr()) { diff --git a/src/sql/rewrite/ob_transform_predicate_move_around.cpp b/src/sql/rewrite/ob_transform_predicate_move_around.cpp index 629f3b7a4f..5903625de8 100644 --- a/src/sql/rewrite/ob_transform_predicate_move_around.cpp +++ b/src/sql/rewrite/ob_transform_predicate_move_around.cpp @@ -1932,7 +1932,7 @@ int ObTransformPredicateMoveAround::pullup_predicates_from_const_select(ObSelect got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or caculable expr", K(ret)); - } else if (!got_result || (!result.is_null() + } else if (!got_result || result.is_ext() || (!result.is_null() && !(lib::is_oracle_mode() && result.is_null_oracle()))) { //do nothing } else if (OB_FAIL(ObRawExprUtils::build_is_not_null_expr(*ctx_->expr_factory_, @@ -3584,7 +3584,7 @@ int ObTransformPredicateMoveAround::create_equal_exprs_for_insert(ObDelUpdStmt * got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or caculable expr", K(ret)); - } else if (!got_result || (!result.is_null() + } else if (!got_result || result.is_ext() || (!result.is_null() && !(lib::is_oracle_mode() && result.is_null_oracle()))) { //do nothing } else { @@ -3707,7 +3707,7 @@ int ObTransformPredicateMoveAround::generate_pullup_predicates_for_dual_stmt( got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or caculable expr", K(ret)); - } else if (!got_result || (!result.is_null() + } else if (!got_result || result.is_ext() || (!result.is_null() && !(lib::is_oracle_mode() && result.is_null_oracle()))) { //do nothing } else if (OB_ISNULL(column_expr = stmt.get_column_expr_by_id(view.table_id_, @@ -3893,7 +3893,7 @@ int ObTransformPredicateMoveAround::is_column_expr_null(ObDMLStmt *stmt, got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or caculable expr", K(ret)); - } else if (got_result && (result.is_null() + } else if (got_result && !result.is_ext() && (result.is_null() || (lib::is_oracle_mode() && result.is_null_oracle()))) { is_null = true; if (!child_expr->is_const_raw_expr() && OB_FAIL(constraints.push_back(child_expr))) { diff --git a/src/sql/rewrite/ob_transform_simplify_expr.cpp b/src/sql/rewrite/ob_transform_simplify_expr.cpp index bd825dcb4f..dfba690ffc 100644 --- a/src/sql/rewrite/ob_transform_simplify_expr.cpp +++ b/src/sql/rewrite/ob_transform_simplify_expr.cpp @@ -531,7 +531,7 @@ int ObTransformSimplifyExpr::extract_null_expr(ObRawExpr *expr, got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or calculable expr", K(ret)); - } else if (got_result && + } else if (got_result && !result.is_ext() && (result.is_null() || (lib::is_oracle_mode() && result.is_null_oracle()))) { if (OB_FAIL(null_expr_lists.push_back(expr))) { LOG_WARN("failed to push back expr", K(ret)); @@ -1440,7 +1440,7 @@ int ObTransformSimplifyExpr::do_remove_dummy_nvl(ObDMLStmt *stmt, got_result, *ctx_->allocator_))) { LOG_WARN("failed to calc const or caculable expr", K(ret)); - } else if (got_result && (result.is_null() + } else if (got_result && !result.is_ext() && (result.is_null() || (lib::is_oracle_mode() && result.is_null_oracle()))) { // NVL(NULL, child_1) -> child_1 ObExprConstraint expr_cons(child_0, PreCalcExprExpectResult::PRE_CALC_RESULT_NULL); diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 8370e5c1da..aa1cb19c9d 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -2272,7 +2272,8 @@ int ObTransformUtils::is_expr_not_null(ObNotNullContext &ctx, 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 && NULL != constraints && + } else if (is_not_null && !expr->is_const_raw_expr() && + NULL != constraints && OB_FAIL(constraints->push_back(const_cast(expr)))) { LOG_WARN("failed to push back constraint expr", K(ret)); } @@ -2352,7 +2353,7 @@ int ObTransformUtils::is_const_expr_not_null(ObNotNullContext &ctx, LOG_WARN("failed to calc const or calculable expr", K(ret)); } - if (OB_SUCC(ret) && got_result) { + if (OB_SUCC(ret) && got_result && !result.is_ext()) { if (result.is_null() || (lib::is_oracle_mode() && result.is_null_oracle())) { is_not_null = false; is_null = true;