/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * 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 is for func json_exists. */ #define USING_LOG_PREFIX SQL_ENG #include "ob_expr_json_exists.h" #include "sql/engine/expr/ob_expr_util.h" #include "share/object/ob_obj_cast.h" #include "sql/session/ob_sql_session_info.h" #include "share/object/ob_obj_cast_util.h" #include "share/object/ob_obj_cast.h" #include "sql/engine/expr/ob_expr_cast.h" #include "sql/engine/expr/ob_datum_cast.h" #include "sql/resolver/expr/ob_raw_expr_util.h" #include "lib/oblog/ob_log_module.h" #include "ob_expr_json_func_helper.h" namespace oceanbase { namespace sql { ObExprJsonExists::ObExprJsonExists(ObIAllocator &alloc) : ObFuncExprOperator(alloc, T_FUN_SYS_JSON_EXISTS, N_JSON_EXISTS, MORE_THAN_TWO, VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION) { } ObExprJsonExists::~ObExprJsonExists() { } int ObExprJsonExists::calc_result_typeN(ObExprResType& type, ObExprResType* types_stack, int64_t param_num, common::ObExprTypeCtx& type_ctx) const { UNUSED(type_ctx); INIT_SUCC(ret); if (OB_UNLIKELY(param_num < 5)) { ret = OB_ERR_PARAM_SIZE; LOG_WARN("invalid param number", K(ret), K(param_num)); } else { // set the result type to bool type.set_int32(); type.set_precision(DEFAULT_PRECISION_FOR_BOOL); type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].scale_); // parser json doc ObObjType doc_type = types_stack[0].get_type(); if (types_stack[0].get_type() == ObNullType) { } else if (!ObJsonExprHelper::is_convertible_to_json(doc_type)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, ob_obj_type_str(types_stack[0].get_type()), "JSON"); } else if (ob_is_string_type(doc_type)) { if (types_stack[0].get_collation_type() == CS_TYPE_BINARY) { // suport string type with binary charset types_stack[0].set_calc_collation_type(CS_TYPE_BINARY); } else if (types_stack[0].get_charset_type() != CHARSET_UTF8MB4) { types_stack[0].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } else if (doc_type == ObJsonType) { // do nothing } else { types_stack[0].set_calc_type(ObVarcharType); types_stack[0].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } // json path : 1 if (OB_SUCC(ret)) { if (types_stack[1].get_type() == ObNullType) { ret = OB_ERR_PATH_EXPRESSION_NOT_LITERAL; LOG_USER_ERROR(OB_ERR_PATH_EXPRESSION_NOT_LITERAL); } else if (ob_is_string_type(types_stack[1].get_type())) { if (types_stack[1].get_charset_type() != CHARSET_UTF8MB4) { types_stack[1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } else { types_stack[1].set_calc_type(ObVarcharType); types_stack[1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } // passing_clause : might be NULL(idx: 2) or even idx: [2, param_num-2) if (OB_SUCC(ret)) { if (param_num == 5) { if (types_stack[2].get_type() != ObNullType) { ret = OB_ERR_UNEXPECTED; LOG_WARN("input option error", K(types_stack[2].get_type()), K(ret)); } } else if (param_num % 2 == 0 && param_num >= 6) { for (int i = 2; i < param_num - 2; ++i) { if (ob_is_string_type(types_stack[i].get_type())) { if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } else if (i % 2 == 1) { types_stack[i].set_calc_type(ObVarcharType); types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN(" param num error", K(param_num)); } } } // on error : param_num-2 if (OB_SUCC(ret)) { if (types_stack[param_num - 2].get_type() == ObNullType) { ret = OB_ERR_UNEXPECTED; LOG_WARN(" param type is unexpected", K(types_stack[param_num - 2].get_type())); } else if (types_stack[param_num - 2].get_type() != ObIntType) { types_stack[param_num - 2].set_calc_type(ObIntType); } } // on empty : param_num-1 if (OB_SUCC(ret)) { if (types_stack[param_num - 1].get_type() == ObNullType) { ret = OB_ERR_UNEXPECTED; LOG_WARN(" param type is unexpected", K(types_stack[param_num - 1].get_type())); } else if (types_stack[param_num - 1].get_type() != ObIntType) { types_stack[param_num - 1].set_calc_type(ObIntType); } } return ret; } int ObExprJsonExists::get_path(const ObExpr &expr, ObEvalCtx &ctx, ObJsonPath* &j_path, common::ObArenaAllocator &allocator, ObJsonPathCache &ctx_cache, ObJsonPathCache* &path_cache) { INIT_SUCC(ret); ObExpr *json_arg = nullptr; ObDatum *json_datum = nullptr; ObObjType type; json_arg = expr.args_[1]; type = json_arg->datum_meta_.type_; if (OB_FAIL(json_arg->eval(ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (type == ObNullType || json_datum->is_null()) { // path为空时会报错 // ORA-40442: JSON path expression syntax error ret = OB_ERR_JSON_PATH_SYNTAX_ERROR; LOG_WARN("JSON path expression syntax error ('')", K(ret)); } else if (!ob_is_string_type(type)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(type)); } else { ObString j_path_text; bool is_null = false; if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, allocator, j_path_text, is_null))) { LOG_WARN("fail to get real data.", K(ret), K(j_path_text)); } else if (is_null || j_path_text.length() == 0) { ret = OB_ERR_JSON_PATH_SYNTAX_ERROR; LOG_WARN("JSON path expression syntax error ('')", K(ret)); } else { path_cache = ObJsonExprHelper::get_path_cache_ctx(expr.expr_ctx_id_, &ctx.exec_ctx_); path_cache = ((path_cache != NULL) ? path_cache : &ctx_cache); if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, 1, true))) { ret = OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR; LOG_USER_ERROR(OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR, j_path_text.length(), j_path_text.ptr()); } } } return ret; } int ObExprJsonExists::get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObArenaAllocator &allocator, uint16_t index, ObIJsonBase*& j_base) { INIT_SUCC(ret); ObDatum *json_datum = NULL; ObExpr *json_arg = expr.args_[index]; ObObjType val_type = json_arg->datum_meta_.type_; ObCollationType cs_type = json_arg->datum_meta_.cs_type_; if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, json_datum)))) { LOG_WARN("eval json arg failed", K(ret)); } else if (OB_ISNULL(json_datum)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType) { ret = OB_ERR_INVALID_VARIABLE_IN_JSON_PATH; LOG_USER_ERROR(OB_ERR_INVALID_VARIABLE_IN_JSON_PATH); } else if (json_datum->is_null()) { if (ob_is_string_type(val_type)) { ObJsonString* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonString))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonString("", 0); j_base = tmp_ans; } } else { ObJsonNull* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonNull))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonNull(); j_base = tmp_ans; } } } else if (val_type == ObJsonType) { bool is_json_null = false; if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, allocator, index, j_base, is_json_null, true, true))) { LOG_WARN("parse json_data fail", K(ret)); } } else if (ob_is_string_type(val_type)) { ObString j_str; bool is_null = false; if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, allocator, j_str, is_null))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); } else if (is_null) { ObJsonNull* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonNull))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonNull", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonNull(); j_base = tmp_ans; } } else { ObJsonString* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonString))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonString", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonString(j_str.ptr(), j_str.length()); j_base = tmp_ans; } } } else if (ObTinyIntType <= val_type && val_type <= ObUInt64Type) { // int ObJsonInt* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonInt))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonInt", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonInt(json_datum->get_int()); j_base = tmp_ans; } } else if (ObFloatType <= val_type && val_type <= ObUDoubleType) { // double if (val_type == ObUFloatType || val_type == ObFloatType) { ObJsonOFloat* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonOFloat))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDouble", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonOFloat(json_datum->get_float()); j_base = tmp_ans; } } else { ObJsonDouble* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonDouble))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDouble", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonDouble(json_datum->get_double()); j_base = tmp_ans; } } } else if (ObNumberType <= val_type && val_type <= ObUNumberType) { // decimal ObJsonDecimal* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonDecimal))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonDecimal(json_datum->get_number()); j_base = tmp_ans; } } else if (val_type == ObDateTimeType || val_type == ObDateType || val_type == ObTimeType) { // datetime ObTime ob_time; int64_t date = json_datum->get_datetime(); ObString j_str = json_datum->get_string(); if (OB_FAIL(ObTimeConverter::usec_to_ob_time(json_datum->get_datetime(), ob_time))) { LOG_WARN("fail to cast int to ob_time", K(ret)); } else { ObJsonDatetime* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonDatetime))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonDatetime(ObJsonNodeType::J_DATE, ob_time); j_base = tmp_ans; } } } else if (ObTimestampTZType == val_type) { ObTime ob_time; ObOTimestampData date = json_datum->get_otimestamp_tiny(); ObString j_str = json_datum->get_string(); if (OB_FAIL(ObTimeConverter::otimestamp_to_ob_time(val_type, json_datum->get_otimestamp_tz(), NULL, ob_time))) { LOG_WARN("fail to cast int to ob_time", K(ret)); } else { ObJsonDatetime* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonDatetime))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonDatetime(ob_time, ObTimestampType); j_base = tmp_ans; } } } else if (ObTimestampLTZType == val_type || ObTimestampNanoType == val_type) { ObTime ob_time; ObOTimestampData date = json_datum->get_otimestamp_tiny(); ObString j_str = json_datum->get_string(); if (OB_FAIL(ObTimeConverter::otimestamp_to_ob_time(val_type, json_datum->get_otimestamp_tiny(), NULL, ob_time))) { LOG_WARN("fail to cast int to ob_time", K(ret)); } else { ObJsonDatetime* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonDatetime))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); } else { tmp_ans = new (tmp_ans) ObJsonDatetime(ob_time, ObTimestampType); j_base = tmp_ans; } } } else { bool is_json_null = false; if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, allocator, index, j_base, is_json_null, true, true))) { LOG_WARN("parse json_data fail", K(ret)); } } return ret; } int ObExprJsonExists::get_passing(const ObExpr &expr, ObEvalCtx &ctx, PassingMap &pass_map, uint32_t param_num, ObArenaAllocator& temp_allocator) { INIT_SUCC(ret); ObExpr *json_arg = nullptr; ObDatum *json_datum = nullptr; ObObjType type; for (uint32_t i = 2; i < param_num - 3 && OB_SUCC(ret); i += 2) { json_arg = expr.args_[i]; type = json_arg->datum_meta_.type_; ObIJsonBase *json_data = nullptr; // get json_value, value could be null if (OB_FAIL(get_var_data(expr, ctx, temp_allocator, i, json_data))) { LOG_WARN("get_json_doc failed", K(ret)); } else { // get keyname, keyname can't be null json_arg = expr.args_[i + 1]; type = json_arg->datum_meta_.type_; json_datum = nullptr; if (OB_FAIL(json_arg->eval(ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (type == ObNullType || json_datum->is_null()) { ret = OB_ERR_JSON_ILLEGAL_ZERO_LENGTH_IDENTIFIER_ERROR; LOG_USER_ERROR(OB_ERR_JSON_ILLEGAL_ZERO_LENGTH_IDENTIFIER_ERROR); } else if (!ob_is_string_type(type)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(type)); } if (OB_SUCC(ret)) { ObString keyname = json_datum->get_string(); if (keyname.length() == 0) { ret = OB_ERR_JSON_ILLEGAL_ZERO_LENGTH_IDENTIFIER_ERROR; LOG_USER_ERROR(OB_ERR_JSON_ILLEGAL_ZERO_LENGTH_IDENTIFIER_ERROR); } else { // Oracle中,若有两个相同keyname,后者的value会覆盖前者 if (OB_FAIL(pass_map.set_refactored(keyname, json_data, 1))) { LOG_WARN("fail to set k-v for passing", K(i)); } } } } } return ret; } int ObExprJsonExists::get_error_or_empty(const ObExpr &expr, ObEvalCtx &ctx, uint32_t idx, uint8_t &result) { INIT_SUCC(ret); ObExpr *json_arg = expr.args_[idx]; ObObjType val_type = json_arg->datum_meta_.type_; ObDatum *json_datum = NULL; val_type = json_arg->datum_meta_.type_; if (OB_FAIL(json_arg->eval(ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObIntType) { int64_t option = json_datum->get_int(); if (option < OB_JSON_FALSE_ON_ERROR || option > OB_JSON_DEFAULT_ON_ERROR) { ret = OB_ERR_UNEXPECTED; LOG_WARN("input option type error", K(option), K(ret)); } else { result = static_cast(option); if (result == OB_JSON_DEFAULT_ON_ERROR) result = 0; } } else if (val_type == ObNumberType) { const uint32_t *option = json_datum->get_number_digits(); if (*option < OB_JSON_FALSE_ON_ERROR || *option > OB_JSON_DEFAULT_ON_ERROR) { ret = OB_ERR_UNEXPECTED; LOG_WARN("input option type error", K(option), K(ret)); } else { result = static_cast(*option); if (result == OB_JSON_DEFAULT_ON_ERROR) result = 0; } } return ret; } int ObExprJsonExists::set_result(ObDatum &res, const ObJsonBaseVector& hit, const uint8_t option_on_error, const uint8_t option_on_empty, const bool is_cover_by_error, const bool is_null_json) { INIT_SUCC(ret); if (is_null_json) { res.set_bool(false); } else if (is_cover_by_error) { switch (option_on_error) { case OB_JSON_ERROR_ON_ERROR: { ret = OB_ERR_JSON_SYNTAX_ERROR; LOG_USER_ERROR(OB_ERR_JSON_SYNTAX_ERROR); break; } case OB_JSON_FALSE_ON_ERROR: { ret = OB_SUCCESS; res.set_bool(false); break; } case OB_JSON_TRUE_ON_ERROR: { ret = OB_SUCCESS; res.set_bool(true); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("on_empty_option type error", K(option_on_empty), K(ret)); } } } else { if (hit.size() == 0) { switch (option_on_empty) { // on empty 子句有两个问题 // 1. json_exists的on empty子句,其轨道图与文档说明不一致: // a. 文档中on empty子句包括: NULL ON EMPTY, ERROR ON EMPTY, DEFAULT literal ON EMPTY // b. 轨道图中on empty子句包括: ERROR ON EMPTY, FALSE ON EMPTY, TRUE ON EMPTY // c. 实际测试时,发现输入NULL ON EMPTY会报语法错误,无法识别改子句,因此按照轨道图实现 // 2. json_exists的on error依据文档说明,主要针对json数据是否出错进行检查,并返回响应结果。 // 但on empty子句因为原因1,无法找到对应子句的正确文档说明。 // 根据:查询结果是否为空 / path表达式是否为空 / json数据是否为空 这三种情况进行了尝试 // 结果发现,三种情况下,error/false/true on empty 的行为完全一致: // a. 查询结果或json数据为空,三种 on empty 子句均返回false // b. path表达式为空,三种 on empty 子句均返回path为空时的错误码 // 因此在实现时,遵循了oracle的行为,未对三种子句做区分,只要不存在为true的结果,即返回false case OB_JSON_ERROR_ON_EMPTY: case OB_JSON_FALSE_ON_EMPTY: case OB_JSON_TRUE_ON_EMPTY: { res.set_bool(false); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("on_empty_option type error", K(option_on_empty), K(ret)); } } } else { res.set_bool(true); } } return ret; } int ObExprJsonExists::eval_json_exists(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) { INIT_SUCC(ret); ObIJsonBase *json_data = NULL; bool is_null_json = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObJsonPathCache ctx_cache(&temp_allocator); ObJsonPathCache* path_cache = nullptr; ObJsonPath* j_path = nullptr; uint32_t param_num = expr.arg_cnt_; bool has_passing = true; PassingMap pass_map; bool is_cover_by_error = false; uint8_t option_on_error = 0; uint8_t option_on_empty = 0; ObJsonBaseVector hit; // get json // json 数据为空时不报错,无论如何都不报错,且结果为false // error on error时,json解析错误时报错,否则不报错(默认时false on error) // ORA-40441: JSON syntax error if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 0, json_data, is_null_json))) { if (ret == OB_ERR_JSON_SYNTAX_ERROR) { is_cover_by_error = true; } LOG_WARN("get_json_doc failed", K(ret)); } // get path if (OB_SUCC(ret) && !is_null_json && !is_cover_by_error) { if (OB_FAIL(get_path(expr, ctx, j_path, temp_allocator, ctx_cache, path_cache))) { LOG_WARN("json_exists fail to get path", K(ret)); } else if (OB_NOT_NULL(j_path) && j_path->is_last_func()) { ret = OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR; LOG_WARN("last path node can't be item function", K(ret)); } } // get passing if (OB_SUCC(ret) && !is_null_json && !is_cover_by_error) { if (param_num == 5) { has_passing = false; } else { if (OB_FAIL(pass_map.create( (param_num - 4) / 2, "json_sql_var"))) { LOG_WARN("fail to create hash_map for passing clause", K(ret)); } else { if (OB_FAIL(get_passing(expr, ctx, pass_map, param_num, temp_allocator))) { LOG_WARN("fail to get hash_map for passing clause", K(ret)); } } } } // get on_error && on_empty // 若json_data是空, 结果无论如何都是false, 即便是 true on error // 若json_data解析出错, 结果由on error子句决定 if (OB_SUCC(ret) || is_cover_by_error) { if (is_null_json) { option_on_error = 0; option_on_empty = 0; } else { // 防止get_error_or_empty导致错误码被吞 int tmp_ret = ret; if (OB_FAIL(get_error_or_empty(expr, ctx, param_num - 2, option_on_error))) { LOG_WARN("fail to get option_on_error for json_exists", K(ret)); } else { if (OB_FAIL(get_error_or_empty(expr, ctx, param_num - 1, option_on_empty))) { LOG_WARN("fail to get option_on_empty for json_exists", K(ret)); } } ret = tmp_ret; } } // seek if (OB_SUCC(ret) && !is_null_json && !is_cover_by_error) { if (has_passing) { if (OB_FAIL(json_data->seek(*j_path, j_path->path_node_cnt(), true, true, hit, &pass_map))) { if (ret == OB_HASH_NOT_EXIST) { ret = OB_ERR_NO_VALUE_IN_PASSING; LOG_USER_ERROR(OB_ERR_NO_VALUE_IN_PASSING); } else if (ret == OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR) { is_cover_by_error = false; } LOG_WARN("failed: json seek.", K(ret)); } } else { if (OB_FAIL(json_data->seek(*j_path, j_path->path_node_cnt(), true, true, hit))) { if (ret == OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR) is_cover_by_error = false; LOG_WARN("failed: json seek.", K(ret)); } } } // set result if (OB_SUCC(ret) || is_cover_by_error) { if (OB_FAIL(set_result(res, hit, option_on_error, option_on_empty, is_cover_by_error, is_null_json))) { LOG_WARN("json_exists failed to set result.", K(ret)); } } return ret; } int ObExprJsonExists::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const { INIT_SUCC(ret); UNUSED(expr_cg_ctx); UNUSED(raw_expr); rt_expr.eval_func_ = eval_json_exists; return OB_SUCCESS; return ret; } } }