From 372a785c8e5e7afc09e8c827186d7c6cd84614ed Mon Sep 17 00:00:00 2001 From: chimyue Date: Thu, 8 Aug 2024 04:12:09 +0000 Subject: [PATCH] adjust locate expr behaviors when null is used as the third param --- .../ob_compatibility_control_feature_def.h | 5 +++ src/sql/engine/expr/ob_expr_locate.cpp | 7 +++++ src/sql/engine/expr/ob_expr_locate.h | 3 ++ src/sql/engine/expr/ob_expr_operator.cpp | 31 ++++++++++++++++--- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/share/ob_compatibility_control_feature_def.h b/src/share/ob_compatibility_control_feature_def.h index ff8f818db6..f6bc89d291 100644 --- a/src/share/ob_compatibility_control_feature_def.h +++ b/src/share/ob_compatibility_control_feature_def.h @@ -33,4 +33,9 @@ DEF_COMPAT_CONTROL_FEATURE(VAR_NAME_LENGTH, "MySQL will limit the length of user-defined variable names to within 64 characters", MOCK_CLUSTER_VERSION_4_2_3_0, CLUSTER_VERSION_4_3_0_0, CLUSTER_VERSION_4_3_2_0) + +DEF_COMPAT_CONTROL_FEATURE(FUNC_LOCATE_NULL, + "The result of REPLACE('x', 'abc', null) is different in MySQL 5.7 and 8.0", + MOCK_CLUSTER_VERSION_4_2_5_0, CLUSTER_VERSION_4_3_0_0, + CLUSTER_VERSION_4_3_3_0) #endif diff --git a/src/sql/engine/expr/ob_expr_locate.cpp b/src/sql/engine/expr/ob_expr_locate.cpp index 26c576029f..32d544c53c 100644 --- a/src/sql/engine/expr/ob_expr_locate.cpp +++ b/src/sql/engine/expr/ob_expr_locate.cpp @@ -61,5 +61,12 @@ int ObExprLocate::calc_result_typeN(ObExprResType &type, return ret; } +DEF_SET_LOCAL_SESSION_VARS(ObExprLocate, raw_expr) { + int ret = OB_SUCCESS; + SET_LOCAL_SYSVAR_CAPACITY(1); + EXPR_ADD_LOCAL_SYSVAR(share::SYS_VAR_OB_COMPATIBILITY_VERSION); + return ret; +} + } //namespace sql } //namespace oceanbase diff --git a/src/sql/engine/expr/ob_expr_locate.h b/src/sql/engine/expr/ob_expr_locate.h index df3ed2316d..8a9caedeaf 100644 --- a/src/sql/engine/expr/ob_expr_locate.h +++ b/src/sql/engine/expr/ob_expr_locate.h @@ -27,6 +27,9 @@ public: ObExprResType *types_array, int64_t param_num, common::ObExprTypeCtx &type_ctx) const; + + DECLARE_SET_LOCAL_SESSION_VARS; + private: static const int8_t PARAM_NUM_TWO = 2; static const int8_t PARAM_NUM_THREE = 3; diff --git a/src/sql/engine/expr/ob_expr_operator.cpp b/src/sql/engine/expr/ob_expr_operator.cpp index 11f7c2e5b8..12fbe4e18f 100644 --- a/src/sql/engine/expr/ob_expr_operator.cpp +++ b/src/sql/engine/expr/ob_expr_operator.cpp @@ -5912,13 +5912,36 @@ int ObLocationExprOperator::calc_(const ObExpr &expr, const ObExpr &sub_arg, if (OB_SUCC(ret) && !has_result && 3 == expr.arg_cnt_) { if (OB_FAIL(expr.args_[2]->eval(ctx, pos))) { LOG_WARN("eval arg 2 failed", K(ret)); - } else if (pos->is_null()) { - res_datum.set_int(0); - has_result = true; - } else { + } else if (!pos->is_null()) { // TODO: 验证MySQL下uint64超过int64值域范围,隐式cast的结果 // pos_int = pos->get_int(); + } else if (lib::is_oracle_mode()) { + res_datum.set_int(0); + has_result = true; + } else { + has_result = true; + ObSolidifiedVarsGetter helper(expr, ctx, ctx.exec_ctx_.get_my_session()); + const ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); + uint64_t compat_version = 0; + ObCompatType compat_type = COMPAT_MYSQL57; + bool is_enable = false; + if (OB_ISNULL(session)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("session info is null", K(ret)); + } else if (OB_FAIL(helper.get_compat_version(compat_version))) { + LOG_WARN("failed to get compat version", K(ret)); + } else if (OB_FAIL(ObCompatControl::check_feature_enable(compat_version, + ObCompatFeatureType::FUNC_LOCATE_NULL, + is_enable))) { + LOG_WARN("failed to check feature enable", K(ret)); + } else if (OB_FAIL(session->get_compatibility_control(compat_type))) { + LOG_WARN("failed to get compat type", K(ret)); + } else if (is_enable && COMPAT_MYSQL8 == compat_type) { + res_datum.set_null(); + } else { + res_datum.set_int(0); + } } }