diff --git a/src/sql/engine/aggregate/ob_aggregate_processor.cpp b/src/sql/engine/aggregate/ob_aggregate_processor.cpp index c6a5812795..103fc31284 100644 --- a/src/sql/engine/aggregate/ob_aggregate_processor.cpp +++ b/src/sql/engine/aggregate/ob_aggregate_processor.cpp @@ -6220,15 +6220,15 @@ int ObAggregateProcessor::get_json_arrayagg_result(const ObAggrInfo &aggr_info, if (OB_FAIL(extra->get_bool_mark(0, is_bool))) { LOG_WARN("get_bool info failed, may not distinguish between bool and int", K(ret)); } + + // get type + ObObj *tmp_obj = NULL; while (OB_SUCC(ret) && OB_SUCC(extra->get_next_row(storted_row))) { if (OB_ISNULL(storted_row)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(storted_row)); } else { - // get type - ObObj *tmp_obj = NULL; - if (OB_ISNULL(tmp_obj = static_cast(tmp_alloc.alloc( - sizeof(ObObj) * (storted_row->cnt_))))) { + if (OB_ISNULL(tmp_obj) && OB_ISNULL(tmp_obj = static_cast(tmp_alloc.alloc(sizeof(ObObj) * (storted_row->cnt_))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret), K(tmp_obj)); } else if (OB_FAIL(convert_datum_to_obj(aggr_info, *storted_row, tmp_obj, storted_row->cnt_))) { diff --git a/src/sql/engine/expr/ob_expr_json_func_helper.cpp b/src/sql/engine/expr/ob_expr_json_func_helper.cpp index 274cfd207b..412580ef92 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -1229,12 +1229,12 @@ int ObJsonExprHelper::transform_convertible_2jsonBase(const T &datum, && OB_FAIL(ObJsonExprHelper::ensure_collation(type, cs_type))) { // should check collation first LOG_WARN("Invalid collation type for input string.", K(ret)); - } else if (deep_copy) { - ret = deep_copy_ob_string(*allocator, datum.get_string(), j_str); } else { j_str = datum.get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, type, cs_type, has_lob_header, j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (deep_copy) { + ret = deep_copy_ob_string(*allocator, j_str, j_str); } } @@ -1303,6 +1303,7 @@ int ObJsonExprHelper::transform_convertible_2jsonBase(const T &datum, LOG_WARN("failed: json tree to bin", K(ret)); } } else { + json_node->set_allocator(allocator); j_base = json_node; } } diff --git a/src/sql/engine/expr/ob_expr_json_object.cpp b/src/sql/engine/expr/ob_expr_json_object.cpp index cbf3ce211e..8ae4111b3e 100644 --- a/src/sql/engine/expr/ob_expr_json_object.cpp +++ b/src/sql/engine/expr/ob_expr_json_object.cpp @@ -41,152 +41,148 @@ int ObExprJsonObject::calc_result_typeN(ObExprResType& type, ObExprTypeCtx& type_ctx) const { INIT_SUCC(ret); - ObSQLSessionInfo *session = const_cast(type_ctx.get_session()); - ObExecContext *exec_ctx = nullptr; - if (OB_ISNULL(session)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("session is NULL", K(ret)); - } else if (lib::is_mysql_mode() && OB_ISNULL(exec_ctx = session->get_cur_exec_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("exec context is NULL", K(ret)); - } else if (OB_UNLIKELY(param_num < 0 || (lib::is_mysql_mode() && param_num % 2 != 0 || (lib::is_oracle_mode() && param_num < 4)))) { + if (OB_UNLIKELY(param_num < 0 + || (lib::is_mysql_mode() && param_num % 2 != 0 + || (lib::is_oracle_mode() && param_num < 4)))) { ret = OB_ERR_PARAM_SIZE; const ObString name = "json_object"; LOG_USER_ERROR(OB_ERR_PARAM_SIZE, name.length(), name.ptr()); - } else if (lib::is_mysql_mode() && exec_ctx->is_ps_prepare_stage()) { - // the ps prepare stage does not do type deduction, and directly gives a default type. - type.set_json(); - type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length()); - } else { - if (lib::is_oracle_mode()) { - // type.set_json(); - for (int64_t i = 0; OB_SUCC(ret) && i < param_num - 4; i += 3) { - if ((types_stack[i].get_type() == ObNullType)) { - ret = OB_ERR_JSON_DOCUMENT_NULL_KEY; - LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY); - } else if (types_stack[i].get_type() != ObCharType - && types_stack[i].get_type() != ObVarcharType - && types_stack[i].get_type() != ObNCharType - && types_stack[i].get_type() != ObNVarchar2Type) { - ret = OB_ERR_INVALID_TYPE_FOR_OP; - LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, ob_obj_type_str(types_stack[i].get_type()), "CHAR"); - } else if (ob_is_string_type(types_stack[i].get_type())) { - if (types_stack[i].get_charset_type() == CHARSET_BINARY) { - ret = OB_ERR_INVALID_JSON_CHARSET; - LOG_USER_ERROR(OB_ERR_INVALID_JSON_CHARSET); - } else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { - types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } - } else { - types_stack[i].set_calc_type(ObCharType); + } else if (lib::is_oracle_mode()) { + // type.set_json(); + for (int64_t i = 0; OB_SUCC(ret) && i < param_num - 4; i += 3) { + if ((types_stack[i].get_type() == ObNullType)) { + ret = OB_ERR_JSON_DOCUMENT_NULL_KEY; + LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY); + } else if (types_stack[i].get_type() != ObCharType + && types_stack[i].get_type() != ObVarcharType + && types_stack[i].get_type() != ObNCharType + && types_stack[i].get_type() != ObNVarchar2Type) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, ob_obj_type_str(types_stack[i].get_type()), "CHAR"); + } else if (ob_is_string_type(types_stack[i].get_type())) { + if (types_stack[i].get_charset_type() == CHARSET_BINARY) { + ret = OB_ERR_INVALID_JSON_CHARSET; + LOG_USER_ERROR(OB_ERR_INVALID_JSON_CHARSET); + } else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } + } else { + types_stack[i].set_calc_type(ObCharType); + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } - if (OB_SUCC(ret)) { - ObObjType doc_type = types_stack[i + 1].get_type(); - if (types_stack[i + 1].get_type() == ObNullType) { - } else if (ob_is_string_type(doc_type)) { - if (types_stack[i + 1].get_collation_type() == CS_TYPE_BINARY) { - if (lib::is_mysql_mode()) { - // unsuport string type with binary charset - ret = OB_ERR_INVALID_JSON_CHARSET; - LOG_WARN("Unsupport for string type with binary charset input.", K(ret), K(doc_type)); - } else { - types_stack[i + 1].set_calc_collation_type(CS_TYPE_BINARY); - } - } else if (types_stack[i + 1].get_charset_type() != CHARSET_UTF8MB4) { - types_stack[i + 1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + if (OB_SUCC(ret)) { + ObObjType doc_type = types_stack[i + 1].get_type(); + if (types_stack[i + 1].get_type() == ObNullType) { + } else if (ob_is_string_type(doc_type)) { + if (types_stack[i + 1].get_collation_type() == CS_TYPE_BINARY) { + if (lib::is_mysql_mode()) { + // unsuport string type with binary charset + ret = OB_ERR_INVALID_JSON_CHARSET; + LOG_WARN("Unsupport for string type with binary charset input.", K(ret), K(doc_type)); + } else { + types_stack[i + 1].set_calc_collation_type(CS_TYPE_BINARY); } - } else if (doc_type == ObJsonType) { + } else if (types_stack[i + 1].get_charset_type() != CHARSET_UTF8MB4) { types_stack[i + 1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } else { - types_stack[i + 1].set_calc_type(types_stack[i + 1].get_type()); - types_stack[i + 1].set_calc_collation_type(types_stack[i + 1].get_collation_type()); } - } - - if (OB_SUCC(ret)) { - if (types_stack[i + 2].get_type() == ObNullType) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN(" param type is unexpected", K(types_stack[i + 2].get_type()), K(ret)); - } else if (types_stack[i + 2].get_type() != ObIntType) { - types_stack[i + 2].set_calc_type(ObIntType); - } - } - } - - // null type : param_num - 4 - if (OB_SUCC(ret)) { - if (types_stack[param_num - 4].get_type() == ObNullType) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN(" param type is unexpected", K(types_stack[param_num - 4].get_type()), K(ret)); - } else if (types_stack[param_num - 4].get_type() != ObIntType) { - types_stack[param_num - 4].set_calc_type(ObIntType); - } - } - - // returning type : param_num - 3 - ObExprResType dst_type; - if (OB_SUCC(ret)) { - if (OB_FAIL(ObJsonExprHelper::get_cast_type(types_stack[param_num - 3], dst_type))) { - LOG_WARN("get cast dest type failed", K(ret)); - } else if (OB_FAIL(ObJsonExprHelper::set_dest_type(types_stack[param_num - 3], type, dst_type, type_ctx))) { - LOG_WARN("set dest type failed", K(ret)); + } else if (doc_type == ObJsonType) { + types_stack[i + 1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } else { - type.set_calc_collation_type(type.get_collation_type()); + types_stack[i + 1].set_calc_type(types_stack[i + 1].get_type()); + types_stack[i + 1].set_calc_collation_type(types_stack[i + 1].get_collation_type()); } } - // strict type : param_num - 2, if (OB_SUCC(ret)) { - if (types_stack[param_num - 2].get_type() == ObNullType) { + if (types_stack[i + 2].get_type() == ObNullType) { ret = OB_ERR_UNEXPECTED; - LOG_WARN(" param type is unexpected", K(types_stack[param_num - 2].get_type()), K(ret)); - } else if (types_stack[param_num - 2].get_type() != ObIntType) { - types_stack[param_num - 2].set_calc_type(ObIntType); - } - } - - // with unique keys type : param_num - 1, - if (OB_SUCC(ret)) { - if (types_stack[param_num - 1].get_type() == ObNullType) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN(" param type is unexpected", K(types_stack[param_num - 1].get_type()), K(ret)); - } else if (types_stack[param_num - 1].get_type() != ObIntType) { - types_stack[param_num - 1].set_calc_type(ObIntType); - } - } - } else { - type.set_json(); - type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length()); - for (int64_t i = 0; OB_SUCC(ret) && i < param_num; i += 2) { - if ((types_stack[i].get_type() == ObNullType)) { - ret = OB_ERR_JSON_DOCUMENT_NULL_KEY; - LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY); - } else if (ob_is_string_type(types_stack[i].get_type())) { - if (types_stack[i].get_charset_type() == CHARSET_BINARY) { - ret = OB_ERR_INVALID_JSON_CHARSET; - LOG_USER_ERROR(OB_ERR_INVALID_JSON_CHARSET); - } else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { - types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } - } else { - types_stack[i].set_calc_type(ObLongTextType); - types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } - - if (OB_SUCC(ret)) { - if (ob_is_string_type(types_stack[i+1].get_type())) { - if (types_stack[i+1].get_charset_type() != CHARSET_UTF8MB4) { - types_stack[i+1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } - } else if (types_stack[i+1].get_type() == ObJsonType) { - types_stack[i+1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } + LOG_WARN(" param type is unexpected", K(types_stack[i + 2].get_type()), K(ret)); + } else if (types_stack[i + 2].get_type() != ObIntType) { + types_stack[i + 2].set_calc_type(ObIntType); } } } + // null type : param_num - 4 + if (OB_SUCC(ret)) { + if (types_stack[param_num - 4].get_type() == ObNullType) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN(" param type is unexpected", K(types_stack[param_num - 4].get_type()), K(ret)); + } else if (types_stack[param_num - 4].get_type() != ObIntType) { + types_stack[param_num - 4].set_calc_type(ObIntType); + } + } + + // returning type : param_num - 3 + ObExprResType dst_type; + if (OB_SUCC(ret)) { + if (OB_FAIL(ObJsonExprHelper::get_cast_type(types_stack[param_num - 3], dst_type))) { + LOG_WARN("get cast dest type failed", K(ret)); + } else if (OB_FAIL(ObJsonExprHelper::set_dest_type(types_stack[param_num - 3], type, dst_type, type_ctx))) { + LOG_WARN("set dest type failed", K(ret)); + } else { + type.set_calc_collation_type(type.get_collation_type()); + } + } + + // strict type : param_num - 2, + if (OB_SUCC(ret)) { + if (types_stack[param_num - 2].get_type() == ObNullType) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN(" param type is unexpected", K(types_stack[param_num - 2].get_type()), K(ret)); + } else if (types_stack[param_num - 2].get_type() != ObIntType) { + types_stack[param_num - 2].set_calc_type(ObIntType); + } + } + + // with unique keys type : param_num - 1, + if (OB_SUCC(ret)) { + if (types_stack[param_num - 1].get_type() == ObNullType) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN(" param type is unexpected", K(types_stack[param_num - 1].get_type()), K(ret)); + } else if (types_stack[param_num - 1].get_type() != ObIntType) { + types_stack[param_num - 1].set_calc_type(ObIntType); + } + } + } else { + type.set_json(); + type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length()); + + ObSQLSessionInfo *session = const_cast(type_ctx.get_session()); + ObExecContext* ctx = nullptr; + + bool is_deduce_input = true; + if (OB_NOT_NULL(session) && OB_NOT_NULL(ctx = session->get_cur_exec_ctx())) { + is_deduce_input = (!ctx->is_ps_prepare_stage()); + } + + for (int64_t i = 0; OB_SUCC(ret) && is_deduce_input && i < param_num; i += 2) { + if ((types_stack[i].get_type() == ObNullType)) { + ret = OB_ERR_JSON_DOCUMENT_NULL_KEY; + LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY); + } else if (ob_is_string_type(types_stack[i].get_type())) { + if (types_stack[i].get_charset_type() == CHARSET_BINARY) { + ret = OB_ERR_INVALID_JSON_CHARSET; + LOG_USER_ERROR(OB_ERR_INVALID_JSON_CHARSET); + } else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + } else { + types_stack[i].set_calc_type(ObLongTextType); + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + + if (OB_SUCC(ret)) { + if (ob_is_string_type(types_stack[i+1].get_type())) { + if (types_stack[i+1].get_charset_type() != CHARSET_UTF8MB4) { + types_stack[i+1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + } else if (types_stack[i+1].get_type() == ObJsonType) { + types_stack[i+1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + } + } } return ret; diff --git a/src/sql/engine/expr/ob_expr_json_value.cpp b/src/sql/engine/expr/ob_expr_json_value.cpp index e893e6d6f2..5d709068a1 100644 --- a/src/sql/engine/expr/ob_expr_json_value.cpp +++ b/src/sql/engine/expr/ob_expr_json_value.cpp @@ -1337,7 +1337,7 @@ int ObExprJsonValue::cast_to_string(common::ObIAllocator *allocator, && (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(dst_cs_type))) { char *buf = NULL; - int64_t buf_len = temp_str_val.length() * ObCharset::CharConvertFactorNum; + int64_t buf_len = (temp_str_val.length() == 0 ? 1 : temp_str_val.length()) * ObCharset::CharConvertFactorNum; uint32_t result_len = 0; buf = reinterpret_cast(allocator->alloc(buf_len)); if (OB_ISNULL(buf)) {