diff --git a/src/sql/engine/expr/ob_expr_replace.cpp b/src/sql/engine/expr/ob_expr_replace.cpp index 4721894b3d..aed5ee2399 100644 --- a/src/sql/engine/expr/ob_expr_replace.cpp +++ b/src/sql/engine/expr/ob_expr_replace.cpp @@ -71,7 +71,7 @@ int ObExprReplace::calc_result_typeN(ObExprResType &type, OZ(deduce_string_param_calc_type_and_charset(*type_ctx.get_session(), type, params, LS_BYTE)); } else { if (types_array[0].is_lob()) { - type.set_type(types_array[0].get_type()); + type.set_type(ObLongTextType); } else { type.set_varchar(); type.set_length_semantics(type_ctx.get_session()->get_actual_nls_length_semantics()); @@ -92,6 +92,7 @@ int ObExprReplace::calc_result_typeN(ObExprResType &type, ObLength from_len = 0; ObLength to_len = 0; int64_t result_len = 0; + int64_t max_len = 0; if (lib::is_oracle_mode()) { result_len = types_array[0].get_calc_length(); if (param_num == 2 || types_array[2].is_null()) { @@ -113,8 +114,13 @@ int ObExprReplace::calc_result_typeN(ObExprResType &type, type.set_length(ori_len); } else { result_len = ori_len / from_len * to_len + ori_len % from_len; - if (result_len < 0 || result_len > OB_MAX_VARCHAR_LENGTH) { - result_len = OB_MAX_VARCHAR_LENGTH; + if (type.is_lob()) { + max_len = ObAccuracy::DDL_DEFAULT_ACCURACY[type.get_type()].get_length(); + } else { + max_len = OB_MAX_VARCHAR_LENGTH; + } + if (result_len < 0 || result_len > max_len) { + result_len = max_len; } type.set_length(result_len); } @@ -128,7 +134,8 @@ int ObExprReplace::replace(ObString &ret_str, const ObString &text, const ObString &from, const ObString &to, - ObExprStringBuf &string_buf) + ObExprStringBuf &string_buf, + const int64_t max_len) { int ret = OB_SUCCESS; ObString dst_str; @@ -169,10 +176,10 @@ int ObExprReplace::replace(ObString &ret_str, ret_str.reset(); } else if (locations.count() == 0) { ret_str = text; - } else if (OB_UNLIKELY((OB_MAX_VARCHAR_LENGTH - text.length()) / locations.count() < (to.length() - from.length()))) { + } else if (OB_UNLIKELY((max_len - text.length()) / locations.count() < (to.length() - from.length()))) { ret = OB_ERR_VARCHAR_TOO_LONG; - LOG_ERROR("Result of replace() was larger than OB_MAX_VARCHAR_LENGTH.", - K(text.length()), K(to.length()), K(from.length()), K(OB_MAX_VARCHAR_LENGTH), K(ret)); + LOG_ERROR("Result of replace() was larger than max_len.", + K(text.length()), K(to.length()), K(from.length()), K(max_len), K(locations.count()), K(ret)); ret_str.reset(); } else if (OB_UNLIKELY((tot_length = text.length() + (to.length() - from.length()) * locations.count()) <= 0)) { // tot_length equals to 0 indicates that length_to is zero and "to" is empty string @@ -267,7 +274,9 @@ int ObExprReplace::eval_replace(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &exp LOG_WARN("failed to get string data", K(ret), K(expr.args_[2]->datum_meta_)); } if (OB_SUCC(ret)) { - if (OB_FAIL(replace(res, expr.datum_meta_.cs_type_, text_data, from_data, to_data, temp_allocator))) { + int64_t max_len = ObAccuracy::DDL_DEFAULT_ACCURACY[expr.datum_meta_.get_type()].get_length(); + if (OB_FAIL(replace(res, expr.datum_meta_.cs_type_, text_data, from_data, + to_data, temp_allocator, max_len))) { LOG_WARN("do replace for lob resutl failed", K(ret), K(expr.datum_meta_.type_)); } else if (OB_FAIL(ObTextStringHelper::string_to_templob_result(expr, ctx, expr_datum, res))) { LOG_WARN("set lob result failed", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_replace.h b/src/sql/engine/expr/ob_expr_replace.h index 735ac47101..f070bbf819 100644 --- a/src/sql/engine/expr/ob_expr_replace.h +++ b/src/sql/engine/expr/ob_expr_replace.h @@ -43,7 +43,9 @@ public: const common::ObString &text, const common::ObString &from, const common::ObString &to, - common::ObExprStringBuf &string_buf); + common::ObExprStringBuf &string_buf, + const int64_t max_len = OB_MAX_VARCHAR_LENGTH); + DECLARE_SET_LOCAL_SESSION_VARS; private: