[FEAT MERGE]:Oracle Json Supported
This commit is contained in:
@ -8,12 +8,16 @@
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
* This file contains implementation of json_object.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "ob_expr_json_object.h"
|
||||
#include "sql/engine/expr/ob_expr_json_func_helper.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "sql/engine/expr/ob_expr_cast.h"
|
||||
|
||||
#include "lib/hash/ob_hashset.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::sql;
|
||||
@ -42,46 +46,147 @@ int ObExprJsonObject::calc_result_typeN(ObExprResType& type,
|
||||
if (OB_ISNULL(session)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("session is NULL", K(ret));
|
||||
} else if (OB_ISNULL(exec_ctx = session->get_cur_exec_ctx())) {
|
||||
} 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 || param_num % 2 != 0)) {
|
||||
} else 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 (exec_ctx->is_ps_prepare_stage()) {
|
||||
} 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 {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
types_stack[i].set_calc_type(ObLongTextType);
|
||||
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);
|
||||
}
|
||||
} else if (doc_type == ObJsonType) {
|
||||
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 (ob_is_string_type(types_stack[i+1].get_type())) {
|
||||
if (types_stack[i+1].get_charset_type() != CHARSET_UTF8MB4) {
|
||||
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());
|
||||
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);
|
||||
}
|
||||
} else if (types_stack[i+1].get_type() == ObJsonType) {
|
||||
types_stack[i+1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -145,14 +250,307 @@ int ObExprJsonObject::eval_json_object(const ObExpr &expr, ObEvalCtx &ctx, ObDat
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
|
||||
common::ObIAllocator &temp_allocator = tmp_alloc_g.get_allocator();
|
||||
ObJsonBuffer res_str(&temp_allocator);
|
||||
ObObjType val_type;
|
||||
ObCollationType value_cs_type;
|
||||
uint8_t format_type = OB_JSON_ON_STRICT_IMPLICIT;
|
||||
bool is_column = false;
|
||||
common::hash::ObHashSet<ObString> view_key_names;
|
||||
ObJsonObject j_obj(&temp_allocator);
|
||||
ObIJsonBase *j_base = &j_obj;
|
||||
ObJsonBuffer jbuf(&temp_allocator);
|
||||
|
||||
// parse null type
|
||||
uint8_t null_type = OB_JSON_ON_NULL_IMPLICIT;
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = get_clause(expr, ctx, expr.arg_cnt_ - 4, null_type, OB_JSON_ON_NULL_NUM);
|
||||
}
|
||||
|
||||
// parse returning type
|
||||
ObObjType dst_type;
|
||||
int32_t dst_len = OB_MAX_TEXT_LENGTH;
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = ObJsonExprHelper::get_dest_type(expr, expr.arg_cnt_ - 3, ctx, dst_type, dst_len);
|
||||
}
|
||||
|
||||
// parse strict type
|
||||
uint8_t strict_type = OB_JSON_ON_STRICT_IMPLICIT;
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = get_clause(expr, ctx, expr.arg_cnt_ - 2, strict_type, OB_JSON_ON_STRICT_NUM);
|
||||
}
|
||||
|
||||
// parse unique type
|
||||
uint8_t unique_type = OB_JSON_ON_UNIQUE_IMPLICIT;
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = get_clause(expr, ctx, expr.arg_cnt_ - 1, unique_type, OB_JSON_ON_UNIQUE_NUM);
|
||||
}
|
||||
|
||||
if (OB_FAIL(res_str.append("{"))) {
|
||||
LOG_WARN("symbol write fail");
|
||||
}
|
||||
int64_t size_set= (expr.arg_cnt_ - 4) / 3;
|
||||
int64_t bucket_num = (size_set / 2) + 1;
|
||||
if (size_set > 0 && OB_FAIL(view_key_names.create(bucket_num))) {
|
||||
LOG_WARN("init hash failed", K(ret), K(bucket_num));
|
||||
}
|
||||
for (int32 i = 0; OB_SUCC(ret) && i < expr.arg_cnt_ - 4; i += 3) {
|
||||
ObExpr *arg = expr.args_[i];
|
||||
ObDatum *json_datum = NULL;
|
||||
ObObjType key_type = expr.args_[i]->datum_meta_.type_;
|
||||
if (OB_FAIL(arg->eval(ctx, json_datum))) {
|
||||
LOG_WARN("failed: eval json args datum failed", K(ret));
|
||||
} else if (json_datum->is_null()) {
|
||||
ret = OB_ERR_JSON_DOCUMENT_NULL_KEY;
|
||||
LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY);
|
||||
LOG_WARN("failed:json key is null", K(ret));
|
||||
} else if (!ob_is_string_type(key_type) && key_type != ObJsonType) {
|
||||
ret = OB_ERR_INVALID_TYPE_FOR_OP;
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = get_clause(expr, ctx, i + 2, format_type, OB_JSON_ON_STRICT_NUM);
|
||||
}
|
||||
ObExpr *val_expr = expr.args_[i + 1];
|
||||
val_type = val_expr->datum_meta_.type_;
|
||||
bool can_only_be_null = false;
|
||||
if (OB_SUCC(ret) && format_type
|
||||
&& (!ObJsonExprHelper::is_convertible_to_json(val_type) || val_type == ObJsonType)) {
|
||||
if (val_type == ObObjType::ObNumberType) {
|
||||
can_only_be_null = true;
|
||||
} else {
|
||||
ret = OB_ERR_INVALID_TYPE_FOR_OP;
|
||||
LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, "CHAR", ob_obj_type_str(val_type));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObString key = json_datum->get_string();
|
||||
ObJsonString ob_str(key.ptr(), key.length());
|
||||
if (dst_type == ObJsonType) {
|
||||
|
||||
ObIJsonBase *j_val = NULL;
|
||||
uint32_t parse_flag = (strict_type == OB_JSON_ON_STRICT_IMPLICIT) ?
|
||||
ObJsonParser::JSN_STRICT_FLAG : ObJsonParser::JSN_RELAXED_FLAG;
|
||||
if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val, false, format_type, parse_flag))) {
|
||||
ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM;
|
||||
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT_IN_PARAM);
|
||||
} else if (can_only_be_null && j_val->json_type() != ObJsonNodeType::J_NULL) {
|
||||
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 (j_val->json_type() == ObJsonNodeType::J_NULL && null_type == OB_JSON_ON_NULL_ABSENT) {
|
||||
ObString key = json_datum->get_string();
|
||||
if (unique_type == OB_JSON_ON_UNIQUE_USE && OB_FAIL(check_key_valid(view_key_names, key))) {
|
||||
LOG_WARN("duplicate key fail");
|
||||
}
|
||||
// do nothing
|
||||
} else if (OB_FAIL(check_key_valid(view_key_names, key))) {
|
||||
LOG_WARN("duplicate key fail");
|
||||
} else if (OB_FAIL(j_base->object_add(key, j_val))) {
|
||||
if (ret == OB_ERR_JSON_DOCUMENT_NULL_KEY) {
|
||||
LOG_USER_ERROR(OB_ERR_JSON_DOCUMENT_NULL_KEY);
|
||||
}
|
||||
LOG_WARN("failed: append json object kv", K(ret));
|
||||
}
|
||||
} else {
|
||||
ObDatum *j_datum = NULL;
|
||||
bool t_is_null = false;
|
||||
if (OB_FAIL(get_ora_json_doc(expr, ctx, i+1, j_datum, t_is_null))) {
|
||||
LOG_WARN("get value json doc fail", K(ret), K(j_datum));
|
||||
} else if (can_only_be_null && !t_is_null) {
|
||||
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 (t_is_null && null_type == OB_JSON_ON_NULL_ABSENT) {
|
||||
ObString key = json_datum->get_string();
|
||||
if (unique_type == OB_JSON_ON_UNIQUE_USE && OB_FAIL(check_key_valid(view_key_names, key))) {
|
||||
LOG_WARN("duplicate key fail");
|
||||
}
|
||||
// do nothing only check
|
||||
} else if (t_is_null && null_type <= 1) {
|
||||
if (OB_SUCC(ret) && i > 0 && res_str.length() > 1) {
|
||||
if (OB_FAIL(res_str.append(","))) {
|
||||
LOG_WARN("comma write fail");
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (unique_type == OB_JSON_ON_UNIQUE_USE && OB_FAIL(check_key_valid(view_key_names, key))) {
|
||||
LOG_WARN("duplicate key fail");
|
||||
} else if (OB_FAIL(ob_str.print(res_str, true, false, 0, true))) {
|
||||
LOG_WARN("fail to print json node", K(ret));
|
||||
} else if (OB_FAIL(res_str.append(":"))) {
|
||||
LOG_WARN("colon write fail");
|
||||
} else if (OB_FAIL(res_str.append("null"))) {
|
||||
LOG_WARN("null write fail");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (OB_SUCC(ret) && i > 0 && res_str.length() > 1) {
|
||||
if (res_str.append(",")) {
|
||||
LOG_WARN("comma write fail");
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (unique_type == OB_JSON_ON_UNIQUE_USE && OB_FAIL(check_key_valid(view_key_names, key))) {
|
||||
LOG_WARN("duplicate key fail");
|
||||
} else if (OB_FAIL(ob_str.print(res_str, true, false, 0, true))) {
|
||||
LOG_WARN("fail to print json node", K(ret));
|
||||
} else if (OB_FAIL(res_str.append(":"))) {
|
||||
LOG_WARN("colon write fail");
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
value_cs_type = expr.args_[i + 1]->datum_meta_.cs_type_;
|
||||
if (ObJsonExprHelper::is_convertible_to_json(val_type) || ob_is_raw(val_type)) {
|
||||
if (OB_FAIL(ObJsonExprHelper::transform_convertible_2String(*expr.args_[i + 1], ctx, *j_datum, val_type, value_cs_type, res_str, format_type,
|
||||
strict_type == OB_JSON_ON_STRICT_USE, i + 1))) {
|
||||
LOG_WARN("fail to transfrom to string");
|
||||
}
|
||||
} else {
|
||||
ObScale scale = expr.args_[i + 1]->datum_meta_.scale_;
|
||||
const ObTimeZoneInfo *tz_info = get_timezone_info(ctx.exec_ctx_.get_my_session());
|
||||
if (OB_FAIL(ObJsonExprHelper::transform_scalar_2String(ctx, *j_datum, val_type, scale, tz_info, res_str))) {
|
||||
LOG_WARN("Fail to transformer string");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && res_str.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(res_str.length()),
|
||||
K(OB_MAX_PACKET_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_FAIL(res_str.append("}"))) {
|
||||
LOG_WARN("symbol write fail");
|
||||
}
|
||||
|
||||
if (OB_UNLIKELY(OB_FAIL(ret))) {
|
||||
LOG_WARN("return value fail", K(ret));
|
||||
} else {
|
||||
if (dst_type == ObJsonType) {
|
||||
ObString raw_bin;
|
||||
if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) {
|
||||
LOG_WARN("failed: get json raw binary", K(ret));
|
||||
} else {
|
||||
uint64_t length = raw_bin.length();
|
||||
char *buf = expr.get_str_res_mem(ctx, length);
|
||||
if (buf) {
|
||||
MEMCPY(buf, raw_bin.ptr(), length);
|
||||
res.set_string(buf, length);
|
||||
} else {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed: alloc memory for json object result.", K(ret), K(length));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dst_type == ObVarcharType && res_str.string().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 {
|
||||
ret = set_result(dst_type, res_str.string(), &temp_allocator, ctx, expr, res, strict_type, unique_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprJsonObject::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(expr_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
rt_expr.eval_func_ = eval_json_object;
|
||||
if (lib::is_oracle_mode()) {
|
||||
rt_expr.eval_func_ = eval_ora_json_object;
|
||||
} else {
|
||||
rt_expr.eval_func_ = eval_json_object;
|
||||
}
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprJsonObject::check_key_valid(common::hash::ObHashSet<ObString> &view_key_names, const ObString &key_name)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
if (OB_HASH_EXIST == view_key_names.exist_refactored(key_name)) {
|
||||
ret = OB_ERR_DUPLICATE_KEY;
|
||||
LOG_WARN("duplicate key", K(ret));
|
||||
} else if (OB_FAIL(view_key_names.set_refactored(key_name, 0))) {
|
||||
LOG_WARN("store key to vector failed", K(ret), K(view_key_names.size()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprJsonObject::set_result(ObObjType dst_type, ObString str_res, common::ObIAllocator *allocator, ObEvalCtx &ctx, const ObExpr &expr, ObDatum &res, uint8_t strict_type, uint8_t unique_type) {
|
||||
INIT_SUCC(ret);
|
||||
if (dst_type == ObVarcharType || dst_type == ObLongTextType) {
|
||||
if (strict_type == OB_JSON_ON_STRICT_USE && OB_FAIL(ObJsonParser::check_json_syntax(str_res, allocator, ObJsonParser::JSN_STRICT_FLAG))) {
|
||||
ret = OB_ERR_JSON_SYNTAX_ERROR;
|
||||
LOG_WARN("fail to parse json text strict", K(ret));
|
||||
} else {
|
||||
uint64_t length = str_res.length();
|
||||
char *buf = expr.get_str_res_mem(ctx, length);
|
||||
if (buf) {
|
||||
MEMCPY(buf, str_res.ptr(), length);
|
||||
res.set_string(buf, length);
|
||||
} else {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("failed: allocate res string buffer.", K(ret), K(length));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprJsonObject::get_ora_json_doc(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
uint16_t index, ObDatum*& j_datum,
|
||||
bool &is_null)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
ObExpr *json_arg = expr.args_[index];
|
||||
j_datum = NULL;
|
||||
ObObjType val_type = json_arg->datum_meta_.type_;
|
||||
if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, j_datum)))) {
|
||||
LOG_WARN("eval json arg failed", K(ret), K(val_type));
|
||||
} else if (j_datum->is_null()) {
|
||||
is_null = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprJsonObject::get_clause(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
uint8_t index,
|
||||
uint8_t &type,
|
||||
int64_t size_para)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
ObExpr *json_arg = expr.args_[index];
|
||||
ObObjType val_type = json_arg->datum_meta_.type_;
|
||||
ObDatum *json_datum = NULL;
|
||||
if (OB_FAIL(json_arg->eval(ctx, json_datum))) {
|
||||
LOG_WARN("eval json arg failed", K(ret));
|
||||
} else if (val_type != ObIntType) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("input type error", K(val_type));
|
||||
} else {
|
||||
int64_t option_type = json_datum->get_int();
|
||||
if (option_type < 0 ||
|
||||
option_type >= size_para) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("input option type error", K(option_type));
|
||||
} else {
|
||||
type = static_cast<uint8_t>(option_type);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // sql
|
||||
} // oceanbase
|
||||
Reference in New Issue
Block a user