diff --git a/deps/oblib/src/lib/udt/ob_array_type.cpp b/deps/oblib/src/lib/udt/ob_array_type.cpp index 7b083ce04..251d18e79 100644 --- a/deps/oblib/src/lib/udt/ob_array_type.cpp +++ b/deps/oblib/src/lib/udt/ob_array_type.cpp @@ -102,10 +102,12 @@ int ObArrayTypeObjFactory::construct(common::ObIAllocator &alloc, const ObCollec CONSTRUCT_FIXED_ARRAY_OBJ(uint64_t); break; } + case ObUFloatType: case ObFloatType: { CONSTRUCT_FIXED_ARRAY_OBJ(float); break; } + case ObUDoubleType: case ObDoubleType: { CONSTRUCT_FIXED_ARRAY_OBJ(double); break; @@ -1275,7 +1277,7 @@ int ObArrayNested::print_element(const ObCollectionTypeBase *elem_type, ObString is_first_elem = false; uint32_t start = offset_at(i, offsets_); uint32_t elem_cnt = offsets_[i] - start; - if (OB_FAIL(data_->print_element(array_type->element_type_, format_str, start, elem_cnt, delimiter, null_str))) { + if (OB_FAIL(data_->print_element(array_type->element_type_, format_str, start, elem_cnt, delimiter, has_null_str, null_str))) { OB_LOG(WARN, "fail to append string to format_str", K(ret)); } } diff --git a/deps/oblib/src/lib/udt/ob_array_type.h b/deps/oblib/src/lib/udt/ob_array_type.h index e9f74982c..a6dfc7888 100644 --- a/deps/oblib/src/lib/udt/ob_array_type.h +++ b/deps/oblib/src/lib/udt/ob_array_type.h @@ -358,14 +358,16 @@ public : break; } case ObFloatType: - case ObDoubleType: { - int buf_size = obj_type == ObFloatType ? FLOAT_TO_STRING_CONVERSION_BUFFER_SIZE : DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE; + case ObUFloatType: + case ObDoubleType: + case ObUDoubleType: { + int buf_size = ob_is_float_tc(obj_type) ? FLOAT_TO_STRING_CONVERSION_BUFFER_SIZE : DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE; if (OB_FAIL(format_str.reserve(buf_size + 1))) { OB_LOG(WARN, "fail to reserve memory for format_str", K(ret)); } else { char *start = format_str.ptr() + format_str.length(); uint64_t len = ob_gcvt(data_[i], - obj_type == ObFloatType ? ob_gcvt_arg_type::OB_GCVT_ARG_FLOAT : ob_gcvt_arg_type::OB_GCVT_ARG_DOUBLE, + ob_is_float_tc(obj_type) ? ob_gcvt_arg_type::OB_GCVT_ARG_FLOAT : ob_gcvt_arg_type::OB_GCVT_ARG_DOUBLE, buf_size, start, NULL); if (OB_FAIL(format_str.set_length(format_str.length() + len))) { OB_LOG(WARN, "fail to set format_str len", K(ret), K(format_str.length()), K(len)); diff --git a/deps/oblib/src/lib/udt/ob_array_utils.cpp b/deps/oblib/src/lib/udt/ob_array_utils.cpp index fea92e7fe..a577564b1 100644 --- a/deps/oblib/src/lib/udt/ob_array_utils.cpp +++ b/deps/oblib/src/lib/udt/ob_array_utils.cpp @@ -231,10 +231,12 @@ int ObArrayUtil::append(ObIArrayType &array, const ObObjType elem_type, const Ob FIXED_SIZE_ARRAY_APPEND(uint64_t, get_uint64); break; } + case ObUFloatType: case ObFloatType: { FIXED_SIZE_ARRAY_APPEND(float, get_float); break; } + case ObUDoubleType: case ObDoubleType: { FIXED_SIZE_ARRAY_APPEND(double, get_double); break; diff --git a/deps/oblib/src/lib/udt/ob_collection_type.cpp b/deps/oblib/src/lib/udt/ob_collection_type.cpp index f1277f4ac..0c27a3c52 100644 --- a/deps/oblib/src/lib/udt/ob_collection_type.cpp +++ b/deps/oblib/src/lib/udt/ob_collection_type.cpp @@ -265,6 +265,12 @@ int ObSqlCollectionInfo::set_element_meta_unsigned(ObCollectionBasicType *meta_i case ObIntType: meta_info->basic_meta_.meta_.set_uint64(); break; + case ObFloatType: + meta_info->basic_meta_.meta_.set_ufloat(); + break; + case ObDoubleType: + meta_info->basic_meta_.meta_.set_udouble(); + break; default: ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid meta info", K(ret), K(meta_info)); diff --git a/src/sql/engine/expr/ob_array_cast.cpp b/src/sql/engine/expr/ob_array_cast.cpp index dfb064138..073b9e043 100644 --- a/src/sql/engine/expr/ob_array_cast.cpp +++ b/src/sql/engine/expr/ob_array_cast.cpp @@ -154,11 +154,13 @@ int ObArrayCastUtils::cast_get_element(ObIArrayType *src, const ObCollectionBasi src_elem.set_varchar((*arr)[idx]); break; } + case ObUDoubleType: case ObDoubleType: { ObArrayFixedSize *arr = static_cast *>(src); src_elem.set_double((*arr)[idx]); break; } + case ObUFloatType: case ObFloatType: { ObArrayFixedSize *arr = static_cast *>(src); src_elem.set_float((*arr)[idx]); @@ -251,6 +253,7 @@ int ObArrayCastUtils::cast_add_element(common::ObIAllocator &alloc, ObObj &src_e // to do break; } + case ObUFloatType: case ObFloatType: { ObArrayFixedSize *dst_arr = static_cast *>(dst); if (OB_FAIL(dst_arr->push_back(res.get_float()))) { @@ -258,6 +261,7 @@ int ObArrayCastUtils::cast_add_element(common::ObIAllocator &alloc, ObObj &src_e } break; } + case ObUDoubleType: case ObDoubleType: { ObArrayFixedSize *dst_arr = static_cast *>(dst); if (OB_FAIL(dst_arr->push_back(res.get_double()))) { diff --git a/src/sql/engine/expr/ob_expr_result_type_util.cpp b/src/sql/engine/expr/ob_expr_result_type_util.cpp index f905a8154..7d1df28a7 100644 --- a/src/sql/engine/expr/ob_expr_result_type_util.cpp +++ b/src/sql/engine/expr/ob_expr_result_type_util.cpp @@ -918,8 +918,12 @@ int ObExprResultTypeUtil::get_array_calc_type(ObExecContext *exec_ctx, ObObjType coll_calc_type = ARITH_RESULT_TYPE[type1][type2]; if (ob_is_int_uint(ob_obj_type_class(type1), ob_obj_type_class(type2))) { coll_calc_type = ObIntType; - } else if (type1 == ObFloatType && type2 == ObFloatType) { - coll_calc_type = ObFloatType; + } else if (ob_is_float_tc(type1) && ob_is_float_tc(type2)) { + if (type1 == ObFloatType || type2 == ObFloatType) { + coll_calc_type = ObFloatType; + } else { + coll_calc_type = ObUFloatType; + } } else if (ob_is_null(type1)) { coll_calc_type = type2; } else if (ob_is_null(type2)) { diff --git a/src/sql/engine/expr/ob_expr_string_to_array.cpp b/src/sql/engine/expr/ob_expr_string_to_array.cpp index 0ac7fcd29..4619c9247 100644 --- a/src/sql/engine/expr/ob_expr_string_to_array.cpp +++ b/src/sql/engine/expr/ob_expr_string_to_array.cpp @@ -18,6 +18,7 @@ #include "sql/engine/expr/ob_array_expr_utils.h" #include "sql/engine/ob_exec_context.h" #include "sql/engine/expr/ob_expr_result_type_util.h" +#include "lib/charset/ob_ctype.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -51,6 +52,8 @@ int ObExprStringToArray::calc_result_typeN(ObExprResType &type, if (!ob_is_string_tc(types[i].get_type()) && !ob_is_null(types[i].get_type())) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, "VARCHAR", ob_obj_type_str(types[i].get_type())); + } else { + types[i].set_calc_collation_type(ObCharset::get_system_collation()); } } @@ -73,10 +76,11 @@ int ObExprStringToArray::eval_string_to_array(const ObExpr &expr, ObEvalCtx &ctx ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); uint16_t subschema_id = expr.obj_meta_.get_subschema_id(); - ObDatum *arr_datum = NULL; + ObCollationType cs_type = expr.args_[0]->datum_meta_.cs_type_;; + ObDatum *arr_str_datum = NULL; ObDatum *delimiter_datum = NULL; ObDatum *null_str_datum = NULL; - if (OB_FAIL(expr.args_[0]->eval(ctx, arr_datum))) { + if (OB_FAIL(expr.args_[0]->eval(ctx, arr_str_datum))) { LOG_WARN("eval source array failed", K(ret)); } else if (OB_FAIL(expr.args_[1]->eval(ctx, delimiter_datum))) { LOG_WARN("eval delimiter string failed", K(ret)); @@ -91,9 +95,9 @@ int ObExprStringToArray::eval_string_to_array(const ObExpr &expr, ObEvalCtx &ctx bool has_null_str = false; ObIArrayType *arr_obj = NULL; ObArrayBinary *binary_array = NULL; - if (!arr_datum->is_null()) { + if (!arr_str_datum->is_null()) { has_arr_str = true; - arr_str.assign(arr_datum->get_string().ptr(), arr_datum->get_string().length()); + arr_str.assign(arr_str_datum->get_string().ptr(), arr_str_datum->get_string().length()); } if (!delimiter_datum->is_null()) { has_delimiter = true; @@ -108,7 +112,7 @@ int ObExprStringToArray::eval_string_to_array(const ObExpr &expr, ObEvalCtx &ctx } else if (OB_ISNULL(binary_array = static_cast(arr_obj))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("binary array is null", K(ret), K(subschema_id)); - } else if (OB_FAIL(string_to_array(binary_array, arr_str, delimiter, null_str, has_arr_str, has_delimiter, has_null_str))) { + } else if (OB_FAIL(string_to_array(binary_array, arr_str, delimiter, null_str, cs_type, has_arr_str, has_delimiter, has_null_str))) { LOG_WARN("failed to convert string to array", K(ret)); } else if (!has_arr_str) { res.set_null(); @@ -133,6 +137,7 @@ int ObExprStringToArray::eval_string_to_array_batch(const ObExpr &expr, ObEvalCt ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); const uint16_t subschema_id = expr.obj_meta_.get_subschema_id(); + ObCollationType cs_type = expr.args_[0]->datum_meta_.cs_type_;; ObIArrayType *arr_obj = NULL; if (OB_FAIL(expr.args_[0]->eval_batch(ctx, skip, batch_size))) { @@ -176,7 +181,7 @@ int ObExprStringToArray::eval_string_to_array_batch(const ObExpr &expr, ObEvalCt } else if (OB_ISNULL(binary_array = static_cast(arr_obj))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("binary array is null", K(ret), K(subschema_id)); - } else if (OB_FAIL(string_to_array(binary_array, arr_str, delimiter, null_str, has_arr_str, has_delimiter, has_null_str))) { + } else if (OB_FAIL(string_to_array(binary_array, arr_str, delimiter, null_str, cs_type, has_arr_str, has_delimiter, has_null_str))) { LOG_WARN("failed to convert string to array", K(ret)); } else if (!has_arr_str) { res_datum.at(j)->set_null(); @@ -212,6 +217,7 @@ int ObExprStringToArray::eval_string_to_array_vector(const ObExpr &expr, ObEvalC ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); const uint16_t subschema_id = expr.obj_meta_.get_subschema_id(); + ObCollationType cs_type = expr.args_[0]->datum_meta_.cs_type_;; ObIArrayType *arr_obj = NULL; if (OB_FAIL(expr.args_[0]->eval_vector(ctx, skip, bound))) { @@ -260,7 +266,7 @@ int ObExprStringToArray::eval_string_to_array_vector(const ObExpr &expr, ObEvalC } else if (OB_ISNULL(binary_array = static_cast(arr_obj))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("binary array is null", K(ret), K(subschema_id)); - } else if (OB_FAIL(string_to_array(binary_array, arr_str, delimiter, null_str, has_arr_str, has_delimiter, has_null_str))) { + } else if (OB_FAIL(string_to_array(binary_array, arr_str, delimiter, null_str, cs_type, has_arr_str, has_delimiter, has_null_str))) { LOG_WARN("failed to convert string to array", K(ret)); } else if (!has_arr_str) { res_vec->set_null(idx); @@ -284,18 +290,30 @@ int ObExprStringToArray::eval_string_to_array_vector(const ObExpr &expr, ObEvalC int ObExprStringToArray::string_to_array(ObArrayBinary *binary_array, std::string arr_str, std::string delimiter, std::string null_str, - bool has_arr_str, bool has_delimiter, bool has_null_str) + ObCollationType cs_type, bool has_arr_str, bool has_delimiter, bool has_null_str) { int ret = OB_SUCCESS; - if (!has_arr_str) { + int32_t str_len_char = 0; + if (!has_arr_str || arr_str.empty()) { // do nothing } else if (!has_delimiter) { // add value to array character by character - for (int i = 0; OB_SUCC(ret) && i < arr_str.length(); ++i) { - if (OB_FAIL(add_value_str_to_array(binary_array, std::string(1, arr_str[i]), has_null_str, null_str))) { - LOG_WARN("failed to add character to array", K(ret), K(arr_str[i])); + size_t offset = 0; + const ObCharsetInfo *cs = ObCharset::get_charset(cs_type); + while (offset < arr_str.length() && OB_SUCC(ret)) { + int mb_len = use_mb(cs) ? ob_ismbchar(cs, arr_str.data() + offset, arr_str.data() + arr_str.length()) : 0; + size_t char_len = mb_len ? mb_len : 1; + std::string value_str; + if (offset + char_len > arr_str.length()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected string end", K(arr_str.length()), K(offset), K(char_len)); + } else if (OB_FALSE_IT(value_str = arr_str.substr(offset, char_len))) { + } else if (OB_FAIL(add_value_str_to_array(binary_array, value_str, has_null_str, null_str))) { + LOG_WARN("failed to add character to array", K(ret), K(ObString(value_str.length(), value_str.data()))); + } else { + offset += char_len; } - } + } // end while } else { size_t value_start = 0; size_t value_end = 0; diff --git a/src/sql/engine/expr/ob_expr_string_to_array.h b/src/sql/engine/expr/ob_expr_string_to_array.h index 48ca3d7db..c16726bec 100644 --- a/src/sql/engine/expr/ob_expr_string_to_array.h +++ b/src/sql/engine/expr/ob_expr_string_to_array.h @@ -39,7 +39,7 @@ public: static int add_value_str_to_array(ObArrayBinary *binary_array, std::string value_str, bool has_null_str, std::string null_str); static int string_to_array(ObArrayBinary *binary_array, std::string arr_str, std::string delimiter, std::string null_str, - bool has_arr_str, bool has_delimiter, bool has_null_str); + ObCollationType cs_type, bool has_arr_str, bool has_delimiter, bool has_null_str); virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index 6dbfb6c6c..a9efb4992 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -423,6 +423,7 @@ inline bool ObResolverUtils::is_collection_support_type(const ObObjType type) type == ObUTinyIntType || type == ObUSmallIntType || type == ObUInt32Type || type == ObUInt64Type || type == ObFloatType || type == ObDoubleType || + type == ObUFloatType || type == ObUDoubleType || type == ObVarcharType || type == ObCollectionSQLType); }