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 25f9b8e56..db4b8c684 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -2147,53 +2147,63 @@ bool ObIJsonBase::is_real_json_null(const ObIJsonBase* ptr) const return ret_bool; } -int ObIJsonBase::trans_json_node(ObIAllocator* allocator, ObIJsonBase* &left, ObIJsonBase* &right) const +// left is scalar, right is ans of subpath +int ObIJsonBase::trans_json_node(ObIAllocator* allocator, ObIJsonBase* &scalar, ObIJsonBase* &path_res) const { INIT_SUCC(ret); - ObJsonNodeType left_type = left->json_type(); - ObJsonNodeType right_type = right->json_type(); - // 左边的需要根据右边的类型转换 + ObJsonNodeType left_type = scalar->json_type(); + ObJsonNodeType right_type = path_res->json_type(); if (left_type == ObJsonNodeType::J_STRING) { - ObString str(left->get_data_length(), left->get_data()); + ObString str(scalar->get_data_length(), scalar->get_data()); if (is_json_number(right_type)) { // fail is normal - ret = trans_to_json_number(allocator, str, left); + ret = trans_to_json_number(allocator, str, scalar); } else if (right_type == ObJsonNodeType::J_DATE || right_type == ObJsonNodeType::J_DATETIME || right_type == ObJsonNodeType::J_TIME || right_type == ObJsonNodeType::J_ORACLEDATE) { - ret = trans_to_date_timestamp(allocator, str, left, true); + ret = trans_to_date_timestamp(allocator, str, scalar, true); } else if (right_type == ObJsonNodeType::J_TIMESTAMP || right_type == ObJsonNodeType::J_OTIMESTAMP || right_type == ObJsonNodeType::J_OTIMESTAMPTZ) { - ret = trans_to_date_timestamp(allocator, str, left, false); + ret = trans_to_date_timestamp(allocator, str, scalar, false); } else if (right_type == ObJsonNodeType::J_BOOLEAN) { - ret = trans_to_boolean(allocator, str, left); + // when scalar is string, path_res is boolean, case compare + if (str.case_compare("true") == 0 || str.case_compare("false") == 0) { + ret = trans_to_boolean(allocator, str, scalar); + } else { + ret = OB_NOT_SUPPORTED; + } } else if (right_type != ObJsonNodeType::J_ARRAY && right_type != ObJsonNodeType::J_OBJECT) { ret = ret = OB_INVALID_ARGUMENT; LOG_WARN("CAN'T TRANS", K(ret)); } - // 右边需要根据左边的转换 + } else if (left_type == ObJsonNodeType::J_NULL) { + // return error code, mean can't cast, return false ans directly + ret = OB_NOT_SUPPORTED; } else if (right_type == ObJsonNodeType::J_STRING) { - ObString str(right->get_data_length(), right->get_data()); + ObString str(path_res->get_data_length(), path_res->get_data()); if (is_json_number(left_type)) { // fail is normal - ret = trans_to_json_number(allocator, str, right); + ret = trans_to_json_number(allocator, str, path_res); } else if (left_type == ObJsonNodeType::J_DATE || left_type == ObJsonNodeType::J_DATETIME || left_type == ObJsonNodeType::J_TIME || left_type == ObJsonNodeType::J_ORACLEDATE) { - ret = trans_to_date_timestamp(allocator, str, right, true); + ret = trans_to_date_timestamp(allocator, str, path_res, true); } else if (left_type == ObJsonNodeType::J_TIMESTAMP || left_type == ObJsonNodeType::J_OTIMESTAMP || left_type == ObJsonNodeType::J_OTIMESTAMPTZ) { - ret = trans_to_date_timestamp(allocator, str, right, false); + ret = trans_to_date_timestamp(allocator, str, path_res, false); } else if (left_type == ObJsonNodeType::J_BOOLEAN) { - ret = trans_to_boolean(allocator, str, right); + ret = trans_to_boolean(allocator, str, path_res); } else if (left_type != ObJsonNodeType::J_ARRAY && left_type != ObJsonNodeType::J_OBJECT) { - ret = ret = OB_INVALID_ARGUMENT; + ret = OB_INVALID_ARGUMENT; LOG_WARN("CAN'T TRANS", K(ret)); } + } else if (left_type == ObJsonNodeType::J_BOOLEAN || is_json_number(left_type)) { + // scalar is boolean or number, and path_res is not string, return false + ret = OB_NOT_SUPPORTED; } else { // do nothing LOG_WARN("CAN'T TRANS", K(ret)); @@ -2247,7 +2257,7 @@ int ObIJsonBase::cmp_to_right_recursively(ObIAllocator* allocator, const ObJsonB // 但只要有一个找到,且为123或"123"则为true ObIJsonBase* left = jb_ptr; ObIJsonBase* right = right_arg; - if (OB_FAIL(trans_json_node(allocator, left, right))) { + if (OB_FAIL(trans_json_node(allocator, right, left))) { // fail is normal, it is not an error. ret = OB_SUCCESS; cmp_result = false; @@ -2270,7 +2280,7 @@ int ObIJsonBase::cmp_to_right_recursively(ObIAllocator* allocator, const ObJsonB // 不相同的类型,同上 ObIJsonBase* left = hit[i]; ObIJsonBase* right = right_arg; - if (OB_FAIL(trans_json_node(allocator, left, right))) { + if (OB_FAIL(trans_json_node(allocator, right, left))) { // fail is normal, it is not an error. ret = OB_SUCCESS; cmp_result = false; @@ -2291,7 +2301,6 @@ int ObIJsonBase::cmp_to_right_recursively(ObIAllocator* allocator, const ObJsonB } // for compare ——> ( scalar/sql_var, subpath) -// 左边调用compare,右边是数组时自动解包 // 只要有一个结果为true则返回true,找不到或结果为false均返回false int ObIJsonBase::cmp_to_left_recursively(ObIAllocator* allocator, const ObJsonBaseVector& hit, const ObJsonPathNodeType node_type, @@ -2310,44 +2319,7 @@ int ObIJsonBase::cmp_to_left_recursively(ObIAllocator* allocator, const ObJsonBa } else if (hit[i]->json_type() == ObJsonNodeType::J_NULL && !is_real_json_null(hit[i])) { cmp_result = false; } else { - // error is ok - // if is array, compare with every node - // but only autowrap once - if (hit[i]->json_type() == ObJsonNodeType::J_ARRAY) { - uint64_t size = hit[i]->element_count(); - ObIJsonBase *jb_ptr = NULL; - for (uint32_t array_i = 0; array_i < size && !cmp_result && OB_SUCC(ret); ++array_i) { - jb_ptr = NULL; // reset jb_ptr to NULL - ret = hit[i]->get_array_element(array_i, jb_ptr); - int cmp_res = -3; - // 类型相同可以直接用compare函数比较 - if(OB_FAIL(ret) || OB_ISNULL(jb_ptr)) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("compare value is null.", K(ret)); - } else if (is_same_type(left_arg, jb_ptr)) { - if (OB_SUCC(left_arg->compare((*jb_ptr), cmp_res, true))) { - cmp_based_on_node_type(node_type, cmp_res, cmp_result); - } - } else { - // 不相同的类型,oracle会将string类型转换为对应类型再进行比较 - // 转换或比较失败也正常,并不报错 - // 例如: [*].a == 123 - // 里面可能有多个元素无法转换成数字或无法和数字比较甚至找不到.a - // 但只要有一个找到,且为123或"123"则为true - ObIJsonBase* left = left_arg; - ObIJsonBase* right = jb_ptr; - if (OB_FAIL(trans_json_node(allocator, left, right))) { - // fail is normal, it is not an error. - ret = OB_SUCCESS; - cmp_result = false; - } else if (OB_SUCC(left->compare((*right), cmp_res, true))) { - cmp_based_on_node_type(node_type, cmp_res, cmp_result); - } else { - cmp_result = false; - } - } - } - } else if (hit[i]->json_type() == ObJsonNodeType::J_OBJECT) { + if (hit[i]->json_type() == ObJsonNodeType::J_OBJECT || hit[i]->json_type() == ObJsonNodeType::J_ARRAY) { cmp_result = false; } else { int cmp_res = -3; diff --git a/deps/oblib/src/lib/json_type/ob_json_path.cpp b/deps/oblib/src/lib/json_type/ob_json_path.cpp index a2823c8eb..ea48b2d61 100644 --- a/deps/oblib/src/lib/json_type/ob_json_path.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_path.cpp @@ -786,13 +786,16 @@ int ObJsonPath::change_json_expr_res_type_if_need(common::ObIAllocator &allocato switch (func_node->get_node_type()) { case JPN_BOOLEAN : case JPN_BOOL_ONLY : { - ret_node.type_ = T_CAST_ARGUMENT; - ret_node.value_ = 0; - ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; - ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; - ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 20; - ret_node.length_semantics_ = 0; - ret_node.is_hidden_const_ = 1; + if (json_expr_flag == OPT_JSON_QUERY && ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] == T_JSON) { // do nothing + } else { + ret_node.type_ = T_CAST_ARGUMENT; + ret_node.value_ = 0; + ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; + ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; + ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 20; + ret_node.length_semantics_ = 0; + ret_node.is_hidden_const_ = 1; + } break; } case JPN_DATE : { @@ -824,14 +827,16 @@ int ObJsonPath::change_json_expr_res_type_if_need(common::ObIAllocator &allocato case JPN_NUMBER : case JPN_FLOOR : case JPN_CEILING : { - ret_node.value_ = 0; - if (ret_node.type_ == T_NULL) { + if (ret_node.type_ == T_NULL + || (json_expr_flag == OPT_JSON_QUERY && ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] == T_JSON)) { + ret_node.value_ = 0; ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 4000; ret_node.length_semantics_ = 0; ret_node.is_hidden_const_ = 1; } else { + ret_node.value_ = 0; ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_NUMBER; ret_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = -1; /* precision */ ret_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = -85; /* scale */ @@ -855,24 +860,29 @@ int ObJsonPath::change_json_expr_res_type_if_need(common::ObIAllocator &allocato case JPN_TYPE: case JPN_STR_ONLY : case JPN_STRING : { - ret_node.type_ = T_CAST_ARGUMENT; - ret_node.value_ = 0; - ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; - ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; - ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 4000; - ret_node.length_semantics_ = 0; - ret_node.is_hidden_const_ = 1; + if (json_expr_flag == OPT_JSON_QUERY && ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] == T_JSON) { + } else { + ret_node.type_ = T_CAST_ARGUMENT; + ret_node.value_ = 0; + ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; + ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; + ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 4000; + ret_node.length_semantics_ = 0; + ret_node.is_hidden_const_ = 1; + } } case JPN_UPPER: case JPN_LOWER: { - ret_node.type_ = T_CAST_ARGUMENT; - ret_node.value_ = 0; - ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; - ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; - ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 75; - ret_node.length_semantics_ = 0; - ret_node.is_hidden_const_ = 1; - break; + if (json_expr_flag == OPT_JSON_QUERY && ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] == T_JSON) { + } else { + ret_node.type_ = T_CAST_ARGUMENT; + ret_node.value_ = 0; + ret_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = T_VARCHAR; + ret_node.int16_values_[OB_NODE_CAST_COLL_IDX] = 0; + ret_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 75; + ret_node.length_semantics_ = 0; + ret_node.is_hidden_const_ = 1; + } break; } default : { @@ -2123,7 +2133,7 @@ int ObJsonPath::parse_name_with_rapidjson(char*& str, uint64_t& len) } // if keyname without double quote, end with ' ', '.', '[', '*' -bool ObJsonPathUtil::is_mysql_terminator(char ch) +bool ObJsonPathUtil::is_key_name_terminator(char ch) { bool ret_bool = false; switch (ch) { @@ -2143,6 +2153,18 @@ bool ObJsonPathUtil::is_mysql_terminator(char ch) ret_bool = true; break; } + case '(': { + ret_bool = true; + break; + } + case '?': { + ret_bool = true; + break; + } + case '-': { + ret_bool = true; + break; + } default: { break; } @@ -2150,98 +2172,6 @@ bool ObJsonPathUtil::is_mysql_terminator(char ch) return ret_bool; } -// process JPN_MEMBER get keyname -// @param[in,out] name Keyname -// @param[in] is_quoted -// @return the error code. -int ObJsonPath::get_mysql_origin_key_name(char*& str, uint64_t& length, bool is_quoted) -{ - INIT_SUCC(ret); - uint64_t start = 0; - uint64_t end = 0; - - int len = expression_.length(); - - if (index_ < len) { - if (is_quoted) { - // with quote, check quote - if (expression_[index_] == ObJsonPathItem::DOUBLE_QUOTE) { - start = index_; - ++index_; - - while (index_ < len && end == 0) { - if (expression_[index_] == '\\') { - index_ += 2; - } else if (expression_[index_] == ObJsonPathItem::DOUBLE_QUOTE) { - end = index_; - ++index_; - } else { - ++index_; - } - } - - if (end == 0 && index_ == len) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("should end with DOUBLE_QUOTE!", K(ret), K(index_), K(expression_)); - } - } else { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("should start with DOUBLE_QUOTE!", K(ret), K(index_), K(expression_)); - } - } else { - start = index_; - while (index_ < len && end == 0) { - if (ObJsonPathUtil::is_mysql_terminator(expression_[index_])) { - end = index_ - 1; - } else { - ++index_; - } - } - if (index_ == len) { - end = index_ - 1; - } - } - } else { - ret = OB_ARRAY_OUT_OF_RANGE; - LOG_WARN("index out of range!", K(ret), K(index_), K(expression_)); - } - - if (OB_SUCC(ret)) { - if (end < start) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("get keyname: end (allocator_->alloc(length)); - if (OB_ISNULL(str)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to allocate memory for member_name.", - K(ret), K(len),KCSTRING(start_ptr)); - } else { - str[0] = ObJsonPathItem::DOUBLE_QUOTE; - MEMCPY(str + 1, start_ptr, len); - str[len + 1] = ObJsonPathItem::DOUBLE_QUOTE; - } - } else { - length = len; - str = static_cast (allocator_->alloc(length)); - if (OB_ISNULL(str)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to allocate memory for member_name.", - K(ret), K(len),KCSTRING(start_ptr)); - } else { - MEMCPY(str, start_ptr, len); - } - } - } - } - - return ret; -} - // parse JPN_MEMBER_WILDCARD // @return the error code. int ObJsonPath::parse_member_wildcard_node() @@ -2331,9 +2261,11 @@ int ObJsonPath::parse_mysql_member_node() char* name = nullptr; uint64_t name_len = 0; + bool is_func = false; + bool with_escape = false; // get name // add double quote for rapidjson requires - if (OB_FAIL(get_mysql_origin_key_name(name, name_len, is_quoted))) { + if (OB_FAIL(get_origin_key_name(name, name_len, is_quoted, is_func, with_escape))) { LOG_WARN("fail to get keyname!", K(ret), K(index_), K(expression_)); } else { if (OB_FAIL(parse_name_with_rapidjson(name, name_len))) { @@ -2431,6 +2363,31 @@ bool ObJsonPathUtil::is_scalar(const ObJsonPathNodeType node_type) return ret_bool; } +bool ObJsonPathUtil::is_escape(char ch) +{ + return (('\n' == ch) || (ch == '\t') || (ch == '\r') || (ch == '\f') || (ch == '\e')); +} +int ObJsonPathUtil::append_character_of_escape(ObJsonBuffer& buf, char ch) +{ + INIT_SUCC(ret); + if ('\n' == ch) { + ret = buf.append("n"); + } else if ('\t' == ch) { + ret = buf.append("t"); + } else if ('\r' == ch) { + ret = buf.append("r"); + } else if ('\f' == ch) { + ret = buf.append("f"); + } else if ('\e' == ch) { + ret = buf.append("e"); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("should be escape", K(ch), K(ret)); + } + return ret; +} + + void ObJsonPathUtil::skip_whitespace(const ObString &path, uint64_t& idx) { while (idx < path.length() && ObJsonPathUtil::is_whitespace(path[idx])) { @@ -3039,7 +2996,7 @@ bool ObJsonPathUtil::is_oracle_keyname(const char* name, uint64_t length) // @param[in,out] name Keyname // @param[in] is_quoted // @return the error code. -int ObJsonPath::get_oracle_origin_key_name(char*& str, uint64_t& length, bool is_quoted, bool& is_func) +int ObJsonPath::get_origin_key_name(char*& str, uint64_t& length, bool is_quoted, bool& is_func, bool& with_escape) { INIT_SUCC(ret); uint64_t start = 0; @@ -3060,6 +3017,9 @@ int ObJsonPath::get_oracle_origin_key_name(char*& str, uint64_t& length, bool is } else if (expression_[index_] == ObJsonPathItem::DOUBLE_QUOTE) { end = index_; ++index_; + } else if (ObJsonPathUtil::is_escape(expression_[index_])) { + with_escape = true; + ++index_; } else { ++index_; } @@ -3074,35 +3034,28 @@ int ObJsonPath::get_oracle_origin_key_name(char*& str, uint64_t& length, bool is LOG_WARN("should start with DOUBLE_QUOTE!", K(ret), K(index_), K(expression_)); } } else { - if (ObJsonPathUtil::letter_or_not(expression_[index_]) || (expression_[index_] == '_')) { - // without '""' - start = index_; - ++index_; - while (index_ < len) { - if (!(ObJsonPathUtil::letter_or_not(expression_[index_]) - || ObJsonPathUtil::is_digit(expression_[index_]) - || (expression_[index_] == '_'))) { + start = index_; + if (ObJsonPathUtil::is_digit(expression_[index_])) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("shouldn't start with number!", K(ret), K(index_), K(expression_)); + } else { + while (index_ < len && end == 0) { + if (ObJsonPathUtil::is_key_name_terminator(expression_[index_])) { end = index_ - 1; break; } else { ++index_; } } - if (index_ == len) { end = index_ - 1; } else { ObJsonPathUtil::skip_whitespace(expression_, index_); // fun_name + () - if (index_ < expression_.length()) { - if (expression_[index_] == '(') { + if (index_ < expression_.length() && expression_[index_] == '(') { is_func = true; - } - }//now, index could equal to len + } } - } else { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("wrong keyname!", K(ret), K(start), K(end), K(expression_)); } } } else { @@ -3115,11 +3068,11 @@ int ObJsonPath::get_oracle_origin_key_name(char*& str, uint64_t& length, bool is ret = OB_INVALID_ARGUMENT; LOG_WARN("get keyname: end (allocator_->alloc(length)); if (OB_ISNULL(str)) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -3182,6 +3135,31 @@ int ObJsonPath::parse_func_node(char*& name, uint64_t& len) return ret; } +int ObJsonPath::deal_with_escape(char* &str, uint64_t& len) +{ + INIT_SUCC(ret); + ObJsonBuffer buf(allocator_); + for (int i = 0; i < len && OB_SUCC(ret); ++i) { + char* tmp = str + i; + if (OB_ISNULL(tmp)) { + } else if (ObJsonPathUtil::is_escape(*tmp)) { + if (OB_FAIL(buf.append("\\"))) { + LOG_WARN("fail to append \\.", K(i), K(ret)); + } else if (OB_FAIL(ObJsonPathUtil::append_character_of_escape(buf, *tmp))) { + LOG_WARN("fail to append_character_of_escape.", K(*tmp), K(i), K(ret)); + } + } else { + ret = buf.append(tmp, 1); + } + } + + if (OB_SUCC(ret)) { + str = buf.ptr(); + len = buf.length(); + } + return ret; +} + // parse JPN_ORACLE_MEMBER // @return the error code. int ObJsonPath::parse_oracle_member_node() @@ -3191,6 +3169,7 @@ int ObJsonPath::parse_oracle_member_node() if (index_ < expression_.length()) { bool is_quoted = false; bool is_func = false; + bool with_escape = false; // check double quote if (expression_[index_] == ObJsonPathItem::DOUBLE_QUOTE) is_quoted = true; @@ -3199,12 +3178,19 @@ int ObJsonPath::parse_oracle_member_node() uint64_t name_len = 0; // get name // add double quote for rapidjson requires - if (OB_FAIL(get_oracle_origin_key_name(name, name_len, is_quoted, is_func))) { + if (OB_FAIL(get_origin_key_name(name, name_len, is_quoted, is_func, with_escape))) { LOG_WARN("fail to get keyname!", K(ret), K(index_), K(expression_)); } else if (is_quoted || (!is_func)) { - // with "", must be member node - if (OB_FAIL(parse_name_with_rapidjson(name, name_len))) { - LOG_WARN("fail to parse name with rapidjson",K(ret), K(index_), K(expression_),K(name)); + if (lib::is_oracle_mode() && with_escape && OB_FAIL(ObJsonPath::deal_with_escape(name, name_len))) { + LOG_WARN("fail to deal escape!", K(ret), K(index_), K(expression_)); + } else if (OB_FAIL(parse_name_with_rapidjson(name, name_len))) { + LOG_WARN("fail to parse name with rapidjson", + K(ret), K(index_), K(expression_),KCSTRING(name)); + } else if (!is_quoted) { + if (!ObJsonPathUtil::is_ecmascript_identifier(name, name_len)) { + LOG_WARN("the key name isn't ECMAScript identifier!", + K(ret), KCSTRING(name)); + } } if (OB_SUCC(ret)) { @@ -3932,7 +3918,8 @@ int ObJsonPath::parse_comp_string_num(ObJsonPathFilterNode* filter_comp_node, bo char* str = nullptr; uint64_t name_len = 0; bool is_func = false; - if (OB_FAIL(get_oracle_origin_key_name(str, name_len, true, is_func))) { + bool with_escape = false; + if (OB_FAIL(get_origin_key_name(str, name_len, true, is_func, with_escape))) { LOG_WARN("fail to get string scalar",K(ret), K(index_), K(expression_),K(str)); } else { if (OB_ISNULL(str)) { diff --git a/deps/oblib/src/lib/json_type/ob_json_path.h b/deps/oblib/src/lib/json_type/ob_json_path.h index 8c487e128..20d5e9367 100644 --- a/deps/oblib/src/lib/json_type/ob_json_path.h +++ b/deps/oblib/src/lib/json_type/ob_json_path.h @@ -359,8 +359,8 @@ private: bool& from_end1, bool& from_end2); int add_single_array_node(bool is_cell_type, uint64_t& index1, uint64_t& index2, bool& from_end1, bool& from_end2); - int get_mysql_origin_key_name(char* &str, uint64_t& length, bool is_quoted); - int get_oracle_origin_key_name(char* &str, uint64_t& length, bool is_quoted, bool& is_func); + int get_origin_key_name(char* &str, uint64_t& length, bool is_quoted, bool& is_func, bool& with_escape); + int deal_with_escape(char* &str, uint64_t& length); int parse_name_with_rapidjson(char*& str, uint64_t& len); int parse_func_node(char*& name, uint64_t& len); int get_char_comparison_type(ObJsonPathFilterNode* filter_comp_node); @@ -455,7 +455,7 @@ public: static bool is_oracle_keyname(const char* name, uint64_t length); // add quote and static int double_quote(ObString &name, ObJsonBuffer* tmp_name); - static bool is_mysql_terminator(char ch); + static bool is_key_name_terminator(char ch); static bool is_begin_field_name(char ch); static bool is_end_of_comparission(char ch); static bool letter_or_not(char ch); @@ -480,6 +480,8 @@ public: bool auto_wrap); static bool is_letter(unsigned codepoint, const char* ori, uint64_t start, uint64_t end); + static bool is_escape(char ch); + static int append_character_of_escape(ObJsonBuffer& buf, char ch); static bool is_connector_punctuation(unsigned codepoint); static bool unicode_combining_mark(unsigned codepoint); static bool is_utf8_unicode_charator(const char* ori, uint64_t& start, int64_t len); diff --git a/src/sql/engine/expr/ob_expr_json_equal.cpp b/src/sql/engine/expr/ob_expr_json_equal.cpp index d5da1074a..39a9689e8 100644 --- a/src/sql/engine/expr/ob_expr_json_equal.cpp +++ b/src/sql/engine/expr/ob_expr_json_equal.cpp @@ -92,14 +92,6 @@ int ObExprJsonEqual::eval_json_equal(const ObExpr &expr, ObEvalCtx &ctx, ObDatum uint8_t option_on_error = 0; // json数据解析出错或非标量,此时根据on error参数返回结果 bool is_cover_by_error = false; - bool both_json = false; - - // 检查是否均为 json 类型,如果均为json类型,标量相比不报错 - // 只要有一个参数不是json类型,标量相比就会报错 - if (expr.args_[0]->datum_meta_.type_ == ObJsonType - || expr.args_[1]->datum_meta_.type_ == ObJsonType) { - both_json = true; - } ObExpr *json_arg_l = expr.args_[0]; ObObjType val_type_l = json_arg_l->datum_meta_.type_; @@ -116,8 +108,9 @@ int ObExprJsonEqual::eval_json_equal(const ObExpr &expr, ObEvalCtx &ctx, ObDatum json_candidate, is_null_result))) { if (ret == OB_ERR_JSON_SYNTAX_ERROR) is_cover_by_error = true; LOG_WARN("get_json_doc failed", K(ret)); - } else if(!is_null_result && !both_json && (is_json_scalar(json_target) - || is_json_scalar(json_candidate))) { + // if is scalar, must be json type + } else if(!is_null_result && ((is_json_scalar(json_target) && expr.args_[0]->datum_meta_.type_ != ObJsonType) + || (is_json_scalar(json_candidate) && expr.args_[1]->datum_meta_.type_ != ObJsonType))) { ret = OB_ERR_JSON_SYNTAX_ERROR; is_cover_by_error = true; LOG_USER_ERROR(OB_ERR_JSON_SYNTAX_ERROR); diff --git a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp index 74ca1dafa..cacd066bf 100644 --- a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp @@ -5718,7 +5718,7 @@ int ObRawExprResolverImpl::process_json_query_node(const ParseNode *node, ObRawE } // pre check default returning type with item method if (OB_SUCC(ret)) { - if (returning_type->type_ == T_NULL) { + if (returning_type->type_ == T_NULL || returning_type->int16_values_[OB_NODE_CAST_TYPE_IDX] == T_JSON) { ObString path_str(node->children_[1]->text_len_, node->children_[1]->raw_text_); if (OB_FAIL(ObJsonPath::change_json_expr_res_type_if_need(ctx_.expr_factory_.get_allocator(), path_str, const_cast(*returning_type), OPT_JSON_QUERY))) { LOG_WARN("set return type by path item method fail", K(ret), K(path_str)); diff --git a/unittest/share/test_json_path.cpp b/unittest/share/test_json_path.cpp index 371a59a43..031ca0370 100644 --- a/unittest/share/test_json_path.cpp +++ b/unittest/share/test_json_path.cpp @@ -54,9 +54,9 @@ TEST_F(TestJsonPath, test_is_mysql_terminator_mysql) for(int i = 0; i < sizeof(ch); ++i) { if (i <= 3) { - ASSERT_EQ(true, ObJsonPathUtil::is_mysql_terminator(ch[i])); + ASSERT_EQ(true, ObJsonPathUtil::is_key_name_terminator(ch[i])); } else { - ASSERT_EQ(false, ObJsonPathUtil::is_mysql_terminator(ch[i])); + ASSERT_EQ(false, ObJsonPathUtil::is_key_name_terminator(ch[i])); } } }