diff --git a/deps/oblib/src/lib/json_type/ob_json_base.cpp b/deps/oblib/src/lib/json_type/ob_json_base.cpp index db4b8c6846..4e2deff7d7 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -5734,6 +5734,24 @@ int ObIJsonBase::to_bit(uint64_t &value) const break; } + case ObJsonNodeType::J_OBJECT: + case ObJsonNodeType::J_ARRAY: { + ObArenaAllocator allocator; + ObStringBuffer buffer(&allocator); + if (OB_FAIL(print(buffer, false))) { + LOG_WARN("bit len too long", K(buffer.length())); + } else if (buffer.length() > sizeof(value)) { + ret = OB_ERR_DATA_TOO_LONG; + LOG_WARN("bit len too long", K(buffer.length())); + } else { + ObString str = buffer.string(); + if (OB_FAIL(ObJsonBaseUtil::string_to_bit(str, bit))) { + LOG_WARN("fail to cast string to bit", K(ret), K(str)); + } + } + break; + } + case ObJsonNodeType::J_BOOLEAN: { bit = get_boolean(); break; diff --git a/deps/oblib/src/lib/json_type/ob_json_base.h b/deps/oblib/src/lib/json_type/ob_json_base.h index 7777b9ec7a..2d7b193c78 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.h +++ b/deps/oblib/src/lib/json_type/ob_json_base.h @@ -150,6 +150,13 @@ public: // @return see ObJsonNodeType. virtual ObJsonNodeType json_type() const = 0; + // for json binary, if need to get_parent, must set_seek_flag = false + // Otherwise, the parent stack will not be saved + // Currently only json patial update will use json bin get_parent, + // unify settings in this interface: ObJsonExprHelper::get_partial_json_bin + virtual int get_parent(ObIJsonBase *& parent) const = 0; + + // Get field type of ObJsonOpaque or ObJsonDatetime. // // @return see ObObjType. diff --git a/deps/oblib/src/lib/json_type/ob_json_bin.cpp b/deps/oblib/src/lib/json_type/ob_json_bin.cpp index 4d109d79a8..3edba86856 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_bin.cpp @@ -1427,6 +1427,10 @@ int ObJsonBin:: deserialize_json_value(const char *data, break; } } + + if (OB_SUCC(ret) && OB_NOT_NULL(json_tree)) { + json_tree->set_allocator(allocator_); + } return ret; } diff --git a/deps/oblib/src/lib/json_type/ob_json_bin.h b/deps/oblib/src/lib/json_type/ob_json_bin.h index 862894f29c..296def9eb2 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.h +++ b/deps/oblib/src/lib/json_type/ob_json_bin.h @@ -381,6 +381,10 @@ public: */ int rebuild(); + int get_parent(ObIJsonBase *& parent) const override + { + return OB_NOT_SUPPORTED; + } /* Rebuild the json binary at iter position, and copy to string This function won't change the data itself. diff --git a/deps/oblib/src/lib/json_type/ob_json_tree.h b/deps/oblib/src/lib/json_type/ob_json_tree.h index 3199721349..02dd713e25 100644 --- a/deps/oblib/src/lib/json_type/ob_json_tree.h +++ b/deps/oblib/src/lib/json_type/ob_json_tree.h @@ -71,6 +71,7 @@ public: OB_INLINE ObJsonInType get_internal_type() const override { return ObJsonInType::JSON_TREE; } OB_INLINE uint64_t element_count() const override { return 1; } virtual uint64_t member_count() const override { return element_count(); } + OB_INLINE int get_parent(ObIJsonBase *&parent) const override { parent = parent_; return OB_SUCCESS; } OB_INLINE ObObjType field_type() const override { return ObMaxType; // ObJsonOpaque override diff --git a/src/share/datum/ob_datum.h b/src/share/datum/ob_datum.h index b98615826a..2e7ab90189 100644 --- a/src/share/datum/ob_datum.h +++ b/src/share/datum/ob_datum.h @@ -272,6 +272,7 @@ public: return res; } inline const ObString get_string() const { return ObString(len_, ptr_); } + inline const ObString get_json() const { return get_string(); } inline int get_enumset_inner(ObEnumSetInnerValue &inner_value) const { int64_t pos = 0; diff --git a/src/sql/engine/expr/ob_expr_eval_functions.cpp b/src/sql/engine/expr/ob_expr_eval_functions.cpp index e0b821811a..c718d9ef71 100644 --- a/src/sql/engine/expr/ob_expr_eval_functions.cpp +++ b/src/sql/engine/expr/ob_expr_eval_functions.cpp @@ -1117,6 +1117,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = { NULL, //ObExprInnerTableSequenceGetter::eval_inner_table_sequence_getter, /* 673 */ NULL, //ObExprDecodeTraceId::calc_decode_trace_id_expr, /* 674 */ ObExprInnerRowCmpVal::eval_inner_row_cmp_val, /* 675 */ + ObExprIs::json_is_true, /* 676 */ + ObExprIs::json_is_false, /* 677 */ }; static ObExpr::EvalBatchFunc g_expr_eval_batch_functions[] = { diff --git a/src/sql/engine/expr/ob_expr_is.cpp b/src/sql/engine/expr/ob_expr_is.cpp index 78c9881dc2..172c0ebe00 100644 --- a/src/sql/engine/expr/ob_expr_is.cpp +++ b/src/sql/engine/expr/ob_expr_is.cpp @@ -13,6 +13,7 @@ #define USING_LOG_PREFIX SQL_ENG #include #include "sql/engine/expr/ob_expr_is.h" +#include "ob_expr_json_func_helper.h" #include "share/object/ob_obj_cast.h" //#include "sql/engine/expr/ob_expr_promotion_util.h" #include "objit/common/ob_item_type.h" @@ -67,6 +68,9 @@ int ObExprIsBase::calc_result_type2(ObExprResType &type, if (ob_is_numeric_type(type1.get_type())) { type1.set_calc_meta(type1.get_obj_meta()); type1.set_calc_accuracy(type1.get_accuracy()); + } else if (ob_is_json(type1.get_type())) { + type1.set_calc_meta(type1.get_obj_meta()); + type1.set_calc_accuracy(type1.get_accuracy()); } else { type1.set_calc_type(ObNumberType); const ObAccuracy &calc_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[0][ObNumberType]; @@ -246,6 +250,10 @@ int ObExprIsBase::cg_result_type_class(ObObjType type, ObExpr::EvalFunc &eval_fu EVAL_FUNC(decimal_int); break; } + case ObJsonType: { + EVAL_FUNC(json); + break; + } case ObMaxType: { ret = OB_ERR_UNEXPECTED; LOG_WARN("is expr got unexpected type param", K(ret), K(type)); @@ -542,6 +550,7 @@ NUMERIC_CALC_FUNC(float, ObExprIsNot, true, true, is_not) NUMERIC_CALC_FUNC(double, ObExprIsNot, true, true, is_not) NUMERIC_CALC_FUNC(number, ObExprIsNot, true, true, is_not) NUMERIC_CALC_FUNC(decimal_int, ObExprIsNot, true, true, is_not) +NUMERIC_CALC_FUNC(json, ObExprIsNot, true, true, is_not) NUMERIC_CALC_FUNC(int, ObExprIsNot, true, false, is_not) @@ -549,18 +558,21 @@ NUMERIC_CALC_FUNC(float, ObExprIsNot, true, false, is_not) NUMERIC_CALC_FUNC(double, ObExprIsNot, true, false, is_not) NUMERIC_CALC_FUNC(number, ObExprIsNot, true, false, is_not) NUMERIC_CALC_FUNC(decimal_int, ObExprIsNot, true, false, is_not) +NUMERIC_CALC_FUNC(json, ObExprIsNot, true, false, is_not) NUMERIC_CALC_FUNC(int, ObExprIs, false, true, is) NUMERIC_CALC_FUNC(float, ObExprIs, false, true, is) NUMERIC_CALC_FUNC(double, ObExprIs, false, true, is) NUMERIC_CALC_FUNC(number, ObExprIs, false, true, is) NUMERIC_CALC_FUNC(decimal_int, ObExprIs, false, true, is) +NUMERIC_CALC_FUNC(json, ObExprIs, false, true, is) NUMERIC_CALC_FUNC(int, ObExprIs, false, false, is) NUMERIC_CALC_FUNC(float, ObExprIs, false, false, is) NUMERIC_CALC_FUNC(double, ObExprIs, false, false, is) NUMERIC_CALC_FUNC(number, ObExprIs, false, false, is) NUMERIC_CALC_FUNC(decimal_int, ObExprIs, false, false, is) +NUMERIC_CALC_FUNC(json, ObExprIs, false, false, is) } } diff --git a/src/sql/engine/expr/ob_expr_is.h b/src/sql/engine/expr/ob_expr_is.h index 4f3264a216..92b13ba0ab 100644 --- a/src/sql/engine/expr/ob_expr_is.h +++ b/src/sql/engine/expr/ob_expr_is.h @@ -72,6 +72,8 @@ class ObExprIs: public ObExprIsBase static int calc_is_null(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int int_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int int_is_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); + static int json_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); + static int json_is_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int float_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int float_is_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int double_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); @@ -106,6 +108,8 @@ public: static int calc_is_not_null(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int int_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int int_is_not_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); + static int json_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); + static int json_is_not_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int float_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int float_is_not_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); static int double_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); diff --git a/src/sql/engine/expr/ob_expr_json_array.cpp b/src/sql/engine/expr/ob_expr_json_array.cpp index bbb5f29f89..d03ae7bac7 100644 --- a/src/sql/engine/expr/ob_expr_json_array.cpp +++ b/src/sql/engine/expr/ob_expr_json_array.cpp @@ -56,7 +56,10 @@ int ObExprJsonArray::calc_result_typeN(ObExprResType& type, type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length()); for (int64_t i = 0; i < param_num; i++) { if (ob_is_string_type(types_stack[i].get_type())) { - if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { + if (types_stack[i].get_type() == ObVarcharType && types_stack[i].get_collation_type() == CS_TYPE_BINARY) { + types_stack[i].set_calc_type(ObHexStringType); + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } else if (types_stack[i].get_type() == ObJsonType) { @@ -270,7 +273,6 @@ int ObExprJsonArray::eval_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObDatum for (uint32_t i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; i++) { ObIJsonBase *j_val; if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i, j_val))) { - ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_WARN("failed: get_json_val failed", K(ret)); } else if (OB_FAIL(j_base->array_append(j_val))) { LOG_WARN("failed: json array append json value", K(ret)); 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 c36a059fa8..5491e4d137 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -306,6 +306,10 @@ int ObJsonExprHelper::get_json_val(const ObExpr &expr, ObEvalCtx &ctx, LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type)); } } + + if (OB_SUCC(ret) && OB_NOT_NULL(j_base)) { + j_base->set_allocator(allocator); + } return ret; } int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, @@ -762,7 +766,10 @@ void ObJsonExprHelper::set_type_for_value(ObExprResType* types_stack, uint32_t i ObObjType in_type = types_stack[index].get_type(); if (in_type == ObNullType) { } else if (ob_is_string_type(in_type)) { - if (types_stack[index].get_charset_type() != CHARSET_UTF8MB4) { + if (in_type == ObVarcharType && types_stack[index].get_collation_type() == CS_TYPE_BINARY) { + types_stack[index].set_calc_type(ObHexStringType); + types_stack[index].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } else if (types_stack[index].get_charset_type() != CHARSET_UTF8MB4) { types_stack[index].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); } } else if (in_type == ObJsonType) { @@ -787,6 +794,37 @@ int ObJsonExprHelper::is_json_zero(const ObString& data, int& result) return ret; } +int ObJsonExprHelper::is_json_true(const ObString& data, int& result) +{ + INIT_SUCC(ret); + int tmp_result = 0; + + ObJsonBin j_bin(data.ptr(), data.length()); + if (data.length() == 0) { + result = 0; + } else if (OB_FAIL(j_bin.reset_iter())) { + LOG_WARN("failed: reset iter", K(ret)); + } else if ((j_bin.json_type() == ObJsonNodeType::J_OBJECT || + j_bin.json_type() == ObJsonNodeType::J_ARRAY || + j_bin.json_type() == ObJsonNodeType::J_STRING || + j_bin.json_type() == ObJsonNodeType::J_NULL || + j_bin.json_type() == ObJsonNodeType::J_BOOLEAN)) { + result = 1; + } else if ((j_bin.json_type() == ObJsonNodeType::J_INT || j_bin.json_type() == ObJsonNodeType::J_UINT) + && OB_FAIL(ObJsonBaseUtil::compare_int_json(0, &j_bin, tmp_result))) { + LOG_WARN("failed: cmp json", K(ret)); + } else if ((j_bin.json_type() == ObJsonNodeType::J_DECIMAL) + && OB_FAIL(ObJsonBaseUtil::compare_decimal_uint(j_bin.get_decimal_data(), 0, tmp_result))) { + LOG_WARN("failed: cmp json", K(ret)); + } else if ((j_bin.json_type() == ObJsonNodeType::J_DOUBLE) + && OB_FAIL(ObJsonBaseUtil::compare_double_int(j_bin.get_double(), 0, tmp_result))) { + LOG_WARN("failed: cmp json", K(ret)); + } else { + result = (tmp_result == 0) ? 0 : 1; + } + return ret; +} + template int ObJsonExprHelper::transform_scalar_2jsonBase(const T &datum, ObObjType type, diff --git a/src/sql/engine/expr/ob_expr_json_func_helper.h b/src/sql/engine/expr/ob_expr_json_func_helper.h index 7919249d5d..a72a04e7a3 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.h +++ b/src/sql/engine/expr/ob_expr_json_func_helper.h @@ -116,6 +116,8 @@ public: static ObJsonPathCache* get_path_cache_ctx(const uint64_t& id, ObExecContext *exec_ctx); static int is_json_zero(const ObString& data, int& result); + + static int is_json_true(const ObString& data, int& result); /* try to transfrom scalar data to jsonBase diff --git a/src/sql/engine/expr/ob_expr_json_length.cpp b/src/sql/engine/expr/ob_expr_json_length.cpp index 3cb6602226..9844f61ee8 100644 --- a/src/sql/engine/expr/ob_expr_json_length.cpp +++ b/src/sql/engine/expr/ob_expr_json_length.cpp @@ -108,13 +108,15 @@ int ObExprJsonLength::calc(ObEvalCtx &ctx, const ObDatum &data1, ObDatumMeta met ObJsonPath *j_path = NULL; if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, *data2, meta2, has_lob_header2, j_path_text))) { LOG_WARN("fail to get real data.", K(ret), K(j_path_text)); - } else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, 1, false))) { + } else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, 1, true))) { LOG_USER_ERROR(OB_ERR_INVALID_JSON_PATH); LOG_WARN("fail to parse json path", K(ret), K(type2), K(j_path_text)); - } else if (OB_FAIL(j_base->seek(*j_path, j_path->path_node_cnt(), true, true, hit))) { + } else if (OB_FAIL(j_base->seek(*j_path, j_path->path_node_cnt(), true, false, hit))) { LOG_WARN("fail to seek json node", K(ret), K(j_path_text)); - } else if (hit.size() != 1) { // not found node by path, display "NULL" + } else if (hit.size() == 0) { // not found node by path, display "NULL" is_null = true; + } else if (hit.size() > 1) { + res_len = hit.size(); } else { res_len = hit[0]->member_count(); } diff --git a/src/sql/engine/expr/ob_expr_json_remove.cpp b/src/sql/engine/expr/ob_expr_json_remove.cpp index 830ff6eec8..252c7bc6f4 100644 --- a/src/sql/engine/expr/ob_expr_json_remove.cpp +++ b/src/sql/engine/expr/ob_expr_json_remove.cpp @@ -54,14 +54,19 @@ int ObExprJsonRemove::calc_result_typeN(ObExprResType& type, return ret; } -static int remove_from_json(ObJsonPath *path_node, ObIJsonBase *parent) +static int remove_from_json(ObJsonPath *path_node, ObIJsonBase *child) { INIT_SUCC(ret); // remove item in hits ObJsonPathBasicNode* last_node = path_node->last_path_node(); // get node to be removed - ObJsonNodeType type = parent->json_type(); - if (type == ObJsonNodeType::J_OBJECT && last_node->get_node_type() == JPN_MEMBER) { + ObJsonNodeType type; + ObIJsonBase* parent = nullptr; + if (OB_FAIL(child->get_parent(parent)) || OB_ISNULL(parent)) { + // may be null parent + ret = OB_SUCCESS; + } else if (FALSE_IT(type = parent->json_type())) { + } else if (type == ObJsonNodeType::J_OBJECT && last_node->get_node_type() == JPN_MEMBER) { ObPathMember member = last_node->get_object(); ObString key(member.len_, member.object_name_); if (OB_FAIL(parent->object_remove(key))) { @@ -120,7 +125,7 @@ int ObExprJsonRemove::eval_json_remove(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (json_path->path_node_cnt() == 0) { ret = OB_ERR_JSON_VACUOUS_PATH; LOG_USER_ERROR(OB_ERR_JSON_VACUOUS_PATH); - } else if (OB_FAIL(json_doc->seek(*json_path, json_path->path_node_cnt() - 1, true, false, hits))) { + } else if (OB_FAIL(json_doc->seek(*json_path, json_path->path_node_cnt(), true, false, hits))) { LOG_WARN("json seek failed", K(path_data->get_string()), K(ret)); } else if (hits.size() == 0){ continue; diff --git a/src/sql/engine/expr/ob_expr_json_search.cpp b/src/sql/engine/expr/ob_expr_json_search.cpp index 50c6096faf..a101a0dc1e 100644 --- a/src/sql/engine/expr/ob_expr_json_search.cpp +++ b/src/sql/engine/expr/ob_expr_json_search.cpp @@ -229,9 +229,7 @@ int ObExprJsonSearch::calc_result_typeN(ObExprResType& type, for (int64_t i = 1; OB_SUCC(ret) && i < param_num; i++) { if (types_stack[i].get_type() == ObNullType) { } else 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); - } + 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); @@ -271,11 +269,19 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (val_type == ObNullType || json_datum->is_null()) { is_null = true; } else if (!ob_is_string_type(val_type)) { + ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(val_type)); } else { ObString target_str = json_datum->get_string(); if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, target_str, is_null))) { LOG_WARN("fail to get real data.", K(ret), K(target_str)); + } else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN && + OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_, + CS_TYPE_UTF8MB4_BIN, + &temp_allocator, + target_str, + target_str))) { + LOG_WARN("fail to convert string", K(ret)); } else if (0 == target_str.case_compare("one")) { one_flag = true; } else if (0 == target_str.case_compare("all")) { @@ -297,12 +303,20 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (val_type == ObNullType || json_datum->is_null()) { // do nothing, null type use default escape } else if (!ob_is_string_type(val_type)) { + ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(val_type)); } else { ObString escape = json_datum->get_string(); bool is_null_str = false; if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, escape, is_null_str))) { LOG_WARN("fail to get real data.", K(ret), K(escape)); + } else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN && + OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_, + CS_TYPE_UTF8MB4_BIN, + &temp_allocator, + escape, + escape))) { + LOG_WARN("fail to convert string", K(ret)); } else if (escape.length() > 0) { const ObCollationType escape_coll = json_arg->datum_meta_.cs_type_; size_t length = ObCharset::strlen_char(escape_coll, escape.ptr(), escape.length()); @@ -328,12 +342,17 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (val_type == ObNullType || json_datum->is_null()) { is_null = true; } else if (!ob_is_string_type(val_type)) { + ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(val_type)); - } else { - target = json_datum->get_string(); - if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, target, is_null))) { - LOG_WARN("fail to get real data.", K(ret), K(target)); - } + } else if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, target, is_null))) { + LOG_WARN("fail to get real data.", K(ret), K(target)); + } else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN && + OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_, + CS_TYPE_UTF8MB4_BIN, + &temp_allocator, + target, + target))) { + LOG_WARN("fail to convert string", K(ret)); } } @@ -364,6 +383,7 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (val_type == ObNullType || json_datum->is_null()) { is_null = true; } else if (!ob_is_string_type(val_type)) { + ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(val_type)); } else { ObString j_path_text = json_datum->get_string(); @@ -372,6 +392,13 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_WARN("fail to get real data.", K(ret), K(j_path_text)); } else if (j_path_text.length() == 0) { is_null = true; + } else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN && + OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_, + CS_TYPE_UTF8MB4_BIN, + &temp_allocator, + j_path_text, + j_path_text))) { + LOG_WARN("fail to convert string", K(ret)); } else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, i, true))) { LOG_WARN("parse text to path failed", K(j_path_text), K(ret)); diff --git a/src/sql/engine/expr/ob_expr_json_valid.cpp b/src/sql/engine/expr/ob_expr_json_valid.cpp index e798f0d005..8a87ad8e1a 100644 --- a/src/sql/engine/expr/ob_expr_json_valid.cpp +++ b/src/sql/engine/expr/ob_expr_json_valid.cpp @@ -131,6 +131,8 @@ int ObExprJsonValid::eval_json_valid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum if (OB_FAIL(arg->eval(ctx, datum))) { LOG_WARN("eval json arg failed", K(ret)); + res.set_int(0); + ret = OB_SUCCESS; } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObIAllocator &tmp_allocator = tmp_alloc_g.get_allocator();