bugfix for string_to_array and support unsigned float and double type in array

This commit is contained in:
qijiax 2024-11-23 22:15:28 +00:00 committed by ob-robot
parent 226981c115
commit 3f08f92f54
9 changed files with 59 additions and 20 deletions

View File

@ -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));
}
}

View File

@ -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));

View File

@ -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;

View File

@ -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));

View File

@ -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<double> *arr = static_cast<ObArrayFixedSize<double> *>(src);
src_elem.set_double((*arr)[idx]);
break;
}
case ObUFloatType:
case ObFloatType: {
ObArrayFixedSize<float> *arr = static_cast<ObArrayFixedSize<float> *>(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<float> *dst_arr = static_cast<ObArrayFixedSize<float> *>(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<double> *dst_arr = static_cast<ObArrayFixedSize<double> *>(dst);
if (OB_FAIL(dst_arr->push_back(res.get_double()))) {

View File

@ -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)) {

View File

@ -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<ObArrayBinary *>(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<ObArrayBinary *>(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<ObArrayBinary *>(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;

View File

@ -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;

View File

@ -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);
}