[CP]: Oracle json bugfix

This commit is contained in:
wu-xingying 2023-12-27 06:18:35 +00:00 committed by ob-robot
parent a52b801e5f
commit c8647966da
6 changed files with 169 additions and 215 deletions

View File

@ -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;

View File

@ -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<start", K(ret), K(start), K(end), K(expression_));
} else {
len = end - start + 1;
char* start_ptr = expression_.ptr() + start;
if (!is_quoted) {
length = len + 2;
str = static_cast<char*> (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<char*> (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<start", K(ret), K(start), K(end), K(expression_));
} else {
len = end-start + 1;
len = end - start + 1;
char* start_ptr = expression_.ptr() + start;
// no "", could be function name
if ((!is_quoted) && (!is_func)) {
length = len+2;
length = len + 2;
str = static_cast<char*> (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)) {

View File

@ -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);

View File

@ -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);

View File

@ -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<ParseNode&>(*returning_type), OPT_JSON_QUERY))) {
LOG_WARN("set return type by path item method fail", K(ret), K(path_str));

View File

@ -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]));
}
}
}