fix:json bugfix json_set,json_object, json_arrayagg

This commit is contained in:
obdev
2023-06-30 04:18:15 +00:00
committed by ob-robot
parent 2776120751
commit 07e0da60be
4 changed files with 131 additions and 134 deletions

View File

@ -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<ObObj*>(tmp_alloc.alloc(
sizeof(ObObj) * (storted_row->cnt_))))) {
if (OB_ISNULL(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 (OB_FAIL(convert_datum_to_obj(aggr_info, *storted_row, tmp_obj, storted_row->cnt_))) {

View File

@ -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;
}
}

View File

@ -41,152 +41,148 @@ int ObExprJsonObject::calc_result_typeN(ObExprResType& type,
ObExprTypeCtx& type_ctx) const
{
INIT_SUCC(ret);
ObSQLSessionInfo *session = const_cast<ObSQLSessionInfo *>(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("<format type> 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("<empty type> 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("<empty type> 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("<empty type> 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("<format type> 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("<empty type> 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("<empty type> 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("<empty type> 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<ObSQLSessionInfo *>(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;

View File

@ -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<char*>(allocator->alloc(buf_len));
if (OB_ISNULL(buf)) {