From 353f6dbe1d2255943ba6d2d4e57a17d8e9950fea Mon Sep 17 00:00:00 2001 From: wu-xingying <729224612@qq.com> Date: Thu, 20 Jul 2023 09:48:07 +0000 Subject: [PATCH] json path memory leak bugfix --- deps/oblib/src/lib/json_type/ob_json_base.cpp | 32 ++-- deps/oblib/src/lib/json_type/ob_json_path.cpp | 66 ++++---- deps/oblib/src/lib/json_type/ob_json_path.h | 71 +++++--- unittest/share/test_json_path.cpp | 154 +++++++++--------- 4 files changed, 167 insertions(+), 156 deletions(-) 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 3a6bc6529..629fe4521 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -2647,7 +2647,7 @@ int ObIJsonBase::get_sign_result_left_subpath(ObIAllocator* allocator, ObSeekPar ret = OB_ERR_NULL_VALUE; LOG_WARN("compare value is null.", K(ret)); } else { - ObPathComparison comp_content = path_node->get_node_content().comp_; + ObPathComparison comp_content = path_node->node_content_.comp_; SMART_VAR (ObJsonBaseVector, hit) { ObJsonPath* sub_path = comp_content.comp_left_.filter_path_; @@ -2697,7 +2697,7 @@ int ObIJsonBase::get_sign_result_right_subpath(ObIAllocator* allocator, ObSeekPa ret = OB_ERR_NULL_VALUE; LOG_WARN("compare value is null.", K(ret)); } else { - ObPathComparison comp_content = path_node->get_node_content().comp_; + ObPathComparison comp_content = path_node->node_content_.comp_; SMART_VAR (ObJsonBaseVector,hit) { ObJsonPath* sub_path = comp_content.comp_right_.filter_path_; @@ -2802,8 +2802,8 @@ int ObIJsonBase::compare_scalar(ObIAllocator* allocator, const ObJsonPathFilterN bool& filter_result) const { INIT_SUCC(ret); - ObJsonPathNodeType left_type = path_node->get_node_content().comp_.left_type_; - ObJsonPathNodeType right_type = path_node->get_node_content().comp_.right_type_; + ObJsonPathNodeType left_type = path_node->node_content_.comp_.left_type_; + ObJsonPathNodeType right_type = path_node->node_content_.comp_.right_type_; int res = -3; switch (left_type) { case JPN_NULL: { @@ -2823,8 +2823,8 @@ int ObIJsonBase::compare_scalar(ObIAllocator* allocator, const ObJsonPathFilterN if (right_type == left_type) res = 0; cmp_based_on_node_type(path_node->get_node_type(), res, filter_result); } else if (right_type == JPN_SCALAR) { - ObString str(path_node->get_node_content().comp_.comp_right_.path_scalar_.s_length_, - path_node->get_node_content().comp_.comp_right_.path_scalar_.scalar_); + ObString str(path_node->node_content_.comp_.comp_right_.path_scalar_.s_length_, + path_node->node_content_.comp_.comp_right_.path_scalar_.scalar_); if (str.length() == strlen("\"true\"") && 0 == strncasecmp(str.ptr(), "\"true\"", strlen("\"true\""))) { if (left_type == JPN_BOOL_TRUE) res = 0; cmp_based_on_node_type(path_node->get_node_type(), res, filter_result); @@ -2846,8 +2846,8 @@ int ObIJsonBase::compare_scalar(ObIAllocator* allocator, const ObJsonPathFilterN if (right_type == JPN_SCALAR) { ObIJsonBase *left_s = NULL; ObIJsonBase *right_s = NULL; - if (OB_FAIL(get_scalar(allocator, left_type, path_node->get_node_content().comp_.comp_left_.path_scalar_, left_s)) - || OB_FAIL(get_scalar(allocator, right_type, path_node->get_node_content().comp_.comp_right_.path_scalar_, right_s))) { + if (OB_FAIL(get_scalar(allocator, left_type, path_node->node_content_.comp_.comp_left_.path_scalar_, left_s)) + || OB_FAIL(get_scalar(allocator, right_type, path_node->node_content_.comp_.comp_right_.path_scalar_, right_s))) { LOG_WARN("fail to get scalar.", K(ret), K(right_type)); } else { if ((is_json_number(left_s->json_type()) && is_json_number(right_s->json_type())) @@ -2865,8 +2865,8 @@ int ObIJsonBase::compare_scalar(ObIAllocator* allocator, const ObJsonPathFilterN } } } else if (right_type == JPN_BOOL_TRUE || right_type == JPN_BOOL_FALSE ) { - ObString str(path_node->get_node_content().comp_.comp_left_.path_scalar_.s_length_, - path_node->get_node_content().comp_.comp_left_.path_scalar_.scalar_); + ObString str(path_node->node_content_.comp_.comp_left_.path_scalar_.s_length_, + path_node->node_content_.comp_.comp_left_.path_scalar_.scalar_); if (str.length() == strlen("\"true\"") && 0 == strncasecmp(str.ptr(), "\"true\"", strlen("\"true\""))) { if (right_type == JPN_BOOL_TRUE) res = 0; cmp_based_on_node_type(path_node->get_node_type(), res, filter_result); @@ -2900,7 +2900,7 @@ int ObIJsonBase::get_sign_comp_result(ObIAllocator* allocator, ObSeekParentInfo // (scalar, subpath/scalar) // (sql_var, subpath) // for scalar: bool, null, number, str(string/date) - ObPathComparison comp_content = path_node->get_node_content().comp_; + ObPathComparison comp_content = path_node->node_content_.comp_; // left is subpath, right could be scalar/sql_var if (comp_content.left_type_ == ObJsonPathNodeType::JPN_SUB_PATH) { @@ -3108,7 +3108,7 @@ int ObIJsonBase::get_str_comp_result(ObIAllocator* allocator, ObSeekParentInfo & PassingMap* sql_var) const { INIT_SUCC(ret); - ObPathComparison comp_content = path_node->get_node_content().comp_; + ObPathComparison comp_content = path_node->node_content_.comp_; bool end_comp = false; // could be:(sub_path,string), (sub_path, var) ,(string, string) // get right_str, right arg could be scalar/var @@ -3215,11 +3215,11 @@ int ObIJsonBase::find_comp_result(ObIAllocator* allocator, ObSeekParentInfo &par } } else if (pnode_type == JPN_EXISTS || pnode_type == JPN_NOT_EXISTS) { // only have right arg - if (path_node->get_node_content().comp_.right_type_ != JPN_SUB_PATH) { + if (path_node->node_content_.comp_.right_type_ != JPN_SUB_PATH) { ret = OB_INVALID_ARGUMENT; LOG_WARN("wrong argument of exists.", K(ret), K(pnode_type)); } else { - ObJsonPath* sub_path = path_node->get_node_content().comp_.comp_right_.filter_path_; + ObJsonPath* sub_path = path_node->node_content_.comp_.comp_right_.filter_path_; ObJsonPathNodeType last_node_type = sub_path->get_last_node_type(); SMART_VAR (ObJsonBaseVector, hit) { if (OB_FAIL(parent_info.parent_jb_->seek(allocator, (*sub_path), @@ -3302,8 +3302,8 @@ int ObIJsonBase::find_cond_result(ObIAllocator* allocator, ObSeekParentInfo &par INIT_SUCC(ret); bool left_ans = false; bool right_ans = false; - ObJsonPathFilterNode* cond_left = path_node->get_node_content().cond_.cond_left_; - ObJsonPathFilterNode* cond_right = path_node->get_node_content().cond_.cond_right_; + ObJsonPathFilterNode* cond_left = path_node->node_content_.cond_.cond_left_; + ObJsonPathFilterNode* cond_right = path_node->node_content_.cond_.cond_right_; ObJsonPathNodeType right_type = cond_right->get_node_type(); if (path_node->get_node_type() == JPN_NOT_COND) { if (OB_FAIL(get_half_ans(allocator, parent_info, right_type, 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 505850993..a2823c8eb 100644 --- a/deps/oblib/src/lib/json_type/ob_json_path.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_path.cpp @@ -97,11 +97,6 @@ ObJsonPathNodeType ObJsonPathNode::get_node_type() const return node_type_; } -ObPathNodeContent ObJsonPathNode::get_node_content() const -{ - return node_content_; -} - ObJsonPathNode::~ObJsonPathNode() {} @@ -310,35 +305,40 @@ int ObJsonPathBasicNode::init(ObJsonPathNodeType cur_node_type, bool is_mysql) return ret; } -ObJsonPathBasicNode::ObJsonPathBasicNode(ObString &keyname) +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, ObString &keyname) +: ObJsonPathNode(allocator) { node_content_.member_.object_name_ = keyname.ptr(); node_content_.member_.len_ = keyname.length(); node_type_ = JPN_MEMBER; } -ObJsonPathBasicNode::ObJsonPathBasicNode(const char* name, uint64_t len) +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, const char* name, uint64_t len) +: ObJsonPathNode(allocator) { node_content_.member_.object_name_ = name; node_content_.member_.len_ = len; node_type_ = JPN_MEMBER; } -ObJsonPathBasicNode::ObJsonPathBasicNode(uint64_t idx) +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t idx) +: ObJsonPathNode(allocator) { node_content_.array_cell_.index_ = idx; node_content_.array_cell_.is_index_from_end_ = false; node_type_ = JPN_ARRAY_CELL; } -ObJsonPathBasicNode::ObJsonPathBasicNode(uint64_t idx, bool is_from_end) +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t idx, bool is_from_end) +: ObJsonPathNode(allocator) { node_content_.array_cell_.index_ = idx; node_content_.array_cell_.is_index_from_end_ = is_from_end; node_type_ = JPN_ARRAY_CELL; } -ObJsonPathBasicNode::ObJsonPathBasicNode(uint64_t first_idx, uint64_t last_idx) +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t first_idx, uint64_t last_idx) +: ObJsonPathNode(allocator) { node_content_.array_range_.first_index_ = first_idx; node_content_.array_range_.is_first_index_from_end_ = false; @@ -347,8 +347,10 @@ ObJsonPathBasicNode::ObJsonPathBasicNode(uint64_t first_idx, uint64_t last_idx) node_type_ = JPN_ARRAY_RANGE; } -ObJsonPathBasicNode::ObJsonPathBasicNode(uint64_t first_idx, bool is_first_from_end, +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t first_idx, + bool is_first_from_end, uint64_t last_idx, bool is_last_from_end) +: ObJsonPathNode(allocator) { node_content_.array_range_.first_index_ = first_idx; node_content_.array_range_.is_first_index_from_end_ = is_first_from_end; @@ -357,7 +359,8 @@ ObJsonPathBasicNode::ObJsonPathBasicNode(uint64_t first_idx, bool is_first_from_ node_type_ = JPN_ARRAY_RANGE; } -ObJsonPathBasicNode::ObJsonPathBasicNode(ObPathArrayRange* o_array) +ObJsonPathBasicNode::ObJsonPathBasicNode(ObIAllocator *allocator, ObPathArrayRange* o_array) +: ObJsonPathNode(allocator) { node_content_.multi_array_.push_back(o_array); node_type_ = JPN_MULTIPLE_ARRAY; @@ -773,7 +776,7 @@ int ObJsonPath::change_json_expr_res_type_if_need(common::ObIAllocator &allocato ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at member_node", K(ret)); } else { - func_node = new (func_node) ObJsonPathFuncNode(); + func_node = new (func_node) ObJsonPathFuncNode(&allocator); if ((OB_FAIL(func_node->init(res_str, name_len)))) { // should not set error only pass set return type ret = OB_SUCCESS; @@ -1062,11 +1065,6 @@ common::ObIAllocator* ObJsonPathCache::get_allocator() { return allocator_; } - -ObJsonPathCache::ObJsonPathCache(common::ObIAllocator *allocator) -{ - allocator_ = allocator; -} int ObJsonPathUtil::append_array_index(uint64_t index, bool from_end, ObJsonBuffer& str) { @@ -1830,7 +1828,7 @@ int ObJsonPath::parse_wildcard_ellipsis_node() ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ellipsis_node", K(ret), K(index_), K(expression_)); } else { - ellipsis_node = new (ellipsis_node) ObJsonPathBasicNode(); + ellipsis_node = new (ellipsis_node) ObJsonPathBasicNode(allocator_); if (OB_FAIL(ellipsis_node->init(JPN_WILDCARD_ELLIPSIS, is_mysql_))) { LOG_WARN("fail to init path basic node with type", K(ret), K(JPN_WILDCARD_ELLIPSIS)); } else if (OB_FAIL(append(ellipsis_node))) { @@ -2062,7 +2060,7 @@ int ObJsonPath::add_single_array_node(bool is_cell_type, uint64_t& index1, uint6 LOG_WARN("allocate row buffer failed at cell_node", K(ret), K(index_), K(expression_)); } else { - cell_node = new (cell_node) ObJsonPathBasicNode(index1, from_end1); + cell_node = new (cell_node) ObJsonPathBasicNode(allocator_, index1, from_end1); if (OB_FAIL(append(cell_node))) { LOG_WARN("fail to append JsonPathNode(cell_node)!", K(ret) , K(index_), K(expression_)); @@ -2084,7 +2082,7 @@ int ObJsonPath::add_single_array_node(bool is_cell_type, uint64_t& index1, uint6 ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at range_node", K(ret), K(index_), K(expression_)); } else { - range_node = new (range_node) ObJsonPathBasicNode(index1, from_end1, index2, from_end2); + range_node = new (range_node) ObJsonPathBasicNode(allocator_, index1, from_end1, index2, from_end2); if (OB_FAIL(append(range_node))) { LOG_WARN("fail to append JsonPathNode!(range_node)", K(ret), K(index_), K(expression_)); } @@ -2259,7 +2257,7 @@ int ObJsonPath::parse_member_wildcard_node() LOG_WARN("allocate row buffer failed at member_wildcard_node", K(ret), K(index_), K(expression_)); } else { - member_wildcard_node = new (member_wildcard_node) ObJsonPathBasicNode(); + member_wildcard_node = new (member_wildcard_node) ObJsonPathBasicNode(allocator_); if (OB_FAIL(member_wildcard_node->init(JPN_MEMBER_WILDCARD, is_mysql_))) { LOG_WARN("fail to PathBasicNode init with type", K(ret), K(JPN_MEMBER_WILDCARD)); } else if (OB_FAIL(append(member_wildcard_node))) { @@ -2285,7 +2283,7 @@ int ObJsonPath::parse_array_wildcard_node() ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at cell_wildcard_node", K(ret), K(expression_)); } else { - cell_wildcard_node = new (cell_wildcard_node) ObJsonPathBasicNode(); + cell_wildcard_node = new (cell_wildcard_node) ObJsonPathBasicNode(allocator_); if (OB_FAIL(cell_wildcard_node->init(JPN_ARRAY_CELL_WILDCARD, is_mysql_))) { allocator_->free(cell_wildcard_node); LOG_WARN("fail to PathBasicNode init with type", K(ret), K(JPN_ARRAY_CELL_WILDCARD)); @@ -2357,7 +2355,7 @@ int ObJsonPath::parse_mysql_member_node() ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at member_node", K(ret), K(index_), K(expression_)); } else { - member_node = new (member_node) ObJsonPathBasicNode(name, name_len); + member_node = new (member_node) ObJsonPathBasicNode(allocator_, name, name_len); if (OB_FAIL(append(member_node) )) { LOG_WARN("fail to append JsonPathNode(member_node)!", K(ret), K(index_), K(expression_)); @@ -2941,7 +2939,7 @@ int ObJsonPath::parse_dot_ellipsis_node() ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ellipsis_node", K(ret), K(index_), K(expression_)); } else { - ellipsis_node = new (ellipsis_node) ObJsonPathBasicNode(); + ellipsis_node = new (ellipsis_node) ObJsonPathBasicNode(allocator_); if (OB_FAIL(ellipsis_node->init(JPN_DOT_ELLIPSIS, is_mysql_))) { allocator_->free(ellipsis_node); LOG_WARN("fail to init path basic node with type", K(ret), K(JPN_WILDCARD_ELLIPSIS)); @@ -3166,7 +3164,7 @@ int ObJsonPath::parse_func_node(char*& name, uint64_t& len) ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at member_node", K(ret), K(index_), K(expression_)); } else { - func_node = new (func_node) ObJsonPathFuncNode(); + func_node = new (func_node) ObJsonPathFuncNode(allocator_); if ((OB_FAIL(func_node->init(name, len))) || OB_FAIL(append(func_node) )) { allocator_->free(func_node); LOG_WARN("fail to append JsonPathNode(member_node)!", @@ -3216,7 +3214,7 @@ int ObJsonPath::parse_oracle_member_node() ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at member_node", K(ret), K(index_), K(expression_)); } else { - member_node = new (member_node) ObJsonPathBasicNode(name, name_len); + member_node = new (member_node) ObJsonPathBasicNode(allocator_, name, name_len); if (OB_FAIL(append(member_node) )) { LOG_WARN("fail to append JsonPathNode(member_node)!", K(ret), K(index_), K(expression_)); @@ -3372,7 +3370,7 @@ int ObJsonPath::parse_multiple_array_node() init_multi_array(o_array, index1, index2, from_end1, from_end2); } if (the_first) { - multi_array_node = new (multi_array_node) ObJsonPathBasicNode(o_array); + multi_array_node = new (multi_array_node) ObJsonPathBasicNode(allocator_, o_array); the_first = false; } else { multi_array_node->add_multi_array(o_array); @@ -4211,8 +4209,8 @@ int ObJsonPath::is_legal_comparison(ObJsonPathFilterNode* filter_comp_node) ObJsonPath* sub_path = nullptr; ObPathScalar scalar; ObJsonPathNodeType scalar_type = JPN_ERROR; - ObJsonPathNodeType right_type = filter_comp_node->get_node_content().comp_.right_type_; - ObCompContent comp_right = filter_comp_node->get_node_content().comp_.comp_right_; + ObJsonPathNodeType right_type = filter_comp_node->node_content_.comp_.right_type_; + ObCompContent comp_right = filter_comp_node->node_content_.comp_.comp_right_; if (filter_comp_node->get_node_type() == ObJsonPathNodeType::JPN_EXISTS || filter_comp_node->get_node_type() == ObJsonPathNodeType::JPN_NOT_EXISTS) { if (right_type != ObJsonPathNodeType::JPN_SUB_PATH) { @@ -4220,8 +4218,8 @@ int ObJsonPath::is_legal_comparison(ObJsonPathFilterNode* filter_comp_node) LOG_WARN("a sub_path must follow by exists!", K(ret)); } } else { - ObJsonPathNodeType left_type = filter_comp_node->get_node_content().comp_.left_type_; - ObCompContent comp_left = filter_comp_node->get_node_content().comp_.comp_left_; + ObJsonPathNodeType left_type = filter_comp_node->node_content_.comp_.left_type_; + ObCompContent comp_left = filter_comp_node->node_content_.comp_.comp_left_; switch (filter_comp_node->get_node_type()) { case ObJsonPathNodeType::JPN_LARGGER: case ObJsonPathNodeType::JPN_LARGGER_EQUAL: @@ -4337,7 +4335,7 @@ int ObJsonPath::parse_comparison(ObFilterArrayPointers& filter_stack, bool not_e LOG_WARN("allocate row buffer failed at filter_comp_node", K(ret), K(index_), K(expression_)); } else { - filter_comp_node = new (filter_comp_node) ObJsonPathFilterNode(); + filter_comp_node = new (filter_comp_node) ObJsonPathFilterNode(allocator_); } if (OB_SUCC(ret)) { @@ -4409,7 +4407,7 @@ int ObJsonPath::parse_condition(ObFilterArrayPointers& filter_stack, ObCharArray K(ret), K(index_), K(expression_)); break; } else { - filter_cond_node = new (filter_cond_node) ObJsonPathFilterNode(); + filter_cond_node = new (filter_cond_node) ObJsonPathFilterNode(allocator_); ObJsonPathFilterNode* right_comp = filter_stack[size_f - 1]; ObJsonPathFilterNode* left_comp = nullptr; if (OB_FAIL(ObJsonPathUtil::pop_filter_stack(filter_stack))) { diff --git a/deps/oblib/src/lib/json_type/ob_json_path.h b/deps/oblib/src/lib/json_type/ob_json_path.h index c45f15462..8c487e128 100644 --- a/deps/oblib/src/lib/json_type/ob_json_path.h +++ b/deps/oblib/src/lib/json_type/ob_json_path.h @@ -115,8 +115,6 @@ typedef struct ObPathArrayRange bool is_last_index_from_end_; } ObPathArrayRange; -using ObMultiArrayPointers = ObVector; -using MultiArrayIterator = ObMultiArrayPointers::const_iterator; class ObJsonPath; class ObJsonPathFilterNode; @@ -160,8 +158,21 @@ typedef struct ObPathCondition ObJsonPathFilterNode* cond_right_; }ObPathCondition; -typedef struct ObPathNodeContent +typedef PageArena PathArrayRangeArena; +using ObMultiArrayPointers = ObVector; +using MultiArrayIterator = ObMultiArrayPointers::const_iterator; +class ObPathNodeContent { +private: + static const int64_t DEFAULT_PAGE_SIZE = (1LL << 10); // 1kb +public: + ObPathNodeContent(ObIAllocator *allocator) + : page_allocator_(*allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), + mode_arena_(DEFAULT_PAGE_SIZE, page_allocator_), + multi_array_(&mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} + + ModulePageAllocator page_allocator_; + PathArrayRangeArena mode_arena_; ObPathMember member_; // JPN_MEMBER ObPathArrayCell array_cell_; // JPN_ARRAY_CELL ObPathArrayRange array_range_; // JPN_ARRAY_RANGE @@ -169,7 +180,7 @@ typedef struct ObPathNodeContent ObMultiArrayPointers multi_array_; //JPN_MULTIPLE_ARRAY, ObPathComparison comp_; ObPathCondition cond_; -} ObPathNodeContent; +}; // for [*] and [ to ], log actual range // example: for size 5 array, [*] should change to [0, 5) @@ -199,14 +210,12 @@ private: class ObJsonPathNode { public: - ObJsonPathNode() : node_content_() {} + ObJsonPathNode(ObIAllocator *allocator) : node_content_(allocator) {} virtual ~ObJsonPathNode(); virtual ObJsonPathNodeType get_node_type() const; - virtual ObPathNodeContent get_node_content() const; virtual bool is_autowrap() const = 0; virtual int node_to_string(ObJsonBuffer&, bool is_mysql, bool is_next_array) = 0; TO_STRING_KV(K_(node_type)); -protected: ObJsonPathNodeType node_type_; ObPathNodeContent node_content_; }; @@ -214,15 +223,15 @@ protected: class ObJsonPathBasicNode : public ObJsonPathNode { public: - ObJsonPathBasicNode() {} + ObJsonPathBasicNode(ObIAllocator *allocator): ObJsonPathNode(allocator) {} virtual ~ObJsonPathBasicNode() {} - explicit ObJsonPathBasicNode(ObString &keyname); // JPN_MEMBER - ObJsonPathBasicNode(const char* name, uint64_t len); // JPN_MEMBER - explicit ObJsonPathBasicNode(uint64_t index); // JPN_ARRAY_CELL - ObJsonPathBasicNode(uint64_t idx, bool is_from_end); - ObJsonPathBasicNode(uint64_t first_idx, uint64_t last_idx); // JPN_ARRAY_RANGE - ObJsonPathBasicNode(uint64_t, bool, uint64_t, bool); - ObJsonPathBasicNode(ObPathArrayRange* o_array); + explicit ObJsonPathBasicNode(ObIAllocator *allocator, ObString &keyname); // JPN_MEMBER + ObJsonPathBasicNode(ObIAllocator *allocator, const char* name, uint64_t len); // JPN_MEMBER + explicit ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t index); // JPN_ARRAY_CELL + ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t idx, bool is_from_end); + ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t first_idx, uint64_t last_idx); // JPN_ARRAY_RANGE + ObJsonPathBasicNode(ObIAllocator *allocator, uint64_t, bool, uint64_t, bool); + ObJsonPathBasicNode(ObIAllocator *allocator, ObPathArrayRange* o_array); int init(ObJsonPathNodeType cur_node_type, bool is_mysql); bool is_autowrap() const; bool is_multi_array_autowrap() const; @@ -243,22 +252,24 @@ public: class ObJsonPathFuncNode : public ObJsonPathNode { public: - ObJsonPathFuncNode() {} + ObJsonPathFuncNode(ObIAllocator *allocator): ObJsonPathNode(allocator) {} virtual ~ObJsonPathFuncNode() {} int init(const char* name, uint64_t len); bool is_autowrap() const; int node_to_string(ObJsonBuffer& str, bool is_mysql, bool is_next_array); }; -using ObFilterArrayPointers = ObVector; +typedef PageArena JsonCharArrayArena; +typedef ObVector ObCharArrayPointers; +typedef PageArena JsonPathFilterArena; +typedef ObVector ObFilterArrayPointers; using ObFilterArrayIterator = ObFilterArrayPointers::iterator; -using ObCharArrayPointers = ObVector; using ObCharArrayIterator = ObCharArrayPointers::iterator; class ObJsonPathFilterNode : public ObJsonPathNode { public: - ObJsonPathFilterNode() {} + ObJsonPathFilterNode(ObIAllocator *allocator): ObJsonPathNode(allocator) {} virtual ~ObJsonPathFilterNode() {} bool is_autowrap() const; int comp_half_to_string(ObJsonBuffer& str, bool is_left); @@ -392,13 +403,20 @@ public: ObPathCacheStat(ObPathParseStat state, int idx) : state_(state), index_(idx) {}; ObPathCacheStat(const ObPathCacheStat& stat) : state_(stat.state_), index_(stat.index_) {} }; - - typedef ObVector ObJsonPathPointers; - typedef ObVector ObPathCacheStatArr; + typedef PageArena JsonPathArena; + typedef PageArena PathCacheStatArena; + typedef ObVector ObJsonPathPointers; + typedef ObVector ObPathCacheStatArr; + static const int64_t DEFAULT_PAGE_SIZE = (1LL << 10); // 1kb public: - ObJsonPathCache() : allocator_(NULL) {}; - ObJsonPathCache(common::ObIAllocator *allocator); + ObJsonPathCache(common::ObIAllocator *allocator) : + allocator_(allocator), + page_allocator_(*allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), + path_cache_arena_(DEFAULT_PAGE_SIZE, page_allocator_), + path_arena_(DEFAULT_PAGE_SIZE, page_allocator_), + path_arr_ptr_(&path_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), + stat_arr_(&path_cache_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} ~ObJsonPathCache() {}; ObJsonPath* path_at(size_t idx); @@ -418,9 +436,12 @@ private: int fill_empty(size_t reserve_size); private: + common::ObIAllocator *allocator_; + ModulePageAllocator page_allocator_; + PathCacheStatArena path_cache_arena_; + JsonPathArena path_arena_; ObJsonPathPointers path_arr_ptr_; ObPathCacheStatArr stat_arr_; - common::ObIAllocator *allocator_; }; using ObPathCacheStat = ObJsonPathCache::ObPathCacheStat; diff --git a/unittest/share/test_json_path.cpp b/unittest/share/test_json_path.cpp index 92d02c745..71a8d8bed 100644 --- a/unittest/share/test_json_path.cpp +++ b/unittest/share/test_json_path.cpp @@ -64,42 +64,43 @@ TEST_F(TestJsonPath, test_is_mysql_terminator_mysql) // 测试 basicNode的构造函数 TEST_F(TestJsonPath, test_create_basic_node) { + ObArenaAllocator allocator(ObModIds::TEST); // ** - ObJsonPathBasicNode temp1; + ObJsonPathBasicNode temp1(&allocator); ASSERT_EQ(0, temp1.init(JPN_WILDCARD_ELLIPSIS, true)); ASSERT_EQ(JPN_WILDCARD_ELLIPSIS, temp1.get_node_type()); - ASSERT_EQ(true, temp1.get_node_content().is_had_wildcard_); + ASSERT_EQ(true, temp1.node_content_.is_had_wildcard_); // .* - ObJsonPathBasicNode temp2; + ObJsonPathBasicNode temp2(&allocator); ASSERT_EQ(0, temp2.init(JPN_MEMBER_WILDCARD, true)); ASSERT_EQ(JPN_MEMBER_WILDCARD, temp2.get_node_type()); - ASSERT_EQ(true, temp2.get_node_content().is_had_wildcard_); + ASSERT_EQ(true, temp2.node_content_.is_had_wildcard_); // [*] - ObJsonPathBasicNode temp3; + ObJsonPathBasicNode temp3(&allocator); ASSERT_EQ(0, temp3.init(JPN_ARRAY_CELL_WILDCARD, true)); ASSERT_EQ(JPN_ARRAY_CELL_WILDCARD, temp3.get_node_type()); - ASSERT_EQ(true, temp3.get_node_content().is_had_wildcard_); + ASSERT_EQ(true, temp3.node_content_.is_had_wildcard_); // [1] - ObJsonPathBasicNode temp4(1,false); + ObJsonPathBasicNode temp4(&allocator,1,false); ASSERT_EQ(JPN_ARRAY_CELL, temp4.get_node_type()); - ASSERT_EQ(1, temp4.get_node_content().array_cell_.index_); - ASSERT_EQ(false, temp4.get_node_content().array_cell_.is_index_from_end_); + ASSERT_EQ(1, temp4.node_content_.array_cell_.index_); + ASSERT_EQ(false, temp4.node_content_.array_cell_.is_index_from_end_); // [last-3 to 6] - ObJsonPathBasicNode temp5(3, true, 6, false); + ObJsonPathBasicNode temp5(&allocator,3, true, 6, false); ASSERT_EQ(JPN_ARRAY_RANGE, temp5.get_node_type()); - ASSERT_EQ(3, temp5.get_node_content().array_range_.first_index_); - ASSERT_EQ(true, temp5.get_node_content().array_range_.is_first_index_from_end_); - ASSERT_EQ(6, temp5.get_node_content().array_range_.last_index_); - ASSERT_EQ(false, temp5.get_node_content().array_range_.is_last_index_from_end_); + ASSERT_EQ(3, temp5.node_content_.array_range_.first_index_); + ASSERT_EQ(true, temp5.node_content_.array_range_.is_first_index_from_end_); + ASSERT_EQ(6, temp5.node_content_.array_range_.last_index_); + ASSERT_EQ(false, temp5.node_content_.array_range_.is_last_index_from_end_); // .keyname ObString kn("keyname"); - ObJsonPathBasicNode temp6(kn); + ObJsonPathBasicNode temp6(&allocator,kn); ASSERT_EQ(JPN_MEMBER, temp6.get_node_type()); - std::cout< (fa1))->get_node_type()); - ASSERT_EQ(true, fa1->get_node_content().is_had_wildcard_); + ASSERT_EQ(true, fa1->node_content_.is_had_wildcard_); } // 测试 append函数 @@ -109,60 +110,60 @@ TEST_F(TestJsonPath, test_append) int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObJsonPath test_path(&allocator); - ObJsonPathBasicNode temp1; + ObJsonPathBasicNode temp1(&allocator); ASSERT_EQ(0, temp1.init(JPN_WILDCARD_ELLIPSIS, true)); ObJsonPathNode *fa1 = &temp1; ret = test_path.append(fa1); ASSERT_EQ(OB_SUCCESS,ret); ASSERT_EQ(JPN_WILDCARD_ELLIPSIS, test_path.path_nodes_[0]->get_node_type()); - ASSERT_EQ(true, test_path.path_nodes_[0]->get_node_content().is_had_wildcard_); + ASSERT_EQ(true, test_path.path_nodes_[0]->node_content_.is_had_wildcard_); // append .* - ObJsonPathBasicNode temp2; + ObJsonPathBasicNode temp2(&allocator); ASSERT_EQ(0, temp2.init(JPN_MEMBER_WILDCARD, true)); ObJsonPathNode *fa2 = &temp2; ret = test_path.append(fa2); ASSERT_EQ(OB_SUCCESS,ret); ASSERT_EQ(JPN_MEMBER_WILDCARD, test_path.path_nodes_[1]->get_node_type()); - ASSERT_EQ(true, test_path.path_nodes_[1]->get_node_content().is_had_wildcard_); + ASSERT_EQ(true, test_path.path_nodes_[1]->node_content_.is_had_wildcard_); // append [*] - ObJsonPathBasicNode temp3; + ObJsonPathBasicNode temp3(&allocator); ASSERT_EQ(0, temp3.init(JPN_ARRAY_CELL_WILDCARD, true)); ObJsonPathNode *fa3 = &temp3; ret = test_path.append(fa3); ASSERT_EQ(OB_SUCCESS,ret); ASSERT_EQ(JPN_ARRAY_CELL_WILDCARD, test_path.path_nodes_[2]->get_node_type()); - ASSERT_EQ(true, test_path.path_nodes_[2]->get_node_content().is_had_wildcard_); + ASSERT_EQ(true, test_path.path_nodes_[2]->node_content_.is_had_wildcard_); // append array_cell - ObJsonPathBasicNode temp4(1,false); + ObJsonPathBasicNode temp4(&allocator,1,false); ObJsonPathNode *fa4 = &temp4; ret = test_path.append(fa4); ASSERT_EQ(OB_SUCCESS,ret); ASSERT_EQ(JPN_ARRAY_CELL, test_path.path_nodes_[3]->get_node_type()); - ASSERT_EQ(1, test_path.path_nodes_[3]->get_node_content().array_cell_.index_); - ASSERT_EQ(false, test_path.path_nodes_[3]->get_node_content().array_cell_.is_index_from_end_); + ASSERT_EQ(1, test_path.path_nodes_[3]->node_content_.array_cell_.index_); + ASSERT_EQ(false, test_path.path_nodes_[3]->node_content_.array_cell_.is_index_from_end_); // [last-3 to 6] - ObJsonPathBasicNode temp5(3, true, 6, false); + ObJsonPathBasicNode temp5(&allocator,3, true, 6, false); ObJsonPathNode *fa5 = &temp5; ret = test_path.append(fa5); ASSERT_EQ(OB_SUCCESS,ret); ASSERT_EQ(JPN_ARRAY_RANGE, test_path.path_nodes_[4]->get_node_type()); - ASSERT_EQ(3, test_path.path_nodes_[4]->get_node_content().array_range_.first_index_); - ASSERT_EQ(true, test_path.path_nodes_[4]->get_node_content().array_range_.is_first_index_from_end_); - ASSERT_EQ(6, test_path.path_nodes_[4]->get_node_content().array_range_.last_index_); - ASSERT_EQ(false, test_path.path_nodes_[4]->get_node_content().array_range_.is_last_index_from_end_); + ASSERT_EQ(3, test_path.path_nodes_[4]->node_content_.array_range_.first_index_); + ASSERT_EQ(true, test_path.path_nodes_[4]->node_content_.array_range_.is_first_index_from_end_); + ASSERT_EQ(6, test_path.path_nodes_[4]->node_content_.array_range_.last_index_); + ASSERT_EQ(false, test_path.path_nodes_[4]->node_content_.array_range_.is_last_index_from_end_); // .keyname ObString kn("keyname"); - ObJsonPathBasicNode temp6(kn); + ObJsonPathBasicNode temp6(&allocator,kn); ObJsonPathNode *fa6 = &temp6; ret = test_path.append(fa6); ASSERT_EQ(OB_SUCCESS,ret); ASSERT_EQ(JPN_MEMBER, test_path.path_nodes_[5]->get_node_type()); - std::cout<<"6: "<get_node_content().member_.object_name_<node_content_.member_.object_name_<get_node_type()); - ASSERT_EQ(10, test_path.path_nodes_[0]->get_node_content().multi_array_[0]->first_index_); - ASSERT_EQ(true,test_path.path_nodes_[0]->get_node_content().multi_array_[0]->is_first_index_from_end_); - ASSERT_EQ(10, test_path.path_nodes_[0]->get_node_content().multi_array_[0]->last_index_); - ASSERT_EQ(true,test_path.path_nodes_[0]->get_node_content().multi_array_[0]->is_last_index_from_end_); + ASSERT_EQ(10, test_path.path_nodes_[0]->node_content_.multi_array_[0]->first_index_); + ASSERT_EQ(true,test_path.path_nodes_[0]->node_content_.multi_array_[0]->is_first_index_from_end_); + ASSERT_EQ(10, test_path.path_nodes_[0]->node_content_.multi_array_[0]->last_index_); + ASSERT_EQ(true,test_path.path_nodes_[0]->node_content_.multi_array_[0]->is_last_index_from_end_); } // 测试能否正确解析array_range_node @@ -236,10 +237,10 @@ TEST_F(TestJsonPath, test_array_range_node) // 只有一个节点 ASSERT_EQ(1, test_path.path_node_cnt()); ASSERT_EQ(JPN_MULTIPLE_ARRAY,test_path.path_nodes_[0]->get_node_type()); - ASSERT_EQ(1, test_path.path_nodes_[0]->get_node_content().multi_array_[0]->first_index_); - ASSERT_EQ(false,test_path.path_nodes_[0]->get_node_content().multi_array_[0]->is_first_index_from_end_); - ASSERT_EQ(10, test_path.path_nodes_[0]->get_node_content().multi_array_[0]->last_index_); - ASSERT_EQ(false,test_path.path_nodes_[0]->get_node_content().multi_array_[0]->is_last_index_from_end_); + ASSERT_EQ(1, test_path.path_nodes_[0]->node_content_.multi_array_[0]->first_index_); + ASSERT_EQ(false,test_path.path_nodes_[0]->node_content_.multi_array_[0]->is_first_index_from_end_); + ASSERT_EQ(10, test_path.path_nodes_[0]->node_content_.multi_array_[0]->last_index_); + ASSERT_EQ(false,test_path.path_nodes_[0]->node_content_.multi_array_[0]->is_last_index_from_end_); } TEST_F(TestJsonPath, test_multi_array_node) @@ -258,17 +259,17 @@ TEST_F(TestJsonPath, test_multi_array_node) // 只有一个节点 ASSERT_EQ(1, test_path.path_node_cnt()); ASSERT_EQ(JPN_MULTIPLE_ARRAY,test_path.path_nodes_[0]->get_node_type()); - ASSERT_EQ(2, test_path.path_nodes_[0]->get_node_content().multi_array_.size()); + ASSERT_EQ(2, test_path.path_nodes_[0]->node_content_.multi_array_.size()); - ASSERT_EQ(10, test_path.path_nodes_[0]->get_node_content().multi_array_[0]->first_index_); - ASSERT_EQ(true,test_path.path_nodes_[0]->get_node_content().multi_array_[0]->is_first_index_from_end_); - ASSERT_EQ(10, test_path.path_nodes_[0]->get_node_content().multi_array_[0]->last_index_); - ASSERT_EQ(true,test_path.path_nodes_[0]->get_node_content().multi_array_[0]->is_last_index_from_end_); + ASSERT_EQ(10, test_path.path_nodes_[0]->node_content_.multi_array_[0]->first_index_); + ASSERT_EQ(true,test_path.path_nodes_[0]->node_content_.multi_array_[0]->is_first_index_from_end_); + ASSERT_EQ(10, test_path.path_nodes_[0]->node_content_.multi_array_[0]->last_index_); + ASSERT_EQ(true,test_path.path_nodes_[0]->node_content_.multi_array_[0]->is_last_index_from_end_); - ASSERT_EQ(1, test_path.path_nodes_[0]->get_node_content().multi_array_[1]->first_index_); - ASSERT_EQ(false,test_path.path_nodes_[0]->get_node_content().multi_array_[1]->is_first_index_from_end_); - ASSERT_EQ(10, test_path.path_nodes_[0]->get_node_content().multi_array_[1]->last_index_); - ASSERT_EQ(false,test_path.path_nodes_[0]->get_node_content().multi_array_[1]->is_last_index_from_end_); + ASSERT_EQ(1, test_path.path_nodes_[0]->node_content_.multi_array_[1]->first_index_); + ASSERT_EQ(false,test_path.path_nodes_[0]->node_content_.multi_array_[1]->is_first_index_from_end_); + ASSERT_EQ(10, test_path.path_nodes_[0]->node_content_.multi_array_[1]->last_index_); + ASSERT_EQ(false,test_path.path_nodes_[0]->node_content_.multi_array_[1]->is_last_index_from_end_); } TEST_F(TestJsonPath, test_filter_node) @@ -295,15 +296,6 @@ TEST_F(TestJsonPath, test_filter_node) } ASSERT_EQ(OB_SUCCESS, ret); std::cout<get_node_type()<get_node_content(); - std::cout<to_string(str); - ObString str_scalar(str.ptr()); - std::cout<get_node_type()); - const auto &member = test_path.path_nodes_[0]->get_node_content().member_; + const auto &member = test_path.path_nodes_[0]->node_content_.member_; ObString str(member.len_, member.object_name_); ASSERT_TRUE(str.case_compare("name") == 0); - std::cout<get_node_content().member_.object_name_<node_content_.member_.object_name_<get_node_type()); ASSERT_EQ(JPN_ARRAY_CELL,test_path.path_nodes_[1]->get_node_type()); - ASSERT_EQ(10,test_path.path_nodes_[1]->get_node_content().array_cell_.index_); - ASSERT_EQ(false,test_path.path_nodes_[1]->get_node_content().array_cell_.is_index_from_end_); + ASSERT_EQ(10,test_path.path_nodes_[1]->node_content_.array_cell_.index_); + ASSERT_EQ(false,test_path.path_nodes_[1]->node_content_.array_cell_.is_index_from_end_); } // 测试能否成功解析path表达式 @@ -727,15 +719,15 @@ TEST_F(TestJsonPath, test_parse_path) //ASSERT_EQ(JPN_ARRAY_CELL_WILDCARD,test_path.path_nodes_[i]->node_type); /* ASSERT_EQ(JPN_MEMBER,test_path.path_nodes_[i]->node_type); - std::cout<get_node_content().member_.object_name_<node_content_.member_.object_name_<node_type); - ASSERT_EQ(10,test_path.path_nodes_[i]->get_node_content().array_cell_.index_); - ASSERT_EQ(true,test_path.path_nodes_[i]->get_node_content().array_cell_.is_index_from_end_); + ASSERT_EQ(10,test_path.path_nodes_[i]->node_content_.array_cell_.index_); + ASSERT_EQ(true,test_path.path_nodes_[i]->node_content_.array_cell_.is_index_from_end_); */ - ASSERT_EQ(10,test_path.path_nodes_[i]->get_node_content().array_range_.first_index_); - ASSERT_EQ(true,test_path.path_nodes_[i]->get_node_content().array_range_.is_first_index_from_end_); - ASSERT_EQ(1,test_path.path_nodes_[i]->get_node_content().array_range_.last_index_); - ASSERT_EQ(true,test_path.path_nodes_[i]->get_node_content().array_range_.is_last_index_from_end_); + ASSERT_EQ(10,test_path.path_nodes_[i]->node_content_.array_range_.first_index_); + ASSERT_EQ(true,test_path.path_nodes_[i]->node_content_.array_range_.is_first_index_from_end_); + ASSERT_EQ(1,test_path.path_nodes_[i]->node_content_.array_range_.last_index_); + ASSERT_EQ(true,test_path.path_nodes_[i]->node_content_.array_range_.is_last_index_from_end_); } } @@ -751,7 +743,7 @@ TEST_F(TestJsonPath, test_array_cell_node_to_string) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer str(&allocator); - ObJsonPathBasicNode node(10, true); + ObJsonPathBasicNode node(&allocator,10, true); node.node_to_string(str, true, false); std::cout<get_node_type()<get_node_content().member_.object_name_<node_content_.member_.object_name_<get_node_content().array_cell_.index_<get_node_content().array_cell_.is_index_from_end_<node_content_.array_cell_.index_<node_content_.array_cell_.is_index_from_end_<