diff --git a/src/sql/engine/basic/ob_json_table_op.cpp b/src/sql/engine/basic/ob_json_table_op.cpp index ac1652aa6b..2e3227b4ea 100644 --- a/src/sql/engine/basic/ob_json_table_op.cpp +++ b/src/sql/engine/basic/ob_json_table_op.cpp @@ -1842,7 +1842,10 @@ int JtScanNode::get_next_row(ObIJsonBase* in, JtScanCtx* ctx, bool& is_null_valu total_ = 1; is_null_value = is_null_result_ = true; curr_ = iter_ = nullptr; - if (col_info_.parent_id_ == common::OB_INVALID_ID) { ret = OB_ITER_END; } + if (col_info_.parent_id_ == common::OB_INVALID_ID + || (ctx->jt_op_->get_root_param() == in && ctx->jt_op_->get_root_entry()->reg_column_count() == 0)) { + ret = OB_ITER_END; + } } else if (hit.size() == 1) { iter_ = curr_ = hit[0]; is_null_value = is_null_result_ = false; diff --git a/src/sql/engine/basic/ob_json_table_op.h b/src/sql/engine/basic/ob_json_table_op.h index c0cf434cfb..a76476a63d 100644 --- a/src/sql/engine/basic/ob_json_table_op.h +++ b/src/sql/engine/basic/ob_json_table_op.h @@ -416,6 +416,8 @@ public: ObJsonNull* get_js_null() { return &j_null_; } ObJsonArray* get_js_array() { return &j_arr_; } ObJsonObject* get_js_object() { return &j_obj_; } + ObIJsonBase* get_root_param() { return in_; } + JtScanNode* get_root_entry() { return jt_root_; } TO_STRING_KV(K_(is_inited), K_(col_count)); diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index e01921334a..5e55564a66 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -3005,6 +3005,11 @@ static int common_string_json(const ObExpr &expr, ObJsonNull j_null; ObJsonNode *j_tree = NULL; bool is_null_res = false; + bool is_scalar = (j_text.length() + && ((j_text[0] == '\'' && j_text[j_text.length() - 1] == '\'') + || (j_text[0] == '\"' && j_text[j_text.length() - 1] == '\"'))); + + bool is_oracle = lib::is_oracle_mode(); bool relaxed_json = lib::is_oracle_mode() && !(CM_IS_STRICT_JSON(expr.extra_)); uint32_t parse_flag = ObJsonParser::JSN_STRICT_FLAG; @@ -3012,28 +3017,46 @@ static int common_string_json(const ObExpr &expr, ADD_FLAG_IF_NEED(relaxed_json, parse_flag, ObJsonParser::JSN_RELAXED_FLAG); ADD_FLAG_IF_NEED(lib::is_oracle_mode(), parse_flag, ObJsonParser::JSN_UNIQUE_FLAG); - if (lib::is_mysql_mode() && in_cs_type == CS_TYPE_BINARY) { + bool is_convert_jstr_type = (in_type == ObTinyTextType + || in_type == ObTextType + || in_type == ObMediumTextType + || in_type == ObLongTextType); + + if (!is_oracle && in_cs_type == CS_TYPE_BINARY) { j_base = &j_opaque; - } else if (lib::is_oracle_mode() && CM_IS_IMPLICIT_CAST(expr.extra_) && OB_ISNULL(j_text.ptr())) { + } else if (is_oracle && CM_IS_IMPLICIT_CAST(expr.extra_) && OB_ISNULL(j_text.ptr())) { res_datum.set_null(); is_null_res = true; - } else if (is_enumset_to_str || (CM_IS_IMPLICIT_CAST(expr.extra_) - && !CM_IS_COLUMN_CONVERT(expr.extra_) && !CM_IS_JSON_VALUE(expr.extra_) - && ob_is_string_type(in_type))) { + } else if (!is_oracle + && (is_enumset_to_str + || (CM_IS_IMPLICIT_CAST(expr.extra_) + && !CM_IS_COLUMN_CONVERT(expr.extra_) + && !CM_IS_JSON_VALUE(expr.extra_) + && is_convert_jstr_type))) { // consistent with mysql: TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. We want to treat them like strings j_base = &j_string; - } else if (lib::is_oracle_mode() && (OB_ISNULL(j_text.ptr()) || j_text.length() == 0)) { + } else if (is_oracle && (OB_ISNULL(j_text.ptr()) || j_text.length() == 0)) { j_base = &j_null; } else if (OB_FAIL(ObJsonParser::get_tree(&temp_allocator, j_text, j_tree, parse_flag))) { - if (lib::is_mysql_mode() && CM_IS_IMPLICIT_CAST(expr.extra_) && !CM_IS_COLUMN_CONVERT(expr.extra_)) { + if (!is_oracle && CM_IS_IMPLICIT_CAST(expr.extra_) && !CM_IS_COLUMN_CONVERT(expr.extra_)) { ret = OB_SUCCESS; j_base = &j_string; } else { - LOG_WARN("fail to parse string as json tree", K(ret), K(in_type), K(in_str)); + LOG_DEBUG("fail to parse string as json tree", K(ret), K(in_type), K(in_str)); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { - if (lib::is_mysql_mode()) { + if (!is_oracle) { ret = OB_ERR_INVALID_JSON_TEXT; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); + } else if (is_scalar) { + ObString tmp; + if (OB_FAIL(ob_write_string(temp_allocator, j_text, tmp))) { + LOG_DEBUG("fail to write buffer", K(ret), K(in_type), K(j_text)); + } else { + tmp.ptr()[0] = tmp.ptr()[tmp.length() - 1] = '"'; + new (&j_string)ObJsonString(tmp.ptr(), tmp.length()); + j_base = &j_string; + } + } } else { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; 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 412580ef92..425567a163 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -1497,14 +1497,17 @@ int ObJsonExprHelper::parse_res_type(ObExprResType& type1, const ObObj ¶m = res_type.get_param(); if (param.get_int() == 0) { - result_type.set_type(type1.get_type()); - result_type.set_collation_type(type1.get_collation_type()); - result_type.set_accuracy(type1.get_accuracy()); - ObObjType obj_type = type1.get_type(); - int16_t length_semantics = ((dst_type.is_string_type()) - ? dst_type.get_length_semantics() - : (OB_NOT_NULL(type_ctx.get_session()) - ? type_ctx.get_session()->get_actual_nls_length_semantics() : LS_BYTE)); + // result_type.set_type(type1.get_type()); + // result_type.set_collation_type(type1.get_collation_type()); + // result_type.set_accuracy(type1.get_accuracy()); + // ObObjType obj_type = type1.get_type(); + + ObObjType obj_type = ObJsonType; + result_type.set_type(ObJsonType); + result_type.set_collation_type(CS_TYPE_UTF8MB4_BIN); + int16_t length_semantics = (OB_NOT_NULL(type_ctx.get_session()) + ? type_ctx.get_session()->get_actual_nls_length_semantics() : LS_BYTE); + result_type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length()); result_type.set_collation_level(CS_LEVEL_IMPLICIT); if (obj_type == ObVarcharType) { @@ -1732,6 +1735,9 @@ int ObJsonExprHelper::parse_asc_option(ObExprResType& asc_type, } else { type1.set_calc_length(length); res_type.set_length(length * 10); + if (res_type.is_lob()) { + res_type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType]).get_length()); + } } } @@ -1749,8 +1755,8 @@ int ObJsonExprHelper::character2_ascii_string(common::ObIAllocator *allocator, int64_t buf_len = result.length() * ObCharset::MAX_MB_LEN * 2; int32_t length = 0; - if ((OB_NOT_NULL(allocator) && OB_ISNULL(buf = static_cast(allocator->alloc(buf_len + reserve_len)))) - || (OB_ISNULL(buf = static_cast(expr.get_str_res_mem(ctx, buf_len + reserve_len))))) { + if ((OB_NOT_NULL(allocator) && OB_ISNULL(buf = static_cast(allocator->alloc(buf_len + reserve_len + 1)))) + || (OB_ISNULL(allocator) && OB_ISNULL(buf = static_cast(expr.get_str_res_mem(ctx, buf_len + reserve_len + 1))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory", K(ret), K(buf_len), K(result.length())); } else if (OB_FAIL(ObJsonExprHelper::calc_asciistr_in_expr(result, @@ -1759,6 +1765,7 @@ int ObJsonExprHelper::character2_ascii_string(common::ObIAllocator *allocator, buf, buf_len, length))) { LOG_WARN("fail to calc unistr", K(ret)); } else { + buf[length] = 0; result.assign_ptr(buf, length); } return ret; diff --git a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp index 51e6f68f12..23506a549d 100644 --- a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp +++ b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp @@ -215,12 +215,15 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt // some constraint check ObObjType dst_type; - int32_t dst_len; // bugfix: + int32_t dst_len; if (OB_FAIL(ret)) { } else if (return_type == 0) { - dst_type = expr.args_[0]->datum_meta_.type_; - const ObAccuracy &default_accuracy = ObAccuracy::DDL_DEFAULT_ACCURACY[dst_type]; - dst_len = dst_type == ObVarcharType ? OB_MAX_ORACLE_VARCHAR_LENGTH : default_accuracy.get_length(); + dst_type = ObJsonType; + const ObAccuracy &default_accuracy = ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]; + dst_len = default_accuracy.get_length(); + // dst_type = expr.args_[0]->datum_meta_.type_; + // const ObAccuracy &default_accuracy = ObAccuracy::DDL_DEFAULT_ACCURACY[dst_type]; + // dst_len = dst_type == ObVarcharType ? OB_MAX_ORACLE_VARCHAR_LENGTH : default_accuracy.get_length(); } else if (OB_FAIL(ObJsonExprHelper::eval_and_check_res_type(return_type, dst_type, dst_len))) { LOG_WARN("fail to check returning type", K(ret)); } else if ((expr.datum_meta_.cs_type_ == CS_TYPE_BINARY || dst_type == ObJsonType) && (opt_array[OPT_PRETTY_ID] > 0 || opt_array[OPT_ASCII_ID] > 0)) { @@ -308,13 +311,13 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt } ObString tmp_val(jbuf.length(), jbuf.ptr()); - if (OB_SUCC(ret) - && is_asc - && !is_res_blob // clob varchar - && OB_FAIL(ObJsonExprHelper::character2_ascii_string(&temp_allocator, expr, ctx, tmp_val, 1))) { - LOG_WARN("fail to transform string 2 ascii character", K(ret)); + 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)); + } } + if (is_trunc && dst_type != ObLongTextType) { if (tmp_val.length() > dst_len) { if (ob_is_string_type(dst_type)) { @@ -372,8 +375,8 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt LOG_WARN("failed to lltostr", K(ret), K(dst_len)); } if (!err_type) { - ret = OB_OPERATE_OVERFLOW; - LOG_USER_ERROR(OB_OPERATE_OVERFLOW, res_ptr, "json_mergepatch"); + ret = OB_ERR_VALUE_EXCEEDED_MAX; + LOG_USER_ERROR(OB_ERR_VALUE_EXCEEDED_MAX, static_cast(length), static_cast(dst_len)); } else { ret = OB_SUCCESS; res.set_null();