[json] json arrayagg, json objectagg refration

This commit is contained in:
obdev
2023-08-08 08:54:37 +00:00
committed by ob-robot
parent c4b59bc122
commit 7a3548cb4b
6 changed files with 229 additions and 772 deletions

View File

@ -6389,176 +6389,91 @@ int ObAggregateProcessor::get_ora_json_arrayagg_result(const ObAggrInfo &aggr_in
LOG_WARN("rewind failed", KPC(extra), K(ret));
} else if (!extra->is_iterated() && OB_FAIL(extra->finish_add_row())) {
LOG_WARN("finish_add_row failed", KPC(extra), K(ret));
} else if (aggr_info.param_exprs_.count() < 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get aggr_info param null", K(ret), K(aggr_info.param_exprs_.count()));
} else {
const ObChunkDatumStore::StoredRow *storted_row = NULL;
ObJsonBuffer json_array_buf(&aggr_alloc_);
ObObj *tmp_obj = NULL;
if (OB_FAIL(json_array_buf.append("["))) {
LOG_WARN("fail to append curly brace", K(ret));
}
bool inited_tmp_obj = false;
const ObChunkDatumStore::StoredRow *storted_row = nullptr;
ObObjMeta data_meta = aggr_info.param_exprs_.at(0)->obj_meta_;
bool is_format_json = aggr_info.format_json_;
bool is_absent_on_null = !aggr_info.absent_on_null_;
bool is_strict = aggr_info.strict_json_;
ObJsonArray json_array(&tmp_alloc);
while (OB_SUCC(ret) && OB_SUCC(extra->get_next_row(storted_row))) {
if (OB_ISNULL(storted_row)) {
if (OB_ISNULL(storted_row) || storted_row->cnt_ < 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(storted_row));
LOG_WARN("get unexpected null or row cnt not correct", K(ret), K(storted_row));
} else {
// get type
if (!inited_tmp_obj && OB_ISNULL(tmp_obj = static_cast<ObObj*>(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 (!inited_tmp_obj && FALSE_IT(inited_tmp_obj = true)) {
} else if (OB_FAIL(convert_datum_to_obj(aggr_info, *storted_row, tmp_obj, storted_row->cnt_))) {
LOG_WARN("failed to convert datum to obj", K(ret));
} else if (storted_row->cnt_ < 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected column count", K(ret), K(storted_row));
} else {
ObObjType val_type = tmp_obj->get_type();
const ObExpr *expr = aggr_info.param_exprs_.at(0);
if (val_type == ObNumberType && aggr_info.format_json_) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, "CHAR", ob_obj_type_str(val_type));
} else {
if (ob_is_null(val_type) && !aggr_info.absent_on_null_) {
continue;
}
ObCollationType cs_type = tmp_obj->get_collation_type();
ObScale scale = tmp_obj->get_scale();
ObIJsonBase *json_val = NULL;
ObDatum converted_datum;
converted_datum.set_datum(storted_row->cells()[0]);
bool is_clob = ob_is_clob(val_type, cs_type);
// convert string charset if neededd
if ((ob_is_string_tc(val_type) || is_clob || ob_is_json(val_type) || ob_is_raw(val_type))
&& (ObCharset::charset_type_by_coll(cs_type) != CHARSET_UTF8MB4)) {
ObString origin_str;
if (ob_is_lob_locator(val_type)) {
const ObLobLocator &lob_locator = converted_datum.get_lob_locator();
origin_str.assign(const_cast<char *>(lob_locator.get_payload_ptr()),
static_cast<ObString::obstr_size_t>(lob_locator.payload_size_));
val_type = ObVarcharType;
} else if (tmp_obj->is_lob_storage()) {
origin_str = converted_datum.get_string();
if (OB_FAIL(ObTextStringHelper::read_real_string_data(&tmp_alloc, val_type,
cs_type, tmp_obj->has_lob_header(), origin_str))) {
LOG_WARN("fail to get real data.", K(ret), K(origin_str));
} else {
val_type = ObVarcharType;
}
} else {
origin_str = converted_datum.get_string();
}
ObString converted_str;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ObExprUtil::convert_string_collation(origin_str, cs_type, converted_str,
CS_TYPE_UTF8MB4_BIN, tmp_alloc))) {
LOG_WARN("convert string collation failed", K(ret), K(cs_type), K(origin_str.length()));
} else {
converted_datum.set_string(converted_str);
cs_type = CS_TYPE_UTF8MB4_BIN;
}
}
ObEvalCtx ctx(eval_ctx_);
if (OB_FAIL(ret)) {
} else if (ObJsonExprHelper::is_convertible_to_json(val_type) || ob_is_raw(val_type)) {
const ObDatum& datum = storted_row->cells()[0];
ObObjType val_type = data_meta.get_type();
ObScale scale = data_meta.get_scale();
ObCollationType cs_type = data_meta.get_collation_type();
ObIJsonBase *json_val = nullptr;
if (OB_FAIL(ObJsonExprHelper::transform_convertible_2String(*expr, ctx, converted_datum, val_type,
cs_type, json_array_buf,
tmp_obj->has_lob_header(),
aggr_info.format_json_,
aggr_info.strict_json_, 0))) {
LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type));
}
} else {
if (OB_FAIL(ObJsonExprHelper::transform_scalar_2String(ctx, converted_datum,
val_type, scale,
eval_ctx_.exec_ctx_.get_my_session()->get_timezone_info(),
json_array_buf))) {
LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type));
}
}
if (OB_FAIL(ret)) {
} else if (json_array_buf.length() > OB_MAX_PACKET_LENGTH) {
ret = OB_ERR_TOO_LONG_STRING_IN_CONCAT;
LOG_WARN("result of json_arrar is too long", K(ret), K(json_array_buf.length()),
K(OB_MAX_PACKET_LENGTH));
} else if (OB_FAIL(json_array_buf.append(","))) {
LOG_WARN("fail to append comma", K(ret));
}
}
if (OB_FAIL(ObJsonExprHelper::oracle_datum2_json_val(&datum, data_meta, &tmp_alloc,
eval_ctx_.exec_ctx_.get_my_session(), json_val, false, is_format_json, is_strict, false))) {
LOG_WARN("failed to eval json val node.", K(ret), K(is_format_json), K(is_strict), K(data_meta));
} else if (is_absent_on_null
&& (val_type == ObNullType || json_val->json_type() == ObJsonNodeType::J_NULL)) {
// do nothing , continue
} else if (OB_FAIL(json_array.append(static_cast<ObJsonNode*>(json_val)))) {
LOG_WARN("failed to append array node", K(ret), K(json_array.element_count()));
} else if (json_array.get_serialize_size() > OB_MAX_PACKET_LENGTH) {
ret = OB_ERR_TOO_LONG_STRING_IN_CONCAT;
LOG_WARN("result of json_arrayagg is too long", K(ret),
K(json_array.get_serialize_size()), K(OB_MAX_PACKET_LENGTH));
}
}
}//end of while
} //end of while
if (ret != OB_ITER_END && ret != OB_SUCCESS) {
LOG_WARN("fail to get next row", K(ret));
} else {
ret = OB_SUCCESS;
ParseNode parse_node;
parse_node.value_ = aggr_info.returning_type_;
ObObjType obj_type = static_cast<ObObjType>(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]);
ObCollationType obj_cs_type = static_cast<ObCollationType>(parse_node.int16_values_[OB_NODE_CAST_COLL_IDX]);
if (json_array_buf.length() > 1) {
char *end_of_obj = json_array_buf.ptr() + json_array_buf.length() - 1;
*end_of_obj = ']';
} else if (OB_FAIL(json_array_buf.append("]"))) {
LOG_WARN("fail to append curly brace", K(ret));
ObObjType rsp_type = static_cast<ObObjType>(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]);
ObCollationType rsp_cs_type = static_cast<ObCollationType>(parse_node.int16_values_[OB_NODE_CAST_COLL_IDX]);
int32_t rsp_len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
if (!parse_node.value_) {
rsp_type = ObJsonType;
rsp_cs_type = CS_TYPE_UTF8MB4_BIN;
rsp_len = (ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length();
}
int32_t dst_len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
ObString res_str(json_array_buf.length(), json_array_buf.ptr());
ObJsonNode* json_node = NULL;
uint32_t parse_flag = ObJsonParser::JSN_STRICT_FLAG;
int64_t result_likely_size = json_array.get_serialize_size();
ADD_FLAG_IF_NEED(!aggr_info.strict_json_, parse_flag, ObJsonParser::JSN_RELAXED_FLAG);
ADD_FLAG_IF_NEED(aggr_info.with_unique_keys_, parse_flag, ObJsonParser::JSN_UNIQUE_FLAG);
ObJsonBuffer string_buffer(&tmp_alloc);
if (obj_type == ObJsonType) {
ADD_FLAG_IF_NEED(true, parse_flag, ObJsonParser::JSN_UNIQUE_FLAG);
}
if (obj_type == ObJsonType && OB_FAIL(ObJsonParser::get_tree(&tmp_alloc, res_str, json_node, parse_flag))) {
LOG_WARN("fail to get json base", K(ret), K(res_str));
} else if (ob_is_string_type(obj_type) || ob_is_lob_locator(obj_type) || ob_is_raw(obj_type)) {
if (ob_is_string_type(obj_type) || ob_is_raw(obj_type)) {
if (obj_type == ObVarcharType && res_str.length() > dst_len) {
char res_ptr[OB_MAX_DECIMAL_PRECISION] = {0};
if (OB_ISNULL(ObCharset::lltostr(dst_len, res_ptr, 10, 1))) {
LOG_WARN("dst_len fail to string.", K(ret));
}
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, res_ptr, "json_arrayagg");
} else if (ob_is_string_type(obj_type)) {
if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(*aggr_info.expr_, eval_ctx_, concat_result, res_str, &aggr_alloc_))) {
LOG_WARN("fail to pack res result.", K(ret));
}
} else {
concat_result.set_string(res_str);
}
} else {
ObLobLocator *result = nullptr;
char *total_buf = NULL;
const int64_t total_buf_len = sizeof(ObLobLocator) + res_str.length();
if (OB_ISNULL(total_buf = aggr_info.expr_->get_str_res_mem(eval_ctx_, total_buf_len))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(total_buf_len));
} else if (FALSE_IT(result = reinterpret_cast<ObLobLocator *> (total_buf))) {
} else if (OB_FAIL(result->init(res_str))) {
LOG_WARN("Failed to init lob locator", K(ret), K(res_str), K(result));
} else {
concat_result.set_lob_locator(*result);
if (ob_is_string_type(rsp_type) || ob_is_raw(rsp_type)) {
if (OB_FAIL(string_buffer.reserve(result_likely_size))) {
LOG_WARN("fail to reserve string.", K(ret), K(result_likely_size));
} else if (OB_FAIL(json_array.print(string_buffer, true, false))) {
LOG_WARN("failed: get json string text", K(ret));
} else if (rsp_type == ObVarcharType && string_buffer.length() > rsp_len) {
char res_ptr[OB_MAX_DECIMAL_PRECISION] = {0};
if (OB_ISNULL(ObCharset::lltostr(rsp_len, res_ptr, 10, 1))) {
LOG_WARN("dst_len fail to string.", K(ret));
}
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, res_ptr, "json_arrayagg");
} else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(*aggr_info.expr_, eval_ctx_,concat_result,
string_buffer.string(), &aggr_alloc_))) {
LOG_WARN("fail to pack res result.", K(ret));
}
} else if (ob_is_json(obj_type)) {
} else if (ob_is_json(rsp_type)) {
ObString raw_binary_str;
if (OB_FAIL(json_node->get_raw_binary(raw_binary_str, &aggr_alloc_))) {
if (OB_FAIL(json_array.get_raw_binary(raw_binary_str, &tmp_alloc))) {
LOG_WARN("get result binary failed", K(ret));
} else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(*aggr_info.expr_, eval_ctx_, concat_result, raw_binary_str, &aggr_alloc_))) {
LOG_WARN("fail to pack res result.", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unpexcted returning type", K(ret), K(obj_type));
LOG_WARN("get unpexcted returning type", K(ret), K(rsp_type));
}
}
}
@ -6750,11 +6665,8 @@ int ObAggregateProcessor::get_ora_json_objectagg_result(const ObAggrInfo &aggr_i
{
int ret = OB_SUCCESS;
common::ObArenaAllocator tmp_alloc(ObModIds::OB_SQL_AGGR_FUNC, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID());
const int64_t MAX_BUCKET_NUM = 1024;
common::hash::ObHashSet<ObString> view_key_names;
if (OB_FAIL(view_key_names.create(MAX_BUCKET_NUM))) {
LOG_WARN("init hash failed", K(ret), K(MAX_BUCKET_NUM));
} else if (OB_ISNULL(extra) || OB_UNLIKELY(extra->empty())) {
if (OB_ISNULL(extra) || OB_UNLIKELY(extra->empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unpexcted null", K(ret), K(extra));
} else if (extra->is_iterated() && OB_FAIL(extra->rewind())) {
@ -6762,215 +6674,134 @@ int ObAggregateProcessor::get_ora_json_objectagg_result(const ObAggrInfo &aggr_i
LOG_WARN("rewind failed", KPC(extra), K(ret));
} else if (!extra->is_iterated() && OB_FAIL(extra->finish_add_row())) {
LOG_WARN("finish_add_row failed", KPC(extra), K(ret));
} else if (aggr_info.param_exprs_.count() < 2) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get aggr_info param null", K(ret), K(aggr_info.param_exprs_.count()));
} else {
const ObChunkDatumStore::StoredRow *storted_row = NULL;
ObJsonBuffer json_object_buf(&aggr_alloc_);
if (OB_FAIL(json_object_buf.append("{"))) {
LOG_WARN("fail to append curly brace", K(ret));
}
bool inited_tmp_obj = false;
ObObj *tmp_obj = NULL;
const ObChunkDatumStore::StoredRow *storted_row = nullptr;
ObObjMeta meta_key = aggr_info.param_exprs_.at(0)->obj_meta_;
ObObjMeta meta_value = aggr_info.param_exprs_.at(1)->obj_meta_;
bool is_format_json = aggr_info.format_json_;
bool is_absent_on_null = (aggr_info.absent_on_null_ >= 1);
bool is_strict = aggr_info.strict_json_;
bool is_with_unique_keys = aggr_info.with_unique_keys_;
ObJsonObject j_obj(&tmp_alloc);
while (OB_SUCC(ret) && OB_SUCC(extra->get_next_row(storted_row))) {
if (OB_ISNULL(storted_row)) {
if (OB_ISNULL(storted_row) || storted_row->cnt_ < 2) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(storted_row));
LOG_WARN("get unexpected null or row cnt not correct", K(ret), K(storted_row));
} else {
// get obj
if (!inited_tmp_obj && OB_ISNULL(tmp_obj = static_cast<ObObj*>(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 (!inited_tmp_obj && FALSE_IT(inited_tmp_obj = true)) {
} else if (OB_FAIL(convert_datum_to_obj(aggr_info, *storted_row, tmp_obj, storted_row->cnt_))) {
LOG_WARN("failed to convert datum to obj", K(ret));
} else if (tmp_obj[0].get_type() == ObNullType) {
ObObjType type_key = meta_key.get_type();
ObCollationType cs_type_key = meta_key.get_collation_type();
if (type_key == ObNullType) {
ret = OB_ERR_JSON_DOCUMENT_NULL_KEY;
LOG_WARN("null type for json_objectagg key");
} else if (ob_is_string_type(tmp_obj[0].get_type())
&& tmp_obj[0].get_collation_type() == CS_TYPE_BINARY) {
// not support binary charset as mysql
LOG_WARN("unsuport json string type with binary charset",
K(tmp_obj[0].get_type()), K(tmp_obj[0].get_collation_type()));
LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY);
} else if (!ob_is_string_type(type_key)) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, "CHAR", ob_obj_type_str(type_key));
} else if (ob_is_string_type(type_key) && cs_type_key == CS_TYPE_BINARY) {
ret = OB_ERR_INVALID_JSON_CHARSET;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_CHARSET);
} else if (NULL == tmp_obj[0].get_string_ptr()) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("unexpected null result", K(ret), K(tmp_obj[0]));
} else {
ObObjType val_type1 = tmp_obj[1].get_type();
const ObExpr *expr = aggr_info.param_exprs_.at(1);
if (val_type1 == ObNumberType && aggr_info.format_json_) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, "CHAR", ob_obj_type_str(val_type1));
} else {
if (ob_is_null(val_type1) && (aggr_info.absent_on_null_ >= 1)) {
continue;
}
ObObjType val_type0 = tmp_obj[0].get_type();
ObCollationType cs_type0 = tmp_obj[0].get_collation_type();
ObScale scale1 = tmp_obj[1].get_scale();
ObCollationType cs_type1 = tmp_obj[1].get_collation_type();
ObString key_string = tmp_obj[0].get_string();
if (OB_SUCC(ret) && ObCharset::charset_type_by_coll(cs_type0) != CHARSET_UTF8MB4) {
ObString converted_key_str;
if (OB_FAIL(ObExprUtil::convert_string_collation(key_string, cs_type0, converted_key_str,
CS_TYPE_UTF8MB4_BIN, tmp_alloc))) {
LOG_WARN("convert key string collation failed", K(ret), K(cs_type0), K(key_string.length()));
} else {
key_string = converted_key_str;
}
}
const ObDatum& datum_key = storted_row->cells()[0];
const ObDatum& datum_value = storted_row->cells()[1];
// get key and value, and append to json_object
if (OB_SUCC(ret) && aggr_info.with_unique_keys_
&& OB_FAIL(check_key_valid(view_key_names, key_string))) {
LOG_WARN("duplicate key", K(ret), K(key_string));
}
ObJsonString ob_str(key_string.ptr(), key_string.length());
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ob_str.print(json_object_buf, true))) {
LOG_WARN("fail to print json node", K(ret));
} else if (OB_FAIL(json_object_buf.append(":"))) {
LOG_WARN("fail to append colon", K(ret));
} else {
ObDatum converted_datum;
converted_datum.set_datum(storted_row->cells()[1]);
bool is_clob = !ob_is_clob(val_type1, cs_type1);
// convert string charset if neededd
if ((ob_is_string_tc(val_type1) || is_clob || ob_is_json(val_type1) || ob_is_raw(val_type1))
&& (ObCharset::charset_type_by_coll(cs_type1) != CHARSET_UTF8MB4)) {
ObString origin_str;
if (ob_is_lob_locator(val_type1)) {
const ObLobLocator &lob_locator = converted_datum.get_lob_locator();
origin_str.assign(const_cast<char *>(lob_locator.get_payload_ptr()),
static_cast<ObString::obstr_size_t>(lob_locator.payload_size_));
val_type1 = ObVarcharType;
} else if (tmp_obj->is_lob_storage()) {
origin_str = converted_datum.get_string();
if (OB_FAIL(ObTextStringHelper::read_real_string_data(&tmp_alloc, val_type1,
cs_type1, tmp_obj[1].has_lob_header(), origin_str))) {
LOG_WARN("fail to get real data.", K(ret), K(origin_str));
} else {
val_type1 = ObVarcharType;
}
} else {
origin_str = converted_datum.get_string();
}
ObString converted_str;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ObExprUtil::convert_string_collation(origin_str, cs_type1, converted_str,
CS_TYPE_UTF8MB4_BIN, tmp_alloc))) {
LOG_WARN("convert string collation failed", K(ret), K(cs_type1), K(origin_str.length()));
} else {
converted_datum.set_string(converted_str);
cs_type1 = CS_TYPE_UTF8MB4_BIN;
}
}
ObObjType type_value = meta_value.get_type();
ObCollationType cs_type_value = meta_value.get_collation_type();
ObScale scale = meta_value.get_scale();
ObIJsonBase *json_val = NULL;
ObString val_data;
ObEvalCtx ctx(eval_ctx_);
if (OB_FAIL(ret)) {
} else if (ObJsonExprHelper::is_convertible_to_json(val_type1) || ob_is_raw(val_type1)) {
if (OB_FAIL(ObJsonExprHelper::transform_convertible_2String(*expr, ctx, converted_datum, val_type1,
cs_type1, json_object_buf,
tmp_obj[1].has_lob_header(),
aggr_info.format_json_,
aggr_info.strict_json_, 0))) {
LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type1));
}
} else {
if (OB_FAIL(ObJsonExprHelper::transform_scalar_2String(ctx, converted_datum,
val_type1, scale1,
eval_ctx_.exec_ctx_.get_my_session()->get_timezone_info(),
json_object_buf))) {
LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type1));
}
}
ObString key_string = datum_key.get_string();
ObIJsonBase *json_val = nullptr;
if (OB_FAIL(ret)) {
} else if (json_object_buf.length() > OB_MAX_PACKET_LENGTH) {
ret = OB_ERR_TOO_LONG_STRING_IN_CONCAT;
LOG_WARN("result of json_objectagg is too long", K(ret), K(json_object_buf.length()),
K(OB_MAX_PACKET_LENGTH));
} else if (OB_FAIL(json_object_buf.append(","))) {
LOG_WARN("fail to append comma", K(ret));
}
}
if (OB_ISNULL(key_string.ptr())) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("unexpected null result", K(ret));
} else if (is_absent_on_null && ob_is_null(type_value)) {
continue;
} else if (ObCharset::charset_type_by_coll(cs_type_key) != CHARSET_UTF8MB4
&& OB_FAIL(ObExprUtil::convert_string_collation(key_string, cs_type_key, key_string,
CS_TYPE_UTF8MB4_BIN, tmp_alloc))) {
LOG_WARN("convert key string collation failed", K(ret), K(cs_type_key), K(key_string.length()));
} else if (OB_FAIL(ObJsonExprHelper::oracle_datum2_json_val(&datum_value, meta_value, &tmp_alloc,
eval_ctx_.exec_ctx_.get_my_session(), json_val, false, is_format_json, is_strict, false))) {
LOG_WARN("failed to eval json val node.", K(ret), K(is_format_json), K(is_strict), K(meta_value));
} else if (is_absent_on_null && json_val->json_type() == ObJsonNodeType::J_NULL) {
// do nothing , continue
} else if (OB_FAIL(j_obj.add(key_string, static_cast<ObJsonNode*>(json_val), false, true, false))) {
LOG_WARN("failed to append array node", K(ret), K(j_obj.element_count()));
} else if (j_obj.get_serialize_size() > OB_MAX_PACKET_LENGTH) {
ret = OB_ERR_TOO_LONG_STRING_IN_CONCAT;
LOG_WARN("result of json_objectagg is too long", K(ret),
K(j_obj.get_serialize_size()), K(OB_MAX_PACKET_LENGTH));
}
}
}
}//end of while
if (ret == OB_ERR_JSON_DOCUMENT_NULL_KEY) {
LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY);
}
} // end of while
if (ret != OB_ITER_END && ret != OB_SUCCESS) {
LOG_WARN("fail to get next row", K(ret));
} else {
ret = OB_SUCCESS;
ParseNode parse_node;
bool is_default_type = false;
parse_node.value_ = aggr_info.returning_type_;
ObObjType obj_type = aggr_info.expr_->obj_meta_.get_type();
ObCollationType obj_cs_type = aggr_info.expr_->obj_meta_.get_collation_type();
if (json_object_buf.length() > 1) {
char *end_of_obj = json_object_buf.ptr() + json_object_buf.length() - 1;
*end_of_obj = '}';
} else if (OB_FAIL(json_object_buf.append("}"))) {
LOG_WARN("fail to append curly brace", K(ret));
}
ObString res_str(json_object_buf.length(), json_object_buf.ptr());
ObJsonNode* json_node = NULL;
int32_t dst_len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
uint32_t parse_flag = ObJsonParser::JSN_STRICT_FLAG;
ObObjType rsp_type = static_cast<ObObjType>(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]);
ObCollationType rsp_cs_type = static_cast<ObCollationType>(parse_node.int16_values_[OB_NODE_CAST_COLL_IDX]);
int32_t rsp_len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
int64_t result_likely_size = j_obj.get_serialize_size();
ADD_FLAG_IF_NEED(!aggr_info.strict_json_, parse_flag, ObJsonParser::JSN_RELAXED_FLAG);
ADD_FLAG_IF_NEED(aggr_info.with_unique_keys_, parse_flag, ObJsonParser::JSN_UNIQUE_FLAG);
if (obj_type == ObJsonType) {
ADD_FLAG_IF_NEED(true, parse_flag, ObJsonParser::JSN_UNIQUE_FLAG);
if (!parse_node.value_) {
is_default_type = true;
rsp_type = ObJsonType;
rsp_cs_type = CS_TYPE_UTF8MB4_BIN;
rsp_len = (ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length();
}
if (obj_type == ObJsonType && OB_FAIL(ObJsonParser::get_tree(&tmp_alloc, res_str, json_node, parse_flag))) {
LOG_WARN("fail to get json base", K(ret));
} else if (ob_is_string_type(obj_type) || ob_is_lob_locator(obj_type) || ob_is_raw(obj_type)) {
if (ob_is_string_type(obj_type) || ob_is_raw(obj_type)) {
if (obj_type == ObVarcharType && res_str.length() > dst_len) {
char res_ptr[OB_MAX_DECIMAL_PRECISION] = {0};
if (OB_ISNULL(ObCharset::lltostr(dst_len, res_ptr, 10, 1))) {
LOG_WARN("dst_len fail to string.", K(ret));
}
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, res_ptr, "json_objectagg");
} else if (ob_is_string_type(obj_type)) {
if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(*aggr_info.expr_, eval_ctx_, concat_result, res_str, &aggr_alloc_))) {
LOG_WARN("fail to pack res result.", K(ret));
}
} else {
concat_result.set_string(res_str);
}
} else {
ObLobLocator *result = nullptr;
char *total_buf = NULL;
const int64_t total_buf_len = sizeof(ObLobLocator) + res_str.length();
if (OB_ISNULL(total_buf = aggr_info.expr_->get_str_res_mem(eval_ctx_, total_buf_len))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(total_buf_len));
} else if (FALSE_IT(result = reinterpret_cast<ObLobLocator *> (total_buf))) {
} else if (OB_FAIL(result->init(res_str))) {
LOG_WARN("Failed to init lob locator", K(ret), K(res_str), K(result));
} else {
concat_result.set_lob_locator(*result);
ObJsonBuffer string_buffer(&tmp_alloc);
uint64_t unsorted_count = j_obj.element_count();
if (is_strict || (ob_is_json(rsp_type) && !is_default_type) || is_with_unique_keys) {
j_obj.stable_sort();
j_obj.unique();
}
uint64_t sorted_count = j_obj.element_count();
if ((is_with_unique_keys || ob_is_json(rsp_type) || is_strict)
&& (unsorted_count > sorted_count)) {
ret = OB_ERR_DUPLICATE_KEY;
LOG_WARN("duplicate key", K(ret));
} else if (ob_is_string_type(rsp_type) || ob_is_raw(rsp_type)) {
if (OB_FAIL(string_buffer.reserve(result_likely_size))) {
LOG_WARN("fail to reserve string.", K(ret), K(result_likely_size));
} else if (OB_FAIL(j_obj.print(string_buffer, true, false))) {
LOG_WARN("failed: get json string text", K(ret));
} else if (rsp_type == ObVarcharType && string_buffer.length() > rsp_len) {
char res_ptr[OB_MAX_DECIMAL_PRECISION] = {0};
if (OB_ISNULL(ObCharset::lltostr(rsp_len, res_ptr, 10, 1))) {
LOG_WARN("dst_len fail to string.", K(ret));
}
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, res_ptr, "json_objectagg");
} else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(*aggr_info.expr_, eval_ctx_,concat_result,
string_buffer.string(), &aggr_alloc_))) {
LOG_WARN("fail to pack res result.", K(ret));
}
} else if (ob_is_json(obj_type)) {
} else if (ob_is_json(rsp_type)) {
ObString raw_binary_str;
if (OB_FAIL(json_node->get_raw_binary(raw_binary_str, &aggr_alloc_))) {
if (OB_FAIL(j_obj.get_raw_binary(raw_binary_str, &tmp_alloc))) {
LOG_WARN("get result binary failed", K(ret));
} else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(*aggr_info.expr_, eval_ctx_, concat_result, raw_binary_str, &aggr_alloc_))) {
LOG_WARN("fail to pack res result.", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unpexcted returning type", K(ret), K(obj_type));
LOG_WARN("get unpexcted returning type", K(ret), K(rsp_type));
}
}
}