diff --git a/deps/oblib/src/lib/json_type/ob_json_bin.cpp b/deps/oblib/src/lib/json_type/ob_json_bin.cpp index 27bba867ce..c0eabf2868 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_bin.cpp @@ -932,7 +932,9 @@ int ObJsonBin::parse_tree(ObJsonNode *json_tree) INIT_SUCC(ret); result_.reuse(); ObJsonNodeType root_type = json_tree->json_type(); - if (root_type == ObJsonNodeType::J_ARRAY || root_type == ObJsonNodeType::J_OBJECT) { + if (OB_FAIL(result_.reserve(json_tree->get_serialize_size()))) { + LOG_WARN("failed to reserve bin buffer", K(ret), K(json_tree->get_serialize_size())); + } else if (root_type == ObJsonNodeType::J_ARRAY || root_type == ObJsonNodeType::J_OBJECT) { if (OB_FAIL(serialize_json_value(json_tree, result_))) { // do recursion LOG_WARN("failed to serialize json tree at recursion", K(ret)); result_.reset(); diff --git a/src/sql/engine/aggregate/ob_aggregate_processor.cpp b/src/sql/engine/aggregate/ob_aggregate_processor.cpp index 98f56e1579..9abd06c7ff 100644 --- a/src/sql/engine/aggregate/ob_aggregate_processor.cpp +++ b/src/sql/engine/aggregate/ob_aggregate_processor.cpp @@ -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(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(lob_locator.get_payload_ptr()), - static_cast(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(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(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]); - ObCollationType obj_cs_type = static_cast(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(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]); + ObCollationType rsp_cs_type = static_cast(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 (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 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(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(lob_locator.get_payload_ptr()), - static_cast(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(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(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]); + ObCollationType rsp_cs_type = static_cast(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 (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)); } } } 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 d830d083f5..8d71b8f143 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -308,7 +308,6 @@ int ObJsonExprHelper::get_json_val(const ObExpr &expr, ObEvalCtx &ctx, } return ret; } - int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, ObEvalCtx &ctx, common::ObIAllocator *allocator, @@ -320,21 +319,49 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, INIT_SUCC(ret); ObDatum *json_datum = nullptr; ObExpr *json_arg = expr; - ObObjType val_type = json_arg->datum_meta_.type_; - ObCollationType cs_type = json_arg->datum_meta_.cs_type_; - bool is_nchar = (val_type == ObNCharType || val_type == ObNVarchar2Type); - bool is_raw_type = val_type == ObRawType; + bool is_bool_data_type = json_arg->is_boolean_; if (OB_FAIL(json_arg->eval(ctx, json_datum))) { - LOG_WARN("eval json arg failed", K(ret), K(val_type)); - } else if (json_datum->is_null() || ob_is_null(val_type)) { + LOG_WARN("eval json arg failed", K(ret), K(json_arg->datum_meta_)); + } else if (OB_FAIL(oracle_datum2_json_val(json_datum, + json_arg->obj_meta_, + allocator, + ctx.exec_ctx_.get_my_session(), + j_base, + is_bool_data_type, + is_format_json, + is_strict, is_bin))) { + LOG_WARN("failed to wrapper json base", K(ret), K(json_arg->datum_meta_), + K(is_format_json), K(is_strict), K(is_bin)); + } + + return ret; +} + +int ObJsonExprHelper::oracle_datum2_json_val(const ObDatum *json_datum, + ObObjMeta& data_meta, + common::ObIAllocator *allocator, + ObBasicSessionInfo *session, + ObIJsonBase*& j_base, + bool is_bool_data_type, + bool is_format_json, + bool is_strict, + bool is_bin) +{ + INIT_SUCC(ret); + ObObjType val_type = data_meta.get_type(); + ObCollationType cs_type = data_meta.get_collation_type(); + bool is_nchar = (val_type == ObNCharType || val_type == ObNVarchar2Type); + bool is_raw_type = (val_type == ObRawType); + + if (json_datum->is_null() || ob_is_null(val_type)) { ObJsonNull *null_node = nullptr; if (OB_ISNULL(null_node = OB_NEWx(ObJsonNull, allocator))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed: alloscate jsonboolean", K(ret)); } j_base = null_node; - } else if (json_arg->is_boolean_ == 1) { + } else if (is_bool_data_type) { ObJsonBoolean *bool_node = nullptr; if (OB_ISNULL(bool_node = OB_NEWx(ObJsonBoolean, allocator, (json_datum->get_bool())))) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -351,21 +378,27 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, || is_raw_type || is_nchar) { - uint32_t parse_flag = is_strict ? ObJsonParser::JSN_STRICT_FLAG : ObJsonParser::JSN_RELAXED_FLAG; + uint32_t parse_flag = ObJsonParser::JSN_RELAXED_FLAG; ObString j_str = json_datum->get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data( - allocator, val_type, cs_type, json_arg->obj_meta_.has_lob_header(), j_str))) { + allocator, val_type, cs_type, data_meta.has_lob_header(), j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); - } else if (!is_format_json || is_nchar || is_raw_type) { + } else if (cs_type != CS_TYPE_INVALID && cs_type != CS_TYPE_BINARY + && OB_FAIL(ObExprUtil::convert_string_collation(j_str, cs_type, j_str, CS_TYPE_UTF8MB4_BIN, *allocator))) { + LOG_WARN("fail to convert charset.", K(ret), K(j_str), K(cs_type)); + } else if (!is_format_json || is_raw_type) { if (is_raw_type) { ObObj tmp_result; ObObj obj; - ObCastCtx cast_ctx(allocator, NULL, CM_NONE, CS_TYPE_INVALID); - if (OB_FAIL(json_datum->to_obj(obj, expr->obj_meta_))) { + ObDatum tmp_datum = *json_datum; + tmp_datum.set_string(j_str); + ObCastCtx cast_ctx(allocator, nullptr, CM_NONE, CS_TYPE_INVALID); + + if (OB_FAIL(tmp_datum.to_obj(obj, data_meta))) { LOG_WARN("datum to obj fail", K(ret)); } else if (OB_FAIL(ObHexUtils::rawtohex(obj, cast_ctx, tmp_result))) { - LOG_WARN("fail to check json syntax", K(ret), K(expr->obj_meta_)); + LOG_WARN("fail to check json syntax", K(ret), K(data_meta)); } else { j_str = tmp_result.get_string(); } @@ -401,7 +434,7 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, ObJsonInType to_type = is_bin ? ObJsonInType::JSON_BIN : ObJsonInType::JSON_TREE; ObString j_str = json_datum->get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data( - allocator, val_type, cs_type, json_arg->obj_meta_.has_lob_header(), j_str))) { + allocator, val_type, cs_type, data_meta.has_lob_header(), j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, ObJsonInType::JSON_BIN, to_type, j_base))) { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; @@ -422,9 +455,7 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, } } } else { - ObBasicSessionInfo *session = ctx.exec_ctx_.get_my_session(); - ObScale scale = json_arg->datum_meta_.scale_; - scale = (val_type == ObBitType) ? json_arg->datum_meta_.length_semantics_ : scale; + ObScale scale = data_meta.get_scale(); if (is_format_json) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("input type error", K(val_type)); @@ -472,7 +503,7 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, LOG_WARN("failed to allocate memory", K(ret)); } else { ObOTimestampData in_val; - ObScale scale = json_arg->datum_meta_.scale_; + ObScale scale = data_meta.get_scale(); const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(session); if (OB_FAIL(common_construct_otimestamp(val_type, *json_datum, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); @@ -807,7 +838,7 @@ int ObJsonExprHelper::transform_scalar_2jsonBase(const T &datum, case ObUFloatType: case ObUDoubleType: { double val; - if (type == ObFloatType || type ==ObUFloatType) { + if (type == ObFloatType || type ==ObUFloatType ) { val = datum.get_float(); } else { val = datum.get_double(); @@ -845,6 +876,7 @@ int ObJsonExprHelper::transform_scalar_2jsonBase(const T &datum, } case ObUNumberType: + case ObNumberFloatType: case ObNumberType: { // won't waster much memory, do deep copy num number::ObNumber num; @@ -972,238 +1004,6 @@ int ObJsonExprHelper::get_timestamp_str_in_oracle_mode(ObEvalCtx &ctx, return ret; } -int ObJsonExprHelper::transform_scalar_2String(ObEvalCtx &ctx, - const ObDatum &datum, - ObObjType type, - ObScale scale, - const ObTimeZoneInfo *tz_info, - ObJsonBuffer &j_buf) -{ - int ret = OB_SUCCESS; - - switch(type) { - case ObTinyIntType: { // support bool - bool val = datum.get_int(); - if(val) { - if (OB_FAIL(j_buf.append("true", 4))) { - LOG_WARN("fail to append true to buffer", K(ret), K(datum.get_int())); - } - } else { - if (OB_FAIL(j_buf.append("false", 5))) { - LOG_WARN("fail to append false to buffer", K(ret), K(datum.get_int())); - } - } - break; - } - case ObSmallIntType: - case ObMediumIntType: - case ObInt32Type: - case ObIntType: { - char tmp_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; - int64_t len = ObFastFormatInt::format_signed(datum.get_int(), tmp_buf); - if (OB_FAIL(j_buf.append(tmp_buf, len))) { - LOG_WARN("fail to append int to buffer", K(ret), K(datum.get_int())); - } - break; - } - case ObUTinyIntType: - case ObUSmallIntType: - case ObUMediumIntType: - case ObUInt32Type: - case ObUInt64Type: { - char tmp_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; - int64_t len = ObFastFormatInt::format_unsigned(datum.get_uint64(), tmp_buf); - if(OB_FAIL(j_buf.append(tmp_buf, len))) { - LOG_WARN("fail to append json uint to buffer", K(ret), K(datum.get_uint64())); - } - break; - } - case ObDateTimeType: { - ObTime ob_time(DT_TYPE_DATETIME); - int64_t value = datum.get_datetime(); - PRINT_OB_DATETIME(ob_time, value, j_buf); - break; - } - case ObDateType: { - ObTime ob_time(DT_TYPE_DATE); - int64_t value = datum.get_date(); - PRINT_OB_TIME(ob_time, value, date_to_ob_time, j_buf); - break; - } - case ObTimeType: { - ObTime ob_time(DT_TYPE_TIME); - int64_t value = datum.get_date(); - PRINT_OB_TIME(ob_time, value, time_to_ob_time, j_buf); - break; - } - case ObTimestampType: - case ObTimestampNanoType: - case ObTimestampTZType : - case ObTimestampLTZType :{ - if (lib::is_oracle_mode()) { - if (OB_FAIL(get_timestamp_str_in_oracle_mode(ctx, datum, type, scale, tz_info, j_buf))) { - LOG_WARN("deal timestamp fail", K(ret)); - } - } else { - ObTime ob_time(DT_TYPE_DATETIME); - int64_t value = datum.get_timestamp(); - PRINT_OB_DATETIME(ob_time, value, j_buf); - } - break; - } - case ObIntervalDSType : - case ObIntervalYMType :{ - char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; - int64_t len = 0; - if (ob_is_interval_ym(type)) { - ObIntervalYMValue in_val(datum.get_interval_nmonth()); - if (OB_FAIL(ObTimeConverter::interval_ym_to_str(in_val, scale, buf, - OB_CAST_TO_VARCHAR_MAX_LENGTH, len, - true))) { - LOG_WARN("interval_ym_to_str failed", K(ret)); - } - } else { - ObIntervalDSValue in_val(datum.get_interval_ds()); - if (OB_FAIL(ObTimeConverter::interval_ds_to_str(in_val, scale, buf, - OB_CAST_TO_VARCHAR_MAX_LENGTH, len, - true))) { - LOG_WARN("interval_ym_to_str failed", K(ret)); - } - } - if (OB_SUCC(ret)) { - ObString in_str(len, buf); - if (OB_FAIL(j_buf.append("\""))) { - LOG_WARN("fail to append \"", K(ret)); - } else if (OB_FAIL(j_buf.append(in_str))) { - LOG_WARN("fail to append date_buf to j_buf", K(ret), K(in_str)); - } else if (OB_FAIL(j_buf.append("\""))) { - LOG_WARN("fail to append \"", K(ret)); - } - } - break; - } - - case ObFloatType: - case ObUFloatType: { - if (OB_FAIL(j_buf.reserve(FLOAT_TO_STRING_CONVERSION_BUFFER_SIZE + 1))) { - LOG_WARN("fail to reserve memory for j_buf", K(ret)); - } else { - double val = datum.get_float(); - if (isnan(val)) { - if (OB_FAIL(j_buf.append("\"Nan\""))) { - LOG_WARN("jbuf add Nan fail", K(ret)); - } - } else if (isinf(val) != 0) { - if (OB_FAIL(j_buf.append("\""))) { - LOG_WARN("jbuf add \" fail", K(ret)); - } else if (isinf(val) == -1 && OB_FAIL(j_buf.append("-"))) { - LOG_WARN("jbuf add - fail", K(ret)); - } else if (OB_FAIL(j_buf.append("Inf"))) { - LOG_WARN("jbuf add Nan fail", K(ret)); - } else if (OB_FAIL(j_buf.append("\""))) { - LOG_WARN("jbuf add \" fail", K(ret)); - } - } else { - char *start = j_buf.ptr() + j_buf.length(); - uint64_t len = ob_gcvt(val, ob_gcvt_arg_type::OB_GCVT_ARG_FLOAT, - FLOAT_TO_STRING_CONVERSION_BUFFER_SIZE, start, NULL); - if (OB_FAIL(j_buf.set_length(j_buf.length() + len))) { - LOG_WARN("fail to set j_buf len", K(ret), K(j_buf.length()), K(len)); - } /*else { - // add ".0" in the end. - ObFindDoubleEscapeFunc func; - if (std::none_of(start, start + len, func)) { - if (OB_FAIL(j_buf.append("."))) { - LOG_WARN("fail to append '.' to buffer", K(ret), K(start), K(len)); - } else if (OB_FAIL(j_buf.append("0"))) { - LOG_WARN("fail to append '0' to buffer", K(ret), K(start), K(len)); - } - } - }*/ - } - } - break; - } - case ObDoubleType: - case ObUDoubleType: { - if (OB_FAIL(j_buf.reserve(DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE + 1))) { - LOG_WARN("fail to reserve memory for j_buf", K(ret)); - } else { - double val = datum.get_double(); - if (isnan(val)) { - if (OB_FAIL(j_buf.append("\"Nan\""))) { - LOG_WARN("jbuf add Nan fail", K(ret)); - } - } else if (isinf(val) != 0) { - if (OB_FAIL(j_buf.append("\""))) { - LOG_WARN("jbuf add \" fail", K(ret)); - } else if (isinf(val) == -1 && OB_FAIL(j_buf.append("-"))) { - LOG_WARN("jbuf add - fail", K(ret)); - } else if (OB_FAIL(j_buf.append("Inf"))) { - LOG_WARN("jbuf add Nan fail", K(ret)); - } else if (OB_FAIL(j_buf.append("\""))) { - LOG_WARN("jbuf add \" fail", K(ret)); - } - } else { - char *start = j_buf.ptr() + j_buf.length(); - uint64_t len = ob_gcvt(val, ob_gcvt_arg_type::OB_GCVT_ARG_DOUBLE, - DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE, start, NULL); - if (OB_FAIL(j_buf.set_length(j_buf.length() + len))) { - LOG_WARN("fail to set j_buf len", K(ret), K(j_buf.length()), K(len)); - }/* else { - // add ".0" in the end. - ObFindDoubleEscapeFunc func; - if (std::none_of(start, start + len, func)) { - if (OB_FAIL(j_buf.append("."))) { - LOG_WARN("fail to append '.' to buffer", K(ret), KCSTRING(start), K(len)); - } else if (OB_FAIL(j_buf.append("0"))) { - LOG_WARN("fail to append '0' to buffer", K(ret), KCSTRING(start), K(len)); - } - } - }*/ - } - } - break; - } - - case ObUNumberType: - case ObNumberFloatType: - case ObNumberType: { - number::ObNumber val = datum.get_number(); - int64_t pos = j_buf.length(); - char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; - int64_t len = 0; - if (lib::is_oracle_mode()) { - if (OB_FAIL(val.format(buf, sizeof(buf), len, scale))) { - LOG_WARN("fail to format", K(ret), K(val)); - } - ObString in_str(len, buf); - if (in_str[0] == '.' && OB_FAIL(j_buf.append("0"))) { - LOG_WARN("fail to append 0 to j_buf", K(ret)); - } else if (OB_FAIL(j_buf.append(in_str))) { - LOG_WARN("fail to append number to j_buf", K(ret), K(in_str)); - } - } else if (OB_FAIL(j_buf.reserve(number::ObNumber::MAX_PRINTABLE_SIZE))) { - LOG_WARN("fail to reserve memory for buf", K(ret)); - } else { - if (OB_FAIL(val.format_v2(j_buf.ptr(), j_buf.capacity(), pos, scale))) { - LOG_WARN("fail to format decimal value", K(ret), K(val), K(j_buf.length()), K(pos)); - } else if (OB_FAIL(j_buf.set_length(pos))){ - LOG_WARN("fail to set buf length", K(ret), K(pos), K(j_buf.length())); - } - } - break; - } - default: - { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("Invalid argument", K(ret), K(type)); - } - } - - return ret; -} - bool ObJsonExprHelper::is_cs_type_bin(ObCollationType &cs_type) { bool res = false; @@ -1219,170 +1019,6 @@ bool ObJsonExprHelper::is_cs_type_bin(ObCollationType &cs_type) return res; } -// format json contrl whether use strict or with unique keys ? TODO -int ObJsonExprHelper::transform_convertible_2String(const ObExpr &expr, - ObEvalCtx &ctx, - const ObDatum &datum, - ObObjType type, - ObCollationType cs_type, - ObJsonBuffer &j_buf, - bool has_lob_header, - bool format_json, - bool strict_json, - int32_t pos) -{ - int ret = OB_SUCCESS; - common::ObArenaAllocator tmp_alloc; - common::ObIAllocator *allocator = &tmp_alloc; - const ObObjMeta obj_meta = expr.obj_meta_; - switch(type) { - case ObNullType: { - if (OB_FAIL(j_buf.append("null"))) { - LOG_WARN("fail to append null", K(ret)); - } - break; - } - case ObRawType: { - ObObj tmp_result; - ObObj obj; - ObCastCtx cast_ctx(allocator, NULL, CM_NONE, CS_TYPE_INVALID); - common::ObString j_str = datum.get_string(); - - if (OB_FAIL(ret)) { - } else if (OB_FAIL(datum.to_obj(obj, obj_meta))) { - LOG_WARN("datum to obj fail", K(ret)); - } else if (OB_FAIL(ObHexUtils::rawtohex(obj, cast_ctx, tmp_result))) { - LOG_WARN("fail to check json syntax", K(ret), K(type), K(j_str)); - } else if (format_json) { - if (strict_json) { - ObIJsonBase *j_tree = NULL; - uint32_t parse_flag = ObJsonParser::JSN_STRICT_FLAG; - if (OB_FAIL(ObJsonParser::check_json_syntax(j_str, allocator, parse_flag))) { - ret = OB_ERR_JSON_SYNTAX_ERROR; - LOG_WARN("fail to parse json text strict", K(ret)); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, ObJsonInType::JSON_TREE, - ObJsonInType::JSON_TREE, j_tree, parse_flag))) { - } else if (OB_FAIL(j_tree->print(j_buf, true))) { - LOG_WARN("fail to print json node", K(ret)); - } - } else if (OB_FAIL(j_buf.append(j_str))) { - LOG_WARN("fail to append string to j_buf", K(ret), K(j_str)); - } - } else { - j_str = tmp_result.get_string(); - if (OB_FAIL(j_buf.append("\"", 1))) { - LOG_WARN("fail to append \"", K(ret)); - } else if (OB_FAIL(j_buf.append(j_str))) { - LOG_WARN("fail to append int to buffer", K(ret), K(j_str)); - } else if (OB_FAIL(j_buf.append("\"", 1))) { - LOG_WARN("fail to append \"", K(ret)); - } - } - break; - } - case ObNVarchar2Type: - case ObNCharType: - case ObVarcharType: - case ObCharType: - case ObTinyTextType: - case ObTextType : - case ObMediumTextType: - case ObLobType: - case ObLongTextType: { - ObString value; - bool is_bin = false; - const ObLobLocator* lob_locator; - ObObj tmp_result; - ObObj obj; - ObCastCtx cast_ctx(allocator, NULL, CM_NONE, CS_TYPE_INVALID); - if (OB_FAIL(datum.to_obj(obj, obj_meta))) { - LOG_WARN("datum to obj fail", K(ret)); - } else if (type == ObLobType) { - const ObLobLocator* lob_locator = obj.get_lob_locator(); - if (OB_ISNULL(lob_locator)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("lob_locator is null", K(ret)); - } else if (OB_FAIL(lob_locator->get_payload(value))) { - LOG_WARN("get payload from lob_locator failed", K(ret), K(*lob_locator)); - } else { - size_t val_len = value.length(); - const char* val_ptr = value.ptr(); - if (val_len > 0) { - char first = val_ptr[0]; - char last = val_ptr[val_len - 1]; - char mid = val_ptr[val_len >> 1]; - } - } - } else { - value = datum.get_string(); - } - if (OB_FAIL(ret)) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, type, - cs_type, has_lob_header, value))) { - LOG_WARN("fail to get real data.", K(ret), K(value)); - } else if (lib::is_oracle_mode() && ObJsonExprHelper::is_cs_type_bin(cs_type) && !format_json) { - is_bin = true; - obj.set_string(type, value); - if (OB_FAIL(ObHexUtils::rawtohex(obj, cast_ctx, tmp_result))) { - LOG_WARN("fail to check json syntax", K(ret), K(type)); - } else { - value = tmp_result.get_string(); - } - } - if (OB_FAIL(ret)) { - } else if (format_json) { - bool relaxed_json = lib::is_oracle_mode() && !strict_json; - uint32_t parse_flag = ObJsonParser::JSN_STRICT_FLAG; - ADD_FLAG_IF_NEED(!strict_json, parse_flag, ObJsonParser::JSN_RELAXED_FLAG); - if (lib::is_mysql_mode() && OB_FAIL(ObJsonExprHelper::ensure_collation(type, cs_type))) { - // should check collation first - LOG_WARN("Invalid collation type for input string.", K(ret)); - } else if (strict_json) { - ObIJsonBase *j_tree = NULL; - uint32_t parse_flag = ObJsonParser::JSN_RELAXED_FLAG; - if (OB_FAIL(ObJsonParser::check_json_syntax(value, allocator, parse_flag))) { - ret = OB_ERR_JSON_SYNTAX_ERROR; - LOG_WARN("fail to check json syntax", K(ret), K(type)); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, value, ObJsonInType::JSON_TREE, - ObJsonInType::JSON_TREE, j_tree, parse_flag))) { - } else if (OB_FAIL(j_tree->print(j_buf, true))) { - LOG_WARN("fail to print json node", K(ret)); - } - } else if (OB_FAIL(j_buf.append(value))) { - LOG_WARN("fail to append string to j_buf", K(ret), K(value)); - } - } else { - ObJsonString ob_str(value.ptr(), value.length()); - if (OB_FAIL(ob_str.print(j_buf, true, false, 0))) { - LOG_WARN("fail to print json node", K(ret)); - } - } - break; - } - case ObJsonType: { - ObIJsonBase* json_node = NULL; - ObString j_str; - 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 (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, ObJsonInType::JSON_BIN, - ObJsonInType::JSON_BIN, json_node))) { - ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; - LOG_WARN("fail to get json base", K(ret)); - } else if (OB_FAIL(json_node->print(j_buf, true, false, 0))) { - LOG_WARN("fail to print json node", K(ret)); - } - break; - } - default: - { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("Invalid argument", K(ret), K(type)); - } - } - return ret; -} - template int ObJsonExprHelper::transform_convertible_2jsonBase(const T &datum, ObObjType type, @@ -1457,19 +1093,20 @@ int ObJsonExprHelper::transform_convertible_2jsonBase(const T &datum, break; } case ObJsonType: { - ObString j_str; - if (deep_copy) { - if (OB_FAIL(deep_copy_ob_string(*allocator, datum.get_string(), j_str))) { - LOG_WARN("do deep copy failed", K(ret)); - } - } else { - j_str = datum.get_string(); - } + ObString j_str = datum.get_string(); if (OB_SUCC(ret)) { - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, type, cs_type, has_lob_header, j_str))) { + ObString tmp_str = j_str; + if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, type, cs_type, has_lob_header, tmp_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (deep_copy) { + if (OB_FAIL(deep_copy_ob_string(*allocator, tmp_str, j_str))) { + LOG_WARN("do deep copy failed", K(ret)); + } + } else { + j_str = tmp_str; } } + if (OB_SUCC(ret)) { ObJsonInType to_type = to_bin ? ObJsonInType::JSON_BIN : ObJsonInType::JSON_TREE; uint32_t parse_flag = relax_type ? ObJsonParser::JSN_RELAXED_FLAG : ObJsonParser::JSN_STRICT_FLAG; diff --git a/src/sql/engine/expr/ob_expr_json_func_helper.h b/src/sql/engine/expr/ob_expr_json_func_helper.h index c34824c2fe..0c709fce41 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.h +++ b/src/sql/engine/expr/ob_expr_json_func_helper.h @@ -93,6 +93,9 @@ public: static int get_json_val(const common::ObObj &data, ObExprCtx &ctx, bool is_bool, common::ObIAllocator *allocator, ObIJsonBase*& j_base, bool to_bin = false); + static int oracle_datum2_json_val(const ObDatum *json_datum, ObObjMeta& data_meta, common::ObIAllocator *allocator, + ObBasicSessionInfo *session, ObIJsonBase*& j_base, bool is_bool_data_type, + bool format_json = false, bool is_strict = false, bool is_bin = false); static int eval_oracle_json_val(ObExpr *expr, ObEvalCtx &ctx, common::ObIAllocator *allocator, ObIJsonBase*& j_base, bool format_json = false, bool is_strict = false, bool is_bin = false); @@ -157,23 +160,6 @@ public: bool relax_type = true, bool format_json = false); - static int transform_convertible_2String(const ObExpr &expr, - ObEvalCtx &ctx, - const ObDatum &datum, - ObObjType type, - ObCollationType cs_type, - ObJsonBuffer &j_buf, - bool has_lob_header, - bool format_json, - bool strict_json, - int32_t pos); - - static int transform_scalar_2String(ObEvalCtx &ctx, - const ObDatum &datum, - ObObjType type, - ObScale scale, - const ObTimeZoneInfo *tz_info, - ObJsonBuffer &j_buf); static bool is_cs_type_bin(ObCollationType &cs_type); static int get_timestamp_str_in_oracle_mode(ObEvalCtx &ctx, const ObDatum &datum, diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index eca25ea2f3..e04c44e712 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -562,7 +562,7 @@ int ObDMLResolver::pre_process_json_object_contain_star(ParseNode *node, common: } else if (value_node->type_ == T_OBJ_ACCESS_REF && OB_NOT_NULL(returning_node->raw_text_)) { if (OB_FAIL(check_is_json_constraint(*allocator_, value_node, format_json, 2))) { LOG_WARN("fail to check json constraint of col", K(ret)); - } else if (returning_node->int16_values_[OB_NODE_CAST_TYPE_IDX] == T_VARCHAR && def_val.case_compare(returning_node->raw_text_) == 0 && format_json) { + } else if (returning_node->value_ == 0 && def_val.case_compare(returning_node->raw_text_) == 0 && format_json) { returning_node->int16_values_[OB_NODE_CAST_TYPE_IDX] = T_JSON; /* data type */ returning_node->int16_values_[OB_NODE_CAST_COLL_IDX] = INVALID_COLLATION; returning_node->int32_values_[OB_NODE_CAST_C_LEN_IDX] = 0; /* length */ 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 ff2954426f..adb8e315d3 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -1247,6 +1247,7 @@ int ObRawExprDeduceType::set_json_agg_result_type(ObAggFunRawExpr &expr, ObExprR parse_node.value_ = static_cast(return_type_expr)->get_value().get_int(); ObScale scale = static_cast(return_type_expr)->get_accuracy().get_scale(); bool is_json_type = (scale == 1) && (col_type.get_type_class() == ObJsonTC); + is_json_type = (is_json_type || parse_node.value_ == 0); ObObjType obj_type = static_cast(parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX]); result_type.set_collation_type(static_cast(parse_node.int16_values_[OB_NODE_CAST_COLL_IDX])); if (ob_is_string_type(obj_type) && !is_json_type) { @@ -2986,7 +2987,7 @@ int ObRawExprDeduceType::set_agg_json_array_result_type(ObAggFunRawExpr &expr, result_type.set_calc_collation_type(my_session_->get_nls_collation()); } result_type.set_collation_level(CS_LEVEL_IMPLICIT); - } else if (ob_is_json(obj_type)) { + } else if (ob_is_json(obj_type) || parse_node.value_ == 0) { result_type.set_json(); result_type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length()); } else if (ob_is_raw(obj_type)) {