diff --git a/deps/oblib/src/common/object/ob_obj_funcs.h b/deps/oblib/src/common/object/ob_obj_funcs.h index f91e007762..ae0e95fc61 100644 --- a/deps/oblib/src/common/object/ob_obj_funcs.h +++ b/deps/oblib/src/common/object/ob_obj_funcs.h @@ -1419,12 +1419,12 @@ DEF_TEXT_FUNCS(ObLongTextType, string, ObString); { \ static uint64_t calc_hash_value(const P ¶m, const uint64_t hash) { \ int ret = OB_SUCCESS; \ - common::ObString j_text = param.get_string(); \ + common::ObString j_bin_str = param.get_string(); \ uint64_t hash_res = 0; \ - ObJsonBin j_bin(j_text.ptr(), j_text.length()); \ + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); \ ObIJsonBase *j_base = &j_bin; \ if (OB_FAIL(j_bin.reset_iter())) { \ - COMMON_LOG(WARN, "fail to reset json bin iter", K(ret), K(j_text)); \ + COMMON_LOG(WARN, "fail to reset json bin iter", K(ret), K(j_bin_str)); \ right_to_die_or_duty_to_live(); \ } else if (OB_FAIL(j_base->calc_json_hash_value(hash, T::hash, hash_res))) { \ COMMON_LOG(ERROR, "fail to calc hash", K(ret), K(*j_base)); \ 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 35b8c971b5..2b65028ee9 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -34,6 +34,8 @@ struct ObJsonBaseCmp { is_eq = (a == b); } else if (a->is_bin() && b->is_bin()) { is_eq = (a->get_data() == b->get_data()); + } else { + LOG_WARN("unexpected type", K(OB_ERR_UNEXPECTED), K(*a), K(*b)); } return is_eq; } @@ -51,9 +53,10 @@ struct ObJsonBaseUnique { } }; +// only use in seek, this can not from stack memory int ObIJsonBase::add_if_missing(ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObJsonBaseCmp cmp; ObJsonBaseUnique unique; ObJsonBaseSortedVector::iterator pos = dup.end(); @@ -73,7 +76,7 @@ int ObIJsonBase::find_ellipsis(const JsonPathIterator &cur_node, bool only_need_one, ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); bool is_done = false; if (OB_FAIL(find_child(next_node, last_node, is_auto_wrap, only_need_one, dup, res))) { @@ -81,10 +84,6 @@ int ObIJsonBase::find_ellipsis(const JsonPathIterator &cur_node, } else if (json_type() == ObJsonNodeType::J_ARRAY) { uint64_t size = element_count(); ObIJsonBase *jb_ptr = NULL; - if (is_bin()) { - ObJsonBin j_bin(allocator_); - jb_ptr = &j_bin; - } for (uint32_t i = 0; i < size && !is_done; ++i) { jb_ptr = NULL; // reset jb_ptr to NULL ret = get_array_element(i, jb_ptr); @@ -125,7 +124,7 @@ int ObIJsonBase::find_array_range(const JsonPathIterator &next_node, bool only_need_one, ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); SMART_VAR (ObArrayRange, range) { if (OB_FAIL(path_node->get_array_range(element_count(), range))) { @@ -158,7 +157,7 @@ int ObIJsonBase::find_array_cell(const JsonPathIterator &next_node, bool only_need_one, ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); SMART_VAR (ObJsonArrayIndex, idx) { if (OB_FAIL(path_node->get_first_array_index(element_count(), idx))) { @@ -186,7 +185,7 @@ int ObIJsonBase::find_member_wildcard(const JsonPathIterator &next_node, bool only_need_one, ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); bool is_done = false; ObIJsonBase *jb_ptr = NULL; uint64_t count = element_count(); @@ -212,7 +211,7 @@ int ObIJsonBase::find_member(const JsonPathIterator &next_node, const JsonPathIt bool only_need_one, ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObString key_name(path_node->get_object().len_, path_node->get_object().object_name_); ObIJsonBase *jb_ptr = NULL; @@ -235,7 +234,7 @@ int ObIJsonBase::find_child(const JsonPathIterator &cur_node, const JsonPathIter bool is_auto_wrap, bool only_need_one, ObJsonBaseSortedVector &dup, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); // If the path expression is already at the end, the current DOM is the res, // and it is added to the res @@ -309,6 +308,8 @@ int ObIJsonBase::find_child(const JsonPathIterator &cur_node, const JsonPathIter } default: + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected json path type.", K(ret), K(path_node->get_node_type())); break; } } @@ -320,7 +321,7 @@ int ObIJsonBase::find_child(const JsonPathIterator &cur_node, const JsonPathIter int ObIJsonBase::seek(const ObJsonPath &path, uint32_t node_cnt, bool is_auto_wrap, bool only_need_one, ObJsonBaseVector &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); JsonPathIterator cur_node = path.begin(); JsonPathIterator last_node = path.begin() + node_cnt; ObJsonBaseSortedVector dup; @@ -334,7 +335,7 @@ int ObIJsonBase::seek(const ObJsonPath &path, uint32_t node_cnt, bool is_auto_wr int ObIJsonBase::print_jtime(ObJsonBuffer &j_buf, bool is_quoted) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (is_quoted) { if (OB_FAIL(j_buf.append("\""))) { @@ -374,7 +375,7 @@ int ObIJsonBase::print_jtime(ObJsonBuffer &j_buf, bool is_quoted) const int ObIJsonBase::print_array(ObJsonBuffer &j_buf, uint64_t depth, bool is_pretty) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_FAIL(j_buf.append("["))) { LOG_WARN("fail to append [", K(ret), K(depth), K(is_pretty)); @@ -387,8 +388,8 @@ int ObIJsonBase::print_array(ObJsonBuffer &j_buf, uint64_t depth, bool is_pretty LOG_WARN("fail to append newline and indent", K(ret), K(depth)); } else { ObIJsonBase *jb_ptr = NULL; + ObJsonBin j_bin(allocator_); if (is_bin()) { - ObJsonBin j_bin(allocator_); jb_ptr = &j_bin; } if (OB_FAIL(get_array_element(i, jb_ptr))) { @@ -414,7 +415,7 @@ int ObIJsonBase::print_array(ObJsonBuffer &j_buf, uint64_t depth, bool is_pretty int ObIJsonBase::print_object(ObJsonBuffer &j_buf, uint64_t depth, bool is_pretty) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_FAIL(j_buf.append("{"))) { LOG_WARN("fail to append '{' to buffer", K(ret)); @@ -439,8 +440,8 @@ int ObIJsonBase::print_object(ObJsonBuffer &j_buf, uint64_t depth, bool is_prett LOG_WARN("fail to append \" \"", K(ret), K(depth), K(i), K(key)); } else { ObIJsonBase *jb_ptr = NULL; + ObJsonBin j_bin(allocator_); if (is_bin()) { - ObJsonBin j_bin(allocator_); // TODO: stack overflow jb_ptr = &j_bin; } if (OB_FAIL(get_object_value(i, jb_ptr))) { @@ -467,7 +468,7 @@ int ObIJsonBase::print_object(ObJsonBuffer &j_buf, uint64_t depth, bool is_prett int ObIJsonBase::print_decimal(ObJsonBuffer &j_buf) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); int64_t pos = j_buf.length(); if (OB_FAIL(j_buf.reserve(number::ObNumber::MAX_PRINTABLE_SIZE))) { @@ -496,7 +497,7 @@ struct ObFindDoubleEscapeFunc { int ObIJsonBase::print_double(ObJsonBuffer &j_buf) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_FAIL(j_buf.reserve(DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE + 1))) { LOG_WARN("fail to reserve memory for j_buf", K(ret)); @@ -581,7 +582,7 @@ static const obmysql::EMySQLFieldType opaque_ob_type_to_mysql_type[ObMaxType] = int ObIJsonBase::print_opaque(ObJsonBuffer &j_buf, uint64_t depth, bool is_quoted) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const char *data = get_data(); uint64_t data_length = get_data_length(); ObObjType f_type = field_type(); @@ -638,7 +639,7 @@ int ObIJsonBase::print_opaque(ObJsonBuffer &j_buf, uint64_t depth, bool is_quote int ObIJsonBase::print(ObJsonBuffer &j_buf, bool is_quoted, bool is_pretty, uint64_t depth) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObJsonNodeType j_type = json_type(); // consistent with mysql 5.7 @@ -757,7 +758,7 @@ int ObIJsonBase::print(ObJsonBuffer &j_buf, bool is_quoted, bool is_pretty, uint int ObIJsonBase::calc_json_hash_value(uint64_t val, hash_algo hash_func, uint64_t &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObJsonHashValue hash_value(val, hash_func); ObJsonNodeType j_type = json_type(); @@ -767,8 +768,8 @@ int ObIJsonBase::calc_json_hash_value(uint64_t val, hash_algo hash_func, uint64_ uint64_t arr_res = 0; uint64_t size = element_count(); ObIJsonBase *jb_ptr = NULL; + ObJsonBin j_bin(allocator_); if (is_bin()) { - ObJsonBin j_bin(allocator_); jb_ptr = &j_bin; } for (uint64_t i = 0; i < size && OB_SUCC(ret); i++) { @@ -792,8 +793,8 @@ int ObIJsonBase::calc_json_hash_value(uint64_t val, hash_algo hash_func, uint64_ uint64_t count = element_count(); ObString key; ObIJsonBase *jb_ptr = NULL; + ObJsonBin j_bin(allocator_); if (is_bin()) { - ObJsonBin j_bin(allocator_); // TODO: stack overflow jb_ptr = &j_bin; } for (uint64_t i = 0; OB_SUCC(ret) && i < count; i++) { @@ -901,7 +902,7 @@ int ObIJsonBase::calc_json_hash_value(uint64_t val, hash_algo hash_func, uint64_ // a[0, 1, 2] vs b[0, 1, 2, 1, 1, 1, 1] ----> a < b int ObIJsonBase::compare_array(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -915,9 +916,9 @@ int ObIJsonBase::compare_array(const ObIJsonBase &other, int &res) const for (uint64_t i = 0; (res == 0) && OB_SUCC(ret) && i < min_size; i++) { ObIJsonBase *jb_a_ptr = NULL; ObIJsonBase *jb_b_ptr = NULL; + ObJsonBin j_bin_a(allocator_); + ObJsonBin j_bin_b(allocator_); if (is_bin()) { - ObJsonBin j_bin_a(allocator_); - ObJsonBin j_bin_b(allocator_); jb_a_ptr = &j_bin_a; jb_b_ptr = &j_bin_b; } @@ -944,7 +945,7 @@ int ObIJsonBase::compare_array(const ObIJsonBase &other, int &res) const // 3. Compare each key-value pair and return the result of the first unequal encounter. int ObIJsonBase::compare_object(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -967,9 +968,9 @@ int ObIJsonBase::compare_object(const ObIJsonBase &other, int &res) const if (res == 0) { ObIJsonBase *jb_a_ptr = NULL; ObIJsonBase *jb_b_ptr = NULL; + ObJsonBin j_bin_a(allocator_); + ObJsonBin j_bin_b(allocator_); if (is_bin()) { - ObJsonBin j_bin_a(allocator_); // TODO: stack overflow - ObJsonBin j_bin_b(allocator_); jb_a_ptr = &j_bin_a; jb_b_ptr = &j_bin_b; } @@ -991,7 +992,7 @@ int ObIJsonBase::compare_object(const ObIJsonBase &other, int &res) const int ObIJsonBase::compare_int(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -1046,7 +1047,7 @@ int ObIJsonBase::compare_int(const ObIJsonBase &other, int &res) const int ObIJsonBase::compare_uint(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -1101,7 +1102,7 @@ int ObIJsonBase::compare_uint(const ObIJsonBase &other, int &res) const int ObIJsonBase::compare_double(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -1156,7 +1157,7 @@ int ObIJsonBase::compare_double(const ObIJsonBase &other, int &res) const int ObIJsonBase::compare_decimal(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -1213,7 +1214,7 @@ int ObIJsonBase::compare_decimal(const ObIJsonBase &other, int &res) const int ObIJsonBase::compare_datetime(ObDTMode dt_mode_a, const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); @@ -1270,7 +1271,7 @@ static constexpr int type_comparison[JSON_TYPE_NUM][JSON_TYPE_NUM] = { int ObIJsonBase::compare(const ObIJsonBase &other, int &res) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonNodeType j_type_a = json_type(); const ObJsonNodeType j_type_b = other.json_type(); res = 0; @@ -1402,7 +1403,7 @@ int ObIJsonBase::compare(const ObIJsonBase &other, int &res) const uint32_t ObIJsonBase::depth() { - int ret = OB_SUCCESS; + INIT_SUCC(ret); uint32_t depth = 0; if (is_bin()) { @@ -1422,7 +1423,7 @@ uint32_t ObIJsonBase::depth() int ObIJsonBase::get_location(ObJsonBuffer &path) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (is_bin()) { ObArenaAllocator allocator; @@ -1443,7 +1444,7 @@ int ObIJsonBase::get_location(ObJsonBuffer &path) int ObIJsonBase::merge_tree(ObIAllocator *allocator, ObIJsonBase *other, ObIJsonBase *&result) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(allocator) || OB_ISNULL(other)) { ret = OB_INVALID_ARGUMENT; @@ -1478,7 +1479,7 @@ int ObIJsonBase::merge_tree(ObIAllocator *allocator, ObIJsonBase *other, ObIJson int ObIJsonBase::get_used_size(uint64_t &size) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (is_bin()) { const ObJsonBin *j_bin = static_cast(this); @@ -1498,7 +1499,7 @@ int ObIJsonBase::get_used_size(uint64_t &size) int ObIJsonBase::get_free_space(uint64_t &size) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (is_bin()) { const ObJsonBin *j_bin = static_cast(this); @@ -1520,7 +1521,7 @@ int ObIJsonBase::get_free_space(uint64_t &size) int ObIJsonBase::get_raw_binary(common::ObString &out, ObIAllocator *allocator) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (is_bin()) { const ObJsonBin *j_bin = static_cast(this); @@ -1551,7 +1552,7 @@ JsonObjectIterator ObIJsonBase::object_iterator() const int ObIJsonBase::to_int(int64_t &value, bool check_range, bool force_convert) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); int64_t val = 0; switch (json_type()) { @@ -1643,7 +1644,7 @@ int ObIJsonBase::to_int(int64_t &value, bool check_range, bool force_convert) co int ObIJsonBase::to_uint(uint64_t &value, bool fail_on_negative, bool check_range) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); uint64_t val = 0; switch (json_type()) { @@ -1739,6 +1740,7 @@ int ObIJsonBase::to_uint(uint64_t &value, bool fail_on_negative, bool check_rang double d = get_double(); if (d < 0 && fail_on_negative) { ret = OB_OPERATE_OVERFLOW; + LOG_WARN("double value is negative", K(ret), K(fail_on_negative), K(d)); } else { ret = ObJsonBaseUtil::double_to_uint(d, val, check_range); } @@ -1761,7 +1763,7 @@ int ObIJsonBase::to_uint(uint64_t &value, bool fail_on_negative, bool check_rang int ObIJsonBase::to_double(double &value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); double val = 0.0; switch (json_type()) { @@ -1809,13 +1811,10 @@ int ObIJsonBase::to_double(double &value) const if ((OB_ISNULL(data) || OB_ISNULL(endptr)) && data != endptr) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer(s)", K(ret), KP(data), KP(endptr)); - } else - // 2. data == endptr include NULL == NULL. - if (OB_UNLIKELY(data == endptr) || OB_UNLIKELY(EDOM == err)) { + } else if (OB_UNLIKELY(data == endptr) || OB_UNLIKELY(EDOM == err)) { // 2. data == endptr include NULL == NULL. ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; //1366 LOG_WARN("wrong value", K(ret), K(length), K(val)); - } else { - // 3. so here we are sure that both data and endptr are not NULL. + } else { // 3. so here we are sure that both data and endptr are not NULL. endptr += ObCharset::scan_str(endptr, data + length, OB_SEQ_SPACES); if (endptr < data + length) { ret = OB_ERR_DATA_TRUNCATED; //1265 @@ -1862,66 +1861,70 @@ int ObIJsonBase::to_double(double &value) const return ret; } -int ObIJsonBase::to_number(number::ObNumber &number) const +int ObIJsonBase::to_number(ObIAllocator *allocator, number::ObNumber &number) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); number::ObNumber num; - ObArenaAllocator allocator; - switch (json_type()) { - case ObJsonNodeType::J_DECIMAL: { - num = get_decimal_data(); - break; - } - - case ObJsonNodeType::J_STRING: { - uint64_t length = get_data_length(); - const char *data = get_data(); - if (OB_ISNULL(data)) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("data is null", K(ret)); - } else if (OB_FAIL(num.from(data, length, allocator))) { - LOG_WARN("fail to create number from string", K(ret), KP(data)); + if (OB_ISNULL(allocator)) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("allocator is null", K(ret)); + } else { + switch (json_type()) { + case ObJsonNodeType::J_DECIMAL: { + num = get_decimal_data(); + break; } - break; - } - case ObJsonNodeType::J_DOUBLE: { - double d = get_double(); - if (OB_FAIL(ObJsonBaseUtil::double_to_number(d, allocator, num))) { - LOG_WARN("fail to cast double to number", K(ret), K(d)); + case ObJsonNodeType::J_STRING: { + uint64_t length = get_data_length(); + const char *data = get_data(); + if (OB_ISNULL(data)) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("data is null", K(ret)); + } else if (OB_FAIL(num.from(data, length, *allocator))) { + LOG_WARN("fail to create number from string", K(ret), KP(data)); + } + break; } - break; - } - case ObJsonNodeType::J_INT: { - int64_t i = get_int(); - if (OB_FAIL(num.from(i, allocator))) { - LOG_WARN("fail to create number from int", K(ret), K(i)); + case ObJsonNodeType::J_DOUBLE: { + double d = get_double(); + if (OB_FAIL(ObJsonBaseUtil::double_to_number(d, *allocator, num))) { + LOG_WARN("fail to cast double to number", K(ret), K(d)); + } + break; } - break; - } - case ObJsonNodeType::J_UINT: { - uint64_t ui = get_uint(); - if (OB_FAIL(num.from(ui, allocator))) { - LOG_WARN("fail to number from uint", K(ret), K(ui)); + case ObJsonNodeType::J_INT: { + int64_t i = get_int(); + if (OB_FAIL(num.from(i, *allocator))) { + LOG_WARN("fail to create number from int", K(ret), K(i)); + } + break; } - break; - } - case ObJsonNodeType::J_BOOLEAN: { - bool b = get_boolean(); - if (OB_FAIL(num.from(static_cast(b), allocator))) { - LOG_WARN("fail to number from int(boolean)", K(ret), K(b)); + case ObJsonNodeType::J_UINT: { + uint64_t ui = get_uint(); + if (OB_FAIL(num.from(ui, *allocator))) { + LOG_WARN("fail to number from uint", K(ret), K(ui)); + } + break; + } + + case ObJsonNodeType::J_BOOLEAN: { + bool b = get_boolean(); + if (OB_FAIL(num.from(static_cast(b), *allocator))) { + LOG_WARN("fail to number from int(boolean)", K(ret), K(b)); + } + break; + } + + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to cast json type to double", K(ret), K(json_type())); + break; } - break; - } - - default: { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to cast json type to double", K(ret), K(json_type())); - break; } } @@ -1934,7 +1937,7 @@ int ObIJsonBase::to_number(number::ObNumber &number) const int ObIJsonBase::to_datetime(int64_t &value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); int64_t datetime; switch (json_type()) { @@ -1983,7 +1986,7 @@ int ObIJsonBase::to_datetime(int64_t &value) const int ObIJsonBase::to_date(int32_t &value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); int32_t date; switch (json_type()) { @@ -2030,7 +2033,7 @@ int ObIJsonBase::to_date(int32_t &value) const int ObIJsonBase::to_time(int64_t &value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); int64_t time; switch (json_type()) { @@ -2075,7 +2078,7 @@ int ObIJsonBase::to_time(int64_t &value) const int ObIJsonBase::to_bit(uint64_t &value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); uint64_t bit; const ObJsonNodeType j_type = json_type(); ObDTMode dt_mode = 0; @@ -2205,12 +2208,15 @@ int ObJsonBaseFactory::get_json_base(ObIAllocator *allocator, const char *ptr, u ObJsonInType in_type, ObJsonInType expect_type, ObIJsonBase *&out) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); void *buf = NULL; - if (OB_ISNULL(allocator) || OB_ISNULL(ptr)) { // check allocator + if (OB_ISNULL(allocator)) { // check allocator ret = OB_ERR_NULL_VALUE; LOG_WARN("param allocator is NULL", K(ret), KP(allocator), KP(ptr)); + } else if (OB_ISNULL(ptr) || length == 0) { + ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; + LOG_WARN("param is NULL", K(ret), KP(ptr), K(length)); } else if (in_type != ObJsonInType::JSON_TREE && in_type != ObJsonInType::JSON_BIN) { // check in_type ret = OB_ERR_UNEXPECTED; LOG_WARN("param in_type is invalid", K(ret), K(in_type)); @@ -2266,7 +2272,7 @@ int ObJsonBaseFactory::get_json_base(ObIAllocator *allocator, const char *ptr, u int ObJsonBaseFactory::transform(ObIAllocator *allocator, ObIJsonBase *src, ObJsonInType expect_type, ObIJsonBase *&out) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); void *buf = NULL; ObJsonInType src_type = src->get_internal_type(); @@ -2318,7 +2324,7 @@ int ObJsonBaseFactory::transform(ObIAllocator *allocator, ObIJsonBase *src, int ObJsonBaseUtil::get_dt_mode_by_json_type(ObJsonNodeType j_type, ObDTMode &dt_mode) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); switch (j_type) { case ObJsonNodeType::J_DATETIME: { @@ -2353,7 +2359,7 @@ int ObJsonBaseUtil::get_dt_mode_by_json_type(ObJsonNodeType j_type, ObDTMode &dt int ObJsonBaseUtil::append_comma(ObJsonBuffer &j_buf, bool is_pretty) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_FAIL(j_buf.append(","))) { LOG_WARN("fail to append \",\" to buffer", K(ret), K(is_pretty)); @@ -2369,7 +2375,7 @@ int ObJsonBaseUtil::append_comma(ObJsonBuffer &j_buf, bool is_pretty) int ObJsonBaseUtil::append_newline_and_indent(ObJsonBuffer &j_buf, uint64_t level) { // Append newline and two spaces per indentation level. - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (level > ObJsonParser::JSON_DOCUMENT_MAX_DEPTH) { ret = OB_ERR_JSON_OUT_OF_DEPTH; @@ -2391,7 +2397,7 @@ int ObJsonBaseUtil::append_newline_and_indent(ObJsonBuffer &j_buf, uint64_t leve int ObJsonBaseUtil::escape_character(char c, ObJsonBuffer &j_buf) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_FAIL(j_buf.append("\\"))) { LOG_WARN("fail to append \"\\\" to j_buf", K(ret), K(c)); @@ -2474,7 +2480,7 @@ struct ObFindEscapeFunc { int ObJsonBaseUtil::add_double_quote(ObJsonBuffer &j_buf, const char *cptr, uint64_t length) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(cptr)) { ret = OB_ERR_NULL_VALUE; @@ -2521,7 +2527,7 @@ int ObJsonBaseUtil::add_double_quote(ObJsonBuffer &j_buf, const char *cptr, uint int ObJsonBaseUtil::append_string(ObJsonBuffer &j_buf, bool is_quoted, const char *data, uint64_t length) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (is_quoted) { if (OB_FAIL(ObJsonBaseUtil::add_double_quote(j_buf, data, length))) { @@ -2551,7 +2557,7 @@ int ObJsonBaseUtil::compare_int_uint(int64_t a, uint64_t b) int ObJsonBaseUtil::compare_decimal_uint(const number::ObNumber &a, uint64_t b, int &res) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const bool a_is_zero = a.is_zero(); const bool a_is_negative = a.is_negative(); @@ -2583,7 +2589,7 @@ int ObJsonBaseUtil::compare_decimal_uint(const number::ObNumber &a, uint64_t b, int ObJsonBaseUtil::compare_decimal_int(const number::ObNumber &a, int64_t b, int &res) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const bool a_is_zero = a.is_zero(); const bool a_is_negative = a.is_negative(); @@ -2614,7 +2620,7 @@ int ObJsonBaseUtil::compare_decimal_int(const number::ObNumber &a, int64_t b, in int ObJsonBaseUtil::compare_decimal_double(const number::ObNumber &a, double b, int &res) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const bool a_is_zero = a.is_zero(); const bool a_is_negative = a.is_negative(); @@ -2648,7 +2654,7 @@ int ObJsonBaseUtil::compare_decimal_double(const number::ObNumber &a, double b, int ObJsonBaseUtil::compare_double_int(double a, int64_t b, int &res) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); double b_double = static_cast(b); if (a < b_double) { @@ -2678,9 +2684,21 @@ int ObJsonBaseUtil::compare_double_int(double a, int64_t b, int &res) return ret; } +int ObJsonBaseUtil::compare_int_json(int a, ObIJsonBase* other, int& result) +{ + INIT_SUCC(ret); + if (other->json_type() != ObJsonNodeType::J_INT) { + result = 1; + } else { + int64_t value = other->get_int(); + result = (a == value) ? 0 : (a > value ? 1 : -1); + } + return ret; +} + int ObJsonBaseUtil::compare_double_uint(double a, uint64_t b, int &res) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); double b_double = static_cast(b); if (a < b_double) { @@ -2713,7 +2731,7 @@ int ObJsonBaseUtil::compare_double_uint(double a, uint64_t b, int &res) template int ObJsonBaseUtil::double_to_number(double d, T &allocator, number::ObNumber &num) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE] = {0}; uint64_t length = ob_gcvt(d, ob_gcvt_arg_type::OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL); @@ -2731,7 +2749,7 @@ int ObJsonBaseUtil::double_to_number(double d, T &allocator, number::ObNumber &n int ObJsonBaseUtil::number_to_uint(number::ObNumber &nmb, uint64_t &value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); int64_t i = 0; uint64_t ui = 0; @@ -2756,7 +2774,7 @@ int ObJsonBaseUtil::number_to_uint(number::ObNumber &nmb, uint64_t &value) int ObJsonBaseUtil::double_to_uint(double d, uint64_t &value, bool check_range) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (d <= LLONG_MIN) { if (check_range) { @@ -2779,7 +2797,7 @@ int ObJsonBaseUtil::double_to_uint(double d, uint64_t &value, bool check_range) int ObJsonBaseUtil::get_bit_len(const ObString &str, int32_t &bit_len) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (str.empty()) { bit_len = 1; @@ -2819,7 +2837,7 @@ uint64_t ObJsonBaseUtil::hex_to_uint64(const ObString &str) int ObJsonBaseUtil::string_to_bit(ObString &str, uint64_t &value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); uint64_t bit; int32_t bit_len = 0; @@ -2870,7 +2888,7 @@ bool ObJsonBaseUtil::binary_search(ObSortedVector &vec, ObIJsonBa int ObJsonHashValue::calc_time(ObDTMode dt_mode, const ObIJsonBase *jb) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObTime time_val; if (OB_FAIL(jb->get_obtime(time_val))) { @@ -2892,7 +2910,7 @@ JsonObjectIterator::JsonObjectIterator(const ObIJsonBase *json_doc) } -bool JsonObjectIterator::empty() const +bool JsonObjectIterator::end() const { return curr_element_ >= element_count_; } 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 657216e933..f43c727a3a 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.h +++ b/deps/oblib/src/lib/json_type/ob_json_base.h @@ -72,7 +72,7 @@ public: explicit JsonObjectIterator(const ObIJsonBase *wrapper); ~JsonObjectIterator() {} - bool empty() const; + bool end() const; int get_elem(ObJsonObjPair &elem); int get_key(ObString &key); int get_value(ObIJsonBase *&value); @@ -282,7 +282,7 @@ public: int to_int(int64_t &value, bool check_range = false, bool force_convert = false) const; int to_uint(uint64_t &value, bool fail_on_negative = false, bool check_range = false) const; int to_double(double &value) const; - int to_number(number::ObNumber &number) const; + int to_number(ObIAllocator *allocator, number::ObNumber &number) const; int to_datetime(int64_t &value) const; int to_date(int32_t &value) const; int to_time(int64_t &value) const; @@ -630,6 +630,14 @@ public: // @return Returns OB_SUCCESS on success, error code otherwise. static int compare_double_int(double a, int64_t b, int &res); + // Compare int with json. + // + // @param [in] a The first value with double to be compared. + // @param [in] other The decond value with json type to be compared. + // @param [out] result Less than returns -1, greater than 1, equal returns 0. + // @return Returns OB_SUCCESS on success, error code otherwise. + static int compare_int_json(int a, ObIJsonBase* other, int& result); + // Compare double with uint. // // @param [in] a The first value with double to be compared. 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 300febe70f..c3ae3c9fa5 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_bin.cpp @@ -53,7 +53,7 @@ int ObJsonBin::get_obtime(ObTime &t) const return ret; } -int ObJsonBin::object_add(const common::ObString &key, ObIJsonBase *value) +int ObJsonBin::check_valid_object_op(ObIJsonBase *value) const { INIT_SUCC(ret); @@ -63,9 +63,68 @@ int ObJsonBin::object_add(const common::ObString &key, ObIJsonBase *value) } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type ret = OB_INVALID_ARGUMENT; LOG_WARN("unexpected json type", K(ret), K(json_type())); - } else if (is_tree() || value->is_tree()) { + } else if (value->is_tree()) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("not support json tree", K(ret), K(is_bin()), K(value->is_bin())); + LOG_WARN("value is json tree, not supported", K(ret), K(*value)); + } + + return ret; +} + +int ObJsonBin::check_valid_array_op(ObIJsonBase *value) const +{ + INIT_SUCC(ret); + + if (OB_ISNULL(value)) { // check param + ret = OB_INVALID_ARGUMENT; + LOG_WARN("param value is NULL", K(ret)); + } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected json type", K(ret), K(json_type())); + } else if (value->is_tree()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("value is json tree, not supported", K(ret), K(*value)); + } + + return ret; +} + +int ObJsonBin::check_valid_object_op(uint64_t index) const +{ + INIT_SUCC(ret); + + if (index >= element_count()) { // check param + ret = OB_OUT_OF_ELEMENT; + LOG_WARN("index is out of range in object", K(ret), K(index), K(element_count())); + } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid json node type", K(ret), K(json_type())); + } + + return ret; +} + +int ObJsonBin::check_valid_array_op(uint64_t index) const +{ + INIT_SUCC(ret); + + if (index >= element_count()) { // check param + ret = OB_OUT_OF_ELEMENT; + LOG_WARN("index is out of range in array", K(ret), K(index), K(element_count())); + } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid json node type", K(ret), K(json_type())); + } + + return ret; +} + +int ObJsonBin::object_add(const common::ObString &key, ObIJsonBase *value) +{ + INIT_SUCC(ret); + + if (OB_FAIL(check_valid_object_op(value))) { + LOG_WARN("invalid json object operation", K(ret), K(key)); } else { ObJsonBin *j_bin = static_cast(this); if (OB_FAIL(j_bin->add(key, static_cast(value)))) { @@ -80,15 +139,8 @@ int ObJsonBin::array_insert(uint64_t index, ObIJsonBase *value) { INIT_SUCC(ret); - if (OB_ISNULL(value)) { // check param - ret = OB_INVALID_ARGUMENT; - LOG_WARN("param value is NULL", K(ret)); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected json type", K(ret), K(json_type())); - } else if (is_tree() || value->is_tree()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("not support json tree", K(ret), K(is_bin()), K(value->is_bin())); + if (OB_FAIL(check_valid_array_op(value))) { + LOG_WARN("invalid json array operation", K(ret), K(index)); } else { ObJsonBin *j_bin = static_cast(this); if (OB_FAIL(j_bin->insert(static_cast(value), index))) { @@ -103,15 +155,8 @@ int ObJsonBin::array_append(ObIJsonBase *value) { INIT_SUCC(ret); - if (OB_ISNULL(value)) { // check param - ret = OB_INVALID_ARGUMENT; - LOG_WARN("param value is NULL", K(ret)); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected json type", K(ret), K(json_type())); - } else if (is_tree() || value->is_tree()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("not support json tree", K(ret), K(is_bin()), K(value->is_bin())); + if (OB_FAIL(check_valid_array_op(value))) { + LOG_WARN("invalid json array operation", K(ret)); } else { ObJsonBin *j_bin = static_cast(this); if (OB_FAIL(j_bin->append(static_cast(value)))) { @@ -186,12 +231,8 @@ int ObJsonBin::array_remove(uint64_t index) { INIT_SUCC(ret); - if (index >= element_count()) { // check param - ret = OB_ERR_WRONG_VALUE; - LOG_WARN("invalid input value", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_array_op(index))) { + LOG_WARN("invalid json array operation", K(ret), K(index)); } else { if (OB_FAIL(remove(index))) { LOG_WARN("fail to remove value in array", K(ret), K(index)); @@ -216,12 +257,8 @@ int ObJsonBin::get_key(uint64_t index, common::ObString &key_out) const { INIT_SUCC(ret); - if (index >= element_count()) { // check param - ret = OB_OUT_OF_ELEMENT; - LOG_WARN("index out of range", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_object_op(index))) { + LOG_WARN("invalid json object operation", K(ret), K(index)); } else { if (OB_FAIL(get_key_in_object(index, key_out))) { LOG_WARN("fail to get object key", K(ret), K(index)); @@ -231,97 +268,73 @@ int ObJsonBin::get_key(uint64_t index, common::ObString &key_out) const return ret; } -int ObJsonBin::get_array_element(uint64_t index, ObIJsonBase *&value) const +int ObJsonBin::create_new_binary(ObIJsonBase *&value, ObJsonBin *&new_bin) const { INIT_SUCC(ret); ObString sub; - if (index >= element_count()) { // check param - ret = OB_ERR_WRONG_VALUE; - LOG_WARN("invalid input value", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret)); - } else { - common::ObIAllocator *allocator = NULL; - void *buf = NULL; - if (value != NULL) { // use stack memory - buf = value; - allocator = value->get_allocator(); - } else if (OB_ISNULL(allocator_)) { // check allocator_ - ret = OB_ERR_NULL_VALUE; - LOG_WARN("json bin allocator is null", K(ret)); - } else { // use allocator_ - allocator = allocator_; - buf = allocator->alloc(sizeof(ObJsonBin)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("alloc json bin fail", K(ret), K(sizeof(ObJsonBin))); - } - } + common::ObIAllocator *allocator = NULL; + void *buf = NULL; + if (value != NULL) { // use stack memory + buf = value; + allocator = value->get_allocator(); + } else if (OB_ISNULL(allocator_)) { // check allocator_ + ret = OB_ERR_NULL_VALUE; + LOG_WARN("json bin allocator is null", K(ret)); + } else { // use allocator_ + allocator = allocator_; + buf = allocator->alloc(sizeof(ObJsonBin)); + if (OB_ISNULL(buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc json bin fail", K(ret), K(sizeof(ObJsonBin))); + } + } - if (OB_SUCC(ret)) { - if (OB_FAIL(raw_binary_at_iter(sub))) { - LOG_WARN("fail to get sub json binary.", K(ret), K(index)); - } else { - ObJsonBin *j_bin = new (buf) ObJsonBin(sub.ptr(), sub.length(), allocator); - if (OB_FAIL(j_bin->reset_iter())) { - LOG_WARN("fail to reset iter for new json bin", K(ret)); - } else if (OB_FAIL(j_bin->element(index))) { - LOG_WARN("fail to access index node for new json bin.", K(ret), K(index)); - } else { - value = j_bin; - } - } + if (OB_SUCC(ret)) { + if (OB_FAIL(raw_binary_at_iter(sub))) { + LOG_WARN("fail to get sub json binary.", K(ret)); + } else { + new_bin = new (buf) ObJsonBin(sub.ptr(), sub.length(), allocator); + if (OB_FAIL(new_bin->reset_iter())) { + LOG_WARN("fail to reset iter for new json bin", K(ret)); + } } } return ret; } +int ObJsonBin::get_array_element(uint64_t index, ObIJsonBase *&value) const +{ + INIT_SUCC(ret); + ObJsonBin *new_bin = NULL; + + if (OB_FAIL(check_valid_array_op(index))) { + LOG_WARN("invalid json array operation", K(ret), K(index)); + } else if (OB_FAIL(create_new_binary(value, new_bin))) { + LOG_WARN("fail to create sub binary", K(ret), K(index)); + } else if (OB_FAIL(new_bin->element(index))) { + LOG_WARN("fail to access index node for new json bin.", K(ret), K(index)); + } else { + value = new_bin; + } + + return ret; +} + int ObJsonBin::get_object_value(uint64_t index, ObIJsonBase *&value) const { INIT_SUCC(ret); - ObString sub; + ObJsonBin *new_bin = NULL; - if (index >= element_count()) { // check param, value can not be null in binary - ret = OB_ERR_WRONG_VALUE; - LOG_WARN("invalid input value", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_object_op(index))) { + LOG_WARN("invalid json object operation", K(ret), K(index)); + } else if (OB_FAIL(create_new_binary(value, new_bin))) { + LOG_WARN("fail to create sub binary", K(ret), K(index)); + } else if (OB_FAIL(new_bin->element(index))) { + LOG_WARN("fail to access index node for new json bin.", K(ret), K(index)); } else { - common::ObIAllocator *allocator = NULL; - void *buf = NULL; - if (value != NULL) { // use stack memory - buf = value; - allocator = value->get_allocator(); - } else if (OB_ISNULL(allocator_)) { // check allocator_ - ret = OB_ERR_NULL_VALUE; - LOG_WARN("json bin allocator is null", K(ret)); - } else { // use allocator_ - allocator = allocator_; - buf = allocator->alloc(sizeof(ObJsonBin)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("alloc json bin fail", K(ret), K(sizeof(ObJsonBin))); - } - } - - if (OB_SUCC(ret)) { - if (OB_FAIL(raw_binary_at_iter(sub))) { - LOG_WARN("fail to get sub json binary.", K(ret), K(index)); - } else { - ObJsonBin *j_bin = new (buf) ObJsonBin(sub.ptr(), sub.length(), allocator); - if (OB_FAIL(j_bin->reset_iter())) { - LOG_WARN("fail to reset iter for new json bin", K(ret)); - } else if (OB_FAIL(j_bin->element(index))) { - LOG_WARN("fail to access index node for new json bin.", K(ret), K(index)); - } else { - value = j_bin; - } - } - } + value = new_bin; } return ret; @@ -330,47 +343,20 @@ int ObJsonBin::get_object_value(uint64_t index, ObIJsonBase *&value) const int ObJsonBin::get_object_value(const ObString &key, ObIJsonBase *&value) const { INIT_SUCC(ret); - ObString sub; + ObJsonBin *new_bin = NULL; if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid json node type", K(ret)); + } else if (OB_FAIL(create_new_binary(value, new_bin))) { + LOG_WARN("fail to create sub binary", K(ret), K(key)); } else { - common::ObIAllocator *allocator = NULL; - void *buf = NULL; - if (value != NULL) { // use stack memory - buf = value; - allocator = value->get_allocator(); - } else if (OB_ISNULL(allocator_)) { // check allocator_ - ret = OB_ERR_NULL_VALUE; - LOG_WARN("json bin allocator is null", K(ret)); - } else { // use allocator_ - allocator = allocator_; - buf = allocator->alloc(sizeof(ObJsonBin)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("alloc json bin fail", K(ret), K(sizeof(ObJsonBin))); - } - } - + ret = new_bin->lookup(key); if (OB_SUCC(ret)) { - if (OB_FAIL(raw_binary_at_iter(sub))) { - LOG_WARN("fail to get sub json binary.", K(ret), K(key)); - } else { - ObJsonBin *j_bin = new (buf) ObJsonBin(sub.ptr(), sub.length(), allocator); - if (OB_FAIL(j_bin->reset_iter())) { - LOG_WARN("fail to reset iter for new json bin", K(ret)); - } else { - ret = j_bin->lookup(key); - if (OB_SUCC(ret)) { - value = j_bin; - } else if (ret == OB_SEARCH_NOT_FOUND) { - LOG_INFO("fail to look up object value", K(ret), K(key)); - } else { - LOG_WARN("fail to access key node for new jsonbin.", K(ret), K(key)); - } - } - } + value = new_bin; + } else if (ret == OB_SEARCH_NOT_FOUND) { + } else { + LOG_WARN("fail to access key node for new jsonbin.", K(ret), K(key)); } } @@ -664,7 +650,10 @@ int ObJsonBin::serialize_json_value(ObJsonNode *json_tree, ObJsonBuffer &result) case ObJsonNodeType::J_DOUBLE: { const ObJsonDouble *d = static_cast(json_tree); double value = d->value(); - if (OB_FAIL(result.append(reinterpret_cast(&value), sizeof(double)))) { + if (isnan(value) || isinf(value)) { + ret = OB_INVALID_NUMERIC; + LOG_WARN("invalid double value", K(ret), K(value)); + } else if (OB_FAIL(result.append(reinterpret_cast(&value), sizeof(double)))) { LOG_WARN("failed to append double json obj", K(ret)); } break; @@ -1443,6 +1432,148 @@ int ObJsonBin::raw_binary(ObString &buf) const return ret; } +int ObJsonBin::get_max_offset(const char* data, ObJsonNodeType cur_node, uint64_t& max_offset) const +{ + INIT_SUCC(ret); + uint8_t cur_node_type = static_cast(cur_node); + if (OB_JSON_TYPE_IS_INLINE(cur_node_type)) { + max_offset = 1; + } else if (!(cur_node == ObJsonNodeType::J_OBJECT || cur_node == ObJsonNodeType::J_ARRAY)) { + if (cur_node == ObJsonNodeType::J_STRING || cur_node == ObJsonNodeType::J_OPAQUE) { + int64_t decode_pos = 1; + int64_t val = 0; + if (OB_FAIL(serialization::decode_vi64(data, curr_.length() - (data - curr_.ptr()), decode_pos, &val))) { + LOG_WARN("decode slength failed.", K(ret)); + } else { + max_offset = decode_pos; + max_offset += val; + } + } else if (cur_node == ObJsonNodeType::J_TIME || cur_node == ObJsonNodeType::J_TIMESTAMP || + cur_node == ObJsonNodeType::J_DATETIME || cur_node == ObJsonNodeType::J_DATE) { + if (cur_node == ObJsonNodeType::J_TIME || cur_node == ObJsonNodeType::J_DATE) { + max_offset = sizeof(int32_t); + } else { + max_offset = sizeof(uint64_t); + } + } else if (cur_node == ObJsonNodeType::J_DECIMAL) { + ObPrecision prec = -1; + ObScale scale = -1; + int64_t pos = 0; + number::ObNumber number; + if (OB_FAIL(serialization::decode_i16(data, curr_.length() - (data - curr_.ptr()), pos, &prec))) { + LOG_WARN("fail to deserialize decimal precision.", K(ret), K(data - curr_.ptr()), K(curr_.length())); + } else if (serialization::decode_i16(data, curr_.length() - (data - curr_.ptr()), pos, &scale)) { + LOG_WARN("fail to deserialize decimal scale.", K(ret), K(data - curr_.ptr()), K(curr_.length())); + } else if (OB_FAIL(number.deserialize(data, curr_.length() - (data - curr_.ptr()), pos))) { + LOG_WARN("failed to deserialize decimal data", K(ret)); + } else { + max_offset = pos; + } + } else if (cur_node == ObJsonNodeType::J_INT || cur_node == ObJsonNodeType::J_UINT) { + int64_t val = 0; + int64_t pos = 0; + if (OB_FAIL(serialization::decode_vi64(data, curr_.length() - (data - curr_.ptr()), pos, &val))) { + LOG_WARN("decode int val failed.", K(ret)); + } else { + max_offset = pos; + } + } else if (cur_node == ObJsonNodeType::J_DOUBLE) { + max_offset = sizeof(double); + } else if (cur_node == ObJsonNodeType::J_NULL || cur_node == ObJsonNodeType::J_BOOLEAN) { + max_offset = 1; + } else { + ret = OB_ERR_INTERVAL_INVALID; + LOG_WARN("get length failed.", K(ret), K(cur_node)); + } + } else { + uint8_t node_type, type, obj_size_type; + uint64_t count, obj_size, offset = 0; + parse_obj_header(data, offset, node_type, type, obj_size_type, count, obj_size); + ObJsonNodeType cur_node = ObJsonVerType::get_json_type(static_cast(node_type)); + + uint64_t val_offset, val_len, max_val_offset = offset; + uint8_t entry_size = ObJsonVar::get_var_size(type); + uint8_t max_offset_type; + bool is_first_uninline = true; + bool is_continuous = (reinterpret_cast(data))->is_continuous_; + + for (int64_t i = count - 1; OB_SUCC(ret) && i >= 0 && is_first_uninline; --i) { + val_offset = offset + (entry_size + sizeof(uint8_t)) * i; + if (cur_node == ObJsonNodeType::J_OBJECT) { + val_offset += count * (entry_size * 2); + } + const char* val_offset_ptr = data + val_offset; + uint64_t node_offset; + + node_type = static_cast(*static_cast(val_offset_ptr + entry_size)); + if (OB_JSON_TYPE_IS_INLINE(node_type)) { + if (max_val_offset < val_offset_ptr + 1 - data) { + max_val_offset = val_offset_ptr + 1 - data; + max_offset_type = node_type; + } + } else if (OB_FAIL(ObJsonVar::read_var(val_offset_ptr, type, &node_offset))) { + LOG_WARN("get max offset failed.", K(ret), K(type)); + } else if (max_val_offset < node_offset) { + max_val_offset = node_offset; + max_offset_type = node_type; + if (is_continuous) { + is_first_uninline = false; + } + } + } + + if (OB_SUCC(ret) && max_val_offset > offset) { + uint64_t node_max_offset = 0; + if (!OB_JSON_TYPE_IS_INLINE(node_type) && + OB_FAIL(get_max_offset(data + max_val_offset, static_cast(max_offset_type), node_max_offset))) { + LOG_WARN("get max offset failed.", K(ret), K(cur_node)); + } else { + max_val_offset += node_max_offset; + } + + if (max_val_offset < obj_size) { + max_offset = obj_size; + } else { + max_offset = max_val_offset; + } + } + } + + return ret; +} + +int ObJsonBin::get_use_size(uint64_t& real_size, uint64_t& used_size) const +{ + INIT_SUCC(ret); + int32_t stk_len = stack_size(stack_buf_); + uint8_t node_type, type, obj_size_type; + uint64_t count, obj_size, offset = 0; + const char* data = curr_.ptr() + pos_; + parse_obj_header(data, offset, node_type, type, obj_size_type, count, obj_size); + ObJsonNodeType cur_node = ObJsonVerType::get_json_type(static_cast(node_type)); + if (stk_len == 0) { + if (!(cur_node == ObJsonNodeType::J_ARRAY || cur_node == ObJsonNodeType::J_OBJECT)) { + real_size = obj_size; + } else { + real_size = curr_.length(); + } + used_size = curr_.length(); + } else { + uint64_t max_offset = 0; + if (OB_FAIL(get_max_offset(data, cur_node, max_offset))) { + LOG_WARN("get max offset.", K(ret)); + } else { + real_size = obj_size; + used_size = max_offset; + if (curr_.length() - pos_ < used_size) { + used_size = curr_.length() - pos_; + } + } + } + + return ret; +} + int ObJsonBin::raw_binary(ObString &buf, ObIAllocator *allocator) const { INIT_SUCC(ret); @@ -1497,14 +1628,17 @@ int ObJsonBin::raw_binary(ObString &buf, ObIAllocator *allocator) const int ObJsonBin::raw_binary_at_iter(ObString &buf) const { INIT_SUCC(ret); + uint64_t used_size = 0, real_size = 0; if (OB_ISNULL(curr_.ptr())) { ret = OB_ERR_NULL_VALUE; LOG_WARN("json binary ptr is null.", K(ret)); } else if (pos_ >= curr_.length()) { ret = OB_ERROR_OUT_OF_RANGE; LOG_WARN("json binary iter pos invalid", K(ret), K(pos_), K(curr_.length())); + } else if (OB_FAIL(get_use_size(real_size, used_size))) { + LOG_WARN("get use size failed", K(ret)); } else { - buf.assign_ptr(curr_.ptr() + pos_, curr_.length() - pos_); + buf.assign_ptr(curr_.ptr() + pos_, used_size); } return ret; } @@ -1654,6 +1788,7 @@ int ObJsonBin::set_curr_by_type(int64_t new_pos, uint64_t val_offset, uint8_t ty INIT_SUCC(ret); char *ptr = curr_.ptr(); data_ = ptr + new_pos; + element_count_ = 1; // scalar is 1, container is acutual k-v pairs number bool is_inlined = OB_JSON_TYPE_IS_INLINE(type); if (!is_inlined && new_pos >= curr_.length()) { ret = OB_ERR_INTERVAL_INVALID; @@ -1942,7 +2077,9 @@ int ObJsonBin::lookup(const ObString &key) LOG_WARN("wrong node_type.", K(ret), K(node_type)); } else { size_t idx = 0; - if (OB_FAIL(lookup_index(key, &idx))) { + ret = lookup_index(key, &idx); + if (ret == OB_SEARCH_NOT_FOUND) { + } else if (OB_FAIL(ret)) { LOG_WARN("look up child node failed.", K(ret), K(key)); } else if (OB_FAIL(element(idx))) { LOG_WARN("move iter to child node failed.", K(ret), K(key), K(idx)); @@ -3764,7 +3901,7 @@ void ObJsonBin::stack_update(ObJsonBuffer& stack, uint32_t idx, const ObJBNodeMe *node = new_value; } -int32_t ObJsonBin::stack_size(ObJsonBuffer& stack) +int32_t ObJsonBin::stack_size(const ObJsonBuffer& stack) const { return stack.length() / JB_PATH_NODE_LEN; } 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 a311d151f9..1d0797ab9d 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.h +++ b/deps/oblib/src/lib/json_type/ob_json_bin.h @@ -170,6 +170,8 @@ public: int get_object_value(const ObString &key, ObIJsonBase *&value) const override; int get_key(uint64_t index, common::ObString &key_out) const override; int get_raw_binary(common::ObString &out, ObIAllocator *allocator = NULL) const; + int get_use_size(uint64_t& obj_size, uint64_t& used_size) const; + int get_max_offset(const char* data, ObJsonNodeType cur_node, uint64_t& max_offset) const ; int array_remove(uint64_t index) override; int object_remove(const common::ObString &key) override; int replace(const ObIJsonBase *old_node, ObIJsonBase *new_node) override; @@ -465,9 +467,14 @@ private: int stack_pop(ObJsonBuffer& stack); int stack_push(ObJsonBuffer& stack, const ObJBNodeMeta& node); int stack_at(ObJsonBuffer& stack, uint32_t idx, ObJBNodeMeta& node); - int32_t stack_size(ObJsonBuffer& stack); + int32_t stack_size(const ObJsonBuffer& stack) const; void stack_reset(ObJsonBuffer& stack); int stack_back(ObJsonBuffer& stack, ObJBNodeMeta& node, bool is_pop = false); + int check_valid_object_op(ObIJsonBase *value) const; + int check_valid_array_op(ObIJsonBase *value) const; + int check_valid_object_op(uint64_t index) const; + int check_valid_array_op(uint64_t index) const; + int create_new_binary(ObIJsonBase *&value, ObJsonBin *&new_bin) const; /* data */ private: common::ObIAllocator *allocator_; diff --git a/deps/oblib/src/lib/json_type/ob_json_parse.cpp b/deps/oblib/src/lib/json_type/ob_json_parse.cpp index b5216e8ba4..195db66cba 100644 --- a/deps/oblib/src/lib/json_type/ob_json_parse.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_parse.cpp @@ -19,7 +19,7 @@ namespace common { int ObJsonParser::get_tree(ObIAllocator *allocator, const ObString &text, ObJsonNode *&j_tree) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); char buf[PARSE_SYNTAXERR_MESSAGE_LENGTH] = {0}; const char *syntaxerr = buf; uint64_t offset = 0; @@ -34,7 +34,7 @@ int ObJsonParser::get_tree(ObIAllocator *allocator, const ObString &text, ObJson int ObJsonParser::get_tree(ObIAllocator *allocator, const char *text, uint64_t length, ObJsonNode *&j_tree) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); char buf[PARSE_SYNTAXERR_MESSAGE_LENGTH] = {0}; const char *syntaxerr = buf; uint64_t offset = 0; @@ -55,7 +55,7 @@ int ObJsonParser::parse_json_text(ObIAllocator *allocator, const char *&syntaxerr, uint64_t *offset, ObJsonNode *&j_tree) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); char *buf = NULL; if (OB_ISNULL(allocator) || OB_ISNULL(text) || length == 0) { @@ -110,7 +110,7 @@ bool ObJsonParser::is_json_doc_over_depth(uint64_t depth) int ObJsonParser::check_json_syntax(const ObString &j_doc, ObIAllocator *allocator) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); char syntax_buf[PARSE_SYNTAXERR_MESSAGE_LENGTH] = {0}; const char *syntaxerr = syntax_buf; uint64_t offset = 0; @@ -166,7 +166,7 @@ bool ObRapidJsonHandler::seeing_value(ObJsonNode *value) } case ObJsonExpectNextState::EXPECT_ARRAY_VALUE: { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObJsonArray *array = dynamic_cast(current_element_); if (OB_FAIL(array->append(value))) { LOG_WARN("fail to append element to json array", K(ret)); @@ -176,7 +176,7 @@ bool ObRapidJsonHandler::seeing_value(ObJsonNode *value) } case ObJsonExpectNextState::EXPECT_OBJECT_VALUE: { - int ret = OB_SUCCESS; + INIT_SUCC(ret); next_state_ = ObJsonExpectNextState::EXPECT_OBJECT_KEY; ObJsonObject *object = dynamic_cast(current_element_); if (OB_FAIL(object->add(key_, value))) { 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 2bd9d8af19..0666096369 100644 --- a/deps/oblib/src/lib/json_type/ob_json_path.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_path.cpp @@ -1299,17 +1299,41 @@ void ObJsonPathUtil::skip_whitespace(const ObString &path, uint64_t& idx) static constexpr unsigned UNICODE_COMBINING_MARK_MIN = 0x300; static constexpr unsigned UNICODE_COMBINING_MARK_MAX = 0x36F; +static constexpr unsigned UNICODE_EXTEND_MARK_MIN = 0x2E80; +static constexpr unsigned UNICODE_EXTEND_MARK_MAX = 0x9fff; + static inline bool unicode_combining_mark(unsigned codepoint) { return ((UNICODE_COMBINING_MARK_MIN <= codepoint) && (codepoint <= UNICODE_COMBINING_MARK_MAX)); } -static bool is_letter(unsigned codepoint) { +static bool is_utf8_unicode_charator(const char* ori, uint64_t& start, int64_t len) +{ + bool ret_bool = false; + int ret = OB_SUCCESS; + int32_t well_formed_error = 0; + int64_t well_formed_len = 0; + if (OB_FAIL(ObCharset::well_formed_len(CS_TYPE_UTF8MB4_BIN, ori + start, len, well_formed_len, well_formed_error))) { + ret_bool = false; + } else { + ret_bool = true; + } + + return ret_bool; +} + +static bool is_letter(unsigned codepoint, const char* ori, uint64_t start, uint64_t end) { bool ret_bool = true; if (unicode_combining_mark(codepoint)) { ret_bool = false; } ret_bool = isalpha(codepoint); - + if (ret_bool) { + } else if (!ret_bool && + (codepoint >= UNICODE_EXTEND_MARK_MIN && + codepoint <= UNICODE_EXTEND_MARK_MAX && + is_utf8_unicode_charator(ori, start, end - start))) { + ret_bool = true; + } return ret_bool; } @@ -1350,9 +1374,10 @@ bool ObJsonPathUtil::is_ecmascript_identifier(const char* name, uint64_t length) */ rapidjson::MemoryStream input_stream(name, length); unsigned codepoint = 0; - + uint64_t last_pos = 0; while (ret_bool && (input_stream.Tell() < length)) { - bool first_codepoint = (input_stream.Tell() == 0); + last_pos = input_stream.Tell(); + bool first_codepoint = (last_pos == 0); if (!rapidjson::UTF8::Decode(input_stream, &codepoint)) { ret_bool = false; LOG_WARN("fail to decode.", @@ -1361,7 +1386,8 @@ bool ObJsonPathUtil::is_ecmascript_identifier(const char* name, uint64_t length) } // a unicode letter - if (is_letter(codepoint)) continue; + uint64_t curr_pos = input_stream.Tell(); + if (is_letter(codepoint, name, last_pos, curr_pos - last_pos)) continue; // $ is ok if (codepoint == 0x24) continue; // _ is ok @@ -1399,7 +1425,6 @@ bool ObJsonPathUtil::is_ecmascript_identifier(const char* name, uint64_t length) return ret_bool; } - int ObJsonPathUtil::string_cmp_skip_charactor(ObString& lhs, ObString& rhs, char ch) { int res = 0; int i = 0, j = 0; diff --git a/deps/oblib/src/lib/json_type/ob_json_tree.cpp b/deps/oblib/src/lib/json_type/ob_json_tree.cpp index 67b6a4a4f4..7d7e18b376 100644 --- a/deps/oblib/src/lib/json_type/ob_json_tree.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_tree.cpp @@ -90,9 +90,10 @@ int ObJsonNode::get_obtime(ObTime &t) const return OB_SUCCESS; // adapt json binary, so return OB_SUCCESS directly. } -int ObJsonNode::object_add(const common::ObString &key, ObIJsonBase *value) + +int ObJsonNode::check_valid_object_op(ObIJsonBase *value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(value)) { // check param ret = OB_INVALID_ARGUMENT; @@ -100,9 +101,68 @@ int ObJsonNode::object_add(const common::ObString &key, ObIJsonBase *value) } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type ret = OB_INVALID_ARGUMENT; LOG_WARN("unexpected json type", K(ret), K(json_type())); - } else if (is_bin() || value->is_bin()) { + } else if (value->is_bin()) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("not support json binary", K(ret), K(is_bin()), K(value->is_bin())); + LOG_WARN("value is json bin, not supported", K(ret), K(*value)); + } + + return ret; +} + +int ObJsonNode::check_valid_array_op(ObIJsonBase *value) const +{ + INIT_SUCC(ret); + + if (OB_ISNULL(value)) { // check param + ret = OB_INVALID_ARGUMENT; + LOG_WARN("param value is NULL", K(ret)); + } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected json type", K(ret), K(json_type())); + } else if (value->is_bin()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("value is json bin, not supported", K(ret), K(*value)); + } + + return ret; +} + +int ObJsonNode::check_valid_object_op(uint64_t index) const +{ + INIT_SUCC(ret); + + if (index >= element_count()) { // check param + ret = OB_OUT_OF_ELEMENT; + LOG_WARN("index is out of range in object", K(ret), K(index), K(element_count())); + } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid json node type", K(ret), K(json_type())); + } + + return ret; +} + +int ObJsonNode::check_valid_array_op(uint64_t index) const +{ + INIT_SUCC(ret); + + if (index >= element_count()) { // check param + ret = OB_OUT_OF_ELEMENT; + LOG_WARN("index is out of range in array", K(ret), K(index), K(element_count())); + } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid json node type", K(ret), K(json_type())); + } + + return ret; +} + +int ObJsonNode::object_add(const common::ObString &key, ObIJsonBase *value) +{ + INIT_SUCC(ret); + + if (OB_FAIL(check_valid_object_op(value))) { + LOG_WARN("invalid json object operation", K(ret), K(key)); } else { ObJsonObject *j_obj = static_cast(this); if (OB_FAIL(j_obj->add(key, static_cast(value)))) { @@ -115,17 +175,10 @@ int ObJsonNode::object_add(const common::ObString &key, ObIJsonBase *value) int ObJsonNode::array_insert(uint64_t index, ObIJsonBase *value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); - if (OB_ISNULL(value)) { // check param - ret = OB_INVALID_ARGUMENT; - LOG_WARN("param value is NULL", K(ret)); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected json type", K(ret), K(json_type())); - } else if (is_bin() || value->is_bin()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("not support json binary", K(ret), K(is_bin()), K(value->is_bin())); + if (OB_FAIL(check_valid_array_op(value))) { + LOG_WARN("invalid json array operation", K(ret), K(index)); } else { ObJsonArray *j_arr = static_cast(this); if (OB_FAIL(j_arr->insert(index, static_cast(value)))) { @@ -138,17 +191,10 @@ int ObJsonNode::array_insert(uint64_t index, ObIJsonBase *value) int ObJsonNode::array_append(ObIJsonBase *value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); - if (OB_ISNULL(value)) { // check param - ret = OB_INVALID_ARGUMENT; - LOG_WARN("param value is NULL", K(ret)); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("unexpected json type", K(ret), K(json_type())); - } else if (is_bin() || value->is_bin()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("not support json binary", K(ret), K(is_bin()), K(value->is_bin())); + if (OB_FAIL(check_valid_array_op(value))) { + LOG_WARN("invalid json array operation", K(ret)); } else { ObJsonArray *j_arr = static_cast(this); if (OB_FAIL(j_arr->append(static_cast(value)))) { @@ -161,7 +207,7 @@ int ObJsonNode::array_append(ObIJsonBase *value) int ObJsonNode::merge_tree(ObIAllocator *allocator, ObIJsonBase *other, ObIJsonBase *&result) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(allocator) || OB_ISNULL(other)) { ret = OB_INVALID_ARGUMENT; @@ -218,7 +264,7 @@ int ObJsonNode::merge_tree(ObIAllocator *allocator, ObIJsonBase *other, ObIJsonB int ObJsonNode::get_location(ObJsonBuffer &path) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(parent_)) { ret = path.append("$"); @@ -260,7 +306,7 @@ int ObJsonNode::get_location(ObJsonBuffer &path) const } else if (OB_FAIL(path.append("["))) { LOG_WARN("path append [ failed", K(ret)); } else if (OB_FAIL(path.append(res_ptr, static_cast(ptr - res_ptr)))) { - LOG_WARN("fail to append the index", K(ret)); + LOG_WARN("fail to append the index", K(ret)); } else if (OB_FAIL(path.append("]"))) { LOG_WARN("path append ] failed", K(ret)); } @@ -280,7 +326,7 @@ int ObJsonNode::get_location(ObJsonBuffer &path) const int ObJsonNode::replace(const ObIJsonBase *old_node, ObIJsonBase *new_node) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(old_node) || OB_ISNULL(new_node)) { // check param ret = OB_INVALID_ARGUMENT; @@ -312,7 +358,7 @@ int ObJsonNode::replace(const ObIJsonBase *old_node, ObIJsonBase *new_node) int ObJsonNode::object_remove(const common::ObString &key) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type ret = OB_INVALID_ARGUMENT; @@ -329,14 +375,10 @@ int ObJsonNode::object_remove(const common::ObString &key) int ObJsonNode::array_remove(uint64_t index) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); - if (index >= element_count()) { // check param - ret = OB_ERR_WRONG_VALUE; - LOG_WARN("invalid input value", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_array_op(index))) { + LOG_WARN("invalid json array operation", K(ret), K(index)); } else { ObJsonArray *j_arr = static_cast(this); if (OB_FAIL(j_arr->remove(index))) { @@ -349,14 +391,10 @@ int ObJsonNode::array_remove(uint64_t index) int ObJsonNode::get_key(uint64_t index, common::ObString &key_out) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); - if (index >= element_count()) { // check param - ret = OB_OUT_OF_ELEMENT; - LOG_WARN("index out of range", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_object_op(index))) { + LOG_WARN("invalid json object operation", K(ret), K(index)); } else { const ObJsonObject *j_obj = static_cast(this); if (OB_FAIL(j_obj->get_key(index, key_out))) { @@ -369,14 +407,10 @@ int ObJsonNode::get_key(uint64_t index, common::ObString &key_out) const int ObJsonNode::get_array_element(uint64_t index, ObIJsonBase *&value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); - if (index >= element_count()) { // check param - ret = OB_ERR_WRONG_VALUE; - LOG_WARN("invalid input value", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_ARRAY) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_array_op(index))) { + LOG_WARN("invalid json array operation", K(ret), K(index)); } else { const ObJsonArray *j_arr = static_cast(this); value = (*j_arr)[index]; @@ -387,14 +421,10 @@ int ObJsonNode::get_array_element(uint64_t index, ObIJsonBase *&value) const int ObJsonNode::get_object_value(uint64_t index, ObIJsonBase *&value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); - if (index >= element_count()) { // check param - ret = OB_ERR_WRONG_VALUE; - LOG_WARN("invalid input value", K(ret), K(index), K(element_count())); - } else if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid json node type", K(ret), K(json_type())); + if (OB_FAIL(check_valid_object_op(index))) { + LOG_WARN("invalid json object operation", K(ret), K(index)); } else { const ObJsonObject *j_obj = static_cast(this); if (OB_ISNULL(value = j_obj->get_value(index))) { // maybe not found. @@ -408,7 +438,7 @@ int ObJsonNode::get_object_value(uint64_t index, ObIJsonBase *&value) const int ObJsonNode::get_object_value(const ObString &key, ObIJsonBase *&value) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (json_type() != ObJsonNodeType::J_OBJECT) { // check json node type ret = OB_INVALID_ARGUMENT; @@ -430,7 +460,7 @@ int ObJsonNode::get_object_value(const ObString &key, ObIJsonBase *&value) const // [key0][key1]...[keyn][value0][value1]...[valuen] void ObJsonObject::update_serialize_size(int64_t change_size) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (change_size != 0) { serialize_size_ += change_size; @@ -484,7 +514,7 @@ void ObJsonObject::update_serialize_size(int64_t change_size) ObJsonNode *ObJsonObject::clone(ObIAllocator* allocator) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObJsonNode *new_node = ObJsonTreeUtil::clone_new_node(allocator, allocator); if (OB_ISNULL(new_node)) { @@ -506,7 +536,7 @@ ObJsonNode *ObJsonObject::clone(ObIAllocator* allocator) const int ObJsonObject::get_key(uint64_t index, common::ObString &key_out) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (index >= object_array_.size()) { ret = OB_OUT_OF_ELEMENT; @@ -547,7 +577,7 @@ ObJsonNode *ObJsonObject::get_value(uint64_t index) const int ObJsonObject::remove(const common::ObString &key) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); const ObJsonObjectPair pair(key, NULL); ObJsonKeyCompare cmp; ObJsonObjectArray::iterator low_iter = std::lower_bound(object_array_.begin(), @@ -565,7 +595,7 @@ int ObJsonObject::remove(const common::ObString &key) int ObJsonObject::replace(const ObJsonNode *old_node, ObJsonNode *new_node) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); bool is_found = false; if (OB_ISNULL(old_node) || OB_ISNULL(new_node)) { // check param @@ -594,7 +624,7 @@ int ObJsonObject::replace(const ObJsonNode *old_node, ObJsonNode *new_node) // the latter one will overwrite the former one int ObJsonObject::add(const common::ObString &key, ObJsonNode *value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(value)) { // check param ret = OB_INVALID_ARGUMENT; @@ -636,7 +666,7 @@ void ObJsonObject::clear() int ObJsonObject::consume(ObIAllocator *allocator, ObJsonObject *other) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(allocator) || OB_ISNULL(other)) { ret = OB_INVALID_ARGUMENT; @@ -677,7 +707,7 @@ int ObJsonObject::consume(ObIAllocator *allocator, ObJsonObject *other) int ObJsonObject::merge_patch(ObIAllocator *allocator, ObJsonObject *patch_obj) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(allocator) || OB_ISNULL(patch_obj)) { ret = OB_INVALID_ARGUMENT; @@ -742,7 +772,7 @@ int ObJsonObject::merge_patch(ObIAllocator *allocator, ObJsonObject *patch_obj) // [noden_offset][noden_type][node0][node1]...[noden] void ObJsonArray::update_serialize_size(int64_t change_size) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (change_size != 0) { serialize_size_ += change_size; @@ -783,7 +813,7 @@ void ObJsonArray::update_serialize_size(int64_t change_size) ObJsonNode *ObJsonArray::clone(ObIAllocator* allocator) const { - int ret = OB_SUCCESS; + INIT_SUCC(ret); ObJsonNode *new_node = ObJsonTreeUtil::clone_new_node(allocator, allocator); if (OB_ISNULL(new_node)) { @@ -835,7 +865,7 @@ ObJsonNode *ObJsonArray::operator[](uint64_t index) const int ObJsonArray::replace(const ObJsonNode *old_node, ObJsonNode *new_node) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); bool is_found = false; if (OB_ISNULL(old_node) || OB_ISNULL(new_node)) { // check param @@ -861,7 +891,7 @@ int ObJsonArray::replace(const ObJsonNode *old_node, ObJsonNode *new_node) int ObJsonArray::append(ObJsonNode *value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(value)) { // check param ret = OB_INVALID_ARGUMENT; @@ -880,7 +910,7 @@ int ObJsonArray::append(ObJsonNode *value) int ObJsonArray::insert(uint64_t index, ObJsonNode *value) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); if (OB_ISNULL(value)) { // check param ret = OB_INVALID_ARGUMENT; @@ -908,7 +938,7 @@ void ObJsonArray::clear() int ObJsonArray::consume(ObIAllocator *allocator, ObJsonArray *other) { UNUSED(allocator); - int ret = OB_SUCCESS; + INIT_SUCC(ret); uint64_t size = other->element_count(); for (uint64_t i = 0; i < size && OB_SUCC(ret); i++){ 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 460f788600..f296853abe 100644 --- a/deps/oblib/src/lib/json_type/ob_json_tree.h +++ b/deps/oblib/src/lib/json_type/ob_json_tree.h @@ -109,6 +109,11 @@ public: int array_append(ObIJsonBase *value) override; int array_insert(uint64_t index, ObIJsonBase *value) override; int object_add(const common::ObString &key, ObIJsonBase *value) override; +private: + int check_valid_object_op(ObIJsonBase *value) const; + int check_valid_array_op(ObIJsonBase *value) const; + int check_valid_object_op(uint64_t index) const; + int check_valid_array_op(uint64_t index) const; private: ObJsonNode *parent_; uint64_t serialize_size_; @@ -685,7 +690,7 @@ private: struct ObJsonKeyCompare { int operator()(const ObJsonObjectPair &left, const ObJsonObjectPair &right) { - int ret = OB_SUCCESS; + INIT_SUCC(ret); common::ObString left_key = left.get_key(); common::ObString right_key = right.get_key(); diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h index cf137fc56b..21de507d95 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h @@ -700,7 +700,14 @@ } else if (OB_FAIL(ObObjCaster::to_type(data_type, cast_ctx, def_obj, dest_obj))) { \ SQL_LOG(WARN, "cast obj failed, ", "src type", def_obj.get_type(), "dest type", data_type); \ } else { \ - dest_obj.set_scale(column.get_data_scale()); \ + if (ob_is_json(data_type)) { \ + dest_obj.set_lob_inrow(); \ + dest_obj.meta_.set_collation_level(CS_LEVEL_IMPLICIT); \ + } \ + else \ + { \ + dest_obj.set_scale(column.get_data_scale()); \ + } \ ret = (class_obj).set_##column_name(dest_obj); \ } \ } \ @@ -913,7 +920,6 @@ namespace sqlclient { class ObMySQLResult { public: // see this for template virtual function - // http://cxh.me/2014/07/01/nvi-usage-of-virtual-template/ DEFINE_ALLOCATOR_WRAPPER ObMySQLResult(); virtual ~ObMySQLResult(); diff --git a/src/observer/mysql/obmp_utils.cpp b/src/observer/mysql/obmp_utils.cpp index 3de834f5e9..717d447325 100644 --- a/src/observer/mysql/obmp_utils.cpp +++ b/src/observer/mysql/obmp_utils.cpp @@ -349,6 +349,11 @@ int ObMPUtils::get_literal_print_length(const ObObj& obj, bool is_plain, int64_t if (CHARSET_UTF8MB4 != ObCharset::charset_type_by_coll(obj.get_collation_type())) { len += len_of_string; } + + if (obj.is_json()) { + // json add quote for stringbegin and end + len += 2; + } } else if (obj.is_binary() || obj.is_varbinary() || obj.is_hex_string() || obj.is_blob()) { // if is_plain is false, 'j' will be print as "X'6a'\0" (With Quotation Marks Here) // otherwise. as X'6a'\0 (Without Quotation Marks Here) diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index 7f7dd16b2e..fe162ecb3d 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -6157,13 +6157,13 @@ static int json_int(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { int64_t value = 0; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_int(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (expect_type < ObIntType && CAST_FAIL(int_range_check(expect_type, value, value))) { @@ -6191,13 +6191,13 @@ static int json_uint(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { uint64_t value = 0; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_uint(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (CAST_FAIL(uint_upper_check(expect_type, value))) { @@ -6248,13 +6248,13 @@ static int json_double(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { double value = 0.0; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_double(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) { @@ -6281,13 +6281,13 @@ static int json_number(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { number::ObNumber value; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); - } else if (CAST_FAIL(j_base->to_number(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); + } else if (CAST_FAIL(j_base->to_number(params.allocator_v2_, value))) { + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) { @@ -6313,13 +6313,13 @@ static int json_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { int64_t value; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_datetime(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { @@ -6343,13 +6343,13 @@ static int json_date(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { int32_t value; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_date(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { @@ -6373,13 +6373,13 @@ static int json_time(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { int64_t value; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_time(value))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { @@ -6404,13 +6404,13 @@ static int json_year(const ObObjType expect_type, ObObjCastParams ¶ms, } else { uint8_t value = 0; int64_t int_value = 0; - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_int(int_value, false, true))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (CAST_FAIL(ObTimeConverter::int_to_year(int_value, value))){ @@ -6444,13 +6444,13 @@ static int json_string(const ObObjType expect_type, ObObjCastParams ¶ms, LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_)); } else { ObJsonBuffer j_buf(params.allocator_v2_); - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->print(j_buf, true))) { - LOG_WARN("fail to cast json to other type", K(ret), K(j_text), K(expect_type)); + LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { @@ -6459,7 +6459,17 @@ static int json_string(const ObObjType expect_type, ObObjCastParams ¶ms, (ObCharset::charset_type_by_coll(in.get_collation_type()) != ObCharset::charset_type_by_coll(params.dest_collation_))); ObString temp_str_val(j_buf.length(), j_buf.ptr()); + + /* this function maybe called in json generated column + * and the generated column may has limitaion constrain the string length */ + uint64_t accuracy_max_len = 0; + if (params.res_accuracy_ && params.res_accuracy_->get_length()) { + accuracy_max_len = params.res_accuracy_->get_length(); + } if (!need_charset_convert) { + if (accuracy_max_len > 0 && accuracy_max_len < j_buf.length()) { + temp_str_val.assign_ptr(j_buf.ptr(), accuracy_max_len); + } ret = copy_string(params, expect_type, temp_str_val, out); } else { ObObj tmp_obj; @@ -6467,6 +6477,10 @@ static int json_string(const ObObjType expect_type, ObObjCastParams ¶ms, tmp_obj.set_collation_level(in.get_collation_level()); tmp_obj.set_string(ObLongTextType, temp_str_val); ret = string_string(expect_type, params, tmp_obj, out, cast_mode); + if (accuracy_max_len && accuracy_max_len < out.get_string().length()) { + ObString tmp_str = out.get_string(); + out.set_string(expect_type, tmp_str.ptr(), accuracy_max_len); + } } } } @@ -6485,11 +6499,11 @@ static int json_bit(const ObObjType expect_type, ObObjCastParams ¶ms, ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { - ObString j_text = in.get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = in.get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_bit(value))) { ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index 46240022a9..f89b72f0d2 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -4812,7 +4812,6 @@ CAST_FUNC_NAME(json, int) int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; const uint64_t extra = CM_UNSET_STRING_INTEGER_TRUNC(CM_SET_WARN_ON_FAIL(expr.extra_)); - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -4839,7 +4838,6 @@ CAST_FUNC_NAME(json, uint) int warning = OB_SUCCESS; uint64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -4868,7 +4866,6 @@ CAST_FUNC_NAME(json, double) int warning = OB_SUCCESS; double out_val = 0.0; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -4896,7 +4893,6 @@ CAST_FUNC_NAME(json, float) double tmp_val = 0.0; float out_val = 0.0; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -4933,7 +4929,7 @@ CAST_FUNC_NAME(json, number) if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); - } else if (CAST_FAIL(j_base->to_number(out_val))) { + } else if (CAST_FAIL(j_base->to_number(&temp_allocator, out_val))) { LOG_WARN("fail to cast json to number type", K(ret), K(j_text)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); @@ -4953,7 +4949,6 @@ CAST_FUNC_NAME(json, datetime) int warning = OB_SUCCESS; int64_t out_val; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -4978,7 +4973,6 @@ CAST_FUNC_NAME(json, date) int warning = OB_SUCCESS; int32_t out_val; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -5003,7 +4997,6 @@ CAST_FUNC_NAME(json, time) int warning = OB_SUCCESS; int64_t out_val; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -5029,7 +5022,6 @@ CAST_FUNC_NAME(json, year) uint8_t out_val = 0; int64_t int_val; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; @@ -5098,16 +5090,16 @@ CAST_FUNC_NAME(json, bit) EVAL_STRING_ARG() { int warning = OB_SUCCESS; - ObString j_text = child_res->get_string(); - ObJsonBin j_bin(j_text.ptr(), j_text.length()); + ObString j_bin_str = child_res->get_string(); + ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; uint64_t out_val; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(j_bin.reset_iter())) { - LOG_WARN("failed to reset json bin iter", K(ret), K(j_text)); + LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_bit(out_val))) { - LOG_WARN("fail to cast json as bit", K(ret), K(j_text)); + LOG_WARN("fail to cast json as bit", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { @@ -5124,7 +5116,6 @@ CAST_FUNC_NAME(json, otimestamp) int warning = OB_SUCCESS; int64_t datetime_val; ObObjType out_type = expr.datum_meta_.type_; - common::ObArenaAllocator &temp_allocator = ctx.get_reset_tmp_alloc(); ObString j_text = child_res->get_string(); ObJsonBin j_bin(j_text.ptr(), j_text.length()); ObIJsonBase *j_base = &j_bin; diff --git a/src/sql/engine/expr/ob_expr_bool.cpp b/src/sql/engine/expr/ob_expr_bool.cpp index dbef6df9a6..a0323eb85a 100644 --- a/src/sql/engine/expr/ob_expr_bool.cpp +++ b/src/sql/engine/expr/ob_expr_bool.cpp @@ -13,6 +13,7 @@ #define USING_LOG_PREFIX SQL_ENG #include "sql/engine/expr/ob_expr_bool.h" +#include "sql/engine/expr/ob_expr_json_func_helper.h" namespace oceanbase { namespace sql { @@ -32,9 +33,12 @@ int ObExprBool::calc_result_type1(ObExprResType& type, ObExprResType& type1, ObE if (!lib::is_mysql_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("bool expr is only for mysql mode", K(ret)); - } else if (ob_is_numeric_type(type1.get_type())) { + } else if (ob_is_numeric_type(type1.get_type()) || ob_is_json(type1.get_type())) { type1.set_calc_meta(type1.get_obj_meta()); type1.set_calc_accuracy(type1.get_accuracy()); + if (ob_is_json(type1.get_type())) { + type1.set_calc_type(type1.get_type()); + } } else { const ObObjType& calc_type = ObDoubleType; type1.set_calc_type(calc_type); @@ -95,8 +99,18 @@ CHECK_IS_TRUE_FUNC_NAME(other_type) { EVAL_ARG() { - int32_t res = child_datum->get_number().is_zero() ? 0 : 1; - res_datum.set_int32(res); + if (ob_is_json(expr.args_[0]->datum_meta_.type_)) { + int cmp_result = 0; + if (OB_FAIL(ObJsonExprHelper::is_json_zero(child_datum->get_string(), cmp_result))) { + LOG_WARN("failed: compare json", K(ret)); + } else { + res_datum.set_int32(cmp_result); + } + } else { + int32_t res = child_datum->get_number().is_zero() ? 0 : 1; + res_datum.set_int32(res); + } + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_column_conv.cpp b/src/sql/engine/expr/ob_expr_column_conv.cpp index d9f590aeec..5fa4ec34fe 100644 --- a/src/sql/engine/expr/ob_expr_column_conv.cpp +++ b/src/sql/engine/expr/ob_expr_column_conv.cpp @@ -162,6 +162,9 @@ int ObExprColumnConv::convert_skip_null_check(ObObj& result, const ObObj& obj, c const ObObj* res_obj = NULL; cast_ctx.expect_obj_collation_ = collation_type; cast_ctx.dest_collation_ = collation_type; + + ObAccuracy tmp_accuracy = accuracy; + cast_ctx.res_accuracy_ = &tmp_accuracy; if (OB_UNLIKELY(ob_is_enum_or_set_type(type))) { ObExpectType expect_type; expect_type.set_type(type); diff --git a/src/sql/engine/expr/ob_expr_json_array.cpp b/src/sql/engine/expr/ob_expr_json_array.cpp index 690a23aa0b..2a0e0d0fa6 100644 --- a/src/sql/engine/expr/ob_expr_json_array.cpp +++ b/src/sql/engine/expr/ob_expr_json_array.cpp @@ -107,16 +107,8 @@ int ObExprJsonArray::calc_resultN(ObObj &result, if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("failed: get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json array result", K(ret), K(length)); - } else { - MEMMOVE(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } diff --git a/src/sql/engine/expr/ob_expr_json_array_append.cpp b/src/sql/engine/expr/ob_expr_json_array_append.cpp index 513f8c45a0..f9ccc22438 100644 --- a/src/sql/engine/expr/ob_expr_json_array_append.cpp +++ b/src/sql/engine/expr/ob_expr_json_array_append.cpp @@ -167,16 +167,8 @@ int ObExprJsonArrayAppend::calc_resultN(ObObj &result, const ObObj *objs, } else if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("fail to get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json array append result", K(ret), K(length)); - } else { - MEMCPY(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } diff --git a/src/sql/engine/expr/ob_expr_json_array_insert.cpp b/src/sql/engine/expr/ob_expr_json_array_insert.cpp index 114c1a3509..1b0a6f9f2f 100644 --- a/src/sql/engine/expr/ob_expr_json_array_insert.cpp +++ b/src/sql/engine/expr/ob_expr_json_array_insert.cpp @@ -147,16 +147,8 @@ int ObExprJsonArrayInsert::calc_resultN(ObObj &result, const ObObj *objs, int64_ } else if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("fail to get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json array insert result", K(ret), K(length)); - } else { - MEMCPY(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } diff --git a/src/sql/engine/expr/ob_expr_json_contains.cpp b/src/sql/engine/expr/ob_expr_json_contains.cpp index 37ec8b055e..b2286700eb 100644 --- a/src/sql/engine/expr/ob_expr_json_contains.cpp +++ b/src/sql/engine/expr/ob_expr_json_contains.cpp @@ -224,13 +224,13 @@ int ObExprJsonContains::json_contains_object(ObIJsonBase* json_target, ObIJsonBa } else { JsonObjectIterator iter_t = json_target->object_iterator(); JsonObjectIterator iter_c = json_candidate->object_iterator(); - while (!iter_t.empty() && !iter_c.empty() && OB_SUCC(ret)) { + while (!iter_t.end() && !iter_c.end() && OB_SUCC(ret)) { // find the same key ObString key1; if (OB_FAIL(iter_c.get_key(key1))) { LOG_WARN("fail to get key from iterator", K(ret)); } else { - while (!iter_t.empty() && OB_SUCC(ret)) { + while (!iter_t.end() && OB_SUCC(ret)) { ObString key2; if (OB_FAIL(iter_t.get_key(key2))) { LOG_WARN("fail to get key from iterator", K(ret)); @@ -240,7 +240,7 @@ int ObExprJsonContains::json_contains_object(ObIJsonBase* json_target, ObIJsonBa iter_t.next(); } } - if (iter_t.empty()) { + if (iter_t.end()) { *result = false; break; } @@ -278,7 +278,8 @@ int ObExprJsonContains::json_contains_array(ObIJsonBase* json_target, if (json_candidate->json_type() != ObJsonNodeType::J_ARRAY) { // convert to array ObIJsonBase *jb_node = NULL; - if (ObJsonBaseFactory::transform(allocator, json_candidate, ObJsonInType::JSON_TREE, jb_node)) { + if (OB_FAIL(ObJsonBaseFactory::transform(allocator, json_candidate, + ObJsonInType::JSON_TREE, jb_node))) { LOG_WARN("fail to transform to tree", K(ret), K(*json_candidate)); } else { ObJsonNode *j_node = static_cast(jb_node); diff --git a/src/sql/engine/expr/ob_expr_json_extract.cpp b/src/sql/engine/expr/ob_expr_json_extract.cpp index 49318e010b..d67faaf34b 100644 --- a/src/sql/engine/expr/ob_expr_json_extract.cpp +++ b/src/sql/engine/expr/ob_expr_json_extract.cpp @@ -107,9 +107,9 @@ int ObExprJsonExtract::calc_resultN(ObObj &result, const ObObj *objs, objs[0].get_collation_type()))) { LOG_WARN("fail to ensure collation", K(ret), K(objs[0].get_type()), K(objs[0].get_collation_type())); } else { - ObString j_text = objs[0].get_string(); + ObString j_str = objs[0].get_string(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(objs[0].get_type()); - if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, j_in_type, j_base))) { + if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { LOG_WARN("fail to get json base", K(ret), K(j_in_type)); ret = OB_ERR_INVALID_JSON_TEXT; } @@ -163,9 +163,10 @@ int ObExprJsonExtract::calc_resultN(ObObj &result, const ObObj *objs, ObJsonNode *j_node = NULL; ObIJsonBase *jb_node = NULL; for (int32_t i = 0; OB_SUCC(ret) && i < hit_size; i++) { - if (ObJsonBaseFactory::transform(allocator, hit[i], ObJsonInType::JSON_TREE, jb_node)) { // to tree + if (OB_FAIL(ObJsonBaseFactory::transform(allocator, hit[i], + ObJsonInType::JSON_TREE, jb_node))) { // to tree LOG_WARN("fail to transform to tree", K(ret), K(i), K(*(hit[i]))); - } else { + } else { // is_tree, need deep copy, cause array append will change parent of value. j_node = static_cast(jb_node); if (OB_FAIL(jb_res->array_append(j_node->clone(allocator)))) { LOG_WARN("result array append failed", K(ret), K(i), K(*j_node)); @@ -174,21 +175,14 @@ int ObExprJsonExtract::calc_resultN(ObObj &result, const ObObj *objs, } } - ObString raw_str; + ObString raw_bin; if (OB_FAIL(ret)) { LOG_WARN("json extarct get results failed", K(ret)); - } else if (OB_FAIL(jb_res->get_raw_binary(raw_str, allocator))) { + } else if (OB_FAIL(jb_res->get_raw_binary(raw_bin, allocator))) { LOG_WARN("json extarct get result binary failed", K(ret)); } else { - char *buf = static_cast(allocator->alloc(raw_str.length())); - if (OB_UNLIKELY(buf == NULL)){ - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed:allocate memory for result", K(raw_str.length()), K(ret)); - } else { - MEMCPY(buf, raw_str.ptr(), raw_str.length()); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, raw_str.length()); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } @@ -227,9 +221,9 @@ int ObExprJsonExtract::eval_json_extract(const ObExpr &expr, ObEvalCtx &ctx, ObD } else if (OB_FAIL(ObJsonExprHelper::ensure_collation(val_type, cs_type))) { LOG_WARN("fail to ensure collation", K(ret), K(val_type), K(cs_type)); } else { - ObString j_text = json_datum->get_string(); + ObString j_str = json_datum->get_string(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type); - if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_text, j_in_type, j_in_type, j_base))) { + if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_str, j_in_type, j_in_type, j_base))) { LOG_WARN("fail to get json base", K(ret), K(j_in_type)); ret = OB_ERR_INVALID_JSON_TEXT; } @@ -285,9 +279,10 @@ int ObExprJsonExtract::eval_json_extract(const ObExpr &expr, ObEvalCtx &ctx, ObD ObJsonNode *j_node = NULL; ObIJsonBase *jb_node = NULL; for (int32_t i = 0; OB_SUCC(ret) && i < hit_size; i++) { - if (ObJsonBaseFactory::transform(&allocator, hit[i], ObJsonInType::JSON_TREE, jb_node)) { // to tree + if (OB_FAIL(ObJsonBaseFactory::transform(&allocator, hit[i], + ObJsonInType::JSON_TREE, jb_node))) { // to tree LOG_WARN("fail to transform to tree", K(ret), K(i), K(*(hit[i]))); - } else { + } else { // is_tree, need deep copy, cause array append will change parent of value. j_node = static_cast(jb_node); if (OB_FAIL(jb_res->array_append(j_node->clone(&allocator)))) { LOG_WARN("result array append failed", K(ret), K(i), K(*j_node)); 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 c7b3d5fef5..a3e2de7c8b 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -60,10 +60,10 @@ int ObJsonExprHelper::get_json_doc(const ObExpr &expr, ObEvalCtx &ctx, } else if (OB_FAIL(ObJsonExprHelper::ensure_collation(val_type, cs_type))) { LOG_WARN("fail to ensure collation", K(ret), K(val_type), K(cs_type)); } else { - ObString j_text = json_datum->get_string(); + ObString j_str = json_datum->get_string(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type); ObJsonInType expect_type = need_to_tree ? ObJsonInType::JSON_TREE : j_in_type; - if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_text, j_in_type, + if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_str, j_in_type, expect_type, j_base))) { LOG_WARN("fail to get json base", K(ret), K(j_in_type)); ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; @@ -89,10 +89,10 @@ int ObJsonExprHelper::get_json_doc(const ObObj *objs, common::ObIAllocator *allo } else if (OB_FAIL(ObJsonExprHelper::ensure_collation(val_type, cs_type))) { LOG_WARN("fail to ensure collation", K(ret), K(val_type), K(cs_type)); } else { - ObString j_text = objs[index].get_string(); + ObString j_str = objs[index].get_string(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type); ObJsonInType expect_type = need_to_tree ? ObJsonInType::JSON_TREE : j_in_type; - if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, expect_type, j_base))) { LOG_WARN("fail to get json base", K(ret), K(j_in_type)); ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; @@ -108,7 +108,22 @@ int ObJsonExprHelper::get_json_val(const common::ObObj &data, ObExprCtx &ctx, { INIT_SUCC(ret); ObObjType val_type = data.get_type(); - if (is_bool) { + if (data.is_null()) { + void *json_node_buf = allocator->alloc(sizeof(ObJsonNull)); + if (OB_ISNULL(json_node_buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed: alloscate jsonboolean", K(ret)); + } else { + ObJsonNull *null_node = static_cast(new(json_node_buf) ObJsonNull()); + if (to_bin) { + if (OB_FAIL(ObJsonBaseFactory::transform(allocator, null_node, ObJsonInType::JSON_BIN, j_base))) { + LOG_WARN("failed: json tree to bin", K(ret)); + } + } else { + j_base = null_node; + } + } + } else if (is_bool) { void *json_node_buf = allocator->alloc(sizeof(ObJsonBoolean)); if (OB_ISNULL(json_node_buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -155,6 +170,21 @@ int ObJsonExprHelper::get_json_val(const ObExpr &expr, ObEvalCtx &ctx, ObObjType val_type = json_arg->datum_meta_.type_; if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, json_datum)))) { LOG_WARN("eval json arg failed", K(ret), K(val_type)); + } else if (json_datum->is_null()) { + void *json_node_buf = allocator->alloc(sizeof(ObJsonNull)); + if (OB_ISNULL(json_node_buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed: alloscate jsonboolean", K(ret)); + } else { + ObJsonNull *null_node = static_cast(new(json_node_buf) ObJsonNull()); + if (to_bin) { + if (OB_FAIL(ObJsonBaseFactory::transform(allocator, null_node, ObJsonInType::JSON_BIN, j_base))) { + LOG_WARN("failed: json tree to bin", K(ret)); + } + } else { + j_base = null_node; + } + } } else if (json_arg->is_boolean_ == 1) { void *json_node_buf = allocator->alloc(sizeof(ObJsonBoolean)); if (OB_ISNULL(json_node_buf)) { @@ -343,6 +373,23 @@ void ObJsonExprHelper::set_type_for_value(ObExprResType* types_stack, uint32_t i } } +int ObJsonExprHelper::is_json_zero(const ObString& data, int& result) +{ + INIT_SUCC(ret); + int tmp_result = 0; + ObJsonBin j_bin(data.ptr(), data.length()); + if (data.length() == 0) { + result = 1; + } else if (OB_FAIL(j_bin.reset_iter())) { + LOG_WARN("failed: reset iter", K(ret)); + } else if (OB_FAIL(ObJsonBaseUtil::compare_int_json(0, &j_bin, 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 f899d66d6f..3ea1b52ce1 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.h +++ b/src/sql/engine/expr/ob_expr_json_func_helper.h @@ -114,6 +114,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); + /* try to transfrom scalar data to jsonBase @param[in] datum the input datum diff --git a/src/sql/engine/expr/ob_expr_json_insert.cpp b/src/sql/engine/expr/ob_expr_json_insert.cpp index 7541cd7544..7cfb1cd16a 100644 --- a/src/sql/engine/expr/ob_expr_json_insert.cpp +++ b/src/sql/engine/expr/ob_expr_json_insert.cpp @@ -184,16 +184,8 @@ int ObExprJsonInsert::calc_resultN(ObObj &result, const ObObj *objs, int64_t par } else if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("fail to get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json insert result", K(ret), K(length)); - } else { - MEMCPY(buf, raw_bin.ptr(), length); - result.set_collation_type(result_type_.get_collation_type()); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } diff --git a/src/sql/engine/expr/ob_expr_json_keys.cpp b/src/sql/engine/expr/ob_expr_json_keys.cpp index 0634d603c6..53cab676b0 100644 --- a/src/sql/engine/expr/ob_expr_json_keys.cpp +++ b/src/sql/engine/expr/ob_expr_json_keys.cpp @@ -120,19 +120,12 @@ int ObExprJsonKeys::calc_resultN(ObObj &result, } else if (is_null_result){ result.set_null(); } else { - ObString str; - if (OB_FAIL(get_keys_from_wrapper(json_doc, allocator, str))) { + ObString raw_bin; + if (OB_FAIL(get_keys_from_wrapper(json_doc, allocator, raw_bin))) { LOG_WARN("get_keys_from_wrapper failed", K(ret)); } else { - char *buf = reinterpret_cast(allocator->alloc(str.length())); - if (OB_UNLIKELY(OB_ISNULL(buf))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json_keys result", K(ret), K(str.length())); - } else { - MEMCPY(buf, str.ptr(), str.length()); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, str.length()); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } @@ -146,7 +139,7 @@ int ObExprJsonKeys::get_keys_from_wrapper(ObIJsonBase *json_doc, INIT_SUCC(ret); ObJsonArray res_array(allocator); JsonObjectIterator iter = json_doc->object_iterator(); - while (!iter.empty() && OB_SUCC(ret)) { + while (!iter.end() && OB_SUCC(ret)) { ObString key; if (OB_FAIL(iter.get_key(key))) { LOG_WARN("fail to get key from iterator", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_json_member_of.cpp b/src/sql/engine/expr/ob_expr_json_member_of.cpp index 86c4fb847d..661ea8000c 100644 --- a/src/sql/engine/expr/ob_expr_json_member_of.cpp +++ b/src/sql/engine/expr/ob_expr_json_member_of.cpp @@ -56,20 +56,27 @@ int ObExprJsonMemberOf::calc_result_type2(ObExprResType &type, return ret; } -static int json_member_of_array(const ObIJsonBase *json_a, const ObIJsonBase *json_b, bool *result) +int ObExprJsonMemberOf::check_json_member_of_array(const ObIJsonBase *json_a, + const ObIJsonBase *json_b, + bool &is_member_of) { int ret = OB_SUCCESS; - int ret_tmp; + is_member_of = false; - uint64_t b_len = json_b->element_count(); - for (uint64_t i = 0; i < b_len && OB_SUCC(ret); i++) { - ObIJsonBase *tmp = NULL; - if (OB_FAIL(json_b->get_array_element(i, tmp))) { - break; - } else { - if (OB_SUCC(json_a->compare(*tmp, ret_tmp)) && ret_tmp == 0) { - *result = true; - break; + if (OB_ISNULL(json_a) || OB_ISNULL(json_b)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("param is null", K(ret), KP(json_a), KP(json_b)); + } else { + int cmp_res = 0; + uint64_t b_len = json_b->element_count(); + for (uint64_t i = 0; i < b_len && OB_SUCC(ret) && !is_member_of; i++) { + ObIJsonBase *tmp = NULL; + if (OB_FAIL(json_b->get_array_element(i, tmp))) { + LOG_WARN("fail to get array element", K(ret), K(i), K(*json_b)); + } else if (OB_FAIL(json_a->compare(*tmp, cmp_res))) { + LOG_WARN("fail to compare json", K(ret), K(i), K(*json_a), K((*tmp))); + } else if (cmp_res == 0) { + is_member_of = true; } } } @@ -114,8 +121,8 @@ int ObExprJsonMemberOf::eval_json_member_of(const ObExpr &expr, ObEvalCtx &ctx, } else { is_member_of = (result == 0); } - } else if (OB_FAIL(json_member_of_array(json_a, json_b, &is_member_of))) { - LOG_WARN("json_member_of_array failed", K(ret)); + } else if (OB_FAIL(check_json_member_of_array(json_a, json_b, is_member_of))) { + LOG_WARN("check_json_member_of_array failed", K(ret)); } } @@ -171,8 +178,8 @@ int ObExprJsonMemberOf::calc_result2(common::ObObj &result, } else { is_member_of = (result == 0); } - } else if (OB_FAIL(json_member_of_array(json_a, json_b, &is_member_of))) { - LOG_WARN("json_member_of_array failed", K(ret)); + } else if (OB_FAIL(check_json_member_of_array(json_a, json_b, is_member_of))) { + LOG_WARN("check_json_member_of_array failed", K(ret)); } } diff --git a/src/sql/engine/expr/ob_expr_json_member_of.h b/src/sql/engine/expr/ob_expr_json_member_of.h index b9e6e8861e..e1a15cf94d 100644 --- a/src/sql/engine/expr/ob_expr_json_member_of.h +++ b/src/sql/engine/expr/ob_expr_json_member_of.h @@ -36,6 +36,9 @@ public: const common::ObObj &obj1, const common::ObObj &obj2, common::ObExprCtx &expr_ctx) const; + static int check_json_member_of_array(const ObIJsonBase *json_a, + const ObIJsonBase *json_b, + bool &is_member_of); static int eval_json_member_of(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; diff --git a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp index 1e21300e37..20dc695ae1 100644 --- a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp +++ b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp @@ -103,12 +103,14 @@ int ObExprJsonMergePatch::calc_resultN(ObObj &result, const ObObj *objs, int64_t j_obj = new (buf) ObJsonObject(allocator); } } - - if (OB_FAIL(j_obj->merge_patch(allocator, static_cast(j_patch_node)))) { - LOG_WARN("error, json merge patch failed", K(ret)); - } else { - j_base = j_obj; - has_null = false; + + if (OB_SUCC(ret)) { + if (OB_FAIL(j_obj->merge_patch(allocator, static_cast(j_patch_node)))) { + LOG_WARN("error, json merge patch failed", K(ret)); + } else { + j_base = j_obj; + has_null = false; + } } } } @@ -120,16 +122,8 @@ int ObExprJsonMergePatch::calc_resultN(ObObj &result, const ObObj *objs, int64_t } else if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("fail to get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json insert result", K(ret), K(length)); - } else { - MEMCPY(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } @@ -178,11 +172,13 @@ int ObExprJsonMergePatch::eval_json_merge_patch(const ObExpr &expr, ObEvalCtx &c } } - if (OB_FAIL(j_obj->merge_patch(&temp_allocator, static_cast(j_patch_node)))) { - LOG_WARN("error, json merge patch failed", K(ret)); - } else { - j_base = j_obj; - has_null = false; + if (OB_SUCC(ret)) { + if (OB_FAIL(j_obj->merge_patch(&temp_allocator, static_cast(j_patch_node)))) { + LOG_WARN("error, json merge patch failed", K(ret)); + } else { + j_base = j_obj; + has_null = false; + } } } } diff --git a/src/sql/engine/expr/ob_expr_json_merge_preserve.cpp b/src/sql/engine/expr/ob_expr_json_merge_preserve.cpp index 56a4a4d271..ab5868ae42 100644 --- a/src/sql/engine/expr/ob_expr_json_merge_preserve.cpp +++ b/src/sql/engine/expr/ob_expr_json_merge_preserve.cpp @@ -105,16 +105,8 @@ int ObExprJsonMergePreserve::calc_resultN(ObObj &result, const ObObj *objs, int6 } else if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("fail to get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json merge result", K(ret), K(length)); - } else { - MEMMOVE(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } diff --git a/src/sql/engine/expr/ob_expr_json_object.cpp b/src/sql/engine/expr/ob_expr_json_object.cpp index 299605879d..dda19eb4ec 100644 --- a/src/sql/engine/expr/ob_expr_json_object.cpp +++ b/src/sql/engine/expr/ob_expr_json_object.cpp @@ -123,16 +123,8 @@ int ObExprJsonObject::calc_resultN(ObObj &result, const ObObj *objs, if (OB_FAIL(j_base->get_raw_binary(raw_bin, allocator))) { LOG_WARN("failed: get json raw binary", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed: alloc memory for json object result", K(ret), K(length)); - } else { - MEMCPY(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } return ret; diff --git a/src/sql/engine/expr/ob_expr_json_overlaps.cpp b/src/sql/engine/expr/ob_expr_json_overlaps.cpp index 229e284602..06348dbc45 100644 --- a/src/sql/engine/expr/ob_expr_json_overlaps.cpp +++ b/src/sql/engine/expr/ob_expr_json_overlaps.cpp @@ -148,7 +148,7 @@ int ObExprJsonOverlaps::json_overlaps_object(ObIJsonBase *json_a, } else { JsonObjectIterator iter_a = json_a->object_iterator(); JsonObjectIterator iter_b = json_b->object_iterator(); - while (!iter_b.empty() && OB_SUCC(ret)) { + while (!iter_b.end() && OB_SUCC(ret)) { ObString key_b; ObIJsonBase *a_tmp = NULL; ObIJsonBase *b_tmp = NULL; @@ -191,7 +191,8 @@ int ObExprJsonOverlaps::json_overlaps_array(ObIJsonBase *json_a, if (json_b->json_type() != ObJsonNodeType::J_ARRAY) { // convert to array if needed ObIJsonBase *jb_node = NULL; - if (ObJsonBaseFactory::transform(allocator, json_b, ObJsonInType::JSON_TREE, jb_node)) { + if (OB_FAIL(ObJsonBaseFactory::transform(allocator, json_b, + ObJsonInType::JSON_TREE, jb_node))) { LOG_WARN("fail to transform to tree", K(ret), K(*json_b)); } else { ObJsonNode *j_node = static_cast(jb_node); diff --git a/src/sql/engine/expr/ob_expr_json_pretty.cpp b/src/sql/engine/expr/ob_expr_json_pretty.cpp index f5e31e4035..10d412983d 100644 --- a/src/sql/engine/expr/ob_expr_json_pretty.cpp +++ b/src/sql/engine/expr/ob_expr_json_pretty.cpp @@ -60,7 +60,7 @@ int ObExprJsonPretty::calc(const T &data, ObObjType type, ObCollationType cs_typ INIT_SUCC(ret); ObIJsonBase *j_base = NULL; ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); - common::ObString j_text = data.get_string(); // json text or json binary + common::ObString j_str = data.get_string(); // json text or json binary if (OB_ISNULL(allocator)) { // check allocator ret = OB_NOT_INIT; @@ -72,11 +72,14 @@ int ObExprJsonPretty::calc(const T &data, ObObjType type, ObCollationType cs_typ LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_JSON, 1, "json_pretty"); } else if (OB_FAIL(ObJsonExprHelper::ensure_collation(type, cs_type))) { LOG_WARN("fail to ensure collation", K(ret), K(type), K(cs_type)); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { - LOG_WARN("fail to get json base", K(ret), K(type), K(j_text), K(j_in_type)); + if (ret == OB_ERR_INVALID_JSON_TEXT) { + ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; + } + LOG_WARN("fail to get json base", K(ret), K(type), K(j_str), K(j_in_type)); } else if (OB_FAIL(j_base->print(j_buf, true, true))) { - LOG_WARN("fail to print json", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to print json", K(ret), K(type), K(j_str), K(j_in_type)); } return ret; diff --git a/src/sql/engine/expr/ob_expr_json_remove.cpp b/src/sql/engine/expr/ob_expr_json_remove.cpp index 723c3c8e20..735f32eaf0 100644 --- a/src/sql/engine/expr/ob_expr_json_remove.cpp +++ b/src/sql/engine/expr/ob_expr_json_remove.cpp @@ -138,19 +138,12 @@ int ObExprJsonRemove::calc_resultN(common::ObObj &result, } else if (is_null_result) { result.set_null(); } else { - ObString str; - if (OB_FAIL(json_doc->get_raw_binary(str, allocator))) { + ObString raw_bin; + if (OB_FAIL(json_doc->get_raw_binary(raw_bin, allocator))) { LOG_WARN("json_remove get result binary failed", K(ret)); } else { - char *buf = reinterpret_cast(allocator->alloc(str.length())); - if (OB_ISNULL(buf)){ - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("json_remove alloc jsonString failed", K(ret), K(str.length())); - } else { - MEMCPY(buf, str.ptr(), str.length()); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, str.length()); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } diff --git a/src/sql/engine/expr/ob_expr_json_replace.cpp b/src/sql/engine/expr/ob_expr_json_replace.cpp index 652e9cba72..6d3bf91396 100644 --- a/src/sql/engine/expr/ob_expr_json_replace.cpp +++ b/src/sql/engine/expr/ob_expr_json_replace.cpp @@ -134,19 +134,12 @@ int ObExprJsonReplace::calc_resultN(common::ObObj &result, } else if (is_null_result) { result.set_null(); } else { - ObString str; - if (OB_FAIL(json_doc->get_raw_binary(str, allocator))) { + ObString raw_bin; + if (OB_FAIL(json_doc->get_raw_binary(raw_bin, allocator))) { LOG_WARN("json_replace result to binary failed", K(ret)); } else { - char *buf = reinterpret_cast(allocator->alloc(str.length())); - if (OB_ISNULL(buf)){ - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("json_remove alloc jsonString failed", K(ret), K(str.length())); - } else { - MEMCPY(buf, str.ptr(), str.length()); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, str.length()); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } diff --git a/src/sql/engine/expr/ob_expr_json_search.cpp b/src/sql/engine/expr/ob_expr_json_search.cpp index 45ff4d268f..45daee095d 100644 --- a/src/sql/engine/expr/ob_expr_json_search.cpp +++ b/src/sql/engine/expr/ob_expr_json_search.cpp @@ -464,16 +464,8 @@ int ObExprJsonSearch::calc_resultN(ObObj& result, if (OB_FAIL(j_res->get_raw_binary(raw_bin, allocator))) { LOG_WARN("json_keys get result binary failed", K(ret)); } else { - uint64_t length = raw_bin.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)){ - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("json_search alloc jsonString failed", K(ret), K(length)); - } else { - MEMCPY(buf, raw_bin.ptr(), length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - result.set_string(ObJsonType, buf, length); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } } diff --git a/src/sql/engine/expr/ob_expr_json_set.cpp b/src/sql/engine/expr/ob_expr_json_set.cpp index 493705a21c..3a244653b6 100644 --- a/src/sql/engine/expr/ob_expr_json_set.cpp +++ b/src/sql/engine/expr/ob_expr_json_set.cpp @@ -122,20 +122,12 @@ int ObExprJsonSet::calc_resultN(common::ObObj &result, } else if (is_null_result) { result.set_null(); } else { - ObString str; - if (OB_FAIL(json_doc->get_raw_binary(str, allocator))) { + ObString raw_bin; + if (OB_FAIL(json_doc->get_raw_binary(raw_bin, allocator))) { LOG_WARN("json_set result to binary failed", K(ret)); } else { - uint64_t length = str.length(); - char *buf = reinterpret_cast(allocator->alloc(length)); - if (OB_ISNULL(buf)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to alloc memory for json set result", K(ret), K(length)); - } else { - MEMCPY(buf, str.ptr(), length); - result.set_string(ObJsonType, buf, length); - result.set_collation_type(CS_TYPE_UTF8MB4_BIN); - } + result.set_collation_type(CS_TYPE_UTF8MB4_BIN); + result.set_string(ObJsonType, raw_bin.ptr(), raw_bin.length()); } } return ret; diff --git a/src/sql/engine/expr/ob_expr_json_storage_free.cpp b/src/sql/engine/expr/ob_expr_json_storage_free.cpp index 0036e03a06..63e792653f 100644 --- a/src/sql/engine/expr/ob_expr_json_storage_free.cpp +++ b/src/sql/engine/expr/ob_expr_json_storage_free.cpp @@ -70,20 +70,20 @@ int ObExprJsonStorageFree::calc(const T &data, ObObjType type, ObCollationType c LOG_WARN("fail to ensure collation", K(ret), K(type), K(cs_type)); } else { uint64_t free_space = 0; - common::ObString j_text = data.get_string(); + common::ObString j_str = data.get_string(); ObIJsonBase *j_base = NULL; ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); - if (j_text.length() == 0) { + if (j_str.length() == 0) { ret = OB_ERR_INVALID_JSON_TEXT; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { if (ret == OB_ERR_INVALID_JSON_TEXT) { LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } - LOG_WARN("fail to get json base", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get json base", K(ret), K(type), K(j_str), K(j_in_type)); } else if (OB_FAIL(j_base->get_free_space(free_space))) { - LOG_WARN("fail to get free space", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get free space", K(ret), K(type), K(j_str), K(j_in_type)); } else { res.set_int32(free_space); } diff --git a/src/sql/engine/expr/ob_expr_json_storage_size.cpp b/src/sql/engine/expr/ob_expr_json_storage_size.cpp index 95f1785df6..b1642e2188 100644 --- a/src/sql/engine/expr/ob_expr_json_storage_size.cpp +++ b/src/sql/engine/expr/ob_expr_json_storage_size.cpp @@ -69,20 +69,20 @@ int ObExprJsonStorageSize::calc(const T &data, ObObjType type, ObCollationType c LOG_WARN("fail to ensure collation", K(ret), K(type), K(cs_type)); } else { uint64_t size = 0; - common::ObString j_text = data.get_string(); + common::ObString j_str = data.get_string(); ObIJsonBase *j_base = NULL; ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); - if (j_text.length() == 0) { + if (j_str.length() == 0) { ret = OB_ERR_INVALID_JSON_TEXT; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { if (ret == OB_ERR_INVALID_JSON_TEXT) { LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } - LOG_WARN("fail to get json base", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get json base", K(ret), K(type), K(j_str), K(j_in_type)); } else if (OB_FAIL(j_base->get_used_size(size))) { - LOG_WARN("fail to get used size", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get used size", K(ret), K(type), K(j_str), K(j_in_type)); } else { res.set_int32(size); } diff --git a/src/sql/engine/expr/ob_expr_json_type.cpp b/src/sql/engine/expr/ob_expr_json_type.cpp index 7c5ca72a95..8a8e4eab1e 100644 --- a/src/sql/engine/expr/ob_expr_json_type.cpp +++ b/src/sql/engine/expr/ob_expr_json_type.cpp @@ -142,17 +142,17 @@ int ObExprJsonType::calc(const T &data, ObObjType type, ObCollationType cs_type, case ObMediumTextType: case ObJsonType: case ObLongTextType: { - common::ObString j_text = data.get_string(); // json text or json binary + common::ObString j_str = data.get_string(); // json text or json binary ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); ObIJsonBase *j_base = NULL; if (OB_FAIL(ObJsonExprHelper::ensure_collation(type, cs_type))) { LOG_WARN("fail to ensure collation", K(ret), K(type), K(cs_type)); - } else if (j_text.length() == 0) { + } else if (j_str.length() == 0) { ret = OB_ERR_INVALID_JSON_TEXT; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { - LOG_WARN("fail to get json base", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get json base", K(ret), K(type), K(j_str), K(j_in_type)); if (ret == OB_ERR_INVALID_JSON_TEXT) { LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } diff --git a/src/sql/engine/expr/ob_expr_json_unquote.cpp b/src/sql/engine/expr/ob_expr_json_unquote.cpp index bb74eba301..0158af79c3 100644 --- a/src/sql/engine/expr/ob_expr_json_unquote.cpp +++ b/src/sql/engine/expr/ob_expr_json_unquote.cpp @@ -83,16 +83,19 @@ int ObExprJsonUnquote::calc(const T &data, ObObjType type, ObCollationType cs_ty LOG_WARN("fail to ensure collation", K(ret), K(type), K(cs_type)); } else { ObIJsonBase *j_base = NULL; - ObString j_text = data.get_string(); - size_t len = j_text.length(); + ObString j_str = data.get_string(); + size_t len = j_str.length(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); - if (ob_is_string_type(type) && (len < 2 || j_text[0] != '"' || j_text[len - 1] != '"')) { - if (OB_FAIL(j_buf.append(j_text))) { - LOG_WARN("failed: copy original string", K(ret), K(j_text)); + if (ob_is_string_type(type) && (len < 2 || j_str[0] != '"' || j_str[len - 1] != '"')) { + if (OB_FAIL(j_buf.append(j_str))) { + LOG_WARN("failed: copy original string", K(ret), K(j_str)); } - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { LOG_WARN("failed: get json base", K(ret), K(type)); + if (OB_ERR_INVALID_JSON_TEXT) { + ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; + } if (ret == OB_ERR_INVALID_JSON_TEXT_IN_PARAM) { LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT_IN_PARAM); } diff --git a/src/sql/engine/expr/ob_expr_json_valid.cpp b/src/sql/engine/expr/ob_expr_json_valid.cpp index f0c2cb97e7..0a824cd921 100644 --- a/src/sql/engine/expr/ob_expr_json_valid.cpp +++ b/src/sql/engine/expr/ob_expr_json_valid.cpp @@ -83,8 +83,8 @@ int ObExprJsonValid::calc(const T &data, ObObjType type, ObCollationType cs_type } else if (ob_is_string_type(type) && cs_type == CS_TYPE_BINARY) { is_invalid = true; } else { - common::ObString j_text = data.get_string(); - if (OB_UNLIKELY(j_text == "")) { + common::ObString j_str = data.get_string(); + if (OB_UNLIKELY(j_str == "")) { if (type == ObJsonType) { is_null = true; } else { @@ -92,13 +92,13 @@ int ObExprJsonValid::calc(const T &data, ObObjType type, ObCollationType cs_type } } else if (type == ObJsonType) { // json bin ObIJsonBase *j_bin = NULL; - if (ObJsonBaseFactory::get_json_base(allocator, j_text, ObJsonInType::JSON_BIN, - ObJsonInType::JSON_BIN, j_bin)) { - LOG_WARN("fail to get json base", K(ret), K(type), K(j_text)); + if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, ObJsonInType::JSON_BIN, + ObJsonInType::JSON_BIN, j_bin))) { + LOG_WARN("fail to get json base", K(ret), K(type), K(j_str)); } } else { // json tree - if (OB_FAIL(ObJsonParser::check_json_syntax(j_text, allocator))) { - LOG_WARN("fail to check json syntax", K(ret), K(type), K(j_text)); + if (OB_FAIL(ObJsonParser::check_json_syntax(j_str, allocator))) { + LOG_WARN("fail to check json syntax", K(ret), K(type), K(j_str)); } } } diff --git a/src/sql/engine/expr/ob_expr_json_value.cpp b/src/sql/engine/expr/ob_expr_json_value.cpp index f0fc48e1e7..e78a10f4e9 100644 --- a/src/sql/engine/expr/ob_expr_json_value.cpp +++ b/src/sql/engine/expr/ob_expr_json_value.cpp @@ -130,8 +130,6 @@ int ObExprJsonValue::calc_result_typeN(ObExprResType& type, types_stack[4].set_calc_type(temp_type.get_type()); types_stack[4].set_calc_collation_type(temp_type.get_collation_type()); types_stack[4].set_calc_collation_level(temp_type.get_collation_level()); - // types_stack[4].set_calc_length(temp_type.get_length()); - // types_stack[4].set_calc_length_semantics(temp_type.get_length_semantics()); types_stack[4].set_calc_accuracy(temp_type.get_accuracy()); } } @@ -152,8 +150,6 @@ int ObExprJsonValue::calc_result_typeN(ObExprResType& type, types_stack[6].set_calc_type(temp_type.get_type()); types_stack[6].set_calc_collation_type(temp_type.get_collation_type()); types_stack[6].set_calc_collation_level(temp_type.get_collation_level()); - // types_stack[6].set_calc_length(temp_type.get_length()); - // types_stack[6].set_calc_length_semantics(temp_type.get_length_semantics()); types_stack[6].set_calc_accuracy(temp_type.get_accuracy()); } } @@ -189,13 +185,13 @@ int ObExprJsonValue::calc_resultN(ObObj& result, ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(type)); } else { - ObString j_text = params[0].get_string(); + ObString j_str = params[0].get_string(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); - if (j_text.length() == 0) { // maybe input json doc is null type + if (j_str.length() == 0) { // maybe input json doc is null type is_null_result = true; - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base))) { - LOG_WARN("fail to get json base.", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get json base.", K(ret), K(type), K(j_str), K(j_in_type)); if (ret == OB_ERR_JSON_OUT_OF_DEPTH) { is_cover_by_error = false; } @@ -238,8 +234,11 @@ int ObExprJsonValue::calc_resultN(ObObj& result, ret = get_on_empty_or_error_old(params, expr_ctx, dst_type, 5, is_cover_by_error, accuracy, error_type, &error_val); } else if (is_cover_by_error) { // always get error option for return default value on error - get_on_empty_or_error_old(params, expr_ctx, dst_type, 5, is_cover_by_error, - accuracy, error_type, &error_val); + int temp_ret = get_on_empty_or_error_old(params, expr_ctx, dst_type, 5, is_cover_by_error, + accuracy, error_type, &error_val); + if (temp_ret != OB_SUCCESS) { + LOG_WARN("failed to get on empty or error.", K(ret), K(dst_type)); + } } // parse json path and do seek @@ -364,13 +363,13 @@ int ObExprJsonValue::eval_json_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum ret = OB_ERR_UNEXPECTED; LOG_WARN("input type error", K(type)); } else { - ObString j_text = json_datum->get_string(); + ObString j_str = json_datum->get_string(); ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); - if (j_text.length() == 0) { // maybe input json doc is null type + if (j_str.length() == 0) { // maybe input json doc is null type is_null_result = true; - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&temp_allocator, j_text, j_in_type, + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&temp_allocator, j_str, j_in_type, j_in_type, j_base))) { - LOG_WARN("fail to get json base.", K(ret), K(type), K(j_text), K(j_in_type)); + LOG_WARN("fail to get json base.", K(ret), K(type), K(j_str), K(j_in_type)); if (ret == OB_ERR_JSON_OUT_OF_DEPTH) { is_cover_by_error = false; } @@ -999,7 +998,7 @@ int ObExprJsonValue::cast_to_number(common::ObIAllocator *allocator, if (OB_ISNULL(j_base)) { ret = OB_ERR_NULL_VALUE; LOG_WARN("json base is null", K(ret)); - } else if (CAST_FAIL(j_base->to_number(val))) { + } else if (CAST_FAIL(j_base->to_number(allocator, val))) { LOG_WARN("fail to cast json as decimal", K(ret)); } else if (ObUNumberType == dst_type && CAST_FAIL(numeric_negative_check(val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(val)); @@ -1538,6 +1537,7 @@ int ObExprJsonValue::get_on_empty_or_error_old(const ObObj *params, expr_ctx.cast_mode_ &= ~CM_NO_RANGE_CHECK; // make cast check range expr_ctx.cast_mode_ &= ~CM_STRING_INTEGER_TRUNC; // make cast check range when string to uint expr_ctx.cast_mode_ |= CM_ERROR_ON_SCALE_OVER; // make cast check presion and scale + expr_ctx.cast_mode_ |= CM_EXPLICIT_CAST; // make cast json fail return error if (OB_FAIL(param_eval(expr_ctx, params[index + 1], index + 1))) { is_cover_by_error = false; LOG_WARN("eval json arg failed", K(ret)); @@ -1597,6 +1597,7 @@ int ObExprJsonValue::get_on_empty_or_error(const ObExpr &expr, json_arg->extra_ &= ~CM_NO_RANGE_CHECK; // make cast check range json_arg->extra_ &= ~CM_STRING_INTEGER_TRUNC; // make cast check range when string to uint json_arg->extra_ |= CM_ERROR_ON_SCALE_OVER; // make cast check presion and scale + json_arg->extra_ |= CM_EXPLICIT_CAST; // make cast json fail return error if (OB_FAIL(json_arg->eval(ctx, json_datum))) { is_cover_by_error = false; LOG_WARN("eval json arg failed", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_or.cpp b/src/sql/engine/expr/ob_expr_or.cpp index 959aef285e..74b1a4faa2 100644 --- a/src/sql/engine/expr/ob_expr_or.cpp +++ b/src/sql/engine/expr/ob_expr_or.cpp @@ -14,7 +14,7 @@ #include "sql/engine/expr/ob_expr_or.h" #include "lib/oblog/ob_log.h" #include "share/object/ob_obj_cast.h" -//#include "sql/engine/expr/ob_expr_promotion_util.h" +#include "sql/engine/expr/ob_expr_json_func_helper.h" #include "sql/session/ob_sql_session_info.h" namespace oceanbase { @@ -49,7 +49,17 @@ int ObExprOr::calc_result2( bool obj1_is_true = false; EXPR_SET_CAST_CTX_MODE(expr_ctx); - if (OB_FAIL(ObLogicalExprOperator::is_true(obj1, expr_ctx.cast_mode_ | CM_NO_RANGE_CHECK, obj1_is_true))) { + if (ob_is_json(obj1.get_type())) { + // cause for json type, in some case can't transform to number type + // add special process for json type + // use the some logical as mysql + int cmp_result = 0; + if (OB_FAIL(ObJsonExprHelper::is_json_zero(obj1.get_string(), cmp_result))) { + LOG_WARN("failed: compare json", K(ret)); + } else { + result.set_int32(cmp_result); + } + } else if (OB_FAIL(ObLogicalExprOperator::is_true(obj1, expr_ctx.cast_mode_ | CM_NO_RANGE_CHECK, obj1_is_true))) { LOG_WARN("fail to evaluate obj1", K(obj1), K(ret)); } else if (obj1_is_true) { result.set_int32(static_cast(true)); @@ -119,7 +129,6 @@ int ObExprOr::cacl_res_with_one_param_null( // By design, compatible with mysql and oracle: // null or false == NULL. null or true == true. // see "NULL and the three-valued logic" - // https://en.wikipedia.org/wiki/Null_(SQL)#Comparisons_with_NULL_and_the_three-valued_logic_(3VL) } else if (value) { res.set_int32(static_cast(true)); } else { diff --git a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp index 28c33d5f39..900d6d89ed 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -245,6 +245,11 @@ int ObRawExprDeduceType::assign_var_exprs_result_type(ObNonTerminalRawExpr& expr return ret; } +bool need_calc_json_as_int(ObItemType item_type) +{ + return item_type == T_OP_BOOL; +} + bool need_calc_json_as_text(ObItemType item_type) { bool bool_ret = true; diff --git a/src/sql/resolver/expr/ob_raw_expr_info_extractor.cpp b/src/sql/resolver/expr/ob_raw_expr_info_extractor.cpp index 6639c6f3d6..85f08cc83f 100644 --- a/src/sql/resolver/expr/ob_raw_expr_info_extractor.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_info_extractor.cpp @@ -602,6 +602,19 @@ int ObRawExprInfoExtractor::visit(ObSysFunRawExpr& expr) expr.clear_flag(IS_CALCULABLE_EXPR); } + if (OB_SUCC(ret) && T_FUN_SYS_JSON_VALUE == expr.get_expr_type()) { + if (expr.get_param_count() == 7) { + ObRawExpr * sub_expr = expr.get_param_expr(6); + if (OB_NOT_NULL(sub_expr)) { + sub_expr->clear_flag(IS_CALCULABLE_EXPR); + } + sub_expr = expr.get_param_expr(4); + if (OB_NOT_NULL(sub_expr)) { + sub_expr->clear_flag(IS_CALCULABLE_EXPR); + } + } + } + if (OB_SUCC(ret) && T_FUN_UDF == expr.get_expr_type() && expr.has_flag(IS_CALCULABLE_EXPR)) {} } return ret; diff --git a/unittest/share/test_json_base.cpp b/unittest/share/test_json_base.cpp index c6c633d73b..e348f420bc 100644 --- a/unittest/share/test_json_base.cpp +++ b/unittest/share/test_json_base.cpp @@ -3055,28 +3055,28 @@ TEST_F(TestJsonBase, test_to_number) // 1. test json tree // number j_tree = &j_dec; - ASSERT_EQ(OB_SUCCESS, j_tree->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_tree->to_number(&allocator, res)); ASSERT_EQ(false, res == res_int); // int j_tree = &j_int; - ASSERT_EQ(OB_SUCCESS, j_tree->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_tree->to_number(&allocator, res)); ASSERT_EQ(true, res == res_int); // uint j_tree = &j_uint; - ASSERT_EQ(OB_SUCCESS, j_tree->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_tree->to_number(&allocator, res)); ASSERT_EQ(true, res == res_int); // string j_tree = &j_str; - ASSERT_EQ(OB_SUCCESS, j_tree->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_tree->to_number(&allocator, res)); ASSERT_EQ(false, res == res_int); // bool j_tree = &j_bool; - ASSERT_EQ(OB_SUCCESS, j_tree->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_tree->to_number(&allocator, res)); res_int = 1; ASSERT_EQ(true, res == res_int); // double j_tree = &j_double; - ASSERT_EQ(OB_SUCCESS, j_tree->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_tree->to_number(&allocator, res)); res_int = 123; ASSERT_EQ(false, res == res_int); @@ -3084,33 +3084,33 @@ TEST_F(TestJsonBase, test_to_number) // number ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, &j_dec, ObJsonInType::JSON_BIN, j_bin)); - ASSERT_EQ(OB_SUCCESS, j_bin->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_bin->to_number(&allocator, res)); ASSERT_EQ(false, res == res_int); // int ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, &j_int, ObJsonInType::JSON_BIN, j_bin)); - ASSERT_EQ(OB_SUCCESS, j_bin->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_bin->to_number(&allocator, res)); ASSERT_EQ(true, res == res_int); // uint ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, &j_uint, ObJsonInType::JSON_BIN, j_bin)); - ASSERT_EQ(OB_SUCCESS, j_bin->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_bin->to_number(&allocator, res)); ASSERT_EQ(true, res == res_int); // string ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, &j_str, ObJsonInType::JSON_BIN, j_bin)); - ASSERT_EQ(OB_SUCCESS, j_bin->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_bin->to_number(&allocator, res)); ASSERT_EQ(false, res == res_int); // bool ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, &j_bool, ObJsonInType::JSON_BIN, j_bin)); - ASSERT_EQ(OB_SUCCESS, j_bin->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_bin->to_number(&allocator, res)); res_int = 1; ASSERT_EQ(true, res == res_int); // double ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, &j_double, ObJsonInType::JSON_BIN, j_bin)); - ASSERT_EQ(OB_SUCCESS, j_bin->to_number(res)); + ASSERT_EQ(OB_SUCCESS, j_bin->to_number(&allocator, res)); res_int = 123; ASSERT_EQ(false, res == res_int); } diff --git a/unittest/share/test_json_bin.cpp b/unittest/share/test_json_bin.cpp index 19b616fc54..91269b3bb4 100644 --- a/unittest/share/test_json_bin.cpp +++ b/unittest/share/test_json_bin.cpp @@ -1461,6 +1461,7 @@ TEST_F(TestJsonBin, large_array_update) bin->element(0); ASSERT_EQ(bin->element_count(), 80000); + ASSERT_EQ(OB_SUCCESS, bin->move_parent_iter()); bin->element(1); ASSERT_EQ(bin->element_count(), 80000); } @@ -1660,7 +1661,7 @@ TEST_F(TestJsonBin, test_double_nan) ObJsonDouble left_val(value); ObIJsonBase *left_base = &left_val; ObIJsonBase *new_bin = NULL; - ASSERT_EQ(OB_SUCCESS, ObJsonBaseFactory::transform(&allocator, left_base, + ASSERT_EQ(OB_INVALID_NUMERIC, ObJsonBaseFactory::transform(&allocator, left_base, ObJsonInType::JSON_BIN, new_bin)); } diff --git a/unittest/share/test_json_tree.cpp b/unittest/share/test_json_tree.cpp index 72a2c1e31e..d783419135 100644 --- a/unittest/share/test_json_tree.cpp +++ b/unittest/share/test_json_tree.cpp @@ -989,7 +989,7 @@ TEST_F(TestJsonTree, test_json_cast_to_number) ASSERT_EQ(OB_SUCCESS, num.from(buf, allocator)); ObJsonDecimal my_num(num); j_base = &my_num; - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(LLONG_MIN, to_int); @@ -999,7 +999,7 @@ TEST_F(TestJsonTree, test_json_cast_to_number) ASSERT_EQ(OB_SUCCESS, num.from(buf, allocator)); my_num.set_value(num); j_base = &my_num; - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(0, to_int); @@ -1009,19 +1009,19 @@ TEST_F(TestJsonTree, test_json_cast_to_number) ASSERT_EQ(OB_SUCCESS, num.from(buf, allocator)); my_num.set_value(num); j_base = &my_num; - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(0, nmb.compare(num)); // uint -> number (10) j_base = &my_uint; my_uint.set_value(10); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(10, to_int); // uint -> number (ULLONG_MAX) my_uint.set_value(ULLONG_MAX); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); pos = 0; ASSERT_EQ(OB_SUCCESS, nmb.format(buf, sizeof(buf), pos, -1)); char *endptr = NULL; @@ -1032,19 +1032,19 @@ TEST_F(TestJsonTree, test_json_cast_to_number) // int -> number (LLONG_MIN) j_base = &my_int; my_int.set_value(LLONG_MIN); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(LLONG_MIN, to_int); // int -> number (0) my_int.set_value(0); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(0, to_int); // int -> number (LLONG_MAX) my_int.set_value(LLONG_MAX); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(LLONG_MAX, to_int); @@ -1053,14 +1053,14 @@ TEST_F(TestJsonTree, test_json_cast_to_number) j_base = &my_str; ASSERT_EQ(strlen("abc"), sprintf(buf, "abc")); my_str.set_value(buf, strlen(buf)); - ASSERT_EQ(OB_INVALID_NUMERIC, j_base->to_number(nmb)); + ASSERT_EQ(OB_INVALID_NUMERIC, j_base->to_number(&alloc, nmb)); // string -> number ("LLONG_MIN") MEMSET(buf, 0, sizeof(buf)); j_base = &my_str; length = sprintf(buf, "%lld", LLONG_MIN); my_str.set_value(buf, length); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(LLONG_MIN, to_int); @@ -1069,7 +1069,7 @@ TEST_F(TestJsonTree, test_json_cast_to_number) j_base = &my_str; length = sprintf(buf, "%llu", ULLONG_MAX); my_str.set_value(buf, length); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); pos = 0; ASSERT_EQ(OB_SUCCESS, nmb.format(buf, sizeof(buf), pos, -1)); uint64_t ui = ObCharset::strntoullrnd(buf, sizeof(buf), true, &endptr, &err); @@ -1080,21 +1080,21 @@ TEST_F(TestJsonTree, test_json_cast_to_number) j_base = &my_str; length = sprintf(buf, "%d", 0); my_str.set_value(buf, length); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(0, to_int); // boolean -> number (true) j_base = &my_bool; my_bool.set_value(true); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(true, to_int); // boolean -> number (false) j_base = &my_bool; my_bool.set_value(false); - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); ASSERT_EQ(OB_SUCCESS, nmb.cast_to_int64(to_int)); ASSERT_EQ(false, to_int); @@ -1102,7 +1102,7 @@ TEST_F(TestJsonTree, test_json_cast_to_number) MEMSET(buf, 0, sizeof(buf)); my_double.set_value(-123.45678); j_base = &my_double; - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); pos = 0; ASSERT_EQ(OB_SUCCESS, nmb.format(buf, sizeof(buf), pos, -1)); dou = ObCharset::strntod(buf, pos, &endptr, &err); @@ -1112,7 +1112,7 @@ TEST_F(TestJsonTree, test_json_cast_to_number) MEMSET(buf, 0, sizeof(buf)); my_double.set_value(123.45678); j_base = &my_double; - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); pos = 0; ASSERT_EQ(OB_SUCCESS, nmb.format(buf, sizeof(buf), pos, -1)); dou = ObCharset::strntod(buf, pos, &endptr, &err); @@ -1121,12 +1121,12 @@ TEST_F(TestJsonTree, test_json_cast_to_number) // double -> number (DBL_MIN) my_double.set_value(DBL_MIN); j_base = &my_double; - ASSERT_EQ(OB_SUCCESS, j_base->to_number(nmb)); + ASSERT_EQ(OB_SUCCESS, j_base->to_number(&alloc, nmb)); // double -> number (DBL_MAN) my_double.set_value(DBL_MAX); j_base = &my_double; - ASSERT_EQ(OB_NUMERIC_OVERFLOW, j_base->to_number(nmb)); + ASSERT_EQ(OB_NUMERIC_OVERFLOW, j_base->to_number(&alloc, nmb)); } static bool ob_time_eq(const ObTime& ans, int64_t year, int64_t month, int64_t day,