From 6e609dd4b1134ce2fdfbe57c800a9dfaed70b9a4 Mon Sep 17 00:00:00 2001 From: qijiax Date: Mon, 16 Dec 2024 10:15:55 +0000 Subject: [PATCH] bugfix: max varchar length in array --- deps/oblib/src/lib/udt/ob_array_type.h | 2 +- deps/oblib/src/lib/udt/ob_collection_type.cpp | 2 +- src/sql/engine/expr/ob_array_expr_utils.cpp | 6 +++++- src/sql/engine/expr/ob_expr_array_append.cpp | 1 - src/sql/engine/expr/ob_expr_array_map.cpp | 8 ++++++++ src/sql/engine/expr/ob_expr_result_type_util.cpp | 12 ++++++------ src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp | 13 ++++++++++++- src/sql/resolver/ob_resolver_utils.cpp | 10 +++++----- 8 files changed, 38 insertions(+), 16 deletions(-) diff --git a/deps/oblib/src/lib/udt/ob_array_type.h b/deps/oblib/src/lib/udt/ob_array_type.h index 2c4000166..c1e213de0 100644 --- a/deps/oblib/src/lib/udt/ob_array_type.h +++ b/deps/oblib/src/lib/udt/ob_array_type.h @@ -45,7 +45,7 @@ struct ObArrayAttr { OB_INLINE bool ob_is_array_supported_type(ObObjType type) { - return ObUNumberType >= type || ObVarcharType == type || ObCharType == type || ObDecimalIntType == type; + return ObUNumberType >= type || ObVarcharType == type || ObDecimalIntType == type; } template diff --git a/deps/oblib/src/lib/udt/ob_collection_type.cpp b/deps/oblib/src/lib/udt/ob_collection_type.cpp index 9a5aeeadb..6cfd89332 100644 --- a/deps/oblib/src/lib/udt/ob_collection_type.cpp +++ b/deps/oblib/src/lib/udt/ob_collection_type.cpp @@ -308,7 +308,7 @@ int ObSqlCollectionInfo::set_element_meta_info(const std::string &name, uint8_t meta_info->basic_meta_.set_scale(default_accuracy.get_scale()); break; case ObStringTC: - if (val <= -1 || val > OB_MAX_ORACLE_VARCHAR_LENGTH) { + if (val <= -1 || val > OB_MAX_VARCHAR_LENGTH / 4) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_WARN("data length is invalid", K(ret), K(val)); } else { diff --git a/src/sql/engine/expr/ob_array_expr_utils.cpp b/src/sql/engine/expr/ob_array_expr_utils.cpp index 9840e0504..287763eea 100644 --- a/src/sql/engine/expr/ob_array_expr_utils.cpp +++ b/src/sql/engine/expr/ob_array_expr_utils.cpp @@ -477,6 +477,10 @@ int ObArrayExprUtils::deduce_array_element_type(ObExecContext *exec_ctx, ObExprR ret = OB_NOT_SUPPORTED; LOG_WARN("unsupported element type", K(ret), K(types_stack[i].get_type())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element type"); + } else if (ob_is_varbinary_or_binary(types_stack[i].get_type(), types_stack[i].get_collation_type())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("array element in binary type isn't supported", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element in binary type"); } else if (OB_FAIL(ObExprResultTypeUtil::get_deduce_element_type(types_stack[i], elem_type))) { LOG_WARN("get deduce type failed", K(ret), K(types_stack[i].get_type()), K(elem_type.get_obj_type()), K(i)); } @@ -487,7 +491,7 @@ int ObArrayExprUtils::deduce_array_element_type(ObExecContext *exec_ctx, ObExprR for (int64_t i = 0; i < param_num && OB_SUCC(ret); i++) { if (types_stack[i].is_null()) { } else if (types_stack[i].get_type() != elem_type.get_obj_type()) { - types_stack[i].set_calc_type(elem_type.get_obj_type()); + types_stack[i].set_calc_meta(elem_type.get_meta_type()); types_stack[i].set_calc_accuracy(elem_type.get_accuracy()); } } diff --git a/src/sql/engine/expr/ob_expr_array_append.cpp b/src/sql/engine/expr/ob_expr_array_append.cpp index 8c6c4540b..c1441a7ba 100644 --- a/src/sql/engine/expr/ob_expr_array_append.cpp +++ b/src/sql/engine/expr/ob_expr_array_append.cpp @@ -175,7 +175,6 @@ int ObExprArrayAppendCommon::eval_append_batch(const ObExpr &expr, ObEvalCtx &ct ObDatumVector val_datum = expr.args_[1]->locate_expr_datumvector(ctx); for (int64_t j = 0; OB_SUCC(ret) && j < batch_size; ++j) { bool is_null_res = false; - int64_t idx = 0; if (skip.at(j) || eval_flags.at(j)) { continue; } diff --git a/src/sql/engine/expr/ob_expr_array_map.cpp b/src/sql/engine/expr/ob_expr_array_map.cpp index cc3161ba2..c312568d8 100644 --- a/src/sql/engine/expr/ob_expr_array_map.cpp +++ b/src/sql/engine/expr/ob_expr_array_map.cpp @@ -172,6 +172,14 @@ int ObExprArrayMap::calc_result_typeN(ObExprResType& type, } else { type.set_collection(subschema_id); } + } else if (!ob_is_array_supported_type(elem_type.get_obj_type())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("unsupported element type", K(ret), K(elem_type.get_obj_type())); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element type"); + } else if (ob_is_varbinary_or_binary(elem_type.get_obj_type(), elem_type.get_collation_type())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not supported binary", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element in binary type"); } else if (OB_FAIL(exec_ctx->get_subschema_id_by_collection_elem_type(ObNestedType::OB_ARRAY_TYPE, elem_type, subschema_id))) { LOG_WARN("failed to get collection subschema id", K(ret)); 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 9a880fe71..efd9e8a9f 100644 --- a/src/sql/engine/expr/ob_expr_result_type_util.cpp +++ b/src/sql/engine/expr/ob_expr_result_type_util.cpp @@ -977,6 +977,7 @@ int ObExprResultTypeUtil::get_deduce_element_type(ObExprResType &input_type, ObD ObObjType type1 = input_type.get_type(); ObObjType type2 = elem_type.get_obj_type(); ObObjType res_type = MERGE_RESULT_TYPE[type1][type2]; + ObCollationType coll_type = elem_type.get_collation_type(); ObObjMeta meta; if (res_type == ObDecimalIntType || res_type == ObNumberType || res_type == ObUNumberType) { // decimal type isn't supported in array, use double/bigint instead @@ -988,19 +989,18 @@ int ObExprResultTypeUtil::get_deduce_element_type(ObExprResType &input_type, ObD } else { meta.set_type(res_type); } - ObAccuracy acc = ObAccuracy::DDL_DEFAULT_ACCURACY[meta.get_type()]; if (ob_is_collection_sql_type(elem_type.get_obj_type())) { ret = OB_ERR_ILLEGAL_ARGUMENT_FOR_FUNCTION; LOG_USER_ERROR(OB_ERR_ILLEGAL_ARGUMENT_FOR_FUNCTION); } else { elem_type.set_meta_type(meta); - if (ob_is_string_tc(input_type.get_type())) { - ObLength len = elem_type.get_length(); - elem_type.set_accuracy(acc); + if (ob_is_string_tc(type1)) { // set max len to fix plan cache issue - elem_type.set_length(OB_MAX_ORACLE_VARCHAR_LENGTH); + elem_type.set_length(OB_MAX_VARCHAR_LENGTH / 4); + elem_type.set_collation_type(input_type.get_collation_type()); } else { - elem_type.set_accuracy(acc); + elem_type.set_accuracy(ObAccuracy::DDL_DEFAULT_ACCURACY[meta.get_type()]); + elem_type.set_collation_type(coll_type); } } diff --git a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp index 55551a7ca..b81b49d6a 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -3770,7 +3770,18 @@ int ObRawExprDeduceType::set_array_agg_result_type(ObAggFunRawExpr &expr, ret = OB_NOT_SUPPORTED; LOG_WARN("unsupported element type", K(ret), K(elem_type.get_obj_type())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element type"); - } else if (elem_type.get_obj_type() == ObDecimalIntType) { + } else if (ob_is_varbinary_or_binary(elem_type.get_obj_type(), elem_type.get_collation_type())) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("array element in binary type isn't supported", K(ret)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element in binary type"); + } else if (elem_type.get_obj_type() == ObVarcharType) { + elem_type.set_accuracy(param_expr->get_accuracy()); + if (elem_type.get_length() < 0) { + elem_type.set_length(OB_MAX_VARCHAR_LENGTH / 4); + } + } else if (elem_type.get_obj_type() == ObDecimalIntType + || elem_type.get_obj_type() == ObNumberType + || elem_type.get_obj_type() == ObUNumberType) { ObObjMeta meta; if (param_expr->get_scale() != 0) { meta.set_double(); diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index 74d56ef2c..02bbdd949 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -446,9 +446,9 @@ int ObResolverUtils::resolve_collection_type_info(const ParseNode &type_node, Ob ret = OB_NOT_SUPPORTED; LOG_WARN("not supported element type", K(ret), K(type_node.type_)); } else if (type_node.int32_values_[1]/*is binary*/ && (type_node.type_ == T_CHAR || type_node.type_ == T_VARCHAR)) { - if (OB_FAIL(buf.append(type_node.type_ == T_CHAR ? "BINARY" : "VARBINARY"))) { - LOG_WARN("failed to append type string", K(ret), K(type_node.type_)); - } + ret = OB_NOT_SUPPORTED; + LOG_WARN("not supported binary", K(ret), K(type_node.type_)); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "array element in binary type"); } else if (is_vector) { // vector type if (OB_FAIL(buf.append("VECTOR"))) { @@ -469,10 +469,10 @@ int ObResolverUtils::resolve_collection_type_info(const ParseNode &type_node, Ob int32_t length = is_bit ? type_node.int16_values_[0] : (is_char ? type_node.int32_values_[0] : type_node.int16_values_[1]); int64_t pos = 0; - if (is_char && (length <= -1 || length > OB_MAX_ORACLE_VARCHAR_LENGTH)) { + if (is_char && (length <= -1 || length > OB_MAX_VARCHAR_LENGTH / 4)) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_WARN("data length is invalid", K(ret), K(length)); - LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, "varchar", static_cast(OB_MAX_ORACLE_VARCHAR_LENGTH)); + LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, "varchar", static_cast(OB_MAX_VARCHAR_LENGTH / 4)); } else if (OB_FAIL(databuff_printf(tmp, MAX_LEN, pos, "(%d)",length))) { LOG_WARN("failed to convert len to string", K(ret), K(length)); } else if (OB_FAIL(buf.append(tmp, pos))) {