fix:is json check constrain bug, json-table path expr not quoted supported, gdb charset result incorrect

This commit is contained in:
obdev
2023-09-22 09:44:04 +00:00
committed by ob-robot
parent be7cd4252e
commit 5a47b904ed
8 changed files with 179 additions and 40 deletions

View File

@ -220,7 +220,17 @@ int ObExprJsonArray::eval_ora_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObD
} else if (OB_FAIL(j_arr.print(string_buffer, true, false))) {
LOG_WARN("failed: get json string text", K(ret));
} else {
res_string.assign_ptr(string_buffer.ptr(), string_buffer.length());
ObCollationType in_cs_type = CS_TYPE_UTF8MB4_BIN;
ObCollationType dst_cs_type = expr.obj_meta_.get_collation_type();
ObString temp_str = string_buffer.string();
if (OB_FAIL(ObJsonExprHelper::convert_string_collation_type(in_cs_type,
dst_cs_type,
&temp_allocator,
temp_str,
res_string))) {
LOG_WARN("fail to convert string result", K(ret));
}
}
}

View File

@ -535,6 +535,72 @@ int ObJsonExprHelper::oracle_datum2_json_val(const ObDatum *json_datum,
return ret;
}
int ObJsonExprHelper::convert_string_collation_type(ObCollationType in_cs_type,
ObCollationType dst_cs_type,
ObIAllocator* allocator,
ObString &in_str,
ObString &out_str)
{
INIT_SUCC(ret);
bool is_need_convert = ((CS_TYPE_BINARY == dst_cs_type)
|| (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(dst_cs_type)));
if (is_need_convert) {
if (CS_TYPE_BINARY != in_cs_type && CS_TYPE_BINARY != dst_cs_type
&& (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(dst_cs_type))) {
char *buf = nullptr;
int64_t buf_len = (in_str.length() == 0 ? 1 : in_str.length()) * ObCharset::CharConvertFactorNum;
uint32_t result_len = 0;
if (OB_ISNULL(buf = reinterpret_cast<char*>(allocator->alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc memory failed", K(ret), K(buf_len));
} else if (OB_FAIL(ObCharset::charset_convert(in_cs_type,
in_str.ptr(),
in_str.length(),
dst_cs_type,
buf,
buf_len,
result_len))) {
LOG_WARN("charset convert failed", K(ret));
} else {
out_str.assign_ptr(buf, result_len);
}
} else {
if (CS_TYPE_BINARY == in_cs_type || CS_TYPE_BINARY == dst_cs_type) {
// just copy string when in_cs_type or out_cs_type is binary
const ObCharsetInfo *cs = NULL;
int64_t align_offset = 0;
if (CS_TYPE_BINARY == in_cs_type && (NULL != (cs = ObCharset::get_charset(dst_cs_type)))) {
if (cs->mbminlen > 0 && in_str.length() % cs->mbminlen != 0) {
align_offset = cs->mbminlen - in_str.length() % cs->mbminlen;
}
}
int64_t len = align_offset + in_str.length();
char *buf = nullptr;
if (OB_ISNULL(buf = static_cast<char*>(allocator->alloc(len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory failed", K(ret), K(len));
} else {
MEMMOVE(buf + align_offset, in_str.ptr(), len - align_offset);
MEMSET(buf, 0, align_offset);
out_str.assign_ptr(buf, len);
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("same charset should not be here, just use cast_eval_arg", K(ret),
K(in_cs_type), K(dst_cs_type), K(in_cs_type), K(dst_cs_type));
}
}
} else {
out_str = in_str;
}
return ret;
}
int ObJsonExprHelper::json_base_replace(ObIJsonBase *json_old, ObIJsonBase *json_new,
ObIJsonBase *&json_doc)
{

View File

@ -163,11 +163,11 @@ public:
static bool is_cs_type_bin(ObCollationType &cs_type);
static int get_timestamp_str_in_oracle_mode(ObEvalCtx &ctx,
const ObDatum &datum,
ObObjType type,
ObScale scale,
const ObTimeZoneInfo *tz_info,
ObJsonBuffer &j_buf);
const ObDatum &datum,
ObObjType type,
ObScale scale,
const ObTimeZoneInfo *tz_info,
ObJsonBuffer &j_buf);
static bool is_convertible_to_json(ObObjType &type);
static int is_valid_for_json(ObExprResType* types_stack, uint32_t index, const char* func_name);
@ -176,6 +176,11 @@ public:
static void set_type_for_value(ObExprResType* types_stack, uint32_t index);
static int ensure_collation(ObObjType type, ObCollationType cs_type);
static ObJsonInType get_json_internal_type(ObObjType type);
static int convert_string_collation_type(ObCollationType in,
ObCollationType dst,
ObIAllocator* allocator,
ObString& in_str,
ObString &out_str);
template <typename T>
static int pack_json_str_res(const ObExpr &expr,
ObEvalCtx &ctx,

View File

@ -294,24 +294,45 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt
if (has_null) {
res.set_null();
} else {
ObJsonBuffer jbuf(&temp_allocator);
ObJsonBuffer* jbuf = nullptr;
ObString res_string;
bool is_res_blob = expr.datum_meta_.cs_type_ == CS_TYPE_BINARY && dst_type == ObLongTextType;
if (dst_type == ObJsonType) {
if (OB_ISNULL( jbuf = OB_NEWx(ObJsonBuffer, &temp_allocator, &temp_allocator))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to construct jbuf", K(ret));
} else if (dst_type == ObJsonType) {
if (OB_FAIL(j_base->get_raw_binary(res_string, &temp_allocator))) {
LOG_WARN("failed: get json raw binary", K(ret));
}
} else {
ObString tmp_val;
ObString result_str;
bool is_quote = j_base->json_type() == ObJsonNodeType::J_STRING;
if (OB_FAIL(j_base->print(jbuf, is_quote, is_pretty > 0))) {
if (OB_FAIL(j_base->print(*jbuf, is_quote, is_pretty > 0))) {
LOG_WARN("json binary to string failed", K(ret));
} else if (jbuf.empty()) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory for result failed", K(ret));
} else if (jbuf->empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("jbuf should not empty", K(ret));
} else {
tmp_val = jbuf->string();
ObCollationType in_cs_type = CS_TYPE_UTF8MB4_BIN;
ObCollationType dst_cs_type = expr.obj_meta_.get_collation_type();
result_str = tmp_val;
if (OB_FAIL(ObJsonExprHelper::convert_string_collation_type(in_cs_type,
dst_cs_type,
&temp_allocator,
tmp_val,
result_str))) {
LOG_WARN("fail to convert string result", K(ret));
} else {
tmp_val = result_str;
}
}
ObString tmp_val(jbuf.length(), jbuf.ptr());
if (OB_SUCC(ret) && is_asc && !is_res_blob /* clob varchar */ ) {
if (OB_FAIL(ObJsonExprHelper::character2_ascii_string(&temp_allocator, expr, ctx, tmp_val, 1))) {
LOG_WARN("fail to transform string 2 ascii character", K(ret));

View File

@ -357,18 +357,38 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O
LOG_WARN("fail to pack json result", K(ret), K(raw_bin));
}
} else {
ObString temp_str;
ObString result_str;
if (OB_FAIL(string_buffer.reserve(j_obj.get_serialize_size()))) {
LOG_WARN("fail to reserve string.", K(ret), K(j_obj.get_serialize_size()));
} else if (OB_FAIL(j_base->print(string_buffer, false, false))) {
LOG_WARN("fail to transform to string.", K(ret), K(string_buffer.length()));
} else if (dst_type == ObVarcharType && string_buffer.length() > dst_len) {
} else {
ObCollationType in_cs_type = CS_TYPE_UTF8MB4_BIN;
ObCollationType dst_cs_type = expr.obj_meta_.get_collation_type();
temp_str = string_buffer.string();
result_str = temp_str;
if (OB_FAIL(ObJsonExprHelper::convert_string_collation_type(in_cs_type,
dst_cs_type,
&temp_allocator,
temp_str,
result_str))) {
LOG_WARN("fail to convert string result", K(ret));
}
}
if (dst_type == ObVarcharType && result_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_object");
} else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(expr, ctx, res, string_buffer.string()))) {
} else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(expr, ctx, res, result_str))) {
LOG_WARN("fail to pack json result", K(ret));
}
}