From a8a00b05fcc98dcc248748d973b18be7eb77b8db Mon Sep 17 00:00:00 2001 From: Carrot-77 <1012982871@qq.com> Date: Wed, 13 Nov 2024 15:15:03 +0000 Subject: [PATCH] [CP] [FEAT MERGE] JSON/XML/GIS MEM OPTIMIZATION AND NEW XML/GIS EXPR --- deps/oblib/src/common/object/ob_obj_funcs.h | 6 +- deps/oblib/src/lib/CMakeLists.txt | 2 + deps/oblib/src/lib/allocator/page_arena.h | 2 + deps/oblib/src/lib/geo/ob_geo.h | 9 +- deps/oblib/src/lib/geo/ob_geo_3d.cpp | 47 +- deps/oblib/src/lib/geo/ob_geo_3d.h | 15 +- deps/oblib/src/lib/geo/ob_geo_bin.cpp | 49 +- deps/oblib/src/lib/geo/ob_geo_bin.h | 34 +- deps/oblib/src/lib/geo/ob_geo_bin_iter.h | 11 +- deps/oblib/src/lib/geo/ob_geo_bin_iter.ipp | 97 +- .../src/lib/geo/ob_geo_box_clip_visitor.cpp | 11 +- .../src/lib/geo/ob_geo_box_clip_visitor.h | 9 +- .../src/lib/geo/ob_geo_cache_polygon.cpp | 2 +- .../src/lib/geo/ob_geo_close_ring_visitor.cpp | 47 + .../src/lib/geo/ob_geo_close_ring_visitor.h | 52 + deps/oblib/src/lib/geo/ob_geo_common.cpp | 4 +- deps/oblib/src/lib/geo/ob_geo_dispatcher.h | 24 + .../src/lib/geo/ob_geo_elevation_visitor.cpp | 11 +- .../src/lib/geo/ob_geo_elevation_visitor.h | 4 +- deps/oblib/src/lib/geo/ob_geo_func_buffer.cpp | 376 ++---- .../src/lib/geo/ob_geo_func_centroid.cpp | 4 +- deps/oblib/src/lib/geo/ob_geo_func_common.h | 13 +- .../src/lib/geo/ob_geo_func_covered_by.cpp | 14 +- .../oblib/src/lib/geo/ob_geo_func_crosses.cpp | 8 +- .../src/lib/geo/ob_geo_func_difference.cpp | 12 +- .../lib/geo/ob_geo_func_dissolve_polygon.cpp | 36 +- .../src/lib/geo/ob_geo_func_intersects.cpp | 2 +- .../src/lib/geo/ob_geo_func_symdifference.cpp | 149 ++- .../oblib/src/lib/geo/ob_geo_func_touches.cpp | 8 +- .../src/lib/geo/ob_geo_func_transform.cpp | 4 +- deps/oblib/src/lib/geo/ob_geo_func_union.cpp | 9 +- deps/oblib/src/lib/geo/ob_geo_func_utils.h | 316 +---- deps/oblib/src/lib/geo/ob_geo_func_within.cpp | 26 +- deps/oblib/src/lib/geo/ob_geo_ibin.cpp | 12 +- deps/oblib/src/lib/geo/ob_geo_ibin.h | 78 +- .../lib/geo/ob_geo_interior_point_visitor.cpp | 10 +- .../lib/geo/ob_geo_interior_point_visitor.h | 8 +- deps/oblib/src/lib/geo/ob_geo_mvt.cpp | 2 +- .../src/lib/geo/ob_geo_normalize_visitor.cpp | 15 - .../src/lib/geo/ob_geo_normalize_visitor.h | 5 +- .../src/lib/geo/ob_geo_to_tree_visitor.cpp | 23 +- .../src/lib/geo/ob_geo_to_tree_visitor.h | 22 +- .../src/lib/geo/ob_geo_to_wkt_visitor.cpp | 77 +- .../oblib/src/lib/geo/ob_geo_to_wkt_visitor.h | 5 + deps/oblib/src/lib/geo/ob_geo_tree.cpp | 64 + deps/oblib/src/lib/geo/ob_geo_tree.h | 256 ++-- deps/oblib/src/lib/geo/ob_geo_utils.cpp | 303 +++-- deps/oblib/src/lib/geo/ob_geo_utils.h | 392 +++++- .../src/lib/geo/ob_geo_zoom_in_visitor.cpp | 33 +- .../src/lib/geo/ob_geo_zoom_in_visitor.h | 9 +- deps/oblib/src/lib/geo/ob_geometry_cast.cpp | 2 +- deps/oblib/src/lib/geo/ob_s2adapter.cpp | 29 +- deps/oblib/src/lib/geo/ob_sdo_geo_object.cpp | 14 +- deps/oblib/src/lib/geo/ob_sdo_geo_object.h | 20 +- .../lib/geo/ob_wkb_to_json_bin_visitor.cpp | 1095 +++++++++++++++++ .../src/lib/geo/ob_wkb_to_json_bin_visitor.h | 149 +++ .../src/lib/geo/ob_wkb_to_json_visitor.cpp | 25 +- deps/oblib/src/lib/json_type/ob_json_base.cpp | 303 +++-- deps/oblib/src/lib/json_type/ob_json_base.h | 4 +- deps/oblib/src/lib/json_type/ob_json_bin.cpp | 90 +- deps/oblib/src/lib/json_type/ob_json_bin.h | 16 +- deps/oblib/src/lib/ob_name_def.h | 5 + .../oblib/src/lib/string/ob_string_buffer.cpp | 10 +- deps/oblib/src/lib/string/ob_string_buffer.h | 10 +- .../oblib/src/lib/xml/ob_binary_aggregate.cpp | 47 +- deps/oblib/src/lib/xml/ob_binary_aggregate.h | 6 +- .../src/lib/xml/ob_multi_mode_interface.cpp | 65 +- .../src/lib/xml/ob_multi_mode_interface.h | 4 + deps/oblib/src/lib/xml/ob_xml_bin.cpp | 76 +- deps/oblib/src/lib/xml/ob_xml_bin.h | 6 +- deps/oblib/src/lib/xml/ob_xml_tree.cpp | 124 ++ deps/oblib/src/lib/xml/ob_xml_tree.h | 5 + deps/oblib/src/lib/xml/ob_xml_util.cpp | 16 + deps/oblib/src/lib/xml/ob_xml_util.h | 2 + deps/oblib/src/lib/xml/ob_xpath.cpp | 35 + deps/oblib/src/lib/xml/ob_xpath.h | 1 + deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp | 2 +- src/pl/ob_pl_interface_pragma.h | 2 + src/share/object/ob_obj_cast.cpp | 6 +- src/share/parameter/ob_parameter_seed.ipp | 3 + src/sql/CMakeLists.txt | 6 + .../aggregate/ob_aggregate_processor.cpp | 16 +- src/sql/engine/basic/ob_json_table_op.cpp | 32 +- src/sql/engine/expr/ob_datum_cast.cpp | 6 +- .../engine/expr/ob_expr_eval_functions.cpp | 15 +- .../engine/expr/ob_expr_existsnode_xml.cpp | 166 +++ src/sql/engine/expr/ob_expr_existsnode_xml.h | 45 + src/sql/engine/expr/ob_expr_extract_value.cpp | 18 +- src/sql/engine/expr/ob_expr_extract_xml.cpp | 141 +-- src/sql/engine/expr/ob_expr_extract_xml.h | 7 - .../engine/expr/ob_expr_insert_child_xml.cpp | 38 +- .../engine/expr/ob_expr_insert_child_xml.h | 7 +- src/sql/engine/expr/ob_expr_is_json.cpp | 6 +- src/sql/engine/expr/ob_expr_is_json.h | 3 +- src/sql/engine/expr/ob_expr_json_array.cpp | 19 +- .../engine/expr/ob_expr_json_array_append.cpp | 10 +- .../engine/expr/ob_expr_json_array_insert.cpp | 9 +- src/sql/engine/expr/ob_expr_json_contains.cpp | 5 +- .../expr/ob_expr_json_contains_path.cpp | 7 +- src/sql/engine/expr/ob_expr_json_depth.cpp | 7 +- src/sql/engine/expr/ob_expr_json_equal.cpp | 5 +- src/sql/engine/expr/ob_expr_json_exists.cpp | 10 +- src/sql/engine/expr/ob_expr_json_exists.h | 8 +- src/sql/engine/expr/ob_expr_json_extract.cpp | 8 +- .../engine/expr/ob_expr_json_func_helper.cpp | 107 +- .../engine/expr/ob_expr_json_func_helper.h | 11 +- src/sql/engine/expr/ob_expr_json_insert.cpp | 10 +- src/sql/engine/expr/ob_expr_json_keys.cpp | 5 +- src/sql/engine/expr/ob_expr_json_length.cpp | 10 +- src/sql/engine/expr/ob_expr_json_length.h | 3 +- .../engine/expr/ob_expr_json_member_of.cpp | 8 +- .../engine/expr/ob_expr_json_merge_patch.cpp | 12 +- .../expr/ob_expr_json_merge_preserve.cpp | 9 +- src/sql/engine/expr/ob_expr_json_object.cpp | 36 +- src/sql/engine/expr/ob_expr_json_object.h | 3 - src/sql/engine/expr/ob_expr_json_overlaps.cpp | 3 +- src/sql/engine/expr/ob_expr_json_pretty.cpp | 11 +- src/sql/engine/expr/ob_expr_json_pretty.h | 3 +- src/sql/engine/expr/ob_expr_json_query.cpp | 4 +- src/sql/engine/expr/ob_expr_json_quote.cpp | 9 +- src/sql/engine/expr/ob_expr_json_quote.h | 3 +- src/sql/engine/expr/ob_expr_json_remove.cpp | 5 +- src/sql/engine/expr/ob_expr_json_replace.cpp | 9 +- .../engine/expr/ob_expr_json_schema_valid.cpp | 3 +- .../ob_expr_json_schema_validation_report.cpp | 4 +- src/sql/engine/expr/ob_expr_json_search.cpp | 11 +- src/sql/engine/expr/ob_expr_json_set.cpp | 9 +- .../engine/expr/ob_expr_json_storage_free.cpp | 6 +- .../engine/expr/ob_expr_json_storage_free.h | 3 +- .../engine/expr/ob_expr_json_storage_size.cpp | 6 +- .../engine/expr/ob_expr_json_storage_size.h | 3 +- src/sql/engine/expr/ob_expr_json_type.cpp | 7 +- src/sql/engine/expr/ob_expr_json_unquote.cpp | 12 +- src/sql/engine/expr/ob_expr_json_unquote.h | 3 +- src/sql/engine/expr/ob_expr_json_utils.cpp | 11 +- src/sql/engine/expr/ob_expr_json_utils.h | 4 +- src/sql/engine/expr/ob_expr_json_valid.cpp | 6 +- src/sql/engine/expr/ob_expr_json_valid.h | 3 +- src/sql/engine/expr/ob_expr_json_value.cpp | 16 +- src/sql/engine/expr/ob_expr_lob_utils.h | 37 + .../expr/ob_expr_multi_mode_func_helper.cpp | 439 +++++++ .../expr/ob_expr_multi_mode_func_helper.h | 135 ++ .../engine/expr/ob_expr_operator_factory.cpp | 11 +- .../expr/ob_expr_priv_attribute_access.cpp | 13 +- .../engine/expr/ob_expr_priv_st_asewkb.cpp | 6 +- .../engine/expr/ob_expr_priv_st_asmvtgeom.cpp | 133 +- .../engine/expr/ob_expr_priv_st_asmvtgeom.h | 10 +- .../expr/ob_expr_priv_st_clipbybox2d.cpp | 34 +- .../engine/expr/ob_expr_priv_st_clipbybox2d.h | 2 +- .../engine/expr/ob_expr_priv_st_equals.cpp | 84 +- src/sql/engine/expr/ob_expr_priv_st_equals.h | 5 +- .../expr/ob_expr_priv_st_geogfromtext.cpp | 6 +- .../engine/expr/ob_expr_priv_st_geohash.cpp | 344 ++++++ src/sql/engine/expr/ob_expr_priv_st_geohash.h | 57 + .../expr/ob_expr_priv_st_geometrytype.cpp | 7 +- .../expr/ob_expr_priv_st_iscollection.cpp | 10 +- .../expr/ob_expr_priv_st_makeenvelope.cpp | 32 +- .../expr/ob_expr_priv_st_makeenvelope.h | 1 - .../engine/expr/ob_expr_priv_st_makepoint.cpp | 150 +++ .../engine/expr/ob_expr_priv_st_makepoint.h | 47 + .../engine/expr/ob_expr_priv_st_makevalid.cpp | 25 +- .../expr/ob_expr_priv_st_numinteriorrings.cpp | 10 +- src/sql/engine/expr/ob_expr_priv_st_point.cpp | 33 +- src/sql/engine/expr/ob_expr_priv_st_point.h | 1 - .../expr/ob_expr_priv_st_pointonsurface.cpp | 28 +- .../expr/ob_expr_priv_st_pointonsurface.h | 3 +- .../engine/expr/ob_expr_priv_st_touches.cpp | 90 +- src/sql/engine/expr/ob_expr_priv_st_touches.h | 5 +- .../engine/expr/ob_expr_priv_st_transform.cpp | 40 +- .../engine/expr/ob_expr_priv_xml_binary.cpp | 4 +- src/sql/engine/expr/ob_expr_sdo_relate.cpp | 17 +- .../expr/ob_expr_spatial_collection.cpp | 10 +- .../engine/expr/ob_expr_sql_udt_construct.cpp | 9 +- src/sql/engine/expr/ob_expr_st_area.cpp | 22 +- src/sql/engine/expr/ob_expr_st_asewkt.cpp | 11 +- src/sql/engine/expr/ob_expr_st_asgeojson.cpp | 45 +- src/sql/engine/expr/ob_expr_st_asgeojson.h | 4 +- src/sql/engine/expr/ob_expr_st_astext.cpp | 17 +- src/sql/engine/expr/ob_expr_st_aswkb.cpp | 14 +- src/sql/engine/expr/ob_expr_st_bestsrid.cpp | 44 +- src/sql/engine/expr/ob_expr_st_bestsrid.h | 3 +- src/sql/engine/expr/ob_expr_st_buffer.cpp | 86 +- src/sql/engine/expr/ob_expr_st_buffer.h | 4 +- src/sql/engine/expr/ob_expr_st_centroid.cpp | 27 +- src/sql/engine/expr/ob_expr_st_contains.cpp | 92 +- src/sql/engine/expr/ob_expr_st_covers.cpp | 35 +- src/sql/engine/expr/ob_expr_st_covers.h | 6 +- src/sql/engine/expr/ob_expr_st_crosses.cpp | 34 +- src/sql/engine/expr/ob_expr_st_crosses.h | 3 +- src/sql/engine/expr/ob_expr_st_difference.cpp | 42 +- src/sql/engine/expr/ob_expr_st_difference.h | 3 +- src/sql/engine/expr/ob_expr_st_distance.cpp | 60 +- .../expr/ob_expr_st_distance_sphere.cpp | 34 +- src/sql/engine/expr/ob_expr_st_dwithin.cpp | 32 +- src/sql/engine/expr/ob_expr_st_dwithin.h | 3 +- .../engine/expr/ob_expr_st_geomfromewkb.cpp | 24 +- .../engine/expr/ob_expr_st_geomfromewkt.cpp | 8 +- .../engine/expr/ob_expr_st_geomfromtext.cpp | 14 +- .../engine/expr/ob_expr_st_geomfromwkb.cpp | 35 +- src/sql/engine/expr/ob_expr_st_intersects.cpp | 36 +- src/sql/engine/expr/ob_expr_st_isvalid.cpp | 22 +- src/sql/engine/expr/ob_expr_st_length.cpp | 34 +- src/sql/engine/expr/ob_expr_st_overlaps.cpp | 34 +- src/sql/engine/expr/ob_expr_st_overlaps.h | 3 +- src/sql/engine/expr/ob_expr_st_srid.cpp | 14 +- .../engine/expr/ob_expr_st_symdifference.cpp | 44 +- .../engine/expr/ob_expr_st_symdifference.h | 4 +- src/sql/engine/expr/ob_expr_st_transform.cpp | 32 +- src/sql/engine/expr/ob_expr_st_union.cpp | 97 +- src/sql/engine/expr/ob_expr_st_union.h | 4 +- src/sql/engine/expr/ob_expr_st_within.cpp | 92 +- src/sql/engine/expr/ob_expr_st_x.cpp | 12 +- src/sql/engine/expr/ob_expr_sys_makexml.cpp | 6 +- src/sql/engine/expr/ob_expr_tokenize.cpp | 5 +- src/sql/engine/expr/ob_expr_update_xml.cpp | 471 ++++--- src/sql/engine/expr/ob_expr_update_xml.h | 53 +- .../engine/expr/ob_expr_xml_attributes.cpp | 5 +- src/sql/engine/expr/ob_expr_xml_concat.cpp | 127 ++ src/sql/engine/expr/ob_expr_xml_concat.h | 47 + .../engine/expr/ob_expr_xml_delete_xml.cpp | 7 +- src/sql/engine/expr/ob_expr_xml_element.cpp | 286 +---- src/sql/engine/expr/ob_expr_xml_element.h | 20 - src/sql/engine/expr/ob_expr_xml_forest.cpp | 181 +++ src/sql/engine/expr/ob_expr_xml_forest.h | 50 + .../engine/expr/ob_expr_xml_func_helper.cpp | 602 ++++++++- src/sql/engine/expr/ob_expr_xml_func_helper.h | 56 + src/sql/engine/expr/ob_expr_xml_sequence.cpp | 1 + src/sql/engine/expr/ob_expr_xml_serialize.cpp | 7 +- src/sql/engine/expr/ob_expr_xmlcast.cpp | 7 +- src/sql/engine/expr/ob_expr_xmlparse.cpp | 10 +- src/sql/engine/expr/ob_geo_expr_utils.cpp | 166 ++- src/sql/engine/expr/ob_geo_expr_utils.h | 29 +- src/sql/monitor/flt/ob_flt_utils.cpp | 2 +- src/sql/ob_spi.cpp | 2 - .../plan_cache/ob_sql_parameterization.cpp | 6 +- src/sql/printer/ob_raw_expr_printer.cpp | 43 + src/sql/printer/ob_raw_expr_printer.h | 1 + src/sql/resolver/expr/ob_raw_expr.h | 4 +- .../expr/ob_raw_expr_resolver_impl.cpp | 79 ++ .../resolver/expr/ob_raw_expr_resolver_impl.h | 1 + .../geometry/r/mysql/st_distance_mysql.result | 19 + .../geometry/t/st_distance_mysql.test | 14 + .../all_virtual_sys_parameter_stat.result | 1 + unittest/share/test_geo_bin.cpp | 75 +- unittest/share/test_geo_func_box.cpp | 35 +- unittest/share/test_geo_func_difference.cpp | 155 ++- unittest/share/test_geo_func_union.cpp | 151 ++- unittest/share/test_geo_tree.cpp | 17 +- unittest/share/test_wkt_parser.cpp | 102 +- .../sql/engine/expr/ob_geo_func_testx.cpp | 5 +- .../sql/engine/expr/test_gis_dispatcher.cpp | 15 +- 251 files changed, 8396 insertions(+), 3296 deletions(-) create mode 100644 deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.cpp create mode 100644 deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.h create mode 100644 deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.cpp create mode 100644 deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.h create mode 100644 src/sql/engine/expr/ob_expr_existsnode_xml.cpp create mode 100644 src/sql/engine/expr/ob_expr_existsnode_xml.h create mode 100644 src/sql/engine/expr/ob_expr_multi_mode_func_helper.cpp create mode 100644 src/sql/engine/expr/ob_expr_multi_mode_func_helper.h create mode 100644 src/sql/engine/expr/ob_expr_priv_st_geohash.cpp create mode 100644 src/sql/engine/expr/ob_expr_priv_st_geohash.h create mode 100644 src/sql/engine/expr/ob_expr_priv_st_makepoint.cpp create mode 100644 src/sql/engine/expr/ob_expr_priv_st_makepoint.h create mode 100644 src/sql/engine/expr/ob_expr_xml_concat.cpp create mode 100644 src/sql/engine/expr/ob_expr_xml_concat.h create mode 100644 src/sql/engine/expr/ob_expr_xml_forest.cpp create mode 100644 src/sql/engine/expr/ob_expr_xml_forest.h diff --git a/deps/oblib/src/common/object/ob_obj_funcs.h b/deps/oblib/src/common/object/ob_obj_funcs.h index f6f1a52f0..302151c38 100644 --- a/deps/oblib/src/common/object/ob_obj_funcs.h +++ b/deps/oblib/src/common/object/ob_obj_funcs.h @@ -1784,7 +1784,7 @@ inline int obj_print_sql(const ObObj &obj, char *buffer, int64_t len } else if (str.empty()) { // nothing to print; } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_allocator, str, in_type, in_type, j_base, parse_flag))) { COMMON_LOG(WARN, "fail to get json base", K(ret), K(in_type)); - } else if (OB_FAIL(j_base->print(jbuf, false))) { // json binary to string + } else if (OB_FAIL(j_base->print(jbuf, false, str.length()))) { // json binary to string COMMON_LOG(WARN, "fail to convert json to string", K(ret), K(obj)); } else if (OB_FAIL(databuff_printf(buffer, length, pos, "'"))) { COMMON_LOG(WARN, "fail to print \"'\"", K(ret), K(length), K(pos)); @@ -1821,7 +1821,7 @@ inline int obj_print_plain_str(const ObObj &obj, char *buffer, int64 } else if (str.empty()) { // nothing to print; } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_allocator, str, in_type, in_type, j_base, parse_flag))) { COMMON_LOG(WARN, "fail to get json base", K(ret), K(in_type)); - } else if (OB_FAIL(j_base->print(jbuf, false))) { // json binary to string + } else if (OB_FAIL(j_base->print(jbuf, false, str.length()))) { // json binary to string COMMON_LOG(WARN, "fail to convert json to string", K(ret), K(obj)); } else if (params.use_memcpy_) { ret = databuff_memcpy(buffer, length, pos, jbuf.length(), jbuf.ptr()); @@ -1849,7 +1849,7 @@ inline int obj_print_json(const ObObj &obj, char *buf, int64_t buf_l } else if (str.empty()) { // nothing to print; } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_allocator, str, in_type, in_type, j_base, parse_flag))) { COMMON_LOG(WARN, "fail to get json base", K(ret), K(in_type)); - } else if (OB_FAIL(j_base->print(jbuf, false))) { // json binary to string + } else if (OB_FAIL(j_base->print(jbuf, false, str.length()))) { // json binary to string COMMON_LOG(WARN, "fail to convert json to string", K(ret), K(obj)); } else if (OB_FAIL(databuff_printf(buf, buf_len, pos, "%.*s", static_cast(MIN(jbuf.length(), buf_len - pos)), diff --git a/deps/oblib/src/lib/CMakeLists.txt b/deps/oblib/src/lib/CMakeLists.txt index 5958b72a1..5d8f6ab32 100644 --- a/deps/oblib/src/lib/CMakeLists.txt +++ b/deps/oblib/src/lib/CMakeLists.txt @@ -93,6 +93,7 @@ ob_set_subtarget(oblib_lib geo geo/ob_sdo_geo_func_to_wkb.cpp geo/ob_wkb_to_sdo_geo_visitor.cpp geo/ob_wkb_to_json_visitor.cpp + geo/ob_wkb_to_json_bin_visitor.cpp geo/ob_wkb_byte_order_visitor.cpp geo/ob_geo_3d.cpp geo/ob_sdo_geo_object.cpp @@ -109,6 +110,7 @@ ob_set_subtarget(oblib_lib geo geo/ob_geo_simplify_visitor.cpp geo/ob_geo_box_clip_visitor.cpp geo/ob_geo_func_dissolve_polygon.cpp + geo/ob_geo_close_ring_visitor.cpp geo/ob_geo_cache.cpp geo/ob_geo_vertex_collect_visitor.cpp geo/ob_geo_segment_collect_visitor.cpp diff --git a/deps/oblib/src/lib/allocator/page_arena.h b/deps/oblib/src/lib/allocator/page_arena.h index 704361732..ea9b778d3 100644 --- a/deps/oblib/src/lib/allocator/page_arena.h +++ b/deps/oblib/src/lib/allocator/page_arena.h @@ -98,6 +98,7 @@ struct ModulePageAllocator: public ObIAllocator void set_tenant_id(uint64_t tenant_id) {attr_.tenant_id_ = tenant_id;}; void set_ctx_id(int64_t ctx_id) { attr_.ctx_id_ = ctx_id; } void set_attr(const lib::ObMemAttr &attr) { attr_ = attr; } + uint64_t get_tenant_id() { return attr_.tenant_id_; } lib::ObLabel get_label() const { return attr_.label_; } void *alloc(const int64_t sz) { @@ -525,6 +526,7 @@ public: // API void set_label(const lib::ObLabel &label) { page_allocator_.set_label(label); } lib::ObLabel get_label() const { return page_allocator_.get_label(); } + uint64_t get_tenant_id() { return page_allocator_.get_tenant_id(); } void set_tenant_id(uint64_t tenant_id) { page_allocator_.set_tenant_id(tenant_id); } void set_ctx_id(int64_t ctx_id) { page_allocator_.set_ctx_id(ctx_id); } void set_attr(const lib::ObMemAttr &attr) { page_allocator_.set_attr(attr); } diff --git a/deps/oblib/src/lib/geo/ob_geo.h b/deps/oblib/src/lib/geo/ob_geo.h index 76b80fe7e..f26657fde 100644 --- a/deps/oblib/src/lib/geo/ob_geo.h +++ b/deps/oblib/src/lib/geo/ob_geo.h @@ -23,10 +23,8 @@ class ObIGeoVisitor; class ObGeometry { public: // constructor - ObGeometry(uint32_t srid = 0, ObIAllocator *allocator = NULL) + ObGeometry(uint32_t srid = 0) : srid_(srid), - zoom_in_value_(0), - allocator_(allocator), version_(ENCODE_GEO_VERSION(GEO_VESION_1)) {} virtual ~ObGeometry() = default; ObGeometry(const ObGeometry& g) = default; @@ -47,14 +45,11 @@ public: // srid uint32_t get_srid() const { return srid_; } void set_srid(uint32_t srid) { srid_ = srid; } - uint32_t get_zoom_in_value() const { return zoom_in_value_; } - void set_zoom_in_value(uint32_t value) { zoom_in_value_ = value; } // version uint8_t get_version() { return version_; } + VIRTUAL_TO_STRING_KV(K_(srid)); protected: uint32_t srid_; - uint32_t zoom_in_value_; - ObIAllocator* allocator_; // for write mode? uint8_t version_; }; diff --git a/deps/oblib/src/lib/geo/ob_geo_3d.cpp b/deps/oblib/src/lib/geo/ob_geo_3d.cpp index 9dcf0055a..92b8490d2 100644 --- a/deps/oblib/src/lib/geo/ob_geo_3d.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_3d.cpp @@ -83,7 +83,7 @@ int ObGeometry3D::to_2d_geo(ObIAllocator &allocator, ObGeometry *&res, uint32_t } if (OB_SUCC(ret)) { bool is_geog = (crs_ == ObGeoCRS::Geographic) ? true : false; - if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(*allocator_, geo_type, is_geog, true, res, srid))) { + if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(allocator, geo_type, is_geog, true, res, srid_))) { LOG_WARN("fail to create 2d geo obj", K(ret), K(geo_type), K(is_geog)); } else { res->set_data(wkb_2d); @@ -127,10 +127,10 @@ int ObGeometry3D::read_nums_value(ObGeoWkbByteOrder bo, uint32_t &nums) int ObGeometry3D::to_wkt(ObIAllocator &allocator, ObString &wkt, uint32_t srid/* = 0*/, int64_t maxdecimaldigits/* = -1*/, bool output_srid0/* = false*/) { int ret = OB_SUCCESS; - ObStringBuffer *buf = NULL; + ObGeoStringBuffer *buf = NULL; ObGeo3DToWktVisitor visitor(maxdecimaldigits); set_pos(0); - if (OB_ISNULL(buf = OB_NEWx(ObStringBuffer, &allocator, (&allocator)))) { + if (OB_ISNULL(buf = OB_NEWx(ObGeoStringBuffer, &allocator, (&allocator)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate buffer", K(ret)); } else if (srid != 0 || output_srid0) { @@ -443,7 +443,7 @@ int ObGeometry3D::create_elevation_extent(ObGeoElevationExtent &extent) return ret; } -int ObGeometry3D::normalize(const ObSrsItem *srs, uint32_t &zoom_in_value) +int ObGeometry3D::normalize(const ObSrsItem *srs) { int ret = OB_SUCCESS; ObGeo3DNormalizeVisitor visitor(srs); @@ -453,8 +453,6 @@ int ObGeometry3D::normalize(const ObSrsItem *srs, uint32_t &zoom_in_value) } else if (!is_end()) { ret = OB_ERR_GIS_INVALID_DATA; LOG_WARN("has extra buffer in wkb", K(ret), K(cur_pos_), K(length())); - } else { - zoom_in_value = visitor.get_zoom_in_value(); } return ret; } @@ -715,9 +713,12 @@ int ObGeo3DTo2DVisitor::visit_header(ObGeoWkbByteOrder bo, ObGeoType geo_type, b int ObGeo3DTo2DVisitor::append_nums(uint32_t nums) { int ret = OB_SUCCESS; + uint64_t reserve_len = WKB_GEO_ELEMENT_NUM_SIZE + nums * WKB_GEO_DOUBLE_STORED_SIZE; if (OB_ISNULL(wkb_buf_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("wkb_buf_ is NULL", K(ret)); + } else if (OB_FAIL(wkb_buf_->reserve(reserve_len))) { + LOG_WARN("fail to resverse buffer", K(ret)); } else if (OB_FAIL(wkb_buf_->append(nums))) { LOG_WARN("fail to append nums value", K(ret)); } @@ -840,7 +841,8 @@ int ObGeo3DToWktVisitor::visit_pointz_inner(double x, double y, double z) uint64_t len_y = 0; uint64_t len_z = 0; char *buff_ptr = NULL; - if (OB_FAIL(wkt_buf_->reserve(3 * double_buff_size + 2))) { + uint32_t reserve_len = 3 * double_buff_size + 2; + if (wkt_buf_->remain() < reserve_len && OB_FAIL(wkt_buf_->reserve(reserve_len))) { LOG_WARN("fail to reserve buffer", K(ret)); } else if (FALSE_IT(buff_ptr = wkt_buf_->ptr() + wkt_buf_->length())) { } else if (OB_FAIL(ObGeoToWktVisitor::convert_double_to_str(buff_ptr, double_buff_size, x, has_scale_, scale_, is_oracle_mode_, len_x))) { @@ -1508,48 +1510,21 @@ int ObGeo3DNormalizeVisitor::visit_pointz_start(ObGeometry3D *geo, bool is_inner ObGeoWkbByteOrder bo = geo->byteorder(); double x = ObGeoWkbByteOrderUtil::read(ptr + cur_pos, bo); double y = ObGeoWkbByteOrderUtil::read(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE, bo); - double z = ObGeoWkbByteOrderUtil::read(ptr + cur_pos + 2 * WKB_GEO_DOUBLE_STORED_SIZE, bo); double nx = 1.0; double ny = 1.0; - double nz = 1.0; if (no_srs_) { nx = x * M_PI / 180.0; ny = y * M_PI / 180.0; - nz = z * M_PI / 180.0; } else { if (OB_FAIL(srs_->latitude_convert_to_radians(y, ny))) { LOG_WARN("normalize y failed", K(ret)); } else if (OB_FAIL(srs_->longtitude_convert_to_radians(x, nx))) { LOG_WARN("normalize x failed", K(ret)); } else { - uint32_t count = 0; - double nx_tmp = nx; - double ny_tmp = ny; - double nz_tmp = nz; - while (nx_tmp != 0.0 && std::fabs(nx_tmp) < ZOOM_IN_THRESHOLD) { - nx_tmp *= 10; - count++; - } - zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; - count = 0; - while (ny_tmp != 0.0 && std::fabs(ny_tmp) < ZOOM_IN_THRESHOLD) { - ny_tmp *= 10; - count++; - } - zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; - count = 0; - while (nz_tmp != 0.0 && std::fabs(nz_tmp) < ZOOM_IN_THRESHOLD) { - nz_tmp *= 10; - count++; - } - zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; + ObGeoWkbByteOrderUtil::write(ptr + cur_pos, nx, bo); + ObGeoWkbByteOrderUtil::write(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE, ny, bo); } } - if (OB_SUCC(ret)) { - ObGeoWkbByteOrderUtil::write(ptr + cur_pos, nx, bo); - ObGeoWkbByteOrderUtil::write(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE, ny, bo); - ObGeoWkbByteOrderUtil::write(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE * 2, nz, bo); - } } } return ret; diff --git a/deps/oblib/src/lib/geo/ob_geo_3d.h b/deps/oblib/src/lib/geo/ob_geo_3d.h index a2e9ef138..4a824bd30 100644 --- a/deps/oblib/src/lib/geo/ob_geo_3d.h +++ b/deps/oblib/src/lib/geo/ob_geo_3d.h @@ -33,8 +33,8 @@ enum ObLineType { class ObGeometry3D: public ObGeometry { public: - ObGeometry3D(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObGeometry(srid, allocator), cur_pos_(0) {} + ObGeometry3D(uint32_t srid = 0) + : ObGeometry(srid), cur_pos_(0) {} virtual ~ObGeometry3D() = default; ObGeometry3D(const ObGeometry3D& g) = default; ObGeometry3D& operator=(const ObGeometry3D& g) = default; @@ -63,7 +63,7 @@ public: int to_sdo_geometry(ObSdoGeoObject &sdo_geo); int to_geo_json(ObIAllocator *allocator, common::ObString &geo_json); int create_elevation_extent(ObGeoElevationExtent &extent); - int normalize(const ObSrsItem *srs, uint32_t &zoom_in_value); + int normalize(const ObSrsItem *srs); int check_empty(bool &is_empty); int correct_lon_lat(const ObSrsItem *srs); private: @@ -146,7 +146,7 @@ class ObGeo3DToWktVisitor : public ObGeo3DVisitor { public: ObGeo3DToWktVisitor(int64_t maxdecimaldigits = -1); - void set_wkt_buf(ObStringBuffer *wkt_buf) { wkt_buf_ = wkt_buf; } + void set_wkt_buf(ObGeoStringBuffer *wkt_buf) { wkt_buf_ = wkt_buf; } virtual int visit_header(ObGeoWkbByteOrder bo, ObGeoType geo_type, bool is_sub_type = false); // pointz virtual int visit_pointz_start(ObGeometry3D *geo, bool is_inner); @@ -173,7 +173,7 @@ private: int append_comma(); int append_paren(bool is_left); private: - ObStringBuffer *wkt_buf_; + ObGeoStringBuffer *wkt_buf_; bool is_oracle_mode_; bool is_mpt_visit_; bool has_scale_; @@ -287,14 +287,11 @@ class ObGeo3DNormalizeVisitor : public ObGeo3DVisitor { public: explicit ObGeo3DNormalizeVisitor(const ObSrsItem *srs, bool no_srs = false) - : srs_(srs), no_srs_(no_srs), zoom_in_value_(0) {} + : srs_(srs), no_srs_(no_srs){} virtual int visit_pointz_start(ObGeometry3D *geo, bool is_inner = false); - uint32_t get_zoom_in_value() { return zoom_in_value_; } private: - static constexpr double ZOOM_IN_THRESHOLD = 0.00000001; const ObSrsItem *srs_; bool no_srs_; // for st_transform, only proj4text is given - uint32_t zoom_in_value_; DISALLOW_COPY_AND_ASSIGN(ObGeo3DNormalizeVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_bin.cpp b/deps/oblib/src/lib/geo/ob_geo_bin.cpp index b2bb4a465..291714279 100644 --- a/deps/oblib/src/lib/geo/ob_geo_bin.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_bin.cpp @@ -13,7 +13,6 @@ #define USING_LOG_PREFIX LIB #include "ob_geo_bin.h" - namespace oceanbase { namespace common { @@ -178,13 +177,21 @@ ObWkbGeomInnerPoint::ObWkbGeomInnerPoint(const ObWkbGeomInnerPoint& p) bool ObWkbGeomInnerPoint::equals(const ObWkbGeomInnerPoint& p) const { bool bret = false; - if ((fabs(this->get<0>() - p.get<0>()) <= 1e-12) && - (fabs(this->get<1>() - p.get<1>()) <= 1e-12)) { + if ((fabs(this->get<0>() - p.get<0>()) <= OB_GEO_TOLERANCE) && + (fabs(this->get<1>() - p.get<1>()) <= OB_GEO_TOLERANCE)) { bret = true; } return bret; } +bool ObWkbGeomInnerPoint::operator==(const ObWkbGeomInnerPoint& p) const { + return (fabs(x_ - p.get<0>()) <= OB_GEO_TOLERANCE) && (fabs(y_ - p.get<1>()) <= OB_GEO_TOLERANCE); +} + +bool ObWkbGeomInnerPoint::operator!=(const ObWkbGeomInnerPoint& p) const { + return !((fabs(x_ - p.get<0>()) <= OB_GEO_TOLERANCE) && (fabs(y_ - p.get<1>()) <= OB_GEO_TOLERANCE)); +} + // Cartesian linestring uint32_t ObWkbGeomLineString::size() const { @@ -203,7 +210,7 @@ ObWkbGeomLineString::size_type ObWkbGeomLineString::length() const // iter adaptor void ObWkbGeomLineString::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { UNUSED(last_addr); UNUSED(last_idx); @@ -230,7 +237,7 @@ ObWkbGeomLinearRing::size_type ObWkbGeomLinearRing::length(ObGeoWkbByteOrder bo // iter adaptor void ObWkbGeomLinearRing::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { UNUSED(last_addr); UNUSED(last_idx); @@ -259,7 +266,7 @@ ObWkbGeomPolygonInnerRings::size_type ObWkbGeomPolygonInnerRings::length() const // iter adaptor void ObWkbGeomPolygonInnerRings::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray *&offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -328,7 +335,7 @@ ObWkbGeomMultiPoint::size_type ObWkbGeomMultiPoint::length() const // iter adaptor void ObWkbGeomMultiPoint::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { UNUSED(last_addr); UNUSED(last_idx); @@ -360,7 +367,7 @@ ObWkbGeomMultiLineString::size_type ObWkbGeomMultiLineString::length() const // iter adaptor void ObWkbGeomMultiLineString::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -384,7 +391,7 @@ ObWkbGeomMultiPolygon::size_type ObWkbGeomMultiPolygon::length() const // iter adaptor void ObWkbGeomMultiPolygon::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -408,7 +415,7 @@ ObWkbGeomCollection::size_type ObWkbGeomCollection::length() const // iter adaptor void ObWkbGeomCollection::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -595,6 +602,14 @@ ObWkbGeogInnerPoint& ObWkbGeogInnerPoint::operator=(const ObWkbGeogInnerPoint& p return *this; } +bool ObWkbGeogInnerPoint::operator==(const ObWkbGeogInnerPoint& p) const { + return (fabs(x_ - p.get<0>()) <= OB_GEO_TOLERANCE) && (fabs(y_ - p.get<1>()) <= OB_GEO_TOLERANCE); +} + +bool ObWkbGeogInnerPoint::operator!=(const ObWkbGeogInnerPoint& p) const { + return !((fabs(x_ - p.get<0>()) <= OB_GEO_TOLERANCE) && (fabs(y_ - p.get<1>()) <= OB_GEO_TOLERANCE)); +} + // Geograph linestring uint32_t ObWkbGeogLineString::size() const { @@ -613,7 +628,7 @@ ObWkbGeogLineString::size_type ObWkbGeogLineString::length() const // iter adaptor void ObWkbGeogLineString::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { UNUSED(last_addr); UNUSED(last_idx); @@ -640,7 +655,7 @@ ObWkbGeogLinearRing::size_type ObWkbGeogLinearRing::length(ObGeoWkbByteOrder bo // iter adaptor void ObWkbGeogLinearRing::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { UNUSED(last_addr); UNUSED(last_idx); @@ -669,7 +684,7 @@ ObWkbGeogPolygonInnerRings::size_type ObWkbGeogPolygonInnerRings::length() const // iter adaptor void ObWkbGeogPolygonInnerRings::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -738,7 +753,7 @@ ObWkbGeogMultiPoint::size_type ObWkbGeogMultiPoint::length() const // iter adaptor void ObWkbGeogMultiPoint::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { UNUSED(last_addr); UNUSED(last_idx); @@ -770,7 +785,7 @@ ObWkbGeogMultiLineString::size_type ObWkbGeogMultiLineString::length() const // iter adaptor void ObWkbGeogMultiLineString::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -793,7 +808,7 @@ ObWkbGeogMultiPolygon::size_type ObWkbGeogMultiPolygon::length() const // iter adaptor void ObWkbGeogMultiPolygon::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } @@ -817,7 +832,7 @@ ObWkbGeogCollection::size_type ObWkbGeogCollection::length() const // iter adaptor void ObWkbGeogCollection::get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data) + ObWkbIterOffsetArray*& offsets, pointer& data) { ObWkbUtils::get_sub_addr_common(*this, last_addr, last_idx, cur_idx, offsets, data); } diff --git a/deps/oblib/src/lib/geo/ob_geo_bin.h b/deps/oblib/src/lib/geo/ob_geo_bin.h index 560fdfa18..f1671ebd0 100644 --- a/deps/oblib/src/lib/geo/ob_geo_bin.h +++ b/deps/oblib/src/lib/geo/ob_geo_bin.h @@ -47,6 +47,8 @@ static const uint32_t WKB_POINT_DATA_SIZE = WKB_GEO_DOUBLE_STORED_SIZE + WKB_GEO static const uint32_t WKB_DATA_OFFSET = WKB_OFFSET + WKB_GEO_BO_SIZE; // skip [srid][bo][type] only used for inner points static const uint32_t WKB_INNER_POINT = WKB_DATA_OFFSET + WKB_GEO_TYPE_SIZE; + +static constexpr double OB_GEO_TOLERANCE = 5e-14; // Cartesian // [bo][type][X][Y] #pragma pack(1) @@ -95,6 +97,8 @@ public: ObWkbGeomInnerPoint& operator=(const ObWkbGeomInnerPoint& p); ObWkbGeomInnerPoint& operator=(const ObWkbGeomInnerPoint& p) const; bool equals(const ObWkbGeomInnerPoint& p) const; + bool operator==(const ObWkbGeomInnerPoint& p) const; + bool operator!=(const ObWkbGeomInnerPoint& p) const; // TODO int64_t to_string(char *buffer, const int64_t length) const{ UNUSED(buffer); @@ -133,7 +137,7 @@ public: index_type iter_idx_max() const { return size(); } index_type iter_idx_min() const { return 0; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } iterator end() { return iterator(iter_idx_max(), this); } @@ -168,7 +172,7 @@ public: index_type iter_idx_max(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const { return size(bo); } index_type iter_idx_min() const { return 0; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); // iter adapt iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } @@ -220,7 +224,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const { return data->length(static_cast(bo_)); }; iterator begin() { return iterator(iter_idx_min(), this); } // for move over exterior const_iterator begin() const { return const_iterator(iter_idx_min(), this); } // for move over exterior @@ -277,7 +281,7 @@ public: index_type iter_idx_max() const { return size(); } index_type iter_idx_min() const { return 0; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } iterator end() { return iterator(iter_idx_max(), this); } @@ -317,7 +321,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const { return data->length(); }; iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } @@ -358,7 +362,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const { return data->length(); }; iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } @@ -402,7 +406,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); // sub obj interface size_type get_sub_size(const_pointer data) const; ObGeoType get_sub_type(const_pointer data) const; @@ -464,6 +468,8 @@ public: template void set(double d, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian); ObWkbGeogInnerPoint& operator=(const ObWkbGeogInnerPoint& p); + bool operator==(const ObWkbGeogInnerPoint& p) const; + bool operator!=(const ObWkbGeogInnerPoint& p) const; // TODO int64_t to_string(char *buffer, const int64_t length) const{ UNUSED(buffer); @@ -502,7 +508,7 @@ public: index_type iter_idx_max() const { return size(); } index_type iter_idx_min() const { return 0; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } iterator end() { return iterator(iter_idx_max(), this); } @@ -537,7 +543,7 @@ public: index_type iter_idx_max(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const { return size(bo); } index_type iter_idx_min() const { return 0; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); // iter adapt iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } @@ -586,7 +592,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const { return data->length(static_cast(bo_)); }; // iter interface iterator begin() { return iterator(iter_idx_min(), this); } @@ -645,7 +651,7 @@ public: index_type iter_idx_max() const { return size(); } index_type iter_idx_min() const { return 0; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } iterator end() { return iterator(iter_idx_max(), this); } @@ -685,7 +691,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const { return data->length(); }; iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } @@ -726,7 +732,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const { return data->length(); }; iterator begin() { return iterator(iter_idx_min(), this); } const_iterator begin() const { return const_iterator(iter_idx_min(), this); } @@ -770,7 +776,7 @@ public: uint32_t data_offset() const { return WKB_COMMON_WKB_HEADER_LEN; } index_type et(index_type curidx) const { return curidx; } void get_sub_addr(const_pointer last_addr, index_type last_idx, index_type cur_idx, - ObWkbIterOffsetArray* offsets, pointer& data); + ObWkbIterOffsetArray*& offsets, pointer& data); size_type get_sub_size(const_pointer data) const; ObGeoType get_sub_type(const_pointer data) const; // iter interface diff --git a/deps/oblib/src/lib/geo/ob_geo_bin_iter.h b/deps/oblib/src/lib/geo/ob_geo_bin_iter.h index 9ef08fbef..fb8d44a65 100644 --- a/deps/oblib/src/lib/geo/ob_geo_bin_iter.h +++ b/deps/oblib/src/lib/geo/ob_geo_bin_iter.h @@ -21,7 +21,7 @@ namespace oceanbase { namespace common { -typedef common::ObSEArray ObWkbIterOffsetArray; +typedef common::ObArray ObWkbIterOffsetArray; template class ObWkbConstIterator @@ -45,7 +45,7 @@ public: ObWkbConstIterator(index_type idx, const owner_t* owner); ObWkbConstIterator(self& iter, bool do_array_assign = true); ObWkbConstIterator(const self& iter, bool do_array_assign = true); - ~ObWkbConstIterator() {} + ~ObWkbConstIterator(); // compare iter interface bool operator==(const self& iter) const { return (idx_ == iter.idx_); } bool operator!=(const self& iter) const { return (idx_ != iter.idx_); } @@ -85,12 +85,9 @@ protected: }; protected: index_type idx_; - index_type idx_min_; - index_type idx_max_; owner_t* owner_; + // should not use pointer to save diff_info_ since iterator can not return error code DiffInfo diff_info_; - DiffInfo* diff_info_ptr_; - ObWkbIterOffsetArray offsets_; ObWkbIterOffsetArray* offsets_ptr_; }; @@ -167,7 +164,7 @@ public: typename T::const_pointer last_addr, typename T::index_type last_idx, typename T::index_type cur_idx, - ObWkbIterOffsetArray* offsets, + ObWkbIterOffsetArray*& offsets, typename T::pointer& data); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_bin_iter.ipp b/deps/oblib/src/lib/geo/ob_geo_bin_iter.ipp index a6f7372bd..965a07f64 100644 --- a/deps/oblib/src/lib/geo/ob_geo_bin_iter.ipp +++ b/deps/oblib/src/lib/geo/ob_geo_bin_iter.ipp @@ -13,6 +13,7 @@ #include "ob_geo.h" #include "lib/container/ob_vector.h" +#include "share/rc/ob_tenant_base.h" namespace oceanbase { namespace common { @@ -20,13 +21,13 @@ namespace common { template ObWkbConstIterator::ObWkbConstIterator() : idx_(-1), owner_(NULL), diff_info_(), - diff_info_ptr_(&diff_info_), offsets_(), offsets_ptr_(&offsets_) -{} + offsets_ptr_(nullptr) +{ +} template ObWkbConstIterator::ObWkbConstIterator(index_type idx, const owner_t* owner) - : idx_(idx), diff_info_(), diff_info_ptr_(&diff_info_), - offsets_(), offsets_ptr_(&offsets_) + : idx_(idx), diff_info_(), offsets_ptr_(nullptr) { owner_ = const_cast(owner); } @@ -36,10 +37,20 @@ template ObWkbConstIterator::ObWkbConstIterator(self& iter, bool do_array_assign) : idx_(iter.idx_), owner_(iter.owner_), diff_info_(iter.diff_info_), - diff_info_ptr_(&diff_info_), offsets_(), offsets_ptr_(&offsets_) + offsets_ptr_(nullptr) { - if (do_array_assign) { - offsets_.assign(iter.offsets_); + int ret = OB_SUCCESS; // for log + if (iter.offsets_ptr_ != nullptr && do_array_assign) { + // If the tenant ID can be obtained, use tenant memory + ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "GeoWkbIter"); + if (nullptr != MTL_CTX()) { + mem_attr.tenant_id_ = MTL_ID(); + } + void *buf = ob_malloc(sizeof(ObWkbIterOffsetArray), mem_attr); + if (nullptr == buf || nullptr == (offsets_ptr_ = new(buf) ObWkbIterOffsetArray(*iter.offsets_ptr_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + COMMON_LOG(WARN, "allocate memory for hashmap failed", K(ret)); + } } } @@ -48,13 +59,29 @@ template ObWkbConstIterator::ObWkbConstIterator(const self& iter, bool do_array_assign) : idx_(iter.idx_), owner_(iter.owner_), diff_info_(iter.diff_info_), - diff_info_ptr_(&diff_info_), offsets_(), offsets_ptr_(&offsets_) + offsets_ptr_(nullptr) { - if (do_array_assign) { - offsets_.assign(iter.offsets_); + int ret = OB_SUCCESS; // for log + if (iter.offsets_ptr_ != nullptr && do_array_assign) { + // If the tenant ID can be obtained, use tenant memory + ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "GeoWkbIter"); + if (nullptr != MTL_CTX()) { + mem_attr.tenant_id_ = MTL_ID(); + } + void *buf = ob_malloc(sizeof(ObWkbIterOffsetArray), mem_attr); + if (nullptr == buf || nullptr == (offsets_ptr_ = new(buf) ObWkbIterOffsetArray(*iter.offsets_ptr_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + COMMON_LOG(WARN, "allocate memory for hashmap failed", K(ret)); + } } } +template +ObWkbConstIterator::~ObWkbConstIterator() +{ + OB_DELETE(ObWkbIterOffsetArray, "GeoWkbIter", offsets_ptr_); +} + // shift iter interface template typename ObWkbConstIterator::self& ObWkbConstIterator::operator++() @@ -93,10 +120,24 @@ const typename ObWkbConstIterator::self& ObWkbConstIterator::operato idx_ = iter.idx_; owner_ = iter.owner_; diff_info_ = iter.diff_info_; - // if fail to allocate memory, return the original iterator. - // offsets_ is used for cache iter, won't affect correctness. - if (OB_FAIL(offsets_.assign(iter.offsets_))) { - COMMON_LOG(WARN, "fail to allocate memory", K(ret), K(iter.offsets_.count())); + if (iter.offsets_ptr_ == nullptr) { + OB_DELETE(ObWkbIterOffsetArray, "GeoWkbIter", offsets_ptr_); + } else { + if (iter.offsets_ptr_ != nullptr) { + *iter.offsets_ptr_ = *iter.offsets_ptr_; + } else { + int ret = OB_SUCCESS; // for log + // If the tenant ID can be obtained, use tenant memory + ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "GeoWkbIter"); + if (nullptr != MTL_CTX()) { + mem_attr.tenant_id_ = MTL_ID(); + } + void *buf = ob_malloc(sizeof(ObWkbIterOffsetArray), mem_attr); + if (nullptr == buf || nullptr == (offsets_ptr_ = new(buf) ObWkbIterOffsetArray(*iter.offsets_ptr_))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + COMMON_LOG(WARN, "allocate memory for hashmap failed", K(ret), KP(iter.offsets_ptr_)); + } + } } return iter; } @@ -160,7 +201,6 @@ typename ObWkbConstIterator::reference ObWkbConstIterator::operator[ { self iter(*this, false); this->move(iter, diff, false); - iter.diff_info_ptr_ = this->diff_info_ptr_; iter.offsets_ptr_ = this->offsets_ptr_; this->update_val(iter); return *(diff_info_.last_addr_); @@ -187,12 +227,12 @@ template void ObWkbConstIterator::update_val(self& iter) const { pointer data = NULL; - iter.owner_->get_sub_addr(iter.diff_info_ptr_->last_addr_, - iter.diff_info_ptr_->last_idx_, + iter.owner_->get_sub_addr(iter.diff_info_.last_addr_, + iter.diff_info_.last_idx_, iter.idx_, iter.offsets_ptr_, data); // update info - iter.diff_info_ptr_->last_addr_ = data; - iter.diff_info_ptr_->last_idx_ = iter.idx_; + iter.diff_info_.last_addr_ = data; + iter.diff_info_.last_idx_ = iter.idx_; } @@ -291,7 +331,6 @@ typename ObWkbIterator::reference ObWkbIterator::operator[](differen { self iter(*this, false); this->move(iter, diff, false); - iter.diff_info_ptr_ = this->diff_info_ptr_; iter.offsets_ptr_ = this->offsets_ptr_; this->update_val(iter); return *(this->diff_info_.last_addr_); @@ -314,12 +353,26 @@ void ObWkbUtils::get_sub_addr_common(const T& obj, typename T::const_pointer last_addr, typename T::index_type last_idx, typename T::index_type cur_idx, - ObWkbIterOffsetArray* offsets, + ObWkbIterOffsetArray *&offsets, typename T::pointer& data) { // init or reverse offset, search from head INIT_SUCC(ret); - bool enable_offset_info = (offsets != NULL); + bool enable_offset_info = true; + if (offsets == nullptr) { + // If the tenant ID can be obtained, use tenant memory + ObMemAttr mem_attr(OB_SERVER_TENANT_ID, "GeoWkbIter"); + if (nullptr != MTL_CTX()) { + mem_attr.tenant_id_ = MTL_ID(); + } + void *buf = ob_malloc(sizeof(ObWkbIterOffsetArray), mem_attr); + if (nullptr == buf || nullptr == (offsets = new(buf) ObWkbIterOffsetArray())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + // allocate memory failed, can't maintain ObWkbIterOffsetArray + enable_offset_info = false; + COMMON_LOG(WARN, "allocate memory for hashmap failed", K(ret)); + } + } bool need_do_scan = false; char* scan_ptr = nullptr; uint32_t offset = 0; diff --git a/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.cpp index 901456a9d..8c7e6b73c 100644 --- a/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.cpp @@ -171,8 +171,7 @@ int ObGeoBoxClipVisitor::visit(ObCartesianMultipoint *geo) allocator_, mpt[i].get<0>(), mpt[i].get<1>(), - geo->get_srid(), - allocator_); + geo->get_srid()); if (OB_ISNULL(pt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for geometry", K(ret)); @@ -398,7 +397,7 @@ int ObGeoBoxClipVisitor::line_visit( { int ret = OB_SUCCESS; if (OB_ISNULL(mls)) { - mls = OB_NEWx(ObCartesianMultilinestring, allocator_); + mls = OB_NEWx(ObCartesianMultilinestring, allocator_, line.get_srid(), *allocator_); if (OB_ISNULL(mls)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for geometry", K(ret)); @@ -768,7 +767,7 @@ int ObGeoBoxClipVisitor::make_polygons( } else { for (uint32_t j = 0; OB_SUCC(ret) && j < new_mpy.size(); ++j) { bool is_covered_by = false; - ObGeoEvalCtx gis_context(allocator_); + ObGeoEvalCtx gis_context(*mem_ctx_); ObCartesianLineString *tmp_line = reinterpret_cast(&ext_ring); if (OB_FAIL(gis_context.append_geo_arg(tmp_line)) || OB_FAIL(gis_context.append_geo_arg(&new_mpy[j]))) { @@ -865,7 +864,7 @@ int ObGeoBoxClipVisitor::visit_polygon_inner_ring( double xmid = xmin_ + (xmax_ - xmin_) / 2; double ymid = ymin_ + (ymax_ - ymin_) / 2; ObCartesianPoint pt(xmid, ymid); - ObGeoEvalCtx gis_context(allocator_); + ObGeoEvalCtx gis_context(*mem_ctx_); if (OB_FAIL(gis_context.append_geo_arg(&pt)) || OB_FAIL(gis_context.append_geo_arg(&tmp_py))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -908,7 +907,7 @@ int ObGeoBoxClipVisitor::visit_polygon_ext_ring(const ObCartesianLinearring &ext double xmid = xmin_ + (xmax_ - xmin_) / 2; double ymid = ymin_ + (ymax_ - ymin_) / 2; ObCartesianPoint pt(xmid, ymid); - ObGeoEvalCtx gis_context(allocator_); + ObGeoEvalCtx gis_context(*mem_ctx_); if (OB_FAIL(gis_context.append_geo_arg(&pt)) || OB_FAIL(gis_context.append_geo_arg(&tmp_py))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::gis_func::eval( diff --git a/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.h b/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.h index 23eae3ca9..1bcc90233 100644 --- a/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_box_clip_visitor.h @@ -38,14 +38,16 @@ enum ObBoxPosition { class ObGeoBoxClipVisitor : public ObEmptyGeoVisitor { public: - explicit ObGeoBoxClipVisitor(const ObGeogBox &box, ObIAllocator &allocator) + explicit ObGeoBoxClipVisitor(const ObGeogBox &box, lib::MemoryContext &mem_ctx) : xmin_(box.xmin), ymin_(box.ymin), xmax_(box.xmax), ymax_(box.ymax), res_geo_(nullptr), - allocator_(&allocator) - {} + allocator_(&mem_ctx->get_arena_allocator()), + mem_ctx_(&mem_ctx) + { + } virtual ~ObGeoBoxClipVisitor() {} @@ -141,6 +143,7 @@ private: ObCartesianGeometrycollection *res_geo_; ObIAllocator *allocator_; bool keep_polygon_; + lib::MemoryContext *mem_ctx_; DISALLOW_COPY_AND_ASSIGN(ObGeoBoxClipVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp b/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp index 03cd108a8..b30e421b7 100644 --- a/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp @@ -584,7 +584,7 @@ int ObCachedGeoPolygon::check_valid(ObGeoEvalCtx& gis_context) int ret = OB_SUCCESS; if (!check_valid_) { bool invalid_for_cache = false; - if (OB_FAIL(ObGeoTypeUtil::polygon_check_self_intersections(*(gis_context.get_allocator()), *origin_geo_, srs_, invalid_for_cache))) { + if (OB_FAIL(ObGeoTypeUtil::polygon_check_self_intersections(gis_context.get_mem_ctx(), *origin_geo_, srs_, invalid_for_cache))) { LOG_WARN("cached polygon fail to check valid", K(ret)); } else { check_valid_ = true; diff --git a/deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.cpp new file mode 100644 index 000000000..61ef43482 --- /dev/null +++ b/deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.cpp @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX LIB +#include "ob_geo_close_ring_visitor.h" + + +namespace oceanbase { +namespace common { + +template +int ObGeoCloseRingVisitor::visit_poly(PolyTree *geo) +{ + int ret = OB_SUCCESS; + if (geo->front() != geo->back()) { + if (OB_FAIL(geo->push_back(geo->front()))) { + LOG_WARN("fail to push back point", K(ret)); + } + } + if (OB_SUCC(ret) && geo->size() < 4) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_WARN("invalid geometry polygon", K(ret), K(geo->size())); + } + return ret; +} + +int ObGeoCloseRingVisitor::visit(ObGeographLinearring *geo) +{ + return visit_poly(geo); +} + +int ObGeoCloseRingVisitor::visit(ObCartesianLinearring *geo) +{ + return visit_poly(geo); +} + +} // namespace common +} // namespace oceanbase \ No newline at end of file diff --git a/deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.h b/deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.h new file mode 100644 index 000000000..301dc636f --- /dev/null +++ b/deps/oblib/src/lib/geo/ob_geo_close_ring_visitor.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_LIB_GEO_OB_GEO_CLOSE_RING_VISITOR_ +#define OCEANBASE_LIB_GEO_OB_GEO_CLOSE_RING_VISITOR_ +#include "lib/geo/ob_geo_visitor.h" +#include "lib/geo/ob_srs_info.h" + +namespace oceanbase +{ +namespace common +{ + +class ObGeoCloseRingVisitor : public ObEmptyGeoVisitor +{ +public: + // need_convert: Configure whether conversion is required when srs type is GEOGRAPHIC_SRS. + explicit ObGeoCloseRingVisitor() {} + virtual ~ObGeoCloseRingVisitor() {} + bool prepare(ObGeometry *geo) override { return geo != nullptr; } + + // tree + int visit(ObPolygon *geo) { UNUSED(geo); return OB_SUCCESS; } + + int visit(ObGeometrycollection *geo) { UNUSED(geo); return OB_SUCCESS; } + + int visit(ObGeographLinearring *geo) override; + int visit(ObCartesianLinearring *geo) override; + + int visit(ObMultipolygon *geo) { UNUSED(geo); return OB_SUCCESS; } + + bool is_end(ObLinearring *geo) override { UNUSED(geo); return true; } + +private: + template + int visit_poly(PolyTree *geo); + DISALLOW_COPY_AND_ASSIGN(ObGeoCloseRingVisitor); +}; + +} // namespace common +} // namespace oceanbase + +#endif \ No newline at end of file diff --git a/deps/oblib/src/lib/geo/ob_geo_common.cpp b/deps/oblib/src/lib/geo/ob_geo_common.cpp index 94815ab6a..399ab1cdd 100644 --- a/deps/oblib/src/lib/geo/ob_geo_common.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_common.cpp @@ -133,12 +133,12 @@ int ObWkbBuffer::append(const char *str) int ObWkbBuffer::append(const char *str, const uint64_t len) { - return buf_.append(str, len); + return buf_.append(str, len, 0); } int ObWkbBuffer::append(const ObString &str) { - return buf_.append(str); + return buf_.append(str, 0); } int ObWkbBuffer::write(uint64_t pos, uint32_t val) diff --git a/deps/oblib/src/lib/geo/ob_geo_dispatcher.h b/deps/oblib/src/lib/geo/ob_geo_dispatcher.h index 3896c299c..817fb1c18 100644 --- a/deps/oblib/src/lib/geo/ob_geo_dispatcher.h +++ b/deps/oblib/src/lib/geo/ob_geo_dispatcher.h @@ -50,6 +50,8 @@ protected: const common::ObGeometry *g2, const ObGeoEvalCtx &context, RetType &result); + + static inline int eval_geo_func_inner(const common::ObGeoEvalCtx &gis_context, RetType &result); }; template @@ -207,6 +209,7 @@ int ObIGeoDispatcher::eval_wkb_binary(const common::ObGeometr INIT_SUCC(ret); if (g1->crs() != g2->crs()) { ret = OB_ERR_GIS_DIFFERENT_SRIDS; + OB_LOG(WARN, "invalid different srids", K(ret), K(g1->crs()), K(g2->crs())); } else { switch (g1->crs()) { case common::ObGeoCRS::Cartesian: @@ -635,6 +638,7 @@ int ObIGeoDispatcher::eval_tree_binary(const common::ObGeomet INIT_SUCC(ret); if (g1->crs() != g2->crs()) { ret = OB_ERR_GIS_DIFFERENT_SRIDS; + OB_LOG(WARN, "invalid different srids", K(ret), K(g1->crs()), K(g2->crs())); } else { switch (g1->crs()) { case common::ObGeoCRS::Cartesian: @@ -1055,6 +1059,25 @@ int ObIGeoDispatcher::eval_tree_binary(const common::ObGeomet template int ObIGeoDispatcher::eval_geo_func( const common::ObGeoEvalCtx &gis_context, RetType &result) +{ + int ret = OB_SUCCESS; + lib::MemoryContext mem_ctx = gis_context.get_mem_ctx(); + WITH_CONTEXT(mem_ctx) { + if (CURRENT_CONTEXT->attr_.label_ != "GISModule" || CURRENT_CONTEXT->attr_.use_500()) { + // only warning, not return error + OB_LOG(WARN, "should not use other label expect GISModule", + K(ret), K(CURRENT_CONTEXT->attr_), K(CURRENT_CONTEXT->attr_.use_500()), K(lbt())); + } + ret = eval_geo_func_inner(gis_context, result); + } else { + OB_LOG(WARN, "fail to do with context", K(ret)); + } + return ret; +} + +template +int ObIGeoDispatcher::eval_geo_func_inner( + const common::ObGeoEvalCtx &gis_context, RetType &result) { INIT_SUCC(ret); try { @@ -1079,6 +1102,7 @@ int ObIGeoDispatcher::eval_geo_func( ret = OB_ERR_NULL_VALUE; // error log at end of func } else if (g1->crs() != g2->crs()) { ret = OB_ERR_GIS_DIFFERENT_SRIDS; + OB_LOG(WARN, "invalid different srids", K(ret), K(g1->crs()), K(g2->crs())); } else if (g1->crs() == common::ObGeoCRS::Geographic && OB_ISNULL(gis_context.get_srs())) { ret = OB_ERR_NULL_VALUE; } else if (g1->is_tree()) { diff --git a/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.cpp index f063d71d2..26b44904b 100644 --- a/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.cpp @@ -125,15 +125,16 @@ void ObGeoElevationExtent::calculate_z() is_z_calculated_ = true; } -ObGeoElevationVisitor::ObGeoElevationVisitor(ObIAllocator &allocator, const common::ObSrsItem *srs) +ObGeoElevationVisitor::ObGeoElevationVisitor(lib::MemoryContext &mem_ctx, const common::ObSrsItem *srs) : extent_(nullptr), is_inited_(false), - allocator_(&allocator), - buffer_(allocator), + allocator_(&mem_ctx->get_arena_allocator()), + buffer_(*allocator_), srs_(srs), type_3D_(ObGeoType::GEO3DTYPEMAX), crs_(ObGeoCRS::Cartesian), - srid_(0) + srid_(0), + mem_ctx_(&mem_ctx) { if (OB_NOT_NULL(srs_)) { crs_ = (srs_->srs_type() == ObSrsType::PROJECTED_SRS) ? ObGeoCRS::Cartesian @@ -156,7 +157,7 @@ int ObGeoElevationVisitor::add_geometry( LOG_WARN("fail to check is geometry empty", K(ret)); } else if (!is_geo_empty) { ObGeometry *geo_2D = nullptr; - ObGeoEvalCtx geo_ctx(allocator_, srs_); + ObGeoEvalCtx geo_ctx(*mem_ctx_, srs_); geo_ctx.set_is_called_in_pg_expr(true); ObGeogBox *box = nullptr; if (OB_FAIL(geo_3D.to_2d_geo(tmp_allocator, geo_2D))) { diff --git a/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.h b/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.h index e70aefac7..d654ba653 100644 --- a/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_elevation_visitor.h @@ -66,7 +66,7 @@ private: class ObGeoElevationVisitor : public ObEmptyGeoVisitor { public: - explicit ObGeoElevationVisitor(ObIAllocator &allocator, const common::ObSrsItem *srs); + explicit ObGeoElevationVisitor(lib::MemoryContext &mem_ctx, const common::ObSrsItem *srs); virtual ~ObGeoElevationVisitor() { if (OB_NOT_NULL(extent_)) { extent_->~ObGeoElevationExtent(); } @@ -154,7 +154,7 @@ private: ObGeoType type_3D_; ObGeoCRS crs_; uint32_t srid_; - + lib::MemoryContext *mem_ctx_; DISALLOW_COPY_AND_ASSIGN(ObGeoElevationVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_func_buffer.cpp b/deps/oblib/src/lib/geo/ob_geo_func_buffer.cpp index fe67e18c6..5cce8e779 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_buffer.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_buffer.cpp @@ -61,13 +61,6 @@ private: static bool apply_bg_equal(ObGeographPolygon &geo1, ObGeographPolygon &geo2, const ObSrsItem *srs); - template - static int apply_bg_remove_duplicate_geo(ObIAllocator &allocator, - const ObSrsItem *srs, - ObGeometry *&geo); - static int remove_duplicate_geo(ObIAllocator &allocator, - const ObSrsItem *srs, - ObGeometry *&geo); template static int unwrap_geo_tree_inner(ObGeometry *geo_in, ObGeometry *&geo_out); @@ -231,10 +224,10 @@ private: ObCartesianMultipolygon *mpt_res = NULL; ObCartesianMultipolygon *ml_res = NULL; ObCartesianMultipolygon *mpo_res = NULL; - ObCartesianMultipolygon *geo_res = NULL; ObGeometry *dedup_pt_ptr = NULL; ObGeometry *dedup_ml_ptr = NULL; ObGeometry *dedup_mpo_ptr = NULL; + ObArenaAllocator tmp_allocator; ObCartesianGeometrycollection *geo_tree = NULL; common::ObIAllocator *allocator = context.get_allocator(); @@ -247,135 +240,106 @@ private: } else if ((srid != 0) && OB_ISNULL(srs)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid strategy for cartisan collection with null srs", K(srid), K(ret)); + } else if (OB_FAIL(ObGeoFuncUtils::ob_gc_prepare(context, const_cast(g), mpt, ml, mpo))) { + LOG_WARN("fail to do gc prepare", K(ret)); + } else if (OB_ISNULL(mpt) || OB_ISNULL(ml) || OB_ISNULL(mpo)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null geometry collection union", K(ret), KP(mpt), KP(ml), KP(mpo)); + } else if (OB_ISNULL(strategy = context.get_val_arg(0)->strategy_)) { + ret = OB_INVALID_ARGUMENT; + } else if (strategy->distance_val_ < 0 && !(mpt->empty() && ml->empty())) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("negative distance is only permitted for geometry collection with only (multi)polygon", K(ret)); + } else if (OB_NOT_NULL(mpt) + && (dedup_pt_ptr = reinterpret_cast(mpt)) + && OB_FAIL(ObGeoTypeUtil::remove_duplicate_geo(dedup_pt_ptr, context.get_mem_ctx(), srs, false))) { + LOG_WARN("failed to deduplicate points", K(ret)); + } else if (OB_NOT_NULL(ml) && (dedup_ml_ptr = reinterpret_cast(ml)) + && OB_FAIL(ObGeoTypeUtil::remove_duplicate_geo(dedup_ml_ptr, context.get_mem_ctx(), srs, false))) { + LOG_WARN("failed to deduplicate lines", K(ret)); + } else if (OB_NOT_NULL(mpo) && (dedup_mpo_ptr = reinterpret_cast(mpo)) + && OB_FAIL(ObGeoTypeUtil::remove_duplicate_geo(dedup_mpo_ptr, context.get_mem_ctx(), srs, false))) { + LOG_WARN("failed to deduplicate polygons", K(ret)); + } else if (OB_ISNULL(mpt_res = OB_NEWx(ObCartesianMultipolygon, &tmp_allocator, srid, tmp_allocator))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); + } else if (OB_ISNULL(ml_res = OB_NEWx(ObCartesianMultipolygon, &tmp_allocator, srid, tmp_allocator))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); + } else if (OB_ISNULL(mpo_res = OB_NEWx(ObCartesianMultipolygon, &tmp_allocator, srid, tmp_allocator))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); } else { - ObGeoToTreeVisitor visitor(allocator); - if (is_tree == false) { - ObIWkbGeomCollection *i_geo = - const_cast(reinterpret_cast(g)); - if (OB_FAIL(i_geo->do_visit(visitor))) { - LOG_WARN("failed to do geo to tree visit", K(ret)); - } else { - geo_tree = static_cast(visitor.get_geometry()); + mpt = reinterpret_cast(dedup_pt_ptr); + ml = reinterpret_cast(dedup_ml_ptr); + mpo = reinterpret_cast(dedup_mpo_ptr); + + // param 1, 2 + bg::strategy::buffer::distance_symmetric distance_s(strategy->distance_val_); + bg::strategy::buffer::side_straight side_s; + // param 3 + bg::strategy::buffer::join_round join_round_s(strategy->join_round_val_); + bg::strategy::buffer::join_miter join_miter_s(strategy->join_miter_val_); + // param 4 + bg::strategy::buffer::end_round end_round_s(strategy->end_round_val_); + bg::strategy::buffer::end_flat end_flat_s; + // param 5 + bg::strategy::buffer::point_circle point_circle_s(strategy->point_circle_val_); + bg::strategy::buffer::point_square point_square_s; + + switch (ObGeoBufferStrategyStateType(strategy->state_num_)) { + case ObGeoBufferStrategyStateType::JR_ER_PC: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_round_s, point_circle_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_round_s, point_circle_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_round_s, point_circle_s); + break; } - } else { - geo_tree = - const_cast(reinterpret_cast(g)); - } - - if (OB_FAIL(ret)) { - // do nothing - } else if (OB_ISNULL(geo_tree)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("failed to convert to geo tree", K(ret), KP(geo_res)); - } else if (OB_ISNULL((geo_res = OB_NEWx(ObCartesianMultipolygon , allocator, srid, *allocator)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory", K(ret), KP(geo_res)); - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_split(*allocator, *geo_tree, mpt, ml, mpo))) { - LOG_WARN("failed to do geometry collection split", K(ret)); - } else if (OB_ISNULL(mpt) || OB_ISNULL(ml) || OB_ISNULL(mpo)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null geometry collection split", K(ret), KP(mpt), KP(ml), KP(mpo)); - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *srs, mpt, ml, mpo))) { - LOG_WARN("failed to do geometry collection union", K(ret)); - } else if (OB_ISNULL(mpt) || OB_ISNULL(ml) || OB_ISNULL(mpo)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null geometry collection union", K(ret), KP(mpt), KP(ml), KP(mpo)); - } else if (OB_ISNULL(strategy = context.get_val_arg(0)->strategy_)) { - ret = OB_INVALID_ARGUMENT; - } else if (strategy->distance_val_ < 0 && !(mpt->empty() && ml->empty())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("negative distance is only permitted for geometry collection with only (multi)polygon", K(ret)); - } else if (OB_NOT_NULL(mpt) - && (dedup_pt_ptr = reinterpret_cast(mpt)) - && OB_FAIL(remove_duplicate_geo(*allocator, srs, dedup_pt_ptr))) { - LOG_WARN("failed to deduplicate points", K(ret)); - } else if (OB_NOT_NULL(ml) && (dedup_ml_ptr = reinterpret_cast(ml)) - && OB_FAIL(remove_duplicate_geo(*allocator, srs, dedup_ml_ptr))) { - LOG_WARN("failed to deduplicate lines", K(ret)); - } else if (OB_NOT_NULL(mpo) && (dedup_mpo_ptr = reinterpret_cast(mpo)) - && OB_FAIL(remove_duplicate_geo(*allocator, srs, dedup_mpo_ptr))) { - LOG_WARN("failed to deduplicate polygons", K(ret)); - } else if (OB_ISNULL(mpt_res = OB_NEWx(ObCartesianMultipolygon, allocator, srid, *allocator))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory", K(ret)); - } else if (OB_ISNULL(ml_res = OB_NEWx(ObCartesianMultipolygon, allocator, srid, *allocator))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory", K(ret)); - } else if (OB_ISNULL(mpo_res = OB_NEWx(ObCartesianMultipolygon, allocator, srid, *allocator))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory", K(ret)); - } else { - mpt = reinterpret_cast(dedup_pt_ptr); - ml = reinterpret_cast(dedup_ml_ptr); - mpo = reinterpret_cast(dedup_mpo_ptr); - - // param 1, 2 - bg::strategy::buffer::distance_symmetric distance_s(strategy->distance_val_); - bg::strategy::buffer::side_straight side_s; - // param 3 - bg::strategy::buffer::join_round join_round_s(strategy->join_round_val_); - bg::strategy::buffer::join_miter join_miter_s(strategy->join_miter_val_); - // param 4 - bg::strategy::buffer::end_round end_round_s(strategy->end_round_val_); - bg::strategy::buffer::end_flat end_flat_s; - // param 5 - bg::strategy::buffer::point_circle point_circle_s(strategy->point_circle_val_); - bg::strategy::buffer::point_square point_square_s; - - switch (ObGeoBufferStrategyStateType(strategy->state_num_)) { - case ObGeoBufferStrategyStateType::JR_ER_PC: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_round_s, point_circle_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_round_s, point_circle_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_round_s, point_circle_s); - break; - } - case ObGeoBufferStrategyStateType::JR_ER_PS: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_round_s, point_square_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_round_s, point_square_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_round_s, point_square_s); - break; - } - case ObGeoBufferStrategyStateType::JR_EF_PC: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_flat_s, point_circle_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_flat_s, point_circle_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_flat_s, point_circle_s); - break; - } - case ObGeoBufferStrategyStateType::JR_EF_PS: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_flat_s, point_square_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_flat_s, point_square_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_flat_s, point_square_s); - break; - } - case ObGeoBufferStrategyStateType::JM_ER_PC: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_round_s, point_circle_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_round_s, point_circle_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_round_s, point_circle_s); - break; - } - case ObGeoBufferStrategyStateType::JM_ER_PS: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_round_s, point_square_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_round_s, point_square_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_round_s, point_square_s); - break; - } - case ObGeoBufferStrategyStateType::JM_EF_PC: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_flat_s, point_circle_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_flat_s, point_circle_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_flat_s, point_circle_s); - break; - } - case ObGeoBufferStrategyStateType::JM_EF_PS: { - bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_flat_s, point_square_s); - bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_flat_s, point_square_s); - bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_flat_s, point_square_s); - break; - } - default: { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("error strategy state number", K(ret), K(strategy->state_num_)); - break; - } + case ObGeoBufferStrategyStateType::JR_ER_PS: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_round_s, point_square_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_round_s, point_square_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_round_s, point_square_s); + break; + } + case ObGeoBufferStrategyStateType::JR_EF_PC: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_flat_s, point_circle_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_flat_s, point_circle_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_flat_s, point_circle_s); + break; + } + case ObGeoBufferStrategyStateType::JR_EF_PS: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_round_s, end_flat_s, point_square_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_round_s, end_flat_s, point_square_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_round_s, end_flat_s, point_square_s); + break; + } + case ObGeoBufferStrategyStateType::JM_ER_PC: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_round_s, point_circle_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_round_s, point_circle_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_round_s, point_circle_s); + break; + } + case ObGeoBufferStrategyStateType::JM_ER_PS: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_round_s, point_square_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_round_s, point_square_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_round_s, point_square_s); + break; + } + case ObGeoBufferStrategyStateType::JM_EF_PC: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_flat_s, point_circle_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_flat_s, point_circle_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_flat_s, point_circle_s); + break; + } + case ObGeoBufferStrategyStateType::JM_EF_PS: { + bg::buffer(*mpt, *mpt_res, distance_s, side_s, join_miter_s, end_flat_s, point_square_s); + bg::buffer(*ml, *ml_res, distance_s, side_s, join_miter_s, end_flat_s, point_square_s); + bg::buffer(*mpo, *mpo_res, distance_s, side_s, join_miter_s, end_flat_s, point_square_s); + break; + } + default: { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("error strategy state number", K(ret), K(strategy->state_num_)); + break; } } } @@ -389,13 +353,13 @@ private: } } else { ObGeometry *temp_geo = NULL; - ObGeoEvalCtx union_context_mpt_ml(allocator, srs); + ObGeoEvalCtx union_context_mpt_ml(context.get_mem_ctx(), srs); union_context_mpt_ml.append_geo_arg(mpt_res); union_context_mpt_ml.append_geo_arg(ml_res); if (OB_FAIL(ObGeoFuncUnion::eval(union_context_mpt_ml, temp_geo))) { LOG_WARN("union buffer result of multipoints and multistringline failed", K(ret)); } else { - ObGeoEvalCtx union_context_mpt_ml_mpo(allocator, srs); + ObGeoEvalCtx union_context_mpt_ml_mpo(context.get_mem_ctx(), srs); union_context_mpt_ml_mpo.append_geo_arg(temp_geo); union_context_mpt_ml_mpo.append_geo_arg(mpo_res); if (OB_FAIL(ObGeoFuncUnion::eval(union_context_mpt_ml_mpo, temp_geo))) { @@ -428,8 +392,8 @@ private: ObGeoBufferStrategy *strategy = context.get_val_arg(0)->strategy_; // Notice: transfrom context use dest srs common::ObIAllocator *allocator = context.get_allocator(); - ObGeoEvalCtx transfrom_proj_context(allocator, strategy->srs_proj_); - ObGeoEvalCtx transfrom_wgs84_context(allocator, strategy->srs_wgs84_); + ObGeoEvalCtx transfrom_proj_context(context.get_mem_ctx(), strategy->srs_proj_); + ObGeoEvalCtx transfrom_wgs84_context(context.get_mem_ctx(), strategy->srs_wgs84_); ObGeometry *projected_geo = NULL; ObGeometry *projected_result = NULL; ObGeometry *projected_bin = NULL; @@ -772,140 +736,6 @@ bool ObGeoFuncBufferImpl::apply_bg_equal(ObGeographPolygon &geo1, return bg::equals(geo1, geo2, line_strategy); } -template -int ObGeoFuncBufferImpl::apply_bg_remove_duplicate_geo(ObIAllocator &allocator, - const ObSrsItem *srs, - ObGeometry *&geo) -{ - INIT_SUCC(ret); - switch (geo->type()) { - case ObGeoType::POINT : - case ObGeoType::LINESTRING : - case ObGeoType::POLYGON : - break; - case ObGeoType::MULTIPOINT : { - MultiPointType *mp = OB_NEWx(MultiPointType, (&allocator)); - if (OB_ISNULL(mp)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory for multipoint", K(ret)); - } else { - bool is_equal = false; - MultiPointType *g = static_cast(geo); - FOREACH_X(item, (*g), OB_SUCC(ret)) { - FOREACH(point, *mp) { - is_equal = ObGeoFuncBufferImpl::apply_bg_equal(*item, *point, srs); - if (is_equal) { - break; - } - } - if (!is_equal) { - if(OB_FAIL(mp->push_back(*item))) { - LOG_WARN("failed to add point to multipoint", K(ret)); - } - } - } - geo = mp; - } - break; - } - case ObGeoType::MULTILINESTRING : { - MultiLineType *ml = OB_NEWx(MultiLineType, (&allocator)); - if (OB_ISNULL(ml)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory for multiline", K(ret)); - } else { - bool is_equal = false; - MultiLineType *g = static_cast(geo); - FOREACH_X(item, (*g), OB_SUCC(ret)) { - FOREACH(line, *ml) { - is_equal = ObGeoFuncBufferImpl::apply_bg_equal(*item, *line, srs); - if (is_equal) { - break; - } - } - if (!is_equal) { - if(OB_FAIL(ml->push_back(*item))) { - LOG_WARN("failed to add line to multiline", K(ret)); - } - } - } - geo = ml; - } - break; - } - case ObGeoType::MULTIPOLYGON : { - MultiPolygonType *mpoly = OB_NEWx(MultiPolygonType, (&allocator)); - if (OB_ISNULL(mpoly)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate memory for multipolygon", K(ret)); - } else { - bool is_equal = false; - MultiPolygonType *g = static_cast(geo); - FOREACH_X(item, *g, OB_SUCC(ret)) { - FOREACH(poly, *mpoly) { - is_equal = ObGeoFuncBufferImpl::apply_bg_equal(*item, *poly, srs); - if (is_equal) { - break; - } - } - if (!is_equal) { - if(OB_FAIL(mpoly->push_back(*item))) { - LOG_WARN("failed to add polygon to multipolygon", K(ret)); - } - } - } - geo = mpoly; - } - break; - } - default : { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid geo type", K(ret), K(geo->type()), K(geo->crs())); - break; - } - } - return ret; -} - -int ObGeoFuncBufferImpl::remove_duplicate_geo(ObIAllocator &allocator, - const ObSrsItem *srs, - ObGeometry *&geo) -{ - INIT_SUCC(ret); - if (geo == NULL) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("input geo is null", K(ret)); - } else if ((srs == NULL || srs->srs_type() != ObSrsType::GEOGRAPHIC_SRS) - && geo->crs() == ObGeoCRS::Geographic) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid srs type", K(ret), KP(srs), K(geo->crs())); - } else { - switch (geo->crs()) { - case ObGeoCRS::Geographic : { - ret = apply_bg_remove_duplicate_geo(allocator, srs, geo); - if (OB_FAIL(ret)) { - LOG_WARN("failed to remove duplicate geo", K(ret), K(geo->crs())); - } - break; - } - case ObGeoCRS::Cartesian : { - ret = apply_bg_remove_duplicate_geo(allocator, srs, geo); - if (OB_FAIL(ret)) { - LOG_WARN("failed to remove duplicate geo", K(ret), K(geo->crs())); - } - break; - } - default : { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid geo type", K(ret), K(srs->srs_type()), K(geo->crs())); - } - } - } - return ret; -} - template int ObGeoFuncBufferImpl::unwrap_geo_tree_inner(ObGeometry *geo_in, ObGeometry *&geo_out) diff --git a/deps/oblib/src/lib/geo/ob_geo_func_centroid.cpp b/deps/oblib/src/lib/geo/ob_geo_func_centroid.cpp index ad979f117..da18f4c14 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_centroid.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_centroid.cpp @@ -51,7 +51,7 @@ private: ObCartesianMultilinestring *ml = nullptr; ObCartesianMultipolygon *mpo = nullptr; ObIAllocator *allocator = context.get_allocator(); - ObCartesianPoint *res_geo = OB_NEWx(ObCartesianPoint, allocator, 0, 0, g->get_srid(), allocator); + ObCartesianPoint *res_geo = OB_NEWx(ObCartesianPoint, allocator, 0, 0, g->get_srid()); ObGeoToTreeVisitor tree_visitor(allocator); if (OB_ISNULL(res_geo)) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -85,7 +85,7 @@ private: static int centroid_default(const ObGeometry *g, const ObGeoEvalCtx &context, ObGeometry *&result) { int ret = OB_SUCCESS; - ObCartesianPoint *res_geo = OB_NEWx(ObCartesianPoint, context.get_allocator(), 0, 0, g->get_srid(), context.get_allocator()); + ObCartesianPoint *res_geo = OB_NEWx(ObCartesianPoint, context.get_allocator(), 0, 0, g->get_srid()); if (OB_ISNULL(res_geo)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for result grometry", K(ret)); diff --git a/deps/oblib/src/lib/geo/ob_geo_func_common.h b/deps/oblib/src/lib/geo/ob_geo_func_common.h index 2be7a383d..aa92b082b 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_common.h +++ b/deps/oblib/src/lib/geo/ob_geo_func_common.h @@ -50,11 +50,12 @@ union ObGeoNormalVal { class ObGeoEvalCtx { public: - ObGeoEvalCtx() : allocator_(NULL), srs_(NULL), g_arg_c_(0), v_arg_c_(0), is_called_in_pg_expr_(false){}; - ObGeoEvalCtx(common::ObIAllocator * allocator) : - allocator_(allocator), srs_(NULL), g_arg_c_(0), v_arg_c_(0), is_called_in_pg_expr_(false) {}; - ObGeoEvalCtx(common::ObIAllocator * allocator, const common::ObSrsItem *srs_item) : - allocator_(allocator), srs_(srs_item), g_arg_c_(0), v_arg_c_(0), is_called_in_pg_expr_(false) {}; + ObGeoEvalCtx(lib::MemoryContext &mem_ctx) : + allocator_(&mem_ctx->get_arena_allocator()), srs_(NULL), g_arg_c_(0), v_arg_c_(0), + is_called_in_pg_expr_(false), mem_ctx_(mem_ctx) {}; + ObGeoEvalCtx(lib::MemoryContext &mem_ctx, const common::ObSrsItem *srs_item) : + allocator_(&mem_ctx->get_arena_allocator()), srs_(srs_item), g_arg_c_(0), v_arg_c_(0), + is_called_in_pg_expr_(false), mem_ctx_(mem_ctx) {}; ~ObGeoEvalCtx() = default; inline int append_geo_arg(const common::ObGeometry *g) @@ -156,6 +157,7 @@ public: inline void set_is_called_in_pg_expr(bool in) { is_called_in_pg_expr_ = in; } inline bool get_is_called_in_pg_expr() const { return is_called_in_pg_expr_; } + inline lib::MemoryContext &get_mem_ctx() const { return mem_ctx_; } // interfaces for unittest only inline void ut_set_geo_count(int count) @@ -180,6 +182,7 @@ private: const common::ObGeometry *gis_args_[MAX_ARG_COUNT]; // geo arguments ObGeoNormalVal val_args_[MAX_ARG_COUNT]; // other arguments bool is_called_in_pg_expr_; // distinguish pg/mysql expr call + lib::MemoryContext &mem_ctx_; private: DISALLOW_COPY_AND_ASSIGN(ObGeoEvalCtx); diff --git a/deps/oblib/src/lib/geo/ob_geo_func_covered_by.cpp b/deps/oblib/src/lib/geo/ob_geo_func_covered_by.cpp index fa16047f7..4b48307a8 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_covered_by.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_covered_by.cpp @@ -162,10 +162,11 @@ OB_GEO_CART_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeomPoint, ObWkbGeomC break; } case ObGeoType::POLYGON : { + ObArenaAllocator tmp_alloc; const ObWkbGeomPolygon *polygon = reinterpret_cast(sub_ptr); ObString tmp(polygon->length(), reinterpret_cast(sub_ptr)); ObString pol_data; - if (OB_FAIL(ob_write_string(*context.get_allocator(), tmp, pol_data))) { + if (OB_FAIL(ob_write_string(tmp_alloc, tmp, pol_data))) { LOG_WARN("failed to copy polygon geo", K(ret)); } else { ObWkbGeomPolygon *poly_copy = reinterpret_cast(pol_data.ptr()); @@ -175,10 +176,11 @@ OB_GEO_CART_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeomPoint, ObWkbGeomC break; } case ObGeoType::MULTIPOLYGON : { + ObArenaAllocator tmp_alloc; const ObWkbGeomMultiPolygon *multi_poly = reinterpret_cast(sub_ptr); ObString tmp(multi_poly->length(), reinterpret_cast(sub_ptr)); ObString multipol_data; - if (OB_FAIL(ob_write_string(*context.get_allocator(), tmp, multipol_data))) { + if (OB_FAIL(ob_write_string(tmp_alloc, tmp, multipol_data))) { LOG_WARN("failed to copy multi_poly geo", K(ret)); } else { ObWkbGeomMultiPolygon *multipoly_copy = reinterpret_cast(multipol_data.ptr()); @@ -655,10 +657,11 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogPoint, ObWkbGeogC } case ObGeoType::POLYGON : { + ObArenaAllocator tmp_alloc; const ObWkbGeogPolygon *polygon = reinterpret_cast(sub_ptr); ObString tmp(polygon->length(), reinterpret_cast(sub_ptr)); ObString pol_data; - if (OB_FAIL(ob_write_string(*context.get_allocator(), tmp, pol_data))) { + if (OB_FAIL(ob_write_string(tmp_alloc, tmp, pol_data))) { LOG_WARN("failed to copy polygon geo", K(ret)); } else { ObWkbGeogPolygon *poly_copy = reinterpret_cast(pol_data.ptr()); @@ -674,10 +677,11 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogPoint, ObWkbGeogC break; } case ObGeoType::MULTIPOLYGON : { + ObArenaAllocator tmp_alloc; const ObWkbGeogMultiPolygon *multi_poly = reinterpret_cast(sub_ptr); ObString tmp(multi_poly->length(), reinterpret_cast(sub_ptr)); ObString multipol_data; - if (OB_FAIL(ob_write_string(*context.get_allocator(), tmp, multipol_data))) { + if (OB_FAIL(ob_write_string(tmp_alloc, tmp, multipol_data))) { LOG_WARN("failed to copy multi_poly geo", K(ret)); } else { ObWkbGeogMultiPolygon *multipoly_copy = reinterpret_cast(multipol_data.ptr()); @@ -1273,7 +1277,7 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogCollection, ObWkb OB_GEO_CART_TREE_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObCartesianLineString, ObCartesianPolygon, bool) { UNUSED(context); - const ObCartesianPoint *geo1 = reinterpret_cast(g1); + const ObCartesianLineString *geo1 = reinterpret_cast(g1); const ObCartesianPolygon *geo2 = reinterpret_cast(g2); result = boost::geometry::covered_by(*geo1, *geo2); return OB_SUCCESS; diff --git a/deps/oblib/src/lib/geo/ob_geo_func_crosses.cpp b/deps/oblib/src/lib/geo/ob_geo_func_crosses.cpp index 2af86b475..cfdd22698 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_crosses.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_crosses.cpp @@ -194,7 +194,7 @@ private: { int ret = OB_SUCCESS; ObGeometry *last_res = res; - ObGeoEvalCtx diff_ctx(context.get_allocator(), context.get_srs()); + ObGeoEvalCtx diff_ctx(context.get_mem_ctx(), context.get_srs()); if (OB_FAIL(diff_ctx.append_geo_arg(g1)) || OB_FAIL(diff_ctx.append_geo_arg(g2))) { LOG_WARN("failed to append geo to ctx", K(ret)); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(diff_ctx, res))) { @@ -357,7 +357,7 @@ private: LOG_WARN("unexpected null geometry collection split", K(ret)); } else if (!mpy1->empty()) { result.is_null = true; - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *srs, mpt1, mls1, mpy1))) { + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *srs, mpt1, mls1, mpy1))) { LOG_WARN("failed to do gc union", K(ret)); } else if (OB_ISNULL(mpt1) || OB_ISNULL(mls1) || OB_ISNULL(mpy1)) { ret = OB_ERR_UNEXPECTED; @@ -381,7 +381,7 @@ private: } else if (OB_ISNULL(mpt2) || OB_ISNULL(mls2) || OB_ISNULL(mpy2)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null geometry collection split", K(ret)); - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *srs, mpt2, mls2, mpy2))) { + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *srs, mpt2, mls2, mpy2))) { LOG_WARN("failed to do gc union", K(ret)); } else if (OB_ISNULL(mpt2) || OB_ISNULL(mls2) || OB_ISNULL(mpy2)) { ret = OB_ERR_UNEXPECTED; @@ -407,7 +407,7 @@ private: static int make_collection(const ObGeometry *g, ObIAllocator *allocator, const ObGeometry *&geo) { int ret = OB_SUCCESS; - GcBinType *gc_bin = OB_NEWx(GcBinType, allocator); + GcBinType *gc_bin = OB_NEWx(GcBinType, allocator, g->get_srid()); ObWkbBuffer buffer(*allocator); if (OB_ISNULL(gc_bin)) { ret = OB_ERR_UNEXPECTED; diff --git a/deps/oblib/src/lib/geo/ob_geo_func_difference.cpp b/deps/oblib/src/lib/geo/ob_geo_func_difference.cpp index 75dc112bf..8e719a4a5 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_difference.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_difference.cpp @@ -178,7 +178,7 @@ private: { INIT_SUCC(ret); - CollType *res = OB_NEWx(CollType, context.get_allocator()); + CollType *res = OB_NEWx(CollType, context.get_allocator(), g1->get_srid(), *context.get_allocator()); MptType *mpt = NULL; MlsType *mls = NULL; MpyType *mpy = NULL; @@ -198,7 +198,7 @@ private: } else if (OB_ISNULL(mpt) || OB_ISNULL(mls) || OB_ISNULL(mpy)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null geometry collection split", K(ret), KP(mpt), KP(mls), KP(mpy)); - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*context.get_allocator(), *context.get_srs(), mpt, mls, mpy))) { + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *context.get_srs(), mpt, mls, mpy))) { LOG_WARN("failed to do geometry collection union", K(ret)); } else if (OB_ISNULL(mpt) || OB_ISNULL(mls) || OB_ISNULL(mpy)) { ret = OB_ERR_UNEXPECTED; @@ -254,7 +254,8 @@ private: MptType *mpt_res_tree = reinterpret_cast(mpt_res); typename MptType::iterator iter = mpt_res_tree->begin(); for (; OB_SUCC(ret) && iter != mpt_res_tree->end(); iter++) { - typename CollType::sub_pt_type *pt = OB_NEWx(typename CollType::sub_pt_type, context.get_allocator()); + typename CollType::sub_pt_type *pt = OB_NEWx( + typename CollType::sub_pt_type, context.get_allocator(), mpt_res_tree->get_srid()); if (OB_ISNULL(pt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memotry for point", K(ret)); @@ -379,8 +380,7 @@ private: allocator, pt.template get<0>(), pt.template get<1>(), - g1->get_srid(), - allocator); + g1->get_srid()); if (OB_ISNULL(pt_tree)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory", K(ret)); @@ -479,7 +479,7 @@ private: LOG_WARN("fail to do eval", K(ret)); } else if (FALSE_IT(iter++)) { } else if (iter != geo2->end()) { - if (OB_FAIL((ObGeoFuncUtils::simplify_multi_geo(result, *allocator)))) { + if (OB_FAIL((ObGeoTypeUtil::simplify_multi_geo(result, *allocator)))) { // should not do simplify in difference functor, it may affect // ObGeoFuncUtils::ob_geo_gc_union LOG_WARN("fail to simplify result", K(ret)); diff --git a/deps/oblib/src/lib/geo/ob_geo_func_dissolve_polygon.cpp b/deps/oblib/src/lib/geo/ob_geo_func_dissolve_polygon.cpp index b5d071bf7..6148c86fc 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_dissolve_polygon.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_dissolve_polygon.cpp @@ -49,15 +49,16 @@ static int eval_dissolve_polygon( ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create go by type", K(ret), K(res)); } else if (is_self_intersects) { + ObArenaAllocator tmp_alloc; MPY *left_part = - OB_NEWx(MPY, context.get_allocator(), g1->get_srid(), *context.get_allocator()); + OB_NEWx(MPY, &tmp_alloc, g1->get_srid(), tmp_alloc); MPY *right_part = - OB_NEWx(MPY, context.get_allocator(), g1->get_srid(), *context.get_allocator()); - if (OB_ISNULL(res) || OB_ISNULL(left_part) || OB_ISNULL(right_part)) { + OB_NEWx(MPY, &tmp_alloc, g1->get_srid(), tmp_alloc); + if (OB_ISNULL(left_part) || OB_ISNULL(right_part)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create go by type", K(ret), K(res), K(left_part), K(right_part)); } else { - GeometryType *g1_rev = OB_NEWx(GeometryType, context.get_allocator(), *geo1); + GeometryType *g1_rev = OB_NEWx(GeometryType, &tmp_alloc, *geo1); if (OB_ISNULL(g1_rev)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create go by type", K(ret)); @@ -67,13 +68,24 @@ static int eval_dissolve_polygon( } } } else { + ObArenaAllocator tmp_alloc; bg::intersection(*geo1, *geo1, *res); if (res->is_empty() && !geo1->is_empty()) { - bg::reverse(*geo1); - bg::intersection(*geo1, *geo1, *res); + GeometryType *g1_rev = OB_NEWx(GeometryType, &tmp_alloc, *geo1); + if (OB_ISNULL(g1_rev)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to create go by type", K(ret)); + } else { + bg::reverse(*g1_rev); + bg::intersection(*g1_rev, *g1_rev, *res); + } + } + if (OB_SUCC(ret)) { + bg::correct(*res); } } - if (res->size() == 1) { + if (OB_FAIL(ret)) { + } else if (res->size() == 1) { result = &res->front(); } else { result = res; @@ -108,11 +120,12 @@ static int eval_dissolve_multipolygon( ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create go by type", K(ret), K(res)); } else if (is_self_intersects) { - MPY *left_part = - OB_NEWx(MPY, context.get_allocator(), g1->get_srid(), *context.get_allocator()); + ObArenaAllocator tmp_alloc; + MPY *left_part = + OB_NEWx(MPY, &tmp_alloc, g1->get_srid(), tmp_alloc); MPY *right_part = - OB_NEWx(MPY, context.get_allocator(), g1->get_srid(), *context.get_allocator()); - if (OB_ISNULL(res) || OB_ISNULL(left_part) || OB_ISNULL(right_part)) { + OB_NEWx(MPY, &tmp_alloc, g1->get_srid(), tmp_alloc); + if (OB_ISNULL(left_part) || OB_ISNULL(right_part)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create go by type", K(ret), K(res), K(left_part), K(right_part)); } else { @@ -127,6 +140,7 @@ static int eval_dissolve_multipolygon( bg::reverse(*geo1); bg::intersection(*geo1, *geo1, *res); } + bg::correct(*res); } if (OB_FAIL(ret)) { } else if (res->size() == 1) { diff --git a/deps/oblib/src/lib/geo/ob_geo_func_intersects.cpp b/deps/oblib/src/lib/geo/ob_geo_func_intersects.cpp index 8d4b6c124..cc77aa8e1 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_intersects.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_intersects.cpp @@ -30,7 +30,7 @@ int eval_intersects_by_disjoint(const ObGeometry *g1, const ObGeometry *g2, cons INIT_SUCC(ret); result = false; // Notice:should not use geoemtry from context, they are the original inputs, maybe changed - ObGeoEvalCtx disjoint_context(context.get_allocator(), context.get_srs()); + ObGeoEvalCtx disjoint_context(context.get_mem_ctx(), context.get_srs()); disjoint_context.append_geo_arg(g1); disjoint_context.append_geo_arg(g2); if (OB_SUCC(ObGeoFuncDisjoint::eval(disjoint_context, result))) { diff --git a/deps/oblib/src/lib/geo/ob_geo_func_symdifference.cpp b/deps/oblib/src/lib/geo/ob_geo_func_symdifference.cpp index a88a856a0..be8889bbb 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_symdifference.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_symdifference.cpp @@ -63,9 +63,9 @@ static int apply_bg_symdifference_pt_pt( if (OB_FAIL(get_specific_geos(g1, g2, context, geo1, geo2, res))) { LOG_WARN("fail to get specific geometry", K(ret)); } else { - ObIAllocator *allocator = context.get_allocator(); - GeometryRes *union_res = OB_NEWx(GeometryRes, allocator, g1->get_srid(), *allocator); - GeometryRes *intersection_res = OB_NEWx(GeometryRes, allocator, g1->get_srid(), *allocator); + ObArenaAllocator tmp_alloc; + GeometryRes *union_res = OB_NEWx(GeometryRes, &tmp_alloc, g1->get_srid(), tmp_alloc); + GeometryRes *intersection_res = OB_NEWx(GeometryRes, &tmp_alloc, g1->get_srid(), tmp_alloc); if (OB_ISNULL(union_res) || OB_ISNULL(intersection_res)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to create geometry", K(ret), K(union_res), K(intersection_res)); @@ -102,8 +102,7 @@ static int push_disjoint_point(PtBinType &geo1, GeoType &geo2, const ObGeoEvalCt allocator, geo1.template get<0>(), geo1.template get<1>(), - 0, - allocator); + res.get_srid()); if (OB_ISNULL(pt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory for geometry", K(ret)); @@ -288,7 +287,7 @@ static int simplify_and_push_geometry( ObIAllocator &allocator, ObGeometry *push_geo, GcTreeType &geo_coll) { int ret = OB_SUCCESS; - if (OB_FAIL((ObGeoFuncUtils::simplify_multi_geo(push_geo, allocator)))) { + if (OB_FAIL((ObGeoTypeUtil::simplify_multi_geo(push_geo, allocator)))) { LOG_WARN("fail to simplify result", K(ret)); } else if (OB_FAIL(geo_coll.push_back(*push_geo))) { LOG_WARN("fail to push back geometry", K(ret)); @@ -321,8 +320,9 @@ static int apply_bg_symdifference_pt_coll(const ObGeometry *g1, const ObGeometry LOG_WARN("fail to do symdifference between pointlike and pointlike type", K(ret)); } else { uint32_t srid = g1->get_srid(); + ObArenaAllocator tmp_alloc; typename GcTreeType::sub_mpt_type *mls_res = - OB_NEWx(typename GcTreeType::sub_mpt_type, allocator, srid, *allocator); + OB_NEWx(typename GcTreeType::sub_mpt_type, &tmp_alloc, srid, tmp_alloc); typename GcTreeType::sub_mpt_type *mpy_res = OB_NEWx(typename GcTreeType::sub_mpt_type, allocator, srid, *allocator); GcTreeType *res = OB_NEWx(GcTreeType, allocator, srid, *allocator); @@ -391,9 +391,10 @@ static int apply_bg_symdifference_line_coll(const ObGeometry *g1, const ObGeomet LOG_WARN("fail to convert geometry to tree", K(ret)); } else if (FALSE_IT(g1_tree = tree_visitor.get_geometry())) { } else { + ObArenaAllocator tmp_alloc; uint32_t srid = g1->get_srid(); typename GcTreeType::sub_ml_type *mls_res = - OB_NEWx(typename GcTreeType::sub_ml_type, allocator, srid, *allocator); + OB_NEWx(typename GcTreeType::sub_ml_type, &tmp_alloc, srid, tmp_alloc); GcTreeType *res = OB_NEWx(GcTreeType, allocator, srid, *allocator); typename GcTreeType::sub_ml_type *mls_diff_res = OB_NEWx(typename GcTreeType::sub_ml_type, allocator, srid, *allocator); @@ -447,7 +448,7 @@ static int apply_bg_symdifference_line_coll(const ObGeometry *g1, const ObGeomet return ret; } -template +template static int apply_bg_symdifference_poly_coll(const ObGeometry *g1, const ObGeometry *g2, const ObGeoEvalCtx &context, ObBGStrategyType strategy, ObGeometry *&result) { @@ -460,64 +461,58 @@ static int apply_bg_symdifference_poly_coll(const ObGeometry *g1, const ObGeomet LOG_WARN("fail to apply symdifference collection common", K(ret)); } else if (OB_ISNULL(result)) { ObIAllocator *allocator = context.get_allocator(); - ObGeometry *g1_tree = nullptr; - ObGeoToTreeVisitor tree_visitor(allocator); - if (OB_FAIL(const_cast(g1)->do_visit(tree_visitor))) { - LOG_WARN("fail to convert geometry to tree", K(ret)); - } else if (FALSE_IT(g1_tree = tree_visitor.get_geometry())) { + const GeomType *g1_bin = reinterpret_cast(g1->val()); + uint32_t srid = g1->get_srid(); + typename GcTreeType::sub_ml_type *mls_res = + OB_NEWx(typename GcTreeType::sub_ml_type, allocator, srid, *allocator); + GcTreeType *res = OB_NEWx(GcTreeType, allocator, srid, *allocator); + typename GcTreeType::sub_mp_type *mpy_res = + OB_NEWx(typename GcTreeType::sub_mp_type, allocator, srid, *allocator); + typename GcTreeType::sub_mpt_type *mpt_res = + OB_NEWx(typename GcTreeType::sub_mpt_type, allocator, srid, *allocator); + if (OB_ISNULL(mpt_res) || OB_ISNULL(mls_res) || OB_ISNULL(res) || OB_ISNULL(mpy_res)) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_WARN("wrong geometry type or create geometry failed", + K(ret), + K(mpt_res), + K(mls_res), + K(res), + K(mpy_res)); + } else if (strategy == ObBGStrategyType::DEFAULT_NONE) { + bg::sym_difference(*g1_bin, *mpy, *mpy_res); + bg::difference(*mls, *g1_bin, *mls_res); + bg::difference(*mpt, *g1_bin, *mpt_res); + } else if (OB_ISNULL(context.get_srs())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("invalid null srs", K(ret)); } else { - uint32_t srid = g1->get_srid(); - typename GcTreeType::sub_ml_type *mls_res = - OB_NEWx(typename GcTreeType::sub_ml_type, allocator, srid, *allocator); - GcTreeType *res = OB_NEWx(GcTreeType, allocator, srid, *allocator); - typename GcTreeType::sub_mp_type *mpy_res = - OB_NEWx(typename GcTreeType::sub_mp_type, allocator, srid, *allocator); - typename GcTreeType::sub_mpt_type *mpt_res = - OB_NEWx(typename GcTreeType::sub_mpt_type, allocator, srid, *allocator); - if (OB_ISNULL(mpt_res) || OB_ISNULL(mls_res) || OB_ISNULL(res) || OB_ISNULL(mpy_res)) { - ret = OB_ERR_GIS_INVALID_DATA; - LOG_WARN("wrong geometry type or create geometry failed", - K(ret), - K(mpt_res), - K(mls_res), - K(res), - K(mpy_res)); - } else if (strategy == ObBGStrategyType::DEFAULT_NONE) { - bg::sym_difference(*reinterpret_cast(g1_tree), *mpy, *mpy_res); - bg::difference(*mls, *reinterpret_cast(g1_tree), *mls_res); - bg::difference(*mpt, *reinterpret_cast(g1_tree), *mpt_res); - } else if (OB_ISNULL(context.get_srs())) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("invalid null srs", K(ret)); - } else { - const ObSrsItem *srs = context.get_srs(); - boost::geometry::srs::spheroid geog_sphere( - srs->semi_major_axis(), srs->semi_minor_axis()); - ObLlLaAaStrategy line_strategy(geog_sphere); - ObPlPaStrategy point_strategy(geog_sphere); - bg::sym_difference( - *reinterpret_cast(g1_tree), *mpy, *mpy_res, line_strategy); - bg::difference(*mls, *reinterpret_cast(g1_tree), *mls_res, line_strategy); - bg::difference(*mpt, *reinterpret_cast(g1_tree), *mpt_res, point_strategy); - } - if (OB_SUCC(ret) && !mpy_res->is_empty() - && OB_FAIL(simplify_and_push_geometry( - *allocator, reinterpret_cast(mpy_res), *res))) { - LOG_WARN("fail to push back geometry", K(ret)); - } - if (OB_SUCC(ret) && !mls_res->is_empty() - && OB_FAIL(simplify_and_push_geometry( - *allocator, reinterpret_cast(mls_res), *res))) { - LOG_WARN("fail to push back geometry", K(ret)); - } - if (OB_SUCC(ret) && !mpt_res->is_empty() - && OB_FAIL(simplify_and_push_geometry( - *allocator, reinterpret_cast(mpt_res), *res))) { - LOG_WARN("fail to push back geometry", K(ret)); - } - if (OB_SUCC(ret)) { - result = res; - } + const ObSrsItem *srs = context.get_srs(); + boost::geometry::srs::spheroid geog_sphere( + srs->semi_major_axis(), srs->semi_minor_axis()); + ObLlLaAaStrategy line_strategy(geog_sphere); + ObPlPaStrategy point_strategy(geog_sphere); + bg::sym_difference( + *g1_bin, *mpy, *mpy_res, line_strategy); + bg::difference(*mls, *g1_bin, *mls_res, line_strategy); + bg::difference(*mpt, *g1_bin, *mpt_res, point_strategy); + } + if (OB_SUCC(ret) && !mpy_res->is_empty() + && OB_FAIL(simplify_and_push_geometry( + *allocator, reinterpret_cast(mpy_res), *res))) { + LOG_WARN("fail to push back geometry", K(ret)); + } + if (OB_SUCC(ret) && !mls_res->is_empty() + && OB_FAIL(simplify_and_push_geometry( + *allocator, reinterpret_cast(mls_res), *res))) { + LOG_WARN("fail to push back geometry", K(ret)); + } + if (OB_SUCC(ret) && !mpt_res->is_empty() + && OB_FAIL(simplify_and_push_geometry( + *allocator, reinterpret_cast(mpt_res), *res))) { + LOG_WARN("fail to push back geometry", K(ret)); + } + if (OB_SUCC(ret)) { + result = res; } } return ret; @@ -613,19 +608,19 @@ private: LOG_WARN("fail to convert geometry tree to bin", K(ret)); } else if (OB_FAIL(eval_wkb_binary(mpy_bin, g2, context, mpy_res))) { LOG_WARN("fail to eval wkb binary", K(ret)); - } else if (OB_FAIL(!mpy_res->is_empty() && (ObGeoFuncUtils::simplify_multi_geo(mpy_res, *allocator)))) { + } else if (OB_FAIL(!mpy_res->is_empty() && (ObGeoTypeUtil::simplify_multi_geo(mpy_res, *allocator)))) { LOG_WARN("fail to simplify result", K(ret)); } else if (OB_FAIL(ObGeoTypeUtil::tree_to_bin(*allocator, mpy_res, mpy_res_bin, srs))) { LOG_WARN("fail to convert geometry tree to bin", K(ret)); } else if (OB_FAIL(eval_wkb_binary(mls_bin, mpy_res_bin, context, mls_res))) { LOG_WARN("fail to eval wkb binary", K(ret)); - } else if (OB_FAIL(!mls_res->is_empty() && (ObGeoFuncUtils::simplify_multi_geo(mls_res, *allocator)))) { + } else if (OB_FAIL(!mls_res->is_empty() && (ObGeoTypeUtil::simplify_multi_geo(mls_res, *allocator)))) { LOG_WARN("fail to simplify result", K(ret)); } else if (OB_FAIL(ObGeoTypeUtil::tree_to_bin(*allocator, mls_res, mls_res_bin, srs))) { LOG_WARN("fail to convert geometry tree to bin", K(ret)); } else if (OB_FAIL(eval_wkb_binary(mpt_bin, mls_res_bin, context, result))) { LOG_WARN("fail to eval wkb binary", K(ret)); - } else if (OB_FAIL(!result->is_empty() && (ObGeoFuncUtils::simplify_multi_geo(result, *allocator)))) { + } else if (OB_FAIL(!result->is_empty() && (ObGeoTypeUtil::simplify_multi_geo(result, *allocator)))) { LOG_WARN("fail to simplify result", K(ret)); } } @@ -813,7 +808,7 @@ OB_GEO_FUNC_END; OB_GEO_CART_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeomPolygon, ObWkbGeomCollection, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g1, g2, context, ObBGStrategyType::DEFAULT_NONE, result); } OB_GEO_FUNC_END; @@ -1000,7 +995,7 @@ OB_GEO_FUNC_END; OB_GEO_CART_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeomMultiPolygon, ObWkbGeomCollection, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g1, g2, context, ObBGStrategyType::DEFAULT_NONE, result); } OB_GEO_FUNC_END; @@ -1025,7 +1020,7 @@ OB_GEO_FUNC_END; OB_GEO_CART_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeomCollection, ObWkbGeomPolygon, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g2, g1, context, ObBGStrategyType::DEFAULT_NONE, result); } OB_GEO_FUNC_END; @@ -1049,7 +1044,7 @@ OB_GEO_FUNC_END; OB_GEO_CART_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeomCollection, ObWkbGeomMultiPolygon, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g2, g1, context, ObBGStrategyType::DEFAULT_NONE, result); } OB_GEO_FUNC_END; @@ -1246,7 +1241,7 @@ OB_GEO_FUNC_END; OB_GEO_GEOG_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeogPolygon, ObWkbGeogCollection, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g1, g2, context, ObBGStrategyType::LL_LA_AA_STRATEGY, result); } OB_GEO_FUNC_END; @@ -1438,7 +1433,7 @@ OB_GEO_FUNC_END; OB_GEO_GEOG_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeogMultiPolygon, ObWkbGeogCollection, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g1, g2, context, ObBGStrategyType::LL_LA_AA_STRATEGY, result); } OB_GEO_FUNC_END; @@ -1463,7 +1458,7 @@ OB_GEO_FUNC_END; OB_GEO_GEOG_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeogCollection, ObWkbGeogPolygon, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g2, g1, context, ObBGStrategyType::LL_LA_AA_STRATEGY, result); } OB_GEO_FUNC_END; @@ -1488,7 +1483,7 @@ OB_GEO_FUNC_END; OB_GEO_GEOG_BINARY_FUNC_BEGIN( ObGeoFuncSymDifferenceImpl, ObWkbGeogCollection, ObWkbGeogMultiPolygon, ObGeometry *) { - return apply_bg_symdifference_poly_coll( + return apply_bg_symdifference_poly_coll( g2, g1, context, ObBGStrategyType::LL_LA_AA_STRATEGY, result); } OB_GEO_FUNC_END; diff --git a/deps/oblib/src/lib/geo/ob_geo_func_touches.cpp b/deps/oblib/src/lib/geo/ob_geo_func_touches.cpp index 906338676..5e945a336 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_touches.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_touches.cpp @@ -605,7 +605,7 @@ private: *context.get_allocator(), mpt1, mpt_bin, context.get_srs()))) { LOG_WARN("failed to convert geo tree to binary", K(ret)); } else { - ObGeoEvalCtx intersects_context(context.get_allocator(), context.get_srs()); + ObGeoEvalCtx intersects_context(context.get_mem_ctx(), context.get_srs()); intersects_context.append_geo_arg(mpt_bin); intersects_context.append_geo_arg(g2); if (OB_FAIL(ObGeoFuncIntersects::eval(intersects_context, point_intersects))) { @@ -617,7 +617,7 @@ private: } if (point_intersects || OB_FAIL(ret)) { - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *context.get_srs(), mpt1, mls1, mpy1))) { + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *context.get_srs(), mpt1, mls1, mpy1))) { LOG_WARN("fail to do gc union", K(ret)); } else { // Check that at least one part of g1 touches at least one part of g2. @@ -676,7 +676,7 @@ private: *context.get_allocator(), mpt1, mpt_bin, context.get_srs()))) { LOG_WARN("failed to convert geo tree to binary", K(ret)); } else { - ObGeoEvalCtx intersects_context(context.get_allocator(), context.get_srs()); + ObGeoEvalCtx intersects_context(context.get_mem_ctx(), context.get_srs()); intersects_context.append_geo_arg(mpt_bin); intersects_context.append_geo_arg(g2); if (OB_FAIL(ObGeoFuncIntersects::eval(intersects_context, point_intersects))) { @@ -688,7 +688,7 @@ private: } if (point_intersects || OB_FAIL(ret)) { - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *context.get_srs(), mpt1, mls1, mpy1))) { + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *context.get_srs(), mpt1, mls1, mpy1))) { LOG_WARN("fail to do gc union", K(ret)); } else { // Check that at least one part of g1 touches at least one part of g2. diff --git a/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp b/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp index 33abf9852..1337b13a0 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp @@ -51,7 +51,7 @@ private: lib::ObMallocHookAttrGuard malloc_guard(last_mem_attr); const PtInType *src_geo = reinterpret_cast(g->val()); PtResType *dest_geo = NULL; - if (OB_ISNULL(dest_geo = OB_NEWx(PtResType, (context.get_allocator())))) { + if (OB_ISNULL(dest_geo = OB_NEWx(PtResType, (context.get_allocator()), g->get_srid(), context.get_allocator()))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { @@ -77,7 +77,7 @@ private: if (OB_ISNULL(alloc)) { ret = OB_ERR_NULL_VALUE; LOG_WARN("unexpected null allocator for transform functor", K(ret)); - } else if (OB_ISNULL(dest_geo = OB_NEWx(GeometryResType, alloc))) { + } else if (OB_ISNULL(dest_geo = OB_NEWx(GeometryResType, alloc, g->get_srid(), *alloc))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create geo by type", K(ret)); } else { diff --git a/deps/oblib/src/lib/geo/ob_geo_func_union.cpp b/deps/oblib/src/lib/geo/ob_geo_func_union.cpp index 07f95fd80..358aaa6c4 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_union.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_union.cpp @@ -245,7 +245,7 @@ static int push_back_innerpoint(const ObWkbGeomInnerPoint &innerpoint, const ObG ObCartesianGeometrycollection &res) { INIT_SUCC(ret); - ObCartesianPoint *point = OB_NEWx(ObCartesianPoint, context.get_allocator()); + ObCartesianPoint *point = OB_NEWx(ObCartesianPoint, context.get_allocator(), res.get_srid()); if (OB_ISNULL(point)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create cartesian point", K(ret)); @@ -263,7 +263,7 @@ static int push_back_innerpoint(const ObWkbGeogInnerPoint &innerpoint, const ObG ObGeographGeometrycollection &res) { INIT_SUCC(ret); - ObGeographPoint *point = OB_NEWx(ObGeographPoint, context.get_allocator()); + ObGeographPoint *point = OB_NEWx(ObGeographPoint, context.get_allocator(), res.get_srid()); if (OB_ISNULL(point)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create geograph point", K(ret)); @@ -494,7 +494,7 @@ public: LOG_WARN("fail to push back geometry", K(ret)); } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_split(*allocator, *geo_coll, mpt, mls, mpy))) { LOG_WARN("failed to do gc split", K(ret)); - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *context.get_srs(), mpt, mls, mpy))) { + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *context.get_srs(), mpt, mls, mpy))) { LOG_WARN("failed to do gc union", K(ret)); } else { for (int i = 0; OB_SUCC(ret) && i < mpy->size(); ++i) { @@ -515,8 +515,7 @@ public: allocator, pt.template get<0>(), pt.template get<1>(), - srid, - allocator); + srid); if (OB_ISNULL(pt_tree)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory", K(ret)); diff --git a/deps/oblib/src/lib/geo/ob_geo_func_utils.h b/deps/oblib/src/lib/geo/ob_geo_func_utils.h index d85627a0a..18a34fcb3 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_utils.h +++ b/deps/oblib/src/lib/geo/ob_geo_func_utils.h @@ -18,6 +18,7 @@ #include "lib/utility/ob_hang_fatal_error.h" #include "lib/geo/ob_geo_to_tree_visitor.h" #include "common/ob_smart_call.h" +#include "share/rc/ob_tenant_base.h" namespace oceanbase { @@ -36,7 +37,7 @@ public: virtual ~ObGeoFuncUtils() = default; template - static int ob_geo_gc_union(common::ObIAllocator &allocator, + static int ob_geo_gc_union(lib::MemoryContext &mem_ctx, const common::ObSrsItem &srs, MultiPointType *&mps, MultiLineType *&mls, @@ -57,12 +58,6 @@ public: typename GcTreeType::sub_mp_type *&multi_poly); static int apply_bg_to_tree(const ObGeometry *g1, const ObGeoEvalCtx &context, ObGeometry *&result); - template - static int remove_duplicate_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs); - template - static int simplify_geo_collection(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs); - template - static int simplify_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator); private: template @@ -70,12 +65,10 @@ private: typename GcTreeType::sub_mpt_type &mpt, typename GcTreeType::sub_ml_type &ml, typename GcTreeType::sub_mp_type &mpo); - template - static int is_in_geometry(const ObGeometry &geo, const MpType &multi_geo, const ObSrsItem *srs, bool &res); }; template -int ObGeoFuncUtils::ob_geo_gc_union(ObIAllocator &allocator, +int ObGeoFuncUtils::ob_geo_gc_union(lib::MemoryContext &mem_ctx, const ObSrsItem &srs, MultiPointType *&mps, MultiLineType *&mls, @@ -83,11 +76,12 @@ int ObGeoFuncUtils::ob_geo_gc_union(ObIAllocator &allocator, { INIT_SUCC(ret); ObGeometry *func_result = NULL; + ObIAllocator &allocator = mem_ctx->get_arena_allocator(); if (!mps->is_tree() || !mls->is_tree() || !mpols->is_tree()) { ret = OB_INVALID_ARGUMENT; OB_LOG(WARN, "invalid geometry type, must be geotree", K(ret)); } else { - MultiPolygonType *mpols_res = OB_NEWx(MultiPolygonType, (&allocator)); + MultiPolygonType *mpols_res = OB_NEWx(MultiPolygonType, (&allocator), mpols->get_srid(), allocator); if (OB_ISNULL(mpols_res)) { ret = OB_ALLOCATE_MEMORY_FAILED; } else { @@ -100,7 +94,7 @@ int ObGeoFuncUtils::ob_geo_gc_union(ObIAllocator &allocator, boost::geometry::correct(*pol, area_strategy); } - ObGeoEvalCtx gis_context(&allocator, &srs); + ObGeoEvalCtx gis_context(mem_ctx, &srs); if (OB_FAIL(gis_context.append_geo_arg(&(*pol))) || OB_FAIL(gis_context.append_geo_arg(&(*mpols_res)))) { OB_LOG(WARN, "failed to append geo to ctx", K(ret)); @@ -123,7 +117,7 @@ int ObGeoFuncUtils::ob_geo_gc_union(ObIAllocator &allocator, } if (OB_SUCC(ret)) { - ObGeoEvalCtx line_diff_context(&allocator, &srs); + ObGeoEvalCtx line_diff_context(mem_ctx, &srs); if (OB_FAIL(line_diff_context.append_geo_arg(mls)) || OB_FAIL(line_diff_context.append_geo_arg(mpols))) { OB_LOG(WARN, "failed to append geo to ctx", K(ret)); @@ -138,7 +132,7 @@ int ObGeoFuncUtils::ob_geo_gc_union(ObIAllocator &allocator, } for (uint8_t i = 0; i < 2 && OB_SUCC(ret); i++) { - ObGeoEvalCtx point_diff_context(&allocator, &srs); + ObGeoEvalCtx point_diff_context(mem_ctx, &srs); ObGeometry *tmp_geo = NULL; if (i == 0) { tmp_geo = mls; @@ -214,23 +208,30 @@ int ObGeoFuncUtils::ob_gc_prepare(const ObGeoEvalCtx &context, ObIAllocator *allocator = context.get_allocator(); const ObSrsItem *srs = context.get_srs(); const GcTreeType *gc_tree = nullptr; + ObArenaAllocator tmp_alloc; if (gc->is_tree()) { gc_tree = static_cast(gc); } else { - ObGeoToTreeVisitor tree_visitor(allocator); + ObGeoToTreeVisitor tree_visitor(&tmp_alloc); if (OB_FAIL(gc->do_visit(tree_visitor))) { OB_LOG(WARN, "failed to transform gc to tree", K(ret)); } else { gc_tree = static_cast(tree_visitor.get_geometry()); } } + // ob_geo_gc_union will rewrite multi_line/multi_poly if success + // so mls/mpy can be temporary + multi_line = OB_NEWx(typename GcTreeType::sub_ml_type, &tmp_alloc, gc->get_srid(), tmp_alloc); + multi_poly = OB_NEWx(typename GcTreeType::sub_mp_type, &tmp_alloc, gc->get_srid(), tmp_alloc); + multi_point = OB_NEWx(typename GcTreeType::sub_mpt_type, allocator, gc->get_srid(), *allocator); if (OB_FAIL(ret)) { - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_split(*allocator, - *gc_tree, - multi_point, multi_line, multi_poly))) { - OB_LOG(WARN, "failed to do gc split", K(ret)); - } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(*allocator, *srs, multi_point, + } else if (OB_ISNULL(multi_point)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "failed to allocate memory", K(ret)); + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_split_inner(*gc_tree, *multi_point, *multi_line, *multi_poly))) { + OB_LOG(WARN, "failed to falatten geometrycollection", K(ret)); + } else if (OB_FAIL(ObGeoFuncUtils::ob_geo_gc_union(context.get_mem_ctx(), *srs, multi_point, multi_line, multi_poly))) { OB_LOG(WARN, "failed to do gc union", K(ret)); } else { /* do nothing */ } @@ -320,281 +321,6 @@ int ObGeoFuncUtils::ob_geo_gc_split_inner(const GcTreeType &gc, return ret; } -template -int ObGeoFuncUtils::is_in_geometry(const ObGeometry &geo, const MpType &multi_geo, const ObSrsItem *srs, bool &res) -{ - int ret = OB_SUCCESS; - ObArenaAllocator temp_allocator; - for (int32_t j = 0; j < multi_geo.size() && OB_SUCC(ret) && !res; j++) { - ObGeoEvalCtx gis_context(&temp_allocator, srs); - if (OB_FAIL(gis_context.append_geo_arg(&geo)) || OB_FAIL(gis_context.append_geo_arg(&multi_geo[j]))) { - OB_LOG(WARN, "build gis context failed", K(ret), K(gis_context.get_geo_count())); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, res))) { - OB_LOG(WARN, "eval st intersection failed", K(ret)); - } - } - return ret; -} - -template -int ObGeoFuncUtils::simplify_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator) -{ - // e.g. MULTILINESTRING((0 0, 1 1)) -> LINESTRING(0 0, 1 1) - int ret= OB_SUCCESS; - switch (geo->type()) { - case ObGeoType::MULTILINESTRING: { - typename GcType::sub_ml_type *mp = reinterpret_cast(geo); - if (OB_ISNULL(mp)) { - ret = OB_ERR_GIS_INVALID_DATA; - OB_LOG(WARN, "invalid null pointer", K(ret)); - } else if (mp->size() == 1) { - geo = &(mp->front()); - } - break; - } - case ObGeoType::MULTIPOINT: { - typename GcType::sub_mpt_type *mpt = reinterpret_cast(geo); - if (OB_ISNULL(mpt)) { - ret = OB_ERR_GIS_INVALID_DATA; - OB_LOG(WARN, "invalid null pointer", K(ret)); - } else if (mpt->size() == 1) { - typename GcType::sub_pt_type *p = OB_NEWx(typename GcType::sub_pt_type, &allocator); - if (OB_ISNULL(p)) { - ret = OB_ERR_GIS_INVALID_DATA; - OB_LOG(WARN, "invalid null pointer", K(ret)); - } else { - p->set_data(mpt->front()); - geo = p; - } - } - break; - } - case ObGeoType::MULTIPOLYGON: { - typename GcType::sub_mp_type *mp = reinterpret_cast(geo); - if (OB_ISNULL(mp)) { - ret = OB_ERR_GIS_INVALID_DATA; - OB_LOG(WARN, "invalid null pointer", K(ret)); - } else if (mp->size() == 1) { - geo = &(mp->front()); - } - break; - } - case ObGeoType::GEOMETRYCOLLECTION: { - GcType *mp = reinterpret_cast(geo); - if (OB_ISNULL(mp)) { - ret = OB_ERR_GIS_INVALID_DATA; - OB_LOG(WARN, "invalid null pointer", K(ret)); - } else if (mp->size() == 1) { - geo = &(mp->front()); - if (OB_FAIL((simplify_multi_geo(geo, allocator)))) { - OB_LOG(WARN, "fail to simplify geometry", K(ret)); - } - } - break; - } - default: { - break; // do nothing - } - } - return ret; -} - -// for geo tree -template -int ObGeoFuncUtils::simplify_geo_collection(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs) -{ - int ret = OB_SUCCESS; - if (geo->type() != ObGeoType::GEOMETRYCOLLECTION) { - // do nothing - } else { - GcTreeType *&geo_coll = reinterpret_cast(geo); - ObGeoType front_type; - bool need_simplify = true; - if (geo_coll->size() < 2) { - need_simplify = false; - } else { - front_type = geo_coll->front().type(); - for (uint32_t i = 1; need_simplify && i < geo_coll->size(); ++i) { - if (((*geo_coll)[i]).type() != front_type) { - need_simplify = false; - } - } - } - if (need_simplify) { - switch(front_type) { - case ObGeoType::POINT: { - typename GcTreeType::sub_mpt_type *res_geo = OB_NEWx(typename GcTreeType::sub_mpt_type, &allocator, geo->get_srid(), allocator); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "fail to alloc memory", K(ret)); - } - for (uint32_t i = 0; OB_SUCC(ret) && i < geo_coll->size(); ++i) { - typename GcTreeType::sub_pt_type &geo_point = reinterpret_cast((*geo_coll)[i]); - if (OB_FAIL(res_geo->push_back(geo_point))) { - OB_LOG(WARN, "failed to add point to multipoint", K(ret)); - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - case ObGeoType::LINESTRING: { - typename GcTreeType::sub_ml_type *res_geo = OB_NEWx(typename GcTreeType::sub_ml_type, &allocator, geo->get_srid(), allocator); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "fail to alloc memory", K(ret)); - } - for (uint32_t i = 0; OB_SUCC(ret) && i < geo_coll->size(); ++i) { - if (OB_FAIL(res_geo->push_back((*geo_coll)[i]))) { - OB_LOG(WARN, "failed to add linestring to multilinestring", K(ret)); - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - case ObGeoType::POLYGON: { - typename GcTreeType::sub_mp_type *res_geo = OB_NEWx(typename GcTreeType::sub_mp_type, &allocator, geo->get_srid(), allocator); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "fail to alloc memory", K(ret)); - } - for (uint32_t i = 0; OB_SUCC(ret) && i < geo_coll->size(); ++i) { - if (OB_FAIL(res_geo->push_back((*geo_coll)[i]))) { - OB_LOG(WARN, "failed to add polygon to multipolygon", K(ret)); - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - default: { - // do nothing - break; - } - } - } - } - return ret; -} - -// for geo tree -template -int ObGeoFuncUtils::remove_duplicate_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs) -{ - int ret = OB_SUCCESS; - ObArenaAllocator temp_allocator; - switch (geo->type()) { - case ObGeoType::POINT: - case ObGeoType::LINESTRING: - case ObGeoType::POLYGON: { - break; - } - case ObGeoType::MULTIPOINT: { - typename GcTreeType::sub_mpt_type *res_geo = OB_NEWx(typename GcTreeType::sub_mpt_type, &allocator, geo->get_srid(), allocator); - typename GcTreeType::sub_mpt_type &sp_geo = reinterpret_cast(*geo); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); - } - for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret); i++) { - bool in_res_geo = false; - for (int32_t j = 0; j < res_geo->size() && OB_SUCC(ret) && !in_res_geo; j++) { - if ((sp_geo[i].template get<0>() == (*res_geo)[j].template get<0>()) - && (sp_geo[i].template get<1>() == (*res_geo)[j].template get<1>())) { - in_res_geo = true; - } - } - if (OB_SUCC(ret) && !in_res_geo) { - typename GcTreeType::sub_pt_type pt(sp_geo[i].template get<0>(), sp_geo[i].template get<1>()); - if (OB_FAIL(res_geo->push_back(pt))) { - OB_LOG(WARN, "fail to push back geometry", K(ret)); - } - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - case ObGeoType::MULTILINESTRING: { - typename GcTreeType::sub_ml_type *res_geo = OB_NEWx(typename GcTreeType::sub_ml_type, &allocator, geo->get_srid(), allocator); - typename GcTreeType::sub_ml_type &sp_geo = reinterpret_cast(*geo); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); - } - for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret); i++) { - bool in_res_geo = false; - if (OB_FAIL(is_in_geometry(sp_geo[i], *res_geo, srs, in_res_geo))) { - OB_LOG(WARN, "fail to check is in geometry", K(ret)); - } else if (!in_res_geo && res_geo->push_back(sp_geo[i])) { - OB_LOG(WARN, "fail to push back geometry", K(ret)); - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - case ObGeoType::MULTIPOLYGON: { - typename GcTreeType::sub_mp_type *res_geo = OB_NEWx(typename GcTreeType::sub_mp_type, &allocator, geo->get_srid(), allocator); - typename GcTreeType::sub_mp_type &sp_geo = reinterpret_cast(*geo); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); - } - for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret); i++) { - bool in_res_geo = false; - if (OB_FAIL(is_in_geometry(sp_geo[i], *res_geo, srs, in_res_geo))) { - OB_LOG(WARN, "fail to check is in geometry", K(ret)); - } else if (!in_res_geo && res_geo->push_back(sp_geo[i])) { - OB_LOG(WARN, "fail to push back geometry", K(ret)); - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - case ObGeoType::GEOMETRYCOLLECTION: { - GcTreeType *res_geo = OB_NEWx(GcTreeType, &allocator, geo->get_srid(), allocator); - GcTreeType *&sp_geo = reinterpret_cast(geo); - if (OB_ISNULL(res_geo)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); - } - for (int32_t i = 0; i < sp_geo->size() && OB_SUCC(ret); i++) { - bool in_res_geo = false; - ObGeometry *cur_geo = &(*sp_geo)[i]; - if (OB_FAIL(remove_duplicate_multi_geo(cur_geo, allocator, srs))) { - OB_LOG(WARN, "fail to remove dupilicate multi geometry", K(ret)); - } else if (OB_FAIL(is_in_geometry(*cur_geo, *res_geo, srs, in_res_geo))) { - OB_LOG(WARN, "fail to check is in geometry", K(ret)); - } else if (!in_res_geo && res_geo->push_back(*cur_geo)) { - OB_LOG(WARN, "fail to push back geometry", K(ret)); - } - } - if (OB_SUCC(ret)) { - geo = res_geo; - } - break; - } - default: { - ret = OB_NOT_SUPPORTED; - OB_LOG(WARN, "geometry type not supported", K(ret), K(geo->type())); - break; - } - } - - if (OB_SUCC(ret) && OB_FAIL((simplify_multi_geo(geo, allocator)))) { - OB_LOG(WARN, "fail to simplify result", K(ret)); - } - return ret; -} } // sql } // oceanbase #endif // OCEANBASE_LIB_OB_GEO_FUNC_UTILS_H_ \ No newline at end of file diff --git a/deps/oblib/src/lib/geo/ob_geo_func_within.cpp b/deps/oblib/src/lib/geo/ob_geo_func_within.cpp index 09fd1c24c..b37a9e4c0 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_within.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_within.cpp @@ -28,7 +28,7 @@ namespace common namespace bg = boost::geometry; static int do_multi_difference(const ObSrsItem &srs, - ObIAllocator &allocator, + const ObGeoEvalCtx &context, ObGeometry *geo, ObGeometry *mpt, ObGeometry *ml, @@ -38,9 +38,9 @@ static int do_multi_difference(const ObSrsItem &srs, INIT_SUCC(ret); ObGeometry *res_geo1 = NULL; ObGeometry *res_geo2 = NULL; - ObGeoEvalCtx gis_context1(&allocator, &srs); - ObGeoEvalCtx gis_context2(&allocator, &srs); - ObGeoEvalCtx gis_context3(&allocator, &srs); + ObGeoEvalCtx gis_context1(context.get_mem_ctx(), &srs); + ObGeoEvalCtx gis_context2(context.get_mem_ctx(), &srs); + ObGeoEvalCtx gis_context3(context.get_mem_ctx(), &srs); if (OB_NOT_NULL(mpt)) { if (OB_FAIL(gis_context1.append_geo_arg(reinterpret_cast(geo))) || OB_FAIL(gis_context1.append_geo_arg(mpt))) { LOG_WARN("build gis context failed", K(ret), K(gis_context1.get_geo_count())); @@ -280,7 +280,7 @@ static int ob_caculate_ml_within_gc(const ObGeometry *g1, const ObGeometry *g2, ObGeometry *i_geo1 = const_cast(g1); if (OB_FAIL(i_geo1->do_visit(visitor))) { LOG_WARN("failed to do geo2 to_tree visit", K(ret)); - } else if (OB_FAIL(do_multi_difference(*srs, *allocator, visitor.get_geometry(), + } else if (OB_FAIL(do_multi_difference(*srs, context, visitor.get_geometry(), NULL, reinterpret_cast(multi_line), reinterpret_cast(multi_poly), @@ -324,7 +324,7 @@ static int ob_caculate_ml_within_gc_geog(const ObGeometry *g1, const ObGeometry ObGeometry *i_geo1 = const_cast(g1); if (OB_FAIL(i_geo1->do_visit(visitor))) { LOG_WARN("failed to do geo2 to_tree visit", K(ret)); - } else if (OB_FAIL(do_multi_difference(*srs, *allocator, visitor.get_geometry(), + } else if (OB_FAIL(do_multi_difference(*srs, context, visitor.get_geometry(), NULL, reinterpret_cast(multi_line), reinterpret_cast(multi_poly), @@ -532,7 +532,7 @@ private: IPointType i_point; i_point.set_data(data); - ObGeoEvalCtx intersects_context(context.get_allocator(), context.get_srs()); + ObGeoEvalCtx intersects_context(context.get_mem_ctx(), context.get_srs()); intersects_context.append_geo_arg(&i_point); intersects_context.append_geo_arg(g2); if (!within) { @@ -983,7 +983,7 @@ OB_GEO_CART_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeomCollection, ObWkbGeo const ObSrsItem *srs = context.get_srs(); ObIAllocator *allocator = context.get_allocator(); ObGeometry *res_geo3 = NULL; - if (OB_FAIL(do_multi_difference(*srs, *allocator, reinterpret_cast(g1_multi_point), + if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast(g1_multi_point), reinterpret_cast(g2_multi_point), reinterpret_cast(g2_multi_line), reinterpret_cast(g2_multi_poly), @@ -993,7 +993,7 @@ OB_GEO_CART_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeomCollection, ObWkbGeo result = false; } else { ObGeometry *res_geo5 = NULL; - if (OB_FAIL(do_multi_difference(*srs, *allocator, reinterpret_cast(g1_multi_line), + if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast(g1_multi_line), NULL, reinterpret_cast(g2_multi_line), reinterpret_cast(g2_multi_poly), @@ -1003,7 +1003,7 @@ OB_GEO_CART_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeomCollection, ObWkbGeo result = false; } else { ObGeometry *res_geo6 = NULL; - if (OB_FAIL(do_multi_difference(*srs, *allocator, reinterpret_cast(g1_multi_poly), + if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast(g1_multi_poly), NULL, NULL, reinterpret_cast(g2_multi_poly), @@ -1635,7 +1635,7 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo ObIAllocator *allocator = context.get_allocator(); ObGeometry *res_geo3 = NULL; - if (OB_FAIL(do_multi_difference(*srs, *allocator, reinterpret_cast(g1_multi_point), + if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast(g1_multi_point), reinterpret_cast(g2_multi_point), reinterpret_cast(g2_multi_line), reinterpret_cast(g2_multi_poly), @@ -1645,7 +1645,7 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo result = false; } else { ObGeometry *res_geo5 = NULL; - if (OB_FAIL(do_multi_difference(*srs, *allocator, reinterpret_cast(g1_multi_line), + if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast(g1_multi_line), NULL, reinterpret_cast(g2_multi_line), reinterpret_cast(g2_multi_poly), @@ -1655,7 +1655,7 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo result = false; } else { ObGeometry * res_geo6 = NULL; - if (OB_FAIL(do_multi_difference(*srs, *allocator, reinterpret_cast(g1_multi_poly), + if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast(g1_multi_poly), NULL, NULL, reinterpret_cast(g2_multi_poly), diff --git a/deps/oblib/src/lib/geo/ob_geo_ibin.cpp b/deps/oblib/src/lib/geo/ob_geo_ibin.cpp index c9ae8f572..bf0176f37 100644 --- a/deps/oblib/src/lib/geo/ob_geo_ibin.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_ibin.cpp @@ -94,11 +94,11 @@ bool ObIWkbGeomPolygon::is_empty_inner() const return (poly->exterior_ring().size(static_cast(poly->get_bo())) == 0) && (poly->inner_rings().size() == 0); } -int ObIWkbGeomCollection::get_sub(uint32_t idx, ObGeometry*& geo) const +int ObIWkbGeomCollection::get_sub(ObIAllocator *allocator, uint32_t idx, ObGeometry*& geo) const { INIT_SUCC(ret); ObWkbGeomCollection* g = reinterpret_cast(const_cast(val())); - if (OB_ISNULL(this->allocator_)) { + if (OB_ISNULL(allocator)) { ret = OB_ERR_NULL_VALUE; LOG_WARN("Null allocator.", K(ret)); } else if (idx >= g->size()) { @@ -112,7 +112,7 @@ int ObIWkbGeomCollection::get_sub(uint32_t idx, ObGeometry*& geo) const // TODO use create_obj_by_type switch (g->get_sub_type(ptr)) { case ObGeoType::POINT: { - geo = OB_NEWx(ObIWkbGeomPoint, this->allocator_); + geo = OB_NEWx(ObIWkbGeomPoint, allocator, srid_); break; } default: { @@ -194,11 +194,11 @@ bool ObIWkbGeogPolygon::is_empty_inner() const return bret; } -int ObIWkbGeogCollection::get_sub(uint32_t idx, ObGeometry*& geo) const +int ObIWkbGeogCollection::get_sub(ObIAllocator *allocator, uint32_t idx, ObGeometry*& geo) const { INIT_SUCC(ret); ObWkbGeogCollection* g = reinterpret_cast(const_cast(val())); - if (OB_ISNULL(this->allocator_)) { + if (OB_ISNULL(allocator)) { ret = OB_ERR_NULL_VALUE; LOG_WARN("Null allocator.", K(ret)); } else if (idx >= g->size()) { @@ -212,7 +212,7 @@ int ObIWkbGeogCollection::get_sub(uint32_t idx, ObGeometry*& geo) const // TODO use create_obj_by_type switch (g->get_sub_type(ptr)) { case ObGeoType::POINT: { - geo = OB_NEWx(ObIWkbGeomPoint, this->allocator_); + geo = OB_NEWx(ObIWkbGeomPoint, allocator, srid_); break; } default: { diff --git a/deps/oblib/src/lib/geo/ob_geo_ibin.h b/deps/oblib/src/lib/geo/ob_geo_ibin.h index 5d095aca7..5dac0a013 100644 --- a/deps/oblib/src/lib/geo/ob_geo_ibin.h +++ b/deps/oblib/src/lib/geo/ob_geo_ibin.h @@ -26,8 +26,8 @@ class ObIGeoVisitor; class ObIWkbGeometry : public ObGeometry { public: - ObIWkbGeometry(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObGeometry(srid, allocator) {} + ObIWkbGeometry(uint32_t srid = 0) + : ObGeometry(srid) {} ~ObIWkbGeometry() = default; ObIWkbGeometry(const ObIWkbGeometry& g) = default; ObIWkbGeometry& operator=(const ObIWkbGeometry& g) = default; @@ -53,8 +53,8 @@ protected: class ObIWkbPoint : public ObIWkbGeometry { public: - ObIWkbPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbPoint(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbPoint() = default; // point interface virtual double x() const = 0; @@ -80,8 +80,8 @@ public: typedef ObWkbGeomPoint value_type; public: // constructor - ObIWkbGeomPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbPoint(srid, allocator) {} + ObIWkbGeomPoint(uint32_t srid = 0) + : ObIWkbPoint(srid) {} ~ObIWkbGeomPoint() = default; ObIWkbGeomPoint(const ObIWkbGeomPoint& g) = default; ObIWkbGeomPoint& operator=(const ObIWkbGeomPoint& g) = default; @@ -101,8 +101,8 @@ public: typedef ObWkbGeomLineString value_type; public: // constructor - ObIWkbGeomLineString(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomLineString(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomLineString() = default; ObIWkbGeomLineString(const ObIWkbGeomLineString& g) = default; ObIWkbGeomLineString& operator=(const ObIWkbGeomLineString& g) = default; @@ -124,8 +124,8 @@ public: typedef ObWkbGeomPolygon value_type; public: // constructor - ObIWkbGeomPolygon(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomPolygon(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomPolygon() = default; ObIWkbGeomPolygon(const ObIWkbGeomPolygon& g) = default; ObIWkbGeomPolygon& operator=(const ObIWkbGeomPolygon& g) = default; @@ -144,8 +144,8 @@ private: class ObIWkbGeomMultiPoint : public ObIWkbGeometry { public: // constructor - ObIWkbGeomMultiPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomMultiPoint(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomMultiPoint() = default; ObIWkbGeomMultiPoint(const ObIWkbGeomMultiPoint& g) = default; ObIWkbGeomMultiPoint& operator=(const ObIWkbGeomMultiPoint& g) = default; @@ -164,8 +164,8 @@ public: class ObIWkbGeomMultiLineString : public ObIWkbGeometry { public: // constructor - ObIWkbGeomMultiLineString(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomMultiLineString(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomMultiLineString() = default; ObIWkbGeomMultiLineString(const ObIWkbGeomMultiLineString& g) = default; ObIWkbGeomMultiLineString& operator=(const ObIWkbGeomMultiLineString& g) = default; @@ -188,8 +188,8 @@ public: public: // constructor - ObIWkbGeomLinearRing(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomLinearRing(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomLinearRing() = default; ObIWkbGeomLinearRing(const ObIWkbGeomLinearRing& g) = default; ObIWkbGeomLinearRing& operator=(const ObIWkbGeomLinearRing& g) = default; @@ -209,8 +209,8 @@ private: class ObIWkbGeomMultiPolygon : public ObIWkbGeometry { public: // constructor - ObIWkbGeomMultiPolygon(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomMultiPolygon(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomMultiPolygon() = default; ObIWkbGeomMultiPolygon(const ObIWkbGeomMultiPolygon& g) = default; ObIWkbGeomMultiPolygon& operator=(const ObIWkbGeomMultiPolygon& g) = default; @@ -233,8 +233,8 @@ private: class ObIWkbGeomCollection : public ObIWkbGeometry { public: // constructor - ObIWkbGeomCollection(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeomCollection(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeomCollection() = default; ObIWkbGeomCollection(const ObIWkbGeomCollection& g) = default; ObIWkbGeomCollection& operator=(const ObIWkbGeomCollection& g) = default; @@ -242,7 +242,8 @@ public: ObGeoType type() const override { return ObGeoType::GEOMETRYCOLLECTION; } ObGeoCRS crs() const override { return ObGeoCRS::Cartesian; } // iter interface - int get_sub(uint32_t idx, ObGeometry*& geo) const; + // no use currently + int get_sub(ObIAllocator *allocator, uint32_t idx, ObGeometry*& geo) const; int do_visit(ObIGeoVisitor &visitor); uint32_t size() const { return reinterpret_cast(val())->size(); } @@ -265,8 +266,8 @@ public: typedef ObWkbGeogPoint value_type; public: // constructor - ObIWkbGeogPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbPoint(srid, allocator) {} + ObIWkbGeogPoint(uint32_t srid = 0) + : ObIWkbPoint(srid) {} ~ObIWkbGeogPoint() = default; ObIWkbGeogPoint(const ObIWkbGeogPoint& g) = default; ObIWkbGeogPoint& operator=(const ObIWkbGeogPoint& g) = default; @@ -286,8 +287,8 @@ public: typedef ObWkbGeogLineString value_type; public: // constructor - ObIWkbGeogLineString(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogLineString(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogLineString() = default; ObIWkbGeogLineString(const ObIWkbGeogLineString& g) = default; ObIWkbGeogLineString& operator=(const ObIWkbGeogLineString& g) = default; @@ -311,8 +312,8 @@ public: public: // constructor - ObIWkbGeogLinearRing(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogLinearRing(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogLinearRing() = default; ObIWkbGeogLinearRing(const ObIWkbGeogLinearRing& g) = default; ObIWkbGeogLinearRing& operator=(const ObIWkbGeogLinearRing& g) = default; @@ -334,8 +335,8 @@ public: typedef ObWkbGeogPolygon value_type; public: // constructor - ObIWkbGeogPolygon(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogPolygon(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogPolygon() = default; ObIWkbGeogPolygon(const ObIWkbGeogPolygon& g) = default; ObIWkbGeogPolygon& operator=(const ObIWkbGeogPolygon& g) = default; @@ -354,8 +355,8 @@ private: class ObIWkbGeogMultiPoint : public ObIWkbGeometry { public: // constructor - ObIWkbGeogMultiPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogMultiPoint(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogMultiPoint() = default; ObIWkbGeogMultiPoint(const ObIWkbGeogMultiPoint& g) = default; ObIWkbGeogMultiPoint& operator=(const ObIWkbGeogMultiPoint& g) = default; @@ -375,8 +376,8 @@ private: class ObIWkbGeogMultiLineString : public ObIWkbGeometry { public: // constructor - ObIWkbGeogMultiLineString(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogMultiLineString(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogMultiLineString() = default; ObIWkbGeogMultiLineString(const ObIWkbGeogMultiLineString& g) = default; ObIWkbGeogMultiLineString& operator=(const ObIWkbGeogMultiLineString& g) = default; @@ -396,8 +397,8 @@ private: class ObIWkbGeogMultiPolygon : public ObIWkbGeometry { public: // constructor - ObIWkbGeogMultiPolygon(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogMultiPolygon(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogMultiPolygon() = default; ObIWkbGeogMultiPolygon(const ObIWkbGeogMultiPolygon& g) = default; ObIWkbGeogMultiPolygon& operator=(const ObIWkbGeogMultiPolygon& g) = default; @@ -417,8 +418,8 @@ private: class ObIWkbGeogCollection : public ObIWkbGeometry { public: // constructor - ObIWkbGeogCollection(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObIWkbGeometry(srid, allocator) {} + ObIWkbGeogCollection(uint32_t srid = 0) + : ObIWkbGeometry(srid) {} ~ObIWkbGeogCollection() = default; ObIWkbGeogCollection(const ObIWkbGeogCollection& g) = default; ObIWkbGeogCollection& operator=(const ObIWkbGeogCollection& g) = default; @@ -426,7 +427,8 @@ public: ObGeoType type() const override { return ObGeoType::GEOMETRYCOLLECTION; } ObGeoCRS crs() const override { return ObGeoCRS::Geographic; } // iter interface - int get_sub(uint32_t idx, ObGeometry*& geo) const; + // no use currently + int get_sub(ObIAllocator *allocator, uint32_t idx, ObGeometry*& geo) const; int do_visit(ObIGeoVisitor &visitor); uint32_t size() const { return reinterpret_cast(val())->size(); } diff --git a/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.cpp index 56d41abed..50f1b145a 100644 --- a/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.cpp @@ -26,7 +26,7 @@ int ObGeoInteriorPointVisitor::init(ObGeometry *geo) if (OB_FAIL(ObGeoTypeUtil::check_empty(geo, is_geo_empty_))) { LOG_WARN("fail to check geometry is empty", K(ret)); } else { - ObGeoEvalCtx centroid_context(allocator_); + ObGeoEvalCtx centroid_context(mem_ctx_); ObGeometry *res_geo = nullptr; if (OB_FAIL(centroid_context.append_geo_arg(geo))) { LOG_WARN("build geo gis context failed", K(ret)); @@ -61,7 +61,7 @@ int ObGeoInteriorPointVisitor::assign_interior_point(double x, double y) { int ret = OB_SUCCESS; if (OB_ISNULL(interior_point_)) { - if (OB_ISNULL(interior_point_ = OB_NEWx(ObCartesianPoint, allocator_, x, y, srid_, allocator_))) { + if (OB_ISNULL(interior_point_ = OB_NEWx(ObCartesianPoint, allocator_, x, y, srid_))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for collection", K(ret)); } @@ -77,7 +77,7 @@ int ObGeoInteriorPointVisitor::assign_interior_endpoint(double x, double y) { int ret = OB_SUCCESS; if (OB_ISNULL(interior_endpoint_)) { - if (OB_ISNULL(interior_endpoint_ = OB_NEWx(ObCartesianPoint, allocator_, x, y, srid_, allocator_))) { + if (OB_ISNULL(interior_endpoint_ = OB_NEWx(ObCartesianPoint, allocator_, x, y, srid_))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to alloc memory for collection", K(ret)); } @@ -237,7 +237,7 @@ int ObGeoInteriorPointVisitor::inner_calculate_interior_y( int ObGeoInteriorPointVisitor::calculate_interior_y(ObIWkbGeomPolygon *geo, double &interior_y) { int ret = OB_SUCCESS; - ObGeoEvalCtx box_ctx(allocator_); + ObGeoEvalCtx box_ctx(mem_ctx_); ObGeogBox *gbox = nullptr; const ObWkbGeomPolygon *polygon = reinterpret_cast(geo->val()); ObWkbGeomLinearRing::iterator iter = polygon->exterior_ring().begin(); @@ -423,7 +423,7 @@ int ObGeoInteriorPointVisitor::visit(ObIWkbGeomCollection *geo) if (OB_FAIL(ObGeoTypeUtil::get_coll_dimension(geo, dimension_))) { LOG_WARN("fail to calculate collection dimension_", K(ret)); } else if (dimension_ == 0 || dimension_ == 1) { - ObGeoEvalCtx centroid_context(allocator_); + ObGeoEvalCtx centroid_context(mem_ctx_); ObGeometry *res_geo = nullptr; if (OB_FAIL(centroid_context.append_geo_arg(geo))) { LOG_WARN("build geo gis context failed", K(ret)); diff --git a/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.h b/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.h index 6ddd213b3..cd869031a 100644 --- a/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_interior_point_visitor.h @@ -22,8 +22,8 @@ namespace common class ObGeoInteriorPointVisitor : public ObEmptyGeoVisitor { public: - explicit ObGeoInteriorPointVisitor(ObIAllocator *allocator) - : allocator_(allocator), + explicit ObGeoInteriorPointVisitor(lib::MemoryContext &mem_ctx) + : allocator_(&mem_ctx->get_arena_allocator()), interior_point_(nullptr), min_dist_(DBL_MAX), interior_endpoint_(nullptr), @@ -34,7 +34,8 @@ public: max_width_(-1), is_geo_empty_(true), is_inited_(false), - dimension_(-1) + dimension_(-1), + mem_ctx_(mem_ctx) {} ~ObGeoInteriorPointVisitor() {} @@ -142,6 +143,7 @@ private: bool is_geo_empty_; bool is_inited_; int8_t dimension_; // for collection + lib::MemoryContext &mem_ctx_; DISALLOW_COPY_AND_ASSIGN(ObGeoInteriorPointVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_mvt.cpp b/deps/oblib/src/lib/geo/ob_geo_mvt.cpp index 7a727a0d6..c21ba8477 100644 --- a/deps/oblib/src/lib/geo/ob_geo_mvt.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_mvt.cpp @@ -80,7 +80,7 @@ int mvt_agg_result::generate_feature(ObObj *tmp_obj, uint32_t obj_cnt) LOG_WARN("Lob: init lob str iter failed ", K(ret), K(str_iter)); } else if (OB_FAIL(str_iter.get_full_data(str))) { LOG_WARN("Lob: str iter get full data failed ", K(ret), K(str_iter)); - } else if (OB_FAIL(ObGeoTypeUtil::construct_geometry(*temp_allocator_, str, NULL, geo, true))) { + } else if (OB_FAIL(ObGeoTypeUtil::construct_geometry(*temp_allocator_, str, NULL, geo, true, !str_iter.is_outrow_lob()))) { LOG_WARN("failed to construct geometry", K(ret)); } else if (ObGeoTypeUtil::is_3d_geo_type(geo->type()) && OB_FAIL(ObGeoTypeUtil::convert_geometry_3D_to_2D(NULL, allocator_, geo, ObGeoBuildFlag::GEO_ALL_DISABLE, geo))) { diff --git a/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.cpp index b41c15d55..255d68df6 100644 --- a/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.cpp @@ -43,21 +43,6 @@ int ObGeoNormalizeVisitor::normalize(ObIWkbPoint *geo) LOG_WARN("normalize y failed", K(ret)); } else if (OB_FAIL(srs_->longtitude_convert_to_radians(geo->x(), nx))) { LOG_WARN("normalize x failed", K(ret)); - } else { - uint32_t count = 0; - double nx_tmp = nx; - double ny_tmp = ny; - while (nx_tmp != 0.0 && std::fabs(nx_tmp) < ZOOM_IN_THRESHOLD) { - nx_tmp *= 10; - count++; - } - zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; - count = 0; - while (ny_tmp != 0.0 && std::fabs(ny_tmp) < ZOOM_IN_THRESHOLD) { - ny_tmp *= 10; - count++; - } - zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; } } diff --git a/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.h b/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.h index 2272d5d20..5cc0b094f 100644 --- a/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_normalize_visitor.h @@ -22,22 +22,19 @@ class ObGeoNormalizeVisitor : public ObEmptyGeoVisitor { public: ObGeoNormalizeVisitor(const ObSrsItem *srs, bool no_srs = false) - : srs_(srs), no_srs_(no_srs), zoom_in_value_(0) {} + : srs_(srs), no_srs_(no_srs) {} virtual ~ObGeoNormalizeVisitor() {} bool prepare(ObGeometry *geo); int visit(ObIWkbGeogPoint *geo); int visit(ObIWkbGeomPoint *geo); int visit(ObIWkbGeometry *geo) { UNUSED(geo); return OB_SUCCESS; } - uint32_t get_zoom_in_value() { return zoom_in_value_; } private: int normalize(ObIWkbPoint *geo); private: - static constexpr double ZOOM_IN_THRESHOLD = 0.00000001; const ObSrsItem *srs_; bool no_srs_; // for st_transform, only proj4text is given - uint32_t zoom_in_value_; DISALLOW_COPY_AND_ASSIGN(ObGeoNormalizeVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.cpp index fee256fc7..3eb61556b 100644 --- a/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.cpp @@ -61,7 +61,9 @@ int ObGeoToTreeVisitor::create_geo_tree_collection(T_IBIN *i_geo) LOG_WARN("failed to alloc tree geog geo string", K(ret)); } else { geo = new(geo)T(i_geo->get_srid(), *allocator_); - if (OB_FAIL(update_root_and_parent(geo))) { + if (OB_FAIL(geo->reserve(i_geo->size()))) { + LOG_WARN("fail to reserve size", K(ret), K(i_geo->size())); + } else if (OB_FAIL(update_root_and_parent(geo))) { LOG_WARN("failed to update parent", K(ret)); } else if (OB_FAIL(parent_.push_back(geo))) { LOG_WARN("failed to set self to parent", K(ret)); @@ -80,6 +82,9 @@ int ObGeoToTreeVisitor::create_geo_multi_point(T_TREE *&geo, T_IBIN *geo_ibin) LOG_WARN("geo value is null", K(ret)); } else { geo = new(geo)T_TREE(geo_ibin->get_srid(), *allocator_); + if (OB_FAIL(geo->reserve(geo_bin->size()))) { + LOG_WARN("fail to reserve size", K(ret), K(geo_bin->size())); + } typename T_BIN::iterator iter = geo_bin->begin(); for ( ; iter != geo_bin->end() && OB_SUCC(ret); iter++) { T_POINT p(iter->template get<0>(), iter->template get<1>()); @@ -190,6 +195,11 @@ int ObGeoToTreeVisitor::polygon_visit(p_ibin_type *geo) // construct and add tree exterior ring L_TYPE& tree_ext_ring = polygon->exterior_ring(); const L_BIN_TYPE &ext_ring = polygon_bin->exterior_ring(); + if (OB_FAIL(polygon->reserve(polygon_bin->size()))) { + LOG_WARN("fail to reserve size", K(ret), K(polygon_bin->size())); + } else if (OB_FAIL(tree_ext_ring.reserve(ext_ring.size()))) { + LOG_WARN("fail to reserve size", K(ret), K(ext_ring.size())); + } typename L_BIN_TYPE::iterator iter = ext_ring.begin(); for ( ; iter != ext_ring.end() && OB_SUCC(ret); iter++) { POINT_TYPE p(iter->template get<0>(), iter->template get<1>()); @@ -202,19 +212,18 @@ int ObGeoToTreeVisitor::polygon_visit(p_ibin_type *geo) const RINGS_TYPE& inner_rings = polygon_bin->inner_rings(); typename RINGS_TYPE::iterator iter = inner_rings.begin(); for (; iter != inner_rings.end() && OB_SUCC(ret); iter++) { - L_TYPE *tree_linearring = NULL; - if (OB_FAIL(alloc_geo_tree_obj(tree_linearring))) { - LOG_WARN("failed to alloc tree linearring", K(ret)); + L_TYPE tree_linearring(geo->get_srid(), *allocator_); + if (OB_FAIL(tree_linearring.reserve(iter->size()))) { + LOG_WARN("fail to reserve size", K(ret), K(iter->size())); } else { - tree_linearring = new(tree_linearring)L_TYPE(geo->get_srid(), *allocator_); typename L_BIN_TYPE::iterator point_iter = iter->begin(); for ( ; point_iter != iter->end() && OB_SUCC(ret); point_iter++) { POINT_TYPE p(point_iter->template get<0>(), point_iter->template get<1>()); - if (OB_FAIL(tree_linearring->push_back(p))) { + if (OB_FAIL(tree_linearring.push_back(p))) { LOG_WARN("failed to push point to ring", K(ret)); } } - if (OB_SUCC(ret) && OB_FAIL(polygon->push_back(*tree_linearring))) { + if (OB_SUCC(ret) && OB_FAIL(polygon->push_back(tree_linearring))) { LOG_WARN("failed to push ring to polygon", K(ret)); } } diff --git a/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.h b/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.h index c698b2287..cf5c4661a 100644 --- a/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_to_tree_visitor.h @@ -24,10 +24,7 @@ class ObGeoToTreeVisitor : public ObEmptyGeoVisitor public: ObGeoToTreeVisitor(ObIAllocator *allocator) : allocator_(allocator), root_(NULL), - page_allocator_(*allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), - mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_), - parent_(&mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} - virtual ~ObGeoToTreeVisitor() { parent_.clear(); } + parent_(GEOM_PAGE_SIZE_GEO, ModulePageAllocator(*allocator, "GISModule")) {} ObGeometry *get_geometry() const { return root_; } template int alloc_geo_tree_obj(T *&obj); @@ -71,21 +68,18 @@ public: bool is_end(ObIWkbGeogPolygon *geo) override { UNUSED(geo); return true; } bool is_end(ObIWkbGeomPolygon *geo) override { UNUSED(geo); return true; } - int finish(ObIWkbGeogMultiLineString *geo) override { UNUSED(geo); return parent_.remove(parent_.last()); } - int finish(ObIWkbGeomMultiLineString *geo) override { UNUSED(geo); return parent_.remove(parent_.last()); } - int finish(ObIWkbGeogMultiPolygon *geo) override { UNUSED(geo); return parent_.remove(parent_.last()); } - int finish(ObIWkbGeomMultiPolygon *geo) override { UNUSED(geo); return parent_.remove(parent_.last()); } - int finish(ObIWkbGeogCollection *geo) override { UNUSED(geo); return parent_.remove(parent_.last()); } - int finish(ObIWkbGeomCollection *geo) override { UNUSED(geo); return parent_.remove(parent_.last()); } + int finish(ObIWkbGeogMultiLineString *geo) override { UNUSED(geo); parent_.pop_back(); return OB_SUCCESS; } + int finish(ObIWkbGeomMultiLineString *geo) override { UNUSED(geo); parent_.pop_back(); return OB_SUCCESS; } + int finish(ObIWkbGeogMultiPolygon *geo) override { UNUSED(geo); parent_.pop_back(); return OB_SUCCESS; } + int finish(ObIWkbGeomMultiPolygon *geo) override { UNUSED(geo); parent_.pop_back(); return OB_SUCCESS; } + int finish(ObIWkbGeogCollection *geo) override { UNUSED(geo); parent_.pop_back(); return OB_SUCCESS; } + int finish(ObIWkbGeomCollection *geo) override { UNUSED(geo); parent_.pop_back(); return OB_SUCCESS; } private: - typedef PageArena ObCGeoModuleArena; ObIAllocator *allocator_; ObGeometry *root_; - ModulePageAllocator page_allocator_; - ObCGeoModuleArena mode_arena_; - ObVector parent_; + ObArray parent_; DISALLOW_COPY_AND_ASSIGN(ObGeoToTreeVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.cpp index c722473cf..62a4f5d5e 100644 --- a/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.cpp @@ -19,6 +19,7 @@ #include "lib/charset/ob_dtoa.h" #include "lib/utility/ob_fast_convert.h" #include "lib/geo/ob_geo_utils.h" +#include "rpc/obmysql/ob_mysql_global.h" namespace oceanbase { @@ -156,8 +157,12 @@ int ObGeoToWktVisitor::appendInnerPoint(double x, double y) int16_t scale = static_cast(scale_); uint64_t len_x = 0; uint64_t len_y = 0; - char *buf_ptr = buffer_.ptr() + buffer_.length(); - if (OB_FAIL(convert_double_to_str(buf_ptr, buffer_.remain(), x, has_scale_, scale, is_oracle_mode_, len_x))) { + char *buf_ptr = nullptr; + uint64_t reserve_len = MAX_DIGITS_IN_DOUBLE * 2; + if (buffer_.remain() < reserve_len && OB_FAIL(buffer_.reserve(reserve_len))) { + LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); + } else if (FALSE_IT(buf_ptr = buffer_.ptr() + buffer_.length())) { + } else if (OB_FAIL(convert_double_to_str(buf_ptr, buffer_.remain(), x, has_scale_, scale, is_oracle_mode_, len_x))) { LOG_WARN("fail to append x to buffer", K(ret), K(x)); } else if (OB_FAIL(buffer_.set_length(buffer_.length() + len_x))) { LOG_WARN("fail to set buffer len", K(ret), K(buffer_.length()), K(len_x)); @@ -176,13 +181,15 @@ template int ObGeoToWktVisitor::appendPoint(T_IBIN *geo) { INIT_SUCC(ret); - const char *type_name = ObGeoTypeUtil::get_geo_name_by_type(geo->type()); - uint64_t reserve_len = MAX_DIGITS_IN_DOUBLE * 2 + 3; + uint64_t reserve_len = PREPARE_DIGITS_IN_DOUBLE * 2 + 4; // two points + "(" ")" "," + if (in_multi_visit_) { + reserve_len += strlen("POINT"); + } // [type_name][(][x][ ][y][)] if (OB_FAIL(buffer_.reserve(reserve_len))) { LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); } else if (!in_multi_visit_ && OB_FAIL(appendTypeNameWithMode(geo))) { - LOG_WARN("fail to append buffer_", K(ret), K(in_multi_visit_), K(type_name)); + LOG_WARN("fail to append buffer_", K(ret), K(in_multi_visit_)); } else if (OB_FAIL(buffer_.append("("))) { LOG_WARN("fail to append buffer_", K(ret)); } else if (OB_FAIL(appendInnerPoint(geo->x(), geo->y()))) { @@ -200,14 +207,15 @@ int ObGeoToWktVisitor::appendLine(T_IBIN *geo) { INIT_SUCC(ret); uint64_t size = geo->size(); - uint64_t reserve_len = (MAX_DIGITS_IN_DOUBLE * 2 + 1) * size; - const char *type_name = ObGeoTypeUtil::get_geo_name_by_type(geo->type()); - reserve_len += in_multi_visit_ ? 0 : 2; + uint64_t reserve_len = 2 + (PREPARE_DIGITS_IN_DOUBLE + 1) * size; + if (in_multi_visit_) { + reserve_len += strlen("LINESTRING"); + } // [type_name][(][x1][ ][y1][,][x2][ ][y2][)] if (OB_FAIL(buffer_.reserve(reserve_len))) { LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); } else if (!in_multi_visit_ && OB_FAIL(appendTypeNameWithMode(geo))) { - LOG_WARN("fail to append buffer_", K(ret), K(in_multi_visit_), K(type_name)); + LOG_WARN("fail to append buffer_", K(ret), K(in_multi_visit_)); } else if (OB_FAIL(buffer_.append("("))) { LOG_WARN("fail to append buffer_", K(ret)); } else { @@ -232,13 +240,39 @@ int ObGeoToWktVisitor::appendLine(T_IBIN *geo) return ret; } +// Assume that each number has a length of PREPARE_DIGITS_IN_DOUBLE +// to estimate polygon wkt lenth, not true length +template +int ObGeoToWktVisitor::estimate_polygon_len(T_IBIN *geo) +{ + T_BIN& poly = *(T_BIN *)(geo->val()); + uint32_t ring_sz = poly.size(); + int reserve_len = ring_sz * 3; // "()," = 3 + uint32_t point_num = 0; + if (in_multi_visit_) { + reserve_len += strlen("POLYGON"); + } + if (ring_sz > 0) { + T_BIN_RING& exterior = poly.exterior_ring(); + point_num += exterior.size(); + T_BIN_INNER_RING& inner_rings = poly.inner_rings(); + typename T_BIN_INNER_RING::iterator iterInnerRing = inner_rings.begin(); + for (; iterInnerRing != inner_rings.end(); ++iterInnerRing) { + point_num += inner_rings.size(); + } + reserve_len += point_num * (PREPARE_DIGITS_IN_DOUBLE + 1); + } + return reserve_len; +} + template int ObGeoToWktVisitor::appendPolygon(T_IBIN *geo) { INIT_SUCC(ret); const char *type_name = ObGeoTypeUtil::get_geo_name_by_type(geo->type()); - uint64_t reserve_len = 2; + uint64_t reserve_len = estimate_polygon_len(geo); // [type_name][(][(][x1][ ][y1][,][x2][ ][y2][,][x3][ ][y3][)][)] if (geo->length() < WKB_COMMON_WKB_HEADER_LEN) { ret = OB_ERR_GIS_INVALID_DATA; @@ -256,9 +290,7 @@ int ObGeoToWktVisitor::appendPolygon(T_IBIN *geo) if (poly.size() != 0) { typename T_BIN_RING::iterator iter = exterior.begin(); // [(][x1][ ][y1][,][x2][ ][y2][,][x3][ ][y3][)] - if (OB_FAIL(buffer_.reserve(reserve_len))) { - LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); - } else if (OB_FAIL(buffer_.append("("))) { + if (OB_FAIL(buffer_.append("("))) { LOG_WARN("fail to append buffer_", K(ret)); } for (; OB_SUCC(ret) && iter != exterior.end(); ++iter) { @@ -281,11 +313,8 @@ int ObGeoToWktVisitor::appendPolygon(T_IBIN *geo) typename T_BIN_INNER_RING::iterator iterInnerRing = inner_rings.begin(); for (; OB_SUCC(ret) && iterInnerRing != inner_rings.end(); ++iterInnerRing) { uint32_t size = iterInnerRing->size(); - uint64_t ring_len = 1 + (MAX_DIGITS_IN_DOUBLE * 2 + 1) * size + 1; typename T_BIN_RING::iterator iter = (*iterInnerRing).begin(); - if (OB_FAIL(buffer_.reserve(ring_len))) { - LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); - } else if (OB_FAIL(buffer_.append("("))) { + if (OB_FAIL(buffer_.append("("))) { LOG_WARN("fail to append buffer_", K(ret)); } for (; OB_SUCC(ret) && iter != (*iterInnerRing).end(); ++iter) { @@ -322,7 +351,7 @@ int ObGeoToWktVisitor::appendMultiPrefix(T_IBIN *geo) { INIT_SUCC(ret); const char *type_name = ObGeoTypeUtil::get_geo_name_by_type(geo->type()); - uint64_t reserve_len = 2; + uint64_t reserve_len = 2 + strlen(type_name); // [type_name][(][x][ ][y][)] if (OB_FAIL(buffer_.reserve(reserve_len))) { LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); @@ -644,7 +673,7 @@ int ObGeoToWktVisitor::init(uint32_t srid, int64_t maxdecimaldigits, bool output LOG_WARN("fail to append buffer_", K(ret)); } else if (srid == UINT32_MAX && OB_FAIL(buffer_.append("NULL"))) { LOG_WARN("fail to append buffer_", K(ret)); - } else if (srid != UINT32_MAX && OB_FAIL(buffer_.append(ffi.ptr(), ffi.length()))) { + } else if (srid != UINT32_MAX && OB_FAIL(buffer_.append(ffi.ptr(), ffi.length(), 0))) { LOG_WARN("fail to append buffer_", K(ret), K(ffi.length())); } else if (OB_FAIL(buffer_.append(";"))) { LOG_WARN("fail to append buffer_", K(ret)); @@ -665,9 +694,7 @@ int ObGeoToWktVisitor::appendCommaWithMode() { // oracle [,][ ] // mysql [,] uint64_t reserve_len = is_oracle_mode_ ? 2 : 1; - if (OB_FAIL(buffer_.reserve(reserve_len))) { - LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); - } else if (OB_FAIL(buffer_.append(","))) { + if (OB_FAIL(buffer_.append(","))) { LOG_WARN("fail to append buffer_", K(ret), K(is_oracle_mode_)); } else if (is_oracle_mode_ && OB_FAIL(buffer_.append(" "))) { LOG_WARN("fail to append buffer_", K(ret), K(is_oracle_mode_)); @@ -682,12 +709,8 @@ int ObGeoToWktVisitor::appendTypeNameWithMode(T_IBIN *geo) { // oracle [typename][ ] // mysql [typename] const char *type_name = ObGeoTypeUtil::get_geo_name_by_type(geo->type()); - uint64_t reserve_len = strlen(type_name); - reserve_len += is_oracle_mode_ ? 1 : 0; - if (OB_FAIL(buffer_.reserve(reserve_len))) { - LOG_WARN("fail to reserve memory for buffer_", K(ret), K(reserve_len)); - } else if (OB_FAIL(buffer_.append(type_name))) { + if (OB_FAIL(buffer_.append(type_name))) { LOG_WARN("fail to append buffer_", K(ret), K(type_name)); } else if (is_oracle_mode_ && OB_FAIL(buffer_.append(" "))) { LOG_WARN("fail to append buffer_", K(ret), K(is_oracle_mode_)); diff --git a/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.h b/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.h index c115c8bf8..0b0196f6b 100644 --- a/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_to_wkt_visitor.h @@ -24,6 +24,7 @@ class ObGeoToWktVisitor : public ObEmptyGeoVisitor { public: static const int MAX_DIGITS_IN_DOUBLE = 25; + static const int PREPARE_DIGITS_IN_DOUBLE = 15; explicit ObGeoToWktVisitor(ObIAllocator *allocator) : buffer_(allocator), has_scale_(false), @@ -97,6 +98,10 @@ private: template int appendTypeNameWithMode(T_IBIN *geo); + template + int estimate_polygon_len(T_IBIN *geo); + public: static int convert_double_to_str(char* buff, uint64_t buff_size, double val, bool has_scale, int16_t scale, bool is_oracle_mode, uint64_t &out_len); diff --git a/deps/oblib/src/lib/geo/ob_geo_tree.cpp b/deps/oblib/src/lib/geo/ob_geo_tree.cpp index 4476629b1..0f6faa908 100644 --- a/deps/oblib/src/lib/geo/ob_geo_tree.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_tree.cpp @@ -80,6 +80,12 @@ int ObCartesianPolygon::push_back(const ObLinearring &ring) return ret; } +int ObCartesianPolygon::reserve(int64_t capacity) +{ + int ret = capacity > 0 ? inner_rings_.reserve(capacity - 1) : OB_SUCCESS; + return ret; +} + int ObGeographPolygon::push_back(const ObLinearring &ring) { INIT_SUCC(ret); @@ -93,6 +99,12 @@ int ObGeographPolygon::push_back(const ObLinearring &ring) return ret; } +int ObGeographPolygon::reserve(int64_t capacity) +{ + int ret = capacity > 0 ? inner_rings_.reserve(capacity - 1) : OB_SUCCESS; + return ret; +} + template @@ -370,6 +382,58 @@ void ObCartesianBox::set_box(double min_x, double min_y, double max_x, double ma max_p_.set<1>(max_y); } +int ObCartesianGeometrycollection::set(uint32_t index, ObGeometry *geo) +{ + int ret = OB_SUCCESS; + if (index >= geoms_.size()) { + ret = OB_ERR_ARGUMENT_OUT_OF_RANGE; + LOG_WARN("index is out of range", K(ret), K(index), K(geoms_.size())); + } else { + geoms_[index] = geo; + } + return ret; +} + +int ObGeographGeometrycollection::set(uint32_t index, ObGeometry *geo) +{ + int ret = OB_SUCCESS; + if (index >= geoms_.size()) { + ret = OB_ERR_ARGUMENT_OUT_OF_RANGE; + LOG_WARN("index is out of range", K(ret), K(index), K(geoms_.size())); + } else { + geoms_[index] = geo; + } + return ret; +} + +int ObCartesianGeometrycollection::resize(int64_t size) { + int ret = OB_SUCCESS; + if (size > geoms_.size()) { + if (OB_FAIL(geoms_.prepare_allocate(size))) { + OB_LOG(WARN, "failed to resize ObGeomVector", K(ret), K(size)); + } + } else { + while (size != geoms_.size()) { + geoms_.pop_back(); + } + } + return ret; +} + +int ObGeographGeometrycollection::resize(int64_t size) { + int ret = OB_SUCCESS; + if (size > geoms_.size()) { + if (OB_FAIL(geoms_.prepare_allocate(size))) { + OB_LOG(WARN, "failed to resize ObGeomVector", K(ret), K(size)); + } + } else { + while (size != geoms_.size()) { + geoms_.pop_back(); + } + } + return ret; +} + bool ObCartesianBox::Contains(ObCartesianBox &other) { double this_min_x = min_corner().get<0>(); diff --git a/deps/oblib/src/lib/geo/ob_geo_tree.h b/deps/oblib/src/lib/geo/ob_geo_tree.h index 918e4ca35..4ebdd733b 100644 --- a/deps/oblib/src/lib/geo/ob_geo_tree.h +++ b/deps/oblib/src/lib/geo/ob_geo_tree.h @@ -21,13 +21,18 @@ namespace oceanbase { namespace common { +static const int64_t DEFAULT_PAGE_SIZE_GEO = 8192; +static const int64_t POINT_PAGE_SIZE_GEO = 512; // 32 point +static const int64_t LINE_PAGE_SIZE_GEO = 1024; // 8 line +static const int64_t POLY_PAGE_SIZE_GEO = 2048; // 8 poly +static const int64_t GEOM_PAGE_SIZE_GEO = 512; // 128 geometry * class ObIGeoVisitor; template -class ObGeomConstIterator : public array::Iterator, T> +class ObGeomConstIterator : public array::Iterator, T> { - typedef array::Iterator, T> base_t; + typedef array::Iterator, T> base_t; typedef ObGeomConstIterator self_t; public: typedef typename std::random_access_iterator_tag iterator_category; @@ -128,7 +133,7 @@ class ObGeomVector public: typedef T value_type; typedef ObGeomConstIterator const_iterator; - typedef typename ObArray::iterator iterator; + typedef typename ObArray::iterator iterator; typedef int64_t size_type; typedef const T *const_pointer; typedef const T &const_reference; @@ -137,8 +142,8 @@ public: typedef int64_t difference_type; public: - ObGeomVector(ModulePageAllocator &page_allocator) - : vec_(OB_MALLOC_NORMAL_BLOCK_SIZE, page_allocator) {} + ObGeomVector(const ModulePageAllocator &page_allocator, int64_t block_size = DEFAULT_PAGE_SIZE_GEO) + : vec_(block_size, page_allocator) {} ObGeomVector(const ObGeomVector &v) = default; ObGeomVector &operator=(const ObGeomVector &rhs) = default; ~ObGeomVector() {}; @@ -147,18 +152,20 @@ public: size_type size() const { return vec_.size(); } bool empty() const { return vec_.size() == 0;} void pop_front() { vec_.remove(0); } - void resize(int32_t size) { + int resize(int64_t size) { int ret = OB_SUCCESS; if (size > vec_.size()) { if (OB_FAIL(vec_.prepare_allocate(size))) { - OB_LOG(WARN, "failed to resize ObGeomVector", K(ret)); + OB_LOG(WARN, "failed to resize ObGeomVector", K(ret), K(size)); } } else { while (size != vec_.size()) { vec_.pop_back(); } } + return ret; } + int reserve(int64_t capacity) { return vec_.reserve(capacity); } void clear() { vec_.reuse(); } value_type &back() { return *(vec_.end()-1); } const value_type &back() const { return *(vec_.end()-1); }; @@ -168,14 +175,14 @@ public: const value_type &operator[](int64_t i) const { return vec_[i]; } // iterator iterator begin() { return vec_.begin(); } - const_iterator begin() const { return const_iterator(&*(const_cast *>(&vec_))->begin()); } + const_iterator begin() const { return const_iterator(&*(const_cast *>(&vec_))->begin()); } iterator end() { return vec_.end(); } - const_iterator end() const { return const_iterator(&*(const_cast *>(&vec_))->end()); } - // ObArray& get_vec_() const { return vec_; } + const_iterator end() const { return const_iterator(&*(const_cast *>(&vec_))->end()); } + // ObArray& get_vec_() const { return vec_; } int remove(int64_t idx) { return vec_.remove(idx); } private: - common::ObArray vec_; + common::ObArray vec_; }; // ObPoint is an abstract class @@ -183,8 +190,8 @@ class ObPoint : public ObGeometry { public: // constructor - ObPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) : - ObGeometry(srid, allocator) {}; + ObPoint(uint32_t srid = 0) : + ObGeometry(srid) {}; ~ObPoint() {}; ObPoint(const ObPoint&) = default; ObPoint &operator=(const ObPoint&) = default; @@ -210,12 +217,12 @@ public: class ObCartesianPoint : public ObPoint { public: - // constructor - ObCartesianPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) : ObPoint(srid, allocator) { + // constructor, allocator is not used, just for compatible with other tree constructors + ObCartesianPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) : ObPoint(srid) { point_.set<0>(std::nan("")); point_.set<1>(std::nan("")); }; - ObCartesianPoint(double x, double y, uint32_t srid = 0, ObIAllocator *allocator = NULL) : ObPoint(srid, allocator) { + ObCartesianPoint(double x, double y, uint32_t srid = 0) : ObPoint(srid) { point_.set<0>(x); point_.set<1>(y); }; @@ -245,11 +252,11 @@ class ObGeographPoint : public ObPoint { public: // constructor - ObGeographPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) : ObPoint(srid, allocator) { + ObGeographPoint(uint32_t srid = 0, ObIAllocator *allocator = NULL) : ObPoint(srid) { point_.set<0>(std::nan("")); point_.set<1>(std::nan("")); }; - ObGeographPoint(double x, double y, uint32_t srid = 0, ObIAllocator *allocator = NULL) : ObPoint(srid, allocator) { + ObGeographPoint(double x, double y, uint32_t srid = 0) : ObPoint(srid) { point_.set<0>(x); point_.set<1>(y); }; @@ -281,16 +288,16 @@ class ObCurve : public ObGeometry public: // do nothing // constructor - ObCurve(uint32_t srid = 0, ObIAllocator *allocator = NULL) : - ObGeometry(srid, allocator){}; + ObCurve(uint32_t srid = 0) : + ObGeometry(srid){}; ~ObCurve() {}; }; class ObLineString : public ObCurve { public: - ObLineString(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObCurve(srid, allocator) + ObLineString(uint32_t srid = 0) + : ObCurve(srid) {} ~ObLineString() {} @@ -309,7 +316,7 @@ public: ObIAllocator &allocator, ObLineString*& output); }; -static const int64_t DEFAULT_PAGE_SIZE_GEO = 8192; + class ObCartesianLineString : public ObLineString { public: @@ -319,14 +326,12 @@ public: typedef ObGeomVector::const_iterator const_iterator; public: ObCartesianLineString(uint32_t srid, ObIAllocator &allocator) - : ObLineString(srid, &allocator), - page_allocator_(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), - points_(page_allocator_) {} + : ObLineString(srid), + points_(ModulePageAllocator(allocator, "GISModule"), POINT_PAGE_SIZE_GEO) {} ObCartesianLineString() - : ObLineString(0, NULL), - page_allocator_(), - points_(page_allocator_) {} + : ObLineString(0), + points_(ModulePageAllocator(CURRENT_CONTEXT->get_arena_allocator(), "GISModule"), POINT_PAGE_SIZE_GEO) {} ObCartesianLineString(const ObCartesianLineString&) = default; ObCartesianLineString &operator=(const ObCartesianLineString&) = default; @@ -341,7 +346,7 @@ public: int push_back(const ObWkbGeomInnerPoint& point) { return points_.push_back(point); } int64_t size() const override { return points_.size(); } void pop_front() override { points_.pop_front(); } - void resize(int32_t size) { points_.resize(size); } + int resize(int64_t size) { return points_.resize(size); } void clear() override { points_.clear(); } ObWkbGeomInnerPoint &back() { return points_.back(); } const ObWkbGeomInnerPoint &back() const { return points_.back(); } @@ -357,11 +362,11 @@ public: const_iterator end() const { return points_.end(); } const ObGeomVector &get_points() const {return points_;} ObGeomVector &get_points() {return points_;} + int reserve(int64_t capacity) { return points_.reserve(capacity); } TO_STRING_KV("type", "ObCartesianLineString", "size", size()); private: - ModulePageAllocator page_allocator_; ObGeomVector points_; }; @@ -373,14 +378,12 @@ public: typedef ObGeomVector::const_iterator const_iterator; public: ObGeographLineString(uint32_t srid, ObIAllocator &allocator) - : ObLineString(srid, &allocator), - page_allocator_(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), - points_(page_allocator_) {} + : ObLineString(srid), + points_(ModulePageAllocator(allocator, "GISModule"), POINT_PAGE_SIZE_GEO) {} ObGeographLineString() - : ObLineString(0, NULL), - page_allocator_(), - points_(page_allocator_) {} + : ObLineString(0), + points_(ModulePageAllocator(CURRENT_CONTEXT->get_arena_allocator(), "GISModule"), POINT_PAGE_SIZE_GEO) {} ObGeographLineString(const ObGeographLineString&) = default; ObGeographLineString &operator=(const ObGeographLineString&) = default; @@ -394,7 +397,7 @@ public: int push_back(const ObWkbGeogInnerPoint& point) { return points_.push_back(point); } int64_t size() const override { return points_.size(); } void pop_front() override { points_.pop_front(); } - void resize(int32_t size) { points_.resize(size); } + int resize(int64_t size) { return points_.resize(size); } void clear() override { points_.clear(); } ObWkbGeogInnerPoint &back() { return points_.back(); } const ObWkbGeogInnerPoint &back() const { return points_.back(); } @@ -411,11 +414,11 @@ public: const_iterator end() const { return points_.end(); } const ObGeomVector &get_points() const {return points_;} ObGeomVector &get_points() {return points_;} + int reserve(int64_t capacity) { return points_.reserve(capacity); } TO_STRING_KV("type", "ObGeographLineString", "size", size()); private: - ModulePageAllocator page_allocator_; ObGeomVector points_; }; @@ -448,7 +451,7 @@ public: bool is_empty() const override { return ObCartesianLineString::is_empty(); } bool empty() const { return ObCartesianLineString::empty(); } void pop_front() override { ObCartesianLineString::pop_front(); } - void resize(int32_t size) { ObCartesianLineString::resize(size); } + int resize(int64_t size) { return ObCartesianLineString::resize(size); } void clear() override { ObCartesianLineString::clear(); } ObWkbGeomInnerPoint &back() { return ObCartesianLineString::back(); } const ObWkbGeomInnerPoint &back() const { return ObCartesianLineString::back(); }; @@ -456,6 +459,8 @@ public: const ObWkbGeomInnerPoint &front() const { return ObCartesianLineString::front(); } ObWkbGeomInnerPoint &operator[](int32_t i) { return ObCartesianLineString::operator[](i); } const ObWkbGeomInnerPoint &operator[](int32_t i) const { return ObCartesianLineString::operator[](i); } + TO_STRING_KV("type", "ObCartesianLinearring", + "size", size()); }; class ObGeographLinearring : public ObGeographLineString, public ObLinearring @@ -479,7 +484,7 @@ public: bool is_empty() const override { return ObGeographLineString::is_empty(); } bool empty() const { return ObGeographLineString::empty(); } void pop_front() override { ObGeographLineString::pop_front(); } - void resize(int32_t size) { ObGeographLineString::resize(size); } + int resize(int64_t size) { return ObGeographLineString::resize(size); } void clear() override { ObGeographLineString::clear(); } ObWkbGeogInnerPoint &back() { return ObGeographLineString::back(); } const ObWkbGeogInnerPoint &back() const { return ObGeographLineString::back(); }; @@ -487,6 +492,8 @@ public: const ObWkbGeogInnerPoint &front() const { return ObGeographLineString::front(); } ObWkbGeogInnerPoint &operator[](int32_t i) { return ObGeographLineString::operator[](i); } const ObWkbGeogInnerPoint &operator[](int32_t i) const { return ObGeographLineString::operator[](i); } + TO_STRING_KV("type", "ObGeographLineString", + "size", size()); }; class ObSurface : public ObGeometry @@ -494,8 +501,8 @@ class ObSurface : public ObGeometry public: // do nothing // constructor - ObSurface(uint32_t srid = 0, ObIAllocator *allocator = NULL) : - ObGeometry(srid, allocator){}; + ObSurface(uint32_t srid = 0) : + ObGeometry(srid){}; ~ObSurface() {}; }; @@ -503,8 +510,8 @@ class ObPolygon : public ObSurface { public: // contructor - ObPolygon(uint32_t srid = 0, ObIAllocator *allocator = NULL) - : ObSurface(srid, allocator) + ObPolygon(uint32_t srid = 0) + : ObSurface(srid) {} ~ObPolygon() {} ObGeoType type() const override { return ObGeoType::POLYGON; } @@ -537,16 +544,14 @@ class ObCartesianPolygon : public ObPolygon public: // constructor ObCartesianPolygon(uint32_t srid, ObIAllocator &allocator) - : ObPolygon(srid, &allocator), - page_allocator_(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), + : ObPolygon(srid), exterior_(srid, allocator), - inner_rings_(page_allocator_) {} + inner_rings_(ModulePageAllocator(allocator, "GISModule"), LINE_PAGE_SIZE_GEO) {} ObCartesianPolygon() : ObPolygon(), - page_allocator_(), exterior_(), - inner_rings_(page_allocator_) {} + inner_rings_(ModulePageAllocator(CURRENT_CONTEXT->get_arena_allocator(), "GISModule"), LINE_PAGE_SIZE_GEO) {} ObCartesianPolygon(const ObCartesianPolygon &v) = default; ObCartesianPolygon &operator=(const ObCartesianPolygon &rhs) = default; ~ObCartesianPolygon() {}; @@ -567,11 +572,11 @@ public: ObCartesianLinearring &cartesian_exterior_ring() const { return const_cast(exterior_); } ObGeomVector &interior_rings() { return inner_rings_; } ObGeomVector const &const_interior_rings() const { return inner_rings_; } + int reserve(int64_t capacity); TO_STRING_KV("type", "ObCartesianPolygon", "size", size()); private: - ModulePageAllocator page_allocator_; ObCartesianLinearring exterior_; ObGeomVector inner_rings_; }; @@ -581,16 +586,14 @@ class ObGeographPolygon : public ObPolygon public: // constructor ObGeographPolygon(uint32_t srid, ObIAllocator &allocator) - : ObPolygon(srid, &allocator), - page_allocator_(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR), + : ObPolygon(srid), exterior_(srid, allocator), - inner_rings_(page_allocator_) {} + inner_rings_(ModulePageAllocator(allocator, "GISModule"), LINE_PAGE_SIZE_GEO) {} ObGeographPolygon() - : ObPolygon(0, NULL), - page_allocator_(), + : ObPolygon(0), exterior_(), - inner_rings_(page_allocator_) {} + inner_rings_(ModulePageAllocator(CURRENT_CONTEXT->get_arena_allocator(), "GISModule"), LINE_PAGE_SIZE_GEO) {} ObGeographPolygon(const ObGeographPolygon &v) = default; ObGeographPolygon &operator=(const ObGeographPolygon &rhs) = default; ~ObGeographPolygon() {}; @@ -612,11 +615,11 @@ public: ObGeographLinearring &geographic_exterior_ring() const { return const_cast(exterior_); } ObGeomVector &interior_rings() { return inner_rings_; } ObGeomVector const &const_interior_rings() const { return inner_rings_; } + int reserve(int64_t capacity); TO_STRING_KV("type", "ObGeographPolygon", "size", size()); private: - ModulePageAllocator page_allocator_; ObGeographLinearring exterior_; ObGeomVector inner_rings_; }; @@ -625,14 +628,12 @@ class ObGeometrycollection : public ObGeometry { public: // constructor - ObGeometrycollection(uint32_t srid, ObIAllocator &allocator) - : ObGeometry(srid, &allocator), - page_allocator_(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) + ObGeometrycollection(uint32_t srid) + : ObGeometry(srid) {} ObGeometrycollection() - : ObGeometry(0, NULL), - page_allocator_() + : ObGeometry(0) {} ~ObGeometrycollection() {}; @@ -643,20 +644,18 @@ public: virtual void pop_front() = 0; virtual bool empty() const = 0; virtual uint64_t size() const = 0; - virtual void resize(int32_t count) = 0; + virtual int resize(int64_t count) = 0; virtual void clear() = 0; virtual int push_back(const ObGeometry &g) = 0; static int create_collection(ObGeoCRS crs, uint32_t srid, ObIAllocator &allocator, ObGeometrycollection*& output); -protected: - ModulePageAllocator page_allocator_; }; class ObMultipoint : public ObGeometrycollection { public: - ObMultipoint(uint32_t srid, ObIAllocator &allocator) : - ObGeometrycollection(srid, allocator){}; + ObMultipoint(uint32_t srid) : + ObGeometrycollection(srid){}; ObMultipoint() : ObGeometrycollection(){}; @@ -678,12 +677,12 @@ public: public: ObCartesianMultipoint(uint32_t srid, ObIAllocator &allocator) - : ObMultipoint(srid, allocator), - points_(page_allocator_) {} + : ObMultipoint(srid), + points_(ModulePageAllocator(allocator, "GISModule"), POINT_PAGE_SIZE_GEO) {} ObCartesianMultipoint() : ObMultipoint(), - points_(page_allocator_) {} + points_(ModulePageAllocator(), POINT_PAGE_SIZE_GEO) {} ~ObCartesianMultipoint() {} @@ -701,7 +700,7 @@ public: return true; } uint64_t size() const override { return points_.size(); } - void resize(int32_t size) { points_.resize(size); } + int resize(int64_t size) { return points_.resize(size); } void clear() override { points_.clear(); } ObWkbGeomInnerPoint &front() { return points_.front(); } const ObWkbGeomInnerPoint &front() const { return points_.front(); } @@ -715,6 +714,7 @@ public: const_iterator begin() const { return points_.begin(); } iterator end() { return points_.end(); } const_iterator end() const { return points_.end(); } + int reserve(int64_t capacity) { return points_.reserve(capacity); } TO_STRING_KV("type", "ObCartesianMultipoint", "size", size()); @@ -732,12 +732,12 @@ public: public: ObGeographMultipoint(uint32_t srid, ObIAllocator &allocator) - : ObMultipoint(srid, allocator), - points_(page_allocator_) {} + : ObMultipoint(srid), + points_(ModulePageAllocator(allocator, "GISModule"), POINT_PAGE_SIZE_GEO) {} ObGeographMultipoint() : ObMultipoint(), - points_(page_allocator_) {} + points_(ModulePageAllocator(), POINT_PAGE_SIZE_GEO) {} ~ObGeographMultipoint() {} ObGeoCRS crs() const override { return ObGeoCRS::Geographic; } @@ -754,7 +754,7 @@ public: return true; } uint64_t size() const override { return points_.size(); } - void resize(int32_t size) { points_.resize(size); } + int resize(int64_t size) { return points_.resize(size); } void clear() override { points_.clear(); } ObWkbGeogInnerPoint &front() { return points_.front(); } const ObWkbGeogInnerPoint &front() const { return points_.front(); } @@ -768,6 +768,7 @@ public: const_iterator begin() const { return points_.begin(); } iterator end() { return points_.end(); } const_iterator end() const { return points_.end(); } + int reserve(int64_t capacity) { return points_.reserve(capacity); } TO_STRING_KV("type", "ObGeographMultipoint", "size", size()); @@ -781,8 +782,8 @@ class ObMulticurve : public ObGeometrycollection public: // do nothing // constructor - ObMulticurve(uint32_t srid, ObIAllocator &allocator) : - ObGeometrycollection(srid, allocator){}; + ObMulticurve(uint32_t srid) : + ObGeometrycollection(srid){}; ObMulticurve() : ObGeometrycollection(){}; ~ObMulticurve() {}; @@ -791,8 +792,8 @@ public: class ObMultilinestring : public ObMulticurve { public: - ObMultilinestring(uint32_t srid, ObIAllocator &allocator) : - ObMulticurve(srid, allocator){}; + ObMultilinestring(uint32_t srid) : + ObMulticurve(srid){}; ObMultilinestring() : ObMulticurve(){}; @@ -813,12 +814,12 @@ public: public: ObCartesianMultilinestring(uint32_t srid, ObIAllocator &allocator) - : ObMultilinestring(srid, allocator), - lines_(page_allocator_) {} + : ObMultilinestring(srid), + lines_(ModulePageAllocator(allocator, "GISModule"), LINE_PAGE_SIZE_GEO) {} ObCartesianMultilinestring() : ObMultilinestring(), - lines_(page_allocator_) {} + lines_(ModulePageAllocator(), LINE_PAGE_SIZE_GEO) {} ~ObCartesianMultilinestring() {} // Geometry interface @@ -836,7 +837,7 @@ public: return true; } uint64_t size() const override { return lines_.size(); } - void resize(int32_t size) { lines_.resize(size); } + int resize(int64_t size) { return lines_.resize(size); } void clear() override { lines_.clear(); } ObCartesianLineString &front() { return *(lines_.begin()); } const ObCartesianLineString &front() const { return *(lines_.begin()); } @@ -851,6 +852,7 @@ public: iterator end() { return lines_.end(); } const_iterator end() const { return lines_.end(); } int remove(int64_t idx) { return lines_.remove(idx); } + int reserve(int64_t capacity) { return lines_.reserve(capacity); } TO_STRING_KV("type", "ObCartesianMultilinestring", "size", size()); @@ -868,12 +870,12 @@ public: public: ObGeographMultilinestring(uint32_t srid, ObIAllocator &allocator) - : ObMultilinestring(srid, allocator), - lines_(page_allocator_) {} + : ObMultilinestring(srid), + lines_(ModulePageAllocator(allocator, "GISModule"), LINE_PAGE_SIZE_GEO) {} ObGeographMultilinestring() : ObMultilinestring(), - lines_(page_allocator_) {} + lines_(ModulePageAllocator(), LINE_PAGE_SIZE_GEO) {} ~ObGeographMultilinestring() {} @@ -893,7 +895,7 @@ public: return true; } uint64_t size() const override { return lines_.size(); } - void resize(int32_t size) { lines_.resize(size); } + int resize(int64_t size) { return lines_.resize(size); } void clear() override { lines_.clear(); } ObGeographLineString &front() { return *(lines_.begin()); } const ObGeographLineString &front() const { return *(lines_.begin()); } @@ -907,6 +909,7 @@ public: const_iterator begin() const { return lines_.begin(); } iterator end() { return lines_.end(); } const_iterator end() const { return lines_.end(); } + int reserve(int64_t capacity) { return lines_.reserve(capacity); } TO_STRING_KV("type", "ObGeographMultilinestring", "size", size()); @@ -920,8 +923,8 @@ class ObMultisurface : public ObGeometrycollection public: // do nothing // constructor - ObMultisurface(uint32_t srid, ObIAllocator &allocator) : - ObGeometrycollection(srid, allocator){}; + ObMultisurface(uint32_t srid) : + ObGeometrycollection(srid){}; ObMultisurface() : ObGeometrycollection(){}; @@ -931,8 +934,8 @@ public: class ObMultipolygon : public ObMultisurface { public: - ObMultipolygon(uint32_t srid, ObIAllocator &allocator) : - ObMultisurface(srid, allocator){}; + ObMultipolygon(uint32_t srid) : + ObMultisurface(srid){}; ObMultipolygon() : ObMultisurface(){}; @@ -953,12 +956,12 @@ public: public: ObCartesianMultipolygon(uint32_t srid, ObIAllocator &allocator) - : ObMultipolygon(srid, allocator), - polygons_(page_allocator_) {} + : ObMultipolygon(srid), + polygons_(ModulePageAllocator(allocator, "GISModule"), POLY_PAGE_SIZE_GEO) {} ObCartesianMultipolygon() : ObMultipolygon(), - polygons_(page_allocator_) {} + polygons_(ModulePageAllocator(), POLY_PAGE_SIZE_GEO) {} ~ObCartesianMultipolygon() {} @@ -978,7 +981,7 @@ public: return true; } uint64_t size() const override { return polygons_.size(); } - void resize(int32_t size) { polygons_.resize(size); } + int resize(int64_t size) { return polygons_.resize(size); } void clear() override { polygons_.clear(); } ObCartesianPolygon &front() { return *(polygons_.begin()); } const ObCartesianPolygon &front() const { return *(polygons_.begin()); } @@ -991,6 +994,7 @@ public: const_iterator begin() const { return polygons_.begin(); } iterator end() { return polygons_.end(); } const_iterator end() const { return polygons_.end(); } + int reserve(int64_t capacity) { return polygons_.reserve(capacity); } TO_STRING_KV("type", "ObCartesianMultipolygon", "size", size()); @@ -1008,12 +1012,12 @@ public: public: ObGeographMultipolygon(uint32_t srid, ObIAllocator &allocator) - : ObMultipolygon(srid, allocator), - polygons_(page_allocator_) {} + : ObMultipolygon(srid), + polygons_(ModulePageAllocator(allocator, "GISModule"), POLY_PAGE_SIZE_GEO) {} ObGeographMultipolygon() : ObMultipolygon(), - polygons_(page_allocator_) {} + polygons_(ModulePageAllocator(), POLY_PAGE_SIZE_GEO) {} ~ObGeographMultipolygon() {} // Geometry interface @@ -1032,7 +1036,7 @@ public: return true; } uint64_t size() const override { return polygons_.size(); } - void resize(int32_t size) { polygons_.resize(size); } + int resize(int64_t size) { return polygons_.resize(size); } void clear() override { polygons_.clear(); } ObGeographPolygon &front() { return *(polygons_.begin()); } const ObGeographPolygon &front() const { return *(polygons_.begin()); } @@ -1046,6 +1050,7 @@ public: const_iterator begin() const { return polygons_.begin(); } iterator end() { return polygons_.end(); } const_iterator end() const { return polygons_.end(); } + int reserve(int64_t capacity) { return polygons_.reserve(capacity); } TO_STRING_KV("type", "ObGeographMultipolygon", "size", size()); @@ -1157,22 +1162,20 @@ public: public: ObCartesianGeometrycollection(uint32_t srid, ObIAllocator &allocator) - : ObGeometrycollection(srid, allocator), - mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_), - geoms_(&mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} + : ObGeometrycollection(srid), + geoms_(GEOM_PAGE_SIZE_GEO, ModulePageAllocator(allocator, "GISModule")) {} ObCartesianGeometrycollection() : ObGeometrycollection(), - mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_), - geoms_(&mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} - ~ObCartesianGeometrycollection() { geoms_.clear(); } + geoms_(GEOM_PAGE_SIZE_GEO, ModulePageAllocator()) {} + ~ObCartesianGeometrycollection() {} ObGeoCRS crs() const override { return ObGeoCRS::Cartesian; } // visitor interface int do_visit(ObIGeoVisitor &visitor); void pop_front() override { - geoms_.remove(geoms_.begin()); + geoms_.remove(0); } - int push_back(const ObGeometry &g) { return geoms_.push_back(&g); } + int push_back(const ObGeometry &g) { return geoms_.push_back(&const_cast(g)); } bool empty() const override { return geoms_.size() == 0; } bool is_empty() const override { for (uint64_t i = 0; i < size(); i++) { @@ -1183,8 +1186,8 @@ public: return true; } uint64_t size() const override { return geoms_.size(); } - void resize(int32_t size) override { geoms_.reserve(size); } - void clear() override { geoms_.clear(); } + int resize(int64_t size) override; + void clear() override { geoms_.reuse(); } iterator begin() { return geoms_.begin(); } const_iterator begin() const { return geoms_.begin(); } @@ -1200,10 +1203,13 @@ public: return *geoms_[i]; } + int set(uint32_t index, ObGeometry *geo); + int reserve(int64_t capacity) { return geoms_.reserve(capacity); } + TO_STRING_KV("type", "ObCartesianGeometrycollection", + "size", size()); private: DISALLOW_COPY_AND_ASSIGN(ObCartesianGeometrycollection); - ObCGeoModuleArena mode_arena_; - ObVector geoms_; + ObArray geoms_; }; class ObGeographGeometrycollection : public ObGeometrycollection @@ -1219,22 +1225,20 @@ public: public: ObGeographGeometrycollection(uint32_t srid, ObIAllocator &allocator) - : ObGeometrycollection(srid, allocator), - mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_), - geoms_(&mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} + : ObGeometrycollection(srid), + geoms_(GEOM_PAGE_SIZE_GEO, ModulePageAllocator(allocator, "GISModule")) {} ObGeographGeometrycollection() : ObGeometrycollection(), - mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_), - geoms_(&mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {} - ~ObGeographGeometrycollection() { geoms_.clear(); } + geoms_(GEOM_PAGE_SIZE_GEO, ModulePageAllocator()) {} + ~ObGeographGeometrycollection() {} ObGeoCRS crs() const override { return ObGeoCRS::Geographic; } // visitor interface int do_visit(ObIGeoVisitor &visitor); void pop_front() override { - geoms_.remove(geoms_.begin()); + geoms_.remove(0); } - int push_back(const ObGeometry &g) { return geoms_.push_back(&g); } + int push_back(const ObGeometry &g) { return geoms_.push_back(&const_cast(g)); } bool empty() const override { return geoms_.size() == 0; } bool is_empty() const override { for (uint64_t i = 0; i < size(); i++) { @@ -1245,8 +1249,8 @@ public: return true; } uint64_t size() const override { return geoms_.size(); } - void resize(int32_t size) override { geoms_.reserve(size); } - void clear() override { geoms_.clear(); } + int resize(int64_t size) override; + void clear() override { geoms_.reuse(); } iterator begin() { return geoms_.begin(); } const_iterator begin() const { return geoms_.begin(); } @@ -1262,10 +1266,14 @@ public: return *geoms_[i]; } + int set(uint32_t index, ObGeometry *geo); + int reserve(int64_t capacity) { return geoms_.reserve(capacity); } + TO_STRING_KV("type", "ObGeographGeometrycollection", + "size", size()); + private: DISALLOW_COPY_AND_ASSIGN(ObGeographGeometrycollection); - ObCGeoModuleArena mode_arena_; - ObVector geoms_; + ObArray geoms_; }; } // namespace common diff --git a/deps/oblib/src/lib/geo/ob_geo_utils.cpp b/deps/oblib/src/lib/geo/ob_geo_utils.cpp index 37e725c46..828e44496 100644 --- a/deps/oblib/src/lib/geo/ob_geo_utils.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_utils.cpp @@ -1,4 +1,3 @@ - /** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. @@ -49,6 +48,8 @@ #include "lib/geo/ob_geo_vertex_collect_visitor.h" #include "lib/geo/ob_geo_point_location_visitor.h" #include "lib/geo/ob_geo_zoom_in_visitor.h" +#include "lib/geo/ob_geo_close_ring_visitor.h" +#include "share/rc/ob_tenant_base.h" namespace oceanbase { @@ -367,7 +368,7 @@ int ObGeoTypeUtil::create_geo_by_type(ObIAllocator &allocator, } } } else if (is_3d_geo_type(geo_type)) { - if (OB_ISNULL(geo = OB_NEWx(ObGeometry3D, (&allocator), srid, (&allocator)))) { + if (OB_ISNULL(geo = OB_NEWx(ObGeometry3D, (&allocator), srid))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create 3d geo object", K(ret), K(geo_type)); } else { @@ -501,23 +502,17 @@ int ObGeoTypeUtil::convert_geometry_3D_to_2D( int ObGeoTypeUtil::normalize_geometry(ObGeometry &geo, const ObSrsItem *srs) { int ret = OB_SUCCESS; - uint32_t zoom_in_value = 0; if (is_3d_geo_type(geo.type())) { ObGeometry3D *geo_3d = static_cast(&geo); - if (OB_FAIL(geo_3d->normalize(srs, zoom_in_value))) { + if (OB_FAIL(geo_3d->normalize(srs))) { LOG_WARN("fail to check coordinate range", K(ret)); } } else { ObGeoNormalizeVisitor normalize_visitor(srs); if (OB_FAIL(geo.do_visit(normalize_visitor))) { LOG_WARN("normalize geo failed", K(ret)); - } else { - zoom_in_value = normalize_visitor.get_zoom_in_value(); } } - if (OB_SUCC(ret)) { - geo.set_zoom_in_value(zoom_in_value); - } return ret; } @@ -564,14 +559,20 @@ int ObGeoTypeUtil::build_geometry(ObIAllocator &allocator, geo->set_srid(header.srid_); ObString wkb; uint32_t offset = 0; - ObString wkb_data; if (OB_FAIL(ObGeoTypeUtil::get_wkb_from_swkb(swkb, wkb, offset))) { LOG_WARN("fail to get wkb from swkb", K(ret), K(swkb)); - } else if (OB_FAIL(ob_write_string(allocator, wkb, wkb_data))) { - LOG_WARN("Failed to copy swkb memory", K(ret)); } else { - geo->set_data(wkb_data); - if (!is_3d_geo_type(header.type_)) { + ObString wkb_data; + if (build_flag & ObGeoBuildFlag::GEO_NOT_COPY_WKB) { + wkb_data = wkb; + } else { + if (OB_FAIL(ob_write_string(allocator, wkb, wkb_data))) { + LOG_WARN("Failed to copy swkb memory", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (FALSE_IT(geo->set_data(wkb_data))) { + } else if (!is_3d_geo_type(header.type_)) { bool need_check_ring = build_flag & ObGeoBuildFlag::GEO_CHECK_RING; ObGeoWkbCheckVisitor wkb_check(wkb_data, header.bo_, need_check_ring); if (OB_FAIL(geo->do_visit(wkb_check))) { @@ -622,7 +623,8 @@ int ObGeoTypeUtil::construct_geometry(ObIAllocator &allocator, const ObString &swkb, const ObSrsItem *srs, ObGeometry *&geo, - bool has_srid /* = true */) + bool has_srid /* = true */, + bool with_copy /* = true */) { int ret = OB_SUCCESS; // has_srid is always true currently @@ -670,14 +672,18 @@ int ObGeoTypeUtil::construct_geometry(ObIAllocator &allocator, ret = OB_ERR_GIS_INVALID_DATA; LOG_WARN("invalid point data length", K(ret), K(len)); } else { - ObString wkb_copy; - if (OB_FAIL(ob_write_string(allocator, wkb, wkb_copy))) { - LOG_WARN("Failed to copy wkb memory", K(ret)); - } else { - geo->set_data(wkb_copy); - if (has_srid) { - geo->set_srid(srid); + if (has_srid) { + geo->set_srid(srid); + } + if (with_copy) { + ObString wkb_copy; + if (OB_FAIL(ob_write_string(allocator, wkb, wkb_copy))) { + LOG_WARN("Failed to copy wkb memory", K(ret)); + } else { + geo->set_data(wkb_copy); } + } else { + geo->set_data(wkb); } if (OB_FAIL(ret)) { @@ -704,21 +710,20 @@ int ObGeoTypeUtil::construct_geometry(ObIAllocator &allocator, return ret; } -int ObGeoTypeUtil::copy_geometry(ObIAllocator &allocator, +int ObGeoTypeUtil::copy_geometry(lib::MemoryContext& ctx, ObGeometry &origin_geo, ObGeometry *©_geo) { int ret = OB_SUCCESS; copy_geo = nullptr; ObString data; - if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(allocator, origin_geo.type(), origin_geo.crs() == ObGeoCRS::Geographic, true, copy_geo))) { + if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(ctx->get_arena_allocator(), origin_geo.type(), origin_geo.crs() == ObGeoCRS::Geographic, true, copy_geo))) { LOG_WARN("fail to create geo by type", K(ret)); - } else if (OB_FAIL(ob_write_string(allocator, ObString(origin_geo.length(), origin_geo.val()), data))) { + } else if (OB_FAIL(ob_write_string(ctx->get_arena_allocator(), ObString(origin_geo.length(), origin_geo.val()), data))) { LOG_WARN("fail to copy geo data", K(ret)); } else { copy_geo->set_data(data); copy_geo->set_srid(origin_geo.get_srid()); - copy_geo->set_zoom_in_value(origin_geo.get_zoom_in_value()); } return ret; } @@ -729,21 +734,21 @@ int ObGeoTypeUtil::correct_polygon(ObIAllocator &alloc, ObGeometry &geo) { int ret = OB_SUCCESS; - if (geo.type() == ObGeoType::POLYGON || geo.type() == ObGeoType::MULTIPOLYGON || geo.type() == ObGeoType::GEOMETRYCOLLECTION) { - if (!is_ring_closed && !geo.is_tree() && - OB_FAIL(ObGeoTypeUtil::geo_close_ring(geo, alloc))) { + if (!is_ring_closed && OB_FAIL(ObGeoTypeUtil::geo_close_ring(geo, alloc))) { LOG_WARN("wkb close ring failed", K(ret)); } if (OB_SUCC(ret)) { - ObGeoEvalCtx correct_context(&alloc, srs); - int res_unused; - if (OB_FAIL(correct_context.append_geo_arg(&geo))) { - LOG_WARN("build geo gis context failed", K(ret)); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(correct_context, res_unused))) { - LOG_WARN("eval geo correct failed", K(ret)); + CREATE_WITH_TEMP_CONTEXT(lib::ContextParam().set_mem_attr(MTL_ID(), "GISModule", ObCtxIds::DEFAULT_CTX_ID)) { + ObGeoEvalCtx correct_context(CURRENT_CONTEXT, srs); + int res_unused; + if (OB_FAIL(correct_context.append_geo_arg(&geo))) { + LOG_WARN("build geo gis context failed", K(ret)); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(correct_context, res_unused))) { + LOG_WARN("eval geo correct failed", K(ret)); + } } } } @@ -825,34 +830,35 @@ int ObGeoTypeUtil::get_buffered_geo(ObArenaAllocator *allocator, const ObSrsItem *srs, ObString &res_wkb) { - ObGeoBufferStrategy buf_strat; - ObGeoEvalCtx gis_context(allocator, srs); - int correct_result; int ret = OB_SUCCESS; - ObGeometry *geo = NULL; - ObGeometry *res_geo = NULL; - buf_strat.distance_val_ = distance; - ObGeoErrLogInfo log_info; - if (OB_FAIL(ObGeoTypeUtil::build_geometry(*allocator, wkb_str, geo, srs, log_info, ObGeoBuildFlag::GEO_ALLOW_3D))) { - LOG_WARN("fail to build geometry", K(ret)); - } else if (OB_FAIL(gis_context.append_geo_arg(geo))) { - LOG_WARN("failed to append geo arg to gis context", K(ret), K(gis_context.get_geo_count())); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, correct_result))) { - LOG_WARN("eval boost correct failed", K(ret)); - } else if (OB_FAIL(gis_context.append_val_arg(&buf_strat))) { - LOG_WARN("failed to append buffer strategy to gis context", K(ret), K(gis_context.get_geo_count())); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, res_geo))) { - LOG_WARN("eval st_buffer failed", K(ret)); - } else if (OB_ISNULL(res_geo)) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("eval st_buffer null result", K(ret)); - } else if (OB_FAIL(ObGeoTypeUtil::to_wkb(*allocator, - *res_geo, - srs, - res_wkb))) { - LOG_WARN("transform to binary failed", K(ret)); + CREATE_WITH_TEMP_CONTEXT(lib::ContextParam().set_mem_attr(MTL_ID(), "GISModule", ObCtxIds::DEFAULT_CTX_ID)) { + ObGeoBufferStrategy buf_strat; + ObGeoEvalCtx gis_context(CURRENT_CONTEXT, srs); + int correct_result; + ObGeometry *geo = NULL; + ObGeometry *res_geo = NULL; + buf_strat.distance_val_ = distance; + ObGeoErrLogInfo log_info; + if (OB_FAIL(ObGeoTypeUtil::build_geometry(*allocator, wkb_str, geo, srs, log_info, ObGeoBuildFlag::GEO_ALLOW_3D))) { + LOG_WARN("fail to build geometry", K(ret)); + } else if (OB_FAIL(gis_context.append_geo_arg(geo))) { + LOG_WARN("failed to append geo arg to gis context", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, correct_result))) { + LOG_WARN("eval boost correct failed", K(ret)); + } else if (OB_FAIL(gis_context.append_val_arg(&buf_strat))) { + LOG_WARN("failed to append buffer strategy to gis context", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, res_geo))) { + LOG_WARN("eval st_buffer failed", K(ret)); + } else if (OB_ISNULL(res_geo)) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("eval st_buffer null result", K(ret)); + } else if (OB_FAIL(ObGeoTypeUtil::to_wkb(*allocator, + *res_geo, + srs, + res_wkb))) { + LOG_WARN("transform to binary failed", K(ret)); + } } - return ret; } @@ -1449,18 +1455,19 @@ void ObGeoBoxUtil::get_point2d_from_geom_point(const ObWkbGeomInnerPoint &point, p2d.y = point.get<1>(); } -int ObGeoBoxUtil::clip_by_box(ObGeometry &geo_in, ObIAllocator &allocator, const ObGeogBox &gbox, ObGeometry *&geo_out, bool is_called_in_pg_expr) +int ObGeoBoxUtil::clip_by_box(ObGeometry &geo_in, lib::MemoryContext &mem_ctx, const ObGeogBox &gbox, ObGeometry *&geo_out, bool is_called_in_pg_expr) { int ret = OB_SUCCESS; ObArenaAllocator tmp_allocator; - ObGeoEvalCtx box_ctx(&tmp_allocator); + ObGeoEvalCtx box_ctx(mem_ctx); box_ctx.set_is_called_in_pg_expr(is_called_in_pg_expr); // clip only used in PG expr currently ObGeogBox *gbox_in = nullptr; ObGeometry *geo_tree = nullptr; ObGeometry *geo_bin = nullptr; + ObArenaAllocator &allocator = mem_ctx->get_arena_allocator(); if (geo_in.is_tree()) { geo_tree = &geo_in; - if (OB_FAIL(ObGeoTypeUtil::tree_to_bin(allocator, geo_tree, geo_bin, nullptr))) { + if (OB_FAIL(ObGeoTypeUtil::tree_to_bin(tmp_allocator, geo_tree, geo_bin, nullptr))) { LOG_WARN("fail to do tree to bin", K(ret)); } } else { @@ -1496,7 +1503,7 @@ int ObGeoBoxUtil::clip_by_box(ObGeometry &geo_in, ObIAllocator &allocator, const } else if (!ObGeoBoxUtil::is_box_valid(gbox)) { geo_out = nullptr; } else { - ObGeoBoxClipVisitor clip_visitor(gbox, allocator); + ObGeoBoxClipVisitor clip_visitor(gbox, mem_ctx); if (OB_FAIL(geo_tree->do_visit(clip_visitor))) { if (ret == OB_ERR_GIS_INVALID_DATA) { // pg behavior: return null @@ -1837,8 +1844,10 @@ int ObGeoTypeUtil::geo_close_ring(ObGeometry &geo, ObIAllocator &allocator) int ret = OB_SUCCESS; ObGeoStringBuffer res(&allocator); if (geo.is_tree()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("tree geo is not support", K(ret)); + ObGeoCloseRingVisitor cr_visitor; + if (OB_FAIL(geo.do_visit(cr_visitor))) { + LOG_WARN("fail to do close ring visitor", K(ret)); + } } else if (OB_ISNULL(geo.val())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("geo value is null", K(ret)); @@ -1874,7 +1883,7 @@ int ObGeoTypeUtil::geo_close_ring(ObGeometry &geo, ObIAllocator &allocator) LOG_WARN("geo type is not support", K(geo.type())); } - if (OB_SUCC(ret)) { + if (OB_SUCC(ret) && !geo.is_tree()) { ObString wkb_nosrid(res.length(), res.ptr()); geo.set_data(wkb_nosrid); } @@ -2056,26 +2065,28 @@ int ObGeoTypeUtil::get_mbr_polygon(ObIAllocator &allocator, int ret = OB_SUCCESS; ObCartesianBox box; // mbr box of input geo ObCartesianBox bounds_box; // bounds box of corresponding srs - ObGeoEvalCtx gis_context(&allocator, NULL); - if (OB_FAIL(srs_bounds_to_mbr_box(bounds, bounds_box))) { - LOG_WARN("get srs bounds box failed", K(ret)); - } else if (OB_FAIL(gis_context.append_geo_arg(&geo_bin))) { - LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); - } else if (OB_FAIL(ObGeoFuncEnvelope::eval(gis_context, box))) { - LOG_WARN("get mbr box failed", K(ret)); - } else if (box.is_empty()) { - ret = OB_ERR_GIS_INVALID_DATA; - // how about some box points is nan? - LOG_WARN("get mbr box failed", K(ret)); - } else { - ObCartesianBox final; // result box - boost::geometry::intersection(box, bounds_box, final); - if (final.is_empty()) { - ret = OB_EMPTY_RESULT; - LOG_WARN("no intersection in bounds", K(ret), K(*bounds), K(box)); - } else if (OB_FAIL(mbr_box_to_geometry(geo_bin.get_srid(), allocator, final, geo_bin_out))) { - LOG_WARN("failed to convert box to geo", K(ret), K(final)); - } else { /* do nothing */ } + CREATE_WITH_TEMP_CONTEXT(lib::ContextParam().set_mem_attr(MTL_ID(), "GISModule", ObCtxIds::DEFAULT_CTX_ID)) { + ObGeoEvalCtx gis_context(CURRENT_CONTEXT, NULL); + if (OB_FAIL(srs_bounds_to_mbr_box(bounds, bounds_box))) { + LOG_WARN("get srs bounds box failed", K(ret)); + } else if (OB_FAIL(gis_context.append_geo_arg(&geo_bin))) { + LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFuncEnvelope::eval(gis_context, box))) { + LOG_WARN("get mbr box failed", K(ret)); + } else if (box.is_empty()) { + ret = OB_ERR_GIS_INVALID_DATA; + // how about some box points is nan? + LOG_WARN("get mbr box failed", K(ret)); + } else { + ObCartesianBox final; // result box + boost::geometry::intersection(box, bounds_box, final); + if (final.is_empty()) { + ret = OB_EMPTY_RESULT; + LOG_WARN("no intersection in bounds", K(ret), K(*bounds), K(box)); + } else if (OB_FAIL(mbr_box_to_geometry(geo_bin.get_srid(), allocator, final, geo_bin_out))) { + LOG_WARN("failed to convert box to geo", K(ret), K(final)); + } else { /* do nothing */ } + } } return ret; } @@ -2537,7 +2548,7 @@ int ObGeoTypeUtil::get_varry_obj_from_map(const QualifiedMap &map, const ObStrin int ObGeoTypeUtil::sql_geo_obj_to_ewkt(const QualifiedMap &map, ObIAllocator &allocator, ObString &ewkt) { int ret = OB_SUCCESS; - ObSdoGeoObject sdo_geometry; + ObSdoGeoObject sdo_geometry(allocator); bool is_null_result = false; uint64_t gtype_num; @@ -2774,6 +2785,74 @@ int ObGeoTypeUtil::check_empty(ObGeometry *geo, bool &is_empty) return ret; } +template +int ObGeoTypeUtil::is_in_geometry(lib::MemoryContext &mem_ctx, const ObGeometry &geo, const MpType &multi_geo, + const ObSrsItem *srs, bool &res, uint32_t start_idx /* = 0*/) +{ + int ret = OB_SUCCESS; + for (int32_t j = start_idx; j < multi_geo.size() && OB_SUCC(ret) && !res; j++) { + ObGeoEvalCtx gis_context(mem_ctx, srs); + if (OB_FAIL(gis_context.append_geo_arg(&geo)) || OB_FAIL(gis_context.append_geo_arg(&multi_geo[j]))) { + OB_LOG(WARN, "build gis context failed", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, res))) { + OB_LOG(WARN, "eval st intersection failed", K(ret)); + } + } + return ret; +} + +int ObGeoTypeUtil::remove_duplicate_geo(ObGeometry *&geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs, bool need_simplify/* = true*/) +{ + INIT_SUCC(ret); + if (geo == NULL) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("input geo is null", K(ret)); + } else if ((srs == NULL || srs->srs_type() != ObSrsType::GEOGRAPHIC_SRS) + && geo->crs() == ObGeoCRS::Geographic) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid srs type", K(ret), KP(srs), K(geo->crs())); + } else { + bool is_duplicate = false; + switch (geo->crs()) { + case ObGeoCRS::Geographic : { + if (OB_FAIL(check_if_geo_duplicate(geo, mem_ctx, srs, is_duplicate))) { + LOG_WARN("fail to check if geometry has duplicate", K(ret)); + } else if (is_duplicate && OB_FAIL(remove_duplicate_multi_geo(geo, mem_ctx, srs))) { + LOG_WARN("failed to remove duplicate geo", K(ret), K(geo->crs())); + } else if (need_simplify) { + if (OB_FAIL((simplify_multi_geo(geo, mem_ctx->get_arena_allocator())))) { + OB_LOG(WARN, "fail to simplify result", K(ret)); + } else if (geo->type() == ObGeoType::GEOMETRYCOLLECTION + && OB_FAIL(simplify_geo_collection(geo, mem_ctx->get_arena_allocator(), srs))) { + OB_LOG(WARN, "fail to simplify_geo_collection", K(ret)); + } + } + break; + } + case ObGeoCRS::Cartesian : { + if (OB_FAIL(check_if_geo_duplicate(geo, mem_ctx, srs, is_duplicate))) { + LOG_WARN("fail to check if geometry has duplicate", K(ret)); + } else if (is_duplicate && OB_FAIL(remove_duplicate_multi_geo(geo, mem_ctx, srs))) { + LOG_WARN("failed to remove duplicate geo", K(ret), K(geo->crs())); + } else if (need_simplify) { + if (OB_FAIL((simplify_multi_geo(geo, mem_ctx->get_arena_allocator())))) { + OB_LOG(WARN, "fail to simplify result", K(ret)); + } else if (geo->type() == ObGeoType::GEOMETRYCOLLECTION + && OB_FAIL(simplify_geo_collection(geo, mem_ctx->get_arena_allocator(), srs))) { + OB_LOG(WARN, "fail to simplify_geo_collection", K(ret)); + } + } + break; + } + default : { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid geo type", K(ret), K(srs->srs_type()), K(geo->crs())); + } + } + } + return ret; +} + int ObGeoMVTUtil::affine_transformation(ObGeometry *geo, const ObAffineMatrix &affine) { int ret = OB_SUCCESS; @@ -2824,7 +2903,7 @@ int ObGeoTypeUtil::get_polygon_size(ObGeometry &geo) return size; } -int ObGeoTypeUtil::magnify_and_recheck(ObIAllocator &allocator, ObGeometry &geo, ObGeoEvalCtx& gis_context, bool& invalid_for_cache) +int ObGeoTypeUtil::magnify_and_recheck(lib::MemoryContext& ctx, ObGeometry &geo, ObGeoEvalCtx& gis_context, bool& invalid_for_cache) { int ret = OB_SUCCESS; ObGeometry *tmp_geo = nullptr; @@ -2832,7 +2911,7 @@ int ObGeoTypeUtil::magnify_and_recheck(ObIAllocator &allocator, ObGeometry &geo, bool need_recheck = false; ObGeoZoomInVisitor zoom_in_visitor(RECHECK_ZOOM_IN_VALUE); const ObGeoNormalVal *val_arg = nullptr; - if (OB_FAIL(copy_geometry(allocator, geo, tmp_geo)) || OB_ISNULL(tmp_geo)) { + if (OB_FAIL(copy_geometry(ctx, geo, tmp_geo)) || OB_ISNULL(tmp_geo)) { // do nothing, return invalid_for_cache } else if (OB_FAIL(tmp_geo->do_visit(zoom_in_visitor))) { LOG_WARN("failed to zoom in visit", K(ret)); @@ -2868,10 +2947,10 @@ int ObGeoTypeUtil::check_valid_and_self_intersects(ObGeoEvalCtx& gis_context, bo return ret; } -int ObGeoTypeUtil::polygon_check_self_intersections(ObIAllocator &allocator, ObGeometry &geo, const ObSrsItem *srs, bool& invalid_for_cache) +int ObGeoTypeUtil::polygon_check_self_intersections(lib::MemoryContext& ctx, ObGeometry &geo, const ObSrsItem *srs, bool& invalid_for_cache) { int ret = OB_SUCCESS; - ObGeoEvalCtx gis_context(&allocator, srs); + ObGeoEvalCtx gis_context(ctx, srs); ObGeoNormalVal reason; bool valid = false; const ObGeoNormalVal *val_arg = nullptr; @@ -2882,7 +2961,7 @@ int ObGeoTypeUtil::polygon_check_self_intersections(ObIAllocator &allocator, ObG LOG_WARN("add reason val to context failed", K(ret)); } else if (OB_FAIL(check_valid_and_self_intersects(gis_context, invalid_for_cache, need_recheck))) { LOG_WARN("fail to check_valid_if_self_intersects.", K(ret)); - } else if (invalid_for_cache && need_recheck && OB_FAIL(magnify_and_recheck(allocator, geo, gis_context, invalid_for_cache))) { + } else if (invalid_for_cache && need_recheck && OB_FAIL(magnify_and_recheck(ctx, geo, gis_context, invalid_for_cache))) { LOG_WARN("fail to magnify_and_recheck.", K(ret)); } else if (invalid_for_cache) { LOG_WARN("self intersects, use geo cache base.", K(ret)); @@ -3245,5 +3324,37 @@ int ObGeoMVTUtil::simplify_geometry(ObGeometry *geo, double tolerance, bool keep } return ret; } -} // namespace common -} // namespace oceanbase + +ObGeoBoostAllocGuard::~ObGeoBoostAllocGuard() +{ + if (inited_) { + DESTROY_CONTEXT(mem_context_); + } +} + +int ObGeoBoostAllocGuard::init() +{ + int ret = OB_SUCCESS; + lib::ContextParam param; + param.set_mem_attr(tenant_id_, "GISModule", ObCtxIds::DEFAULT_CTX_ID) + .set_properties(lib::USE_TL_PAGE_OPTIONAL) // todo: need thread safe? + .set_page_size(OB_MALLOC_NORMAL_BLOCK_SIZE); + if (OB_FAIL(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context_, param))) { + LOG_WARN("failed to create memory context", K(ret)); + } else if (OB_ISNULL(mem_context_)) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("failed to create memory context", K(ret)); + } else { + inited_ = true; + } + return ret; +} + +lib::MemoryContext *ObGeoBoostAllocGuard::get_memory_ctx() +{ + return inited_ ? &mem_context_ : nullptr; +} + + +} // namespace common +} // namespace oceanbase diff --git a/deps/oblib/src/lib/geo/ob_geo_utils.h b/deps/oblib/src/lib/geo/ob_geo_utils.h index f87e41c34..351f843b5 100644 --- a/deps/oblib/src/lib/geo/ob_geo_utils.h +++ b/deps/oblib/src/lib/geo/ob_geo_utils.h @@ -45,6 +45,7 @@ enum ObGeoBuildFlag: uint8_t { GEO_ALLOW_3D = 0x08, GEO_CHECK_RANGE = 0x10, GEO_RESERVE_3D = 0x20, // do not convert 3D Geometry to 2D + GEO_NOT_COPY_WKB = 0x40, // copy input wkb str to output geo data GEO_DEFAULT = GEO_NORMALIZE | GEO_CORRECT | GEO_CHECK_RANGE, GEO_ALLOW_3D_DEFAULT = GEO_DEFAULT | GEO_ALLOW_3D, GEO_CARTESIAN = GEO_CORRECT, @@ -153,8 +154,9 @@ public: const ObString &wkb, const ObSrsItem *srs, ObGeometry *&geo, - bool has_srid = true); - static int copy_geometry(ObIAllocator &allocator, + bool has_srid = true, + bool with_copy = true); + static int copy_geometry(lib::MemoryContext& ctx, ObGeometry &origin_geo, ObGeometry *©_geo); static int correct_polygon(ObIAllocator &alloc, @@ -249,7 +251,7 @@ public: // caculate end point quadrant direction relative to start point static int get_quadrant_direction(const ObPoint2d &start, const ObPoint2d &end, QuadDirection &res); static int get_polygon_size(ObGeometry &geo); - static int polygon_check_self_intersections(ObIAllocator &allocator, ObGeometry &geo, const ObSrsItem *srs, bool& invalid_for_cache); + static int polygon_check_self_intersections(lib::MemoryContext& ctx, ObGeometry &geo, const ObSrsItem *srs, bool& invalid_for_cache); static int create_cached_geometry(ObIAllocator &allocator, ObIAllocator &tmp_allocator, ObGeometry *geo, const ObSrsItem *srs, ObCachedGeom *&cached_geo); template @@ -262,6 +264,15 @@ public: static bool use_point_polygon_short_circuit(const ObGeometry& geo1, const ObGeometry& geo2, ObItemType func_type); static int get_point_polygon_res(ObGeometry *geo1, ObGeometry *geo2, ObItemType func_type, bool& result); static bool need_get_srs(const uint32_t srid); + template + static int remove_duplicate_multi_geo(ObGeometry *&geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs); + template + static int simplify_geo_collection(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs); + template + static int simplify_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator); + static int remove_duplicate_geo(ObGeometry *&geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs, bool need_simplify = true); + template + static int check_if_geo_duplicate(ObGeometry *geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs, bool &is_duplicate); private: template static int create_geo_bin_by_type(ObIAllocator &allocator, @@ -295,9 +306,12 @@ private: template static int collection_has_dimension(T_IBIN *geo, ObGeoDimension dim, bool& has); static int point_polygon_short_circuit(ObGeometry *poly, ObGeometry *point, ObPointLocation& loc, bool& has_internal, bool get_fartest); - static int magnify_and_recheck(ObIAllocator &allocator, ObGeometry &geo, ObGeoEvalCtx& gis_context, bool& invalid_for_cache); + static int magnify_and_recheck(lib::MemoryContext& ctx, ObGeometry &geo, ObGeoEvalCtx& gis_context, bool& invalid_for_cache); static int check_valid_and_self_intersects(ObGeoEvalCtx& gis_context, bool& invalid_for_cache, bool& need_recheck); + template + static int is_in_geometry(lib::MemoryContext &mem_ctx, const ObGeometry &geo, const MpType &multi_geo, + const ObSrsItem *srs, bool &res, uint32_t start_idx = 0); DISALLOW_COPY_AND_ASSIGN(ObGeoTypeUtil); }; @@ -368,7 +382,7 @@ public: static void get_point2d_from_geom_point(const ObWkbGeomInnerPoint &point, ObPoint2d &p2d); template static int get_geom_line_box(const GeometryType &line, ObGeogBox &box); - static int clip_by_box(ObGeometry &geo_in, ObIAllocator &allocator, const ObGeogBox &box, ObGeometry *&geo_out, bool is_called_in_pg_expr); + static int clip_by_box(ObGeometry &geo_in, lib::MemoryContext &mem_ctx, const ObGeogBox &box, ObGeometry *&geo_out, bool is_called_in_pg_expr); static bool boxes_overlaps(const ObGeogBox &box1, const ObGeogBox &box2); static bool boxes_contains(const ObGeogBox &box1, const ObGeogBox &box2); template @@ -381,8 +395,6 @@ public: static inline bool is_float_gteq(double left, double right) { return (left + OB_GEO_TOLERANCE) >= right; } static inline bool is_float_zero(double ft) { return fabs(ft) <= OB_GEO_TOLERANCE; } static bool is_box_valid(const ObGeogBox &box); - - static constexpr double OB_GEO_TOLERANCE = 5e-14; }; /* @@ -418,6 +430,28 @@ typedef struct double z_size; } ObGeoGrid; +class ObGeoBoostAllocGuard +{ +public: + ObGeoBoostAllocGuard(uint64_t tenant_id) + : mem_context_(nullptr), + inited_(false), + malloc_guard_(lib::ObMemAttr(tenant_id, "GISModule")), + tenant_id_(tenant_id) + {} + ~ObGeoBoostAllocGuard(); + int init(); + lib::MemoryContext *get_memory_ctx(); + bool is_inited() { return inited_; } +private: + static const int64_t CONTEXT_MEMORY_LIMIT = 512 << 10; + lib::MemoryContext mem_context_; + bool inited_; + lib::ObMallocHookAttrGuard malloc_guard_; + uint64_t tenant_id_; +}; + + class ObGeoMVTUtil { public: @@ -469,31 +503,31 @@ int ObGeoTypeUtil::create_geo_bin_by_type(ObIAllocator &allocator, switch(geo_type) { case ObGeoType::POINT: { - tmp_geo = OB_NEWx(PT, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(PT, (&allocator), srid); break; } case ObGeoType::LINESTRING: { - tmp_geo = OB_NEWx(LN, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(LN, (&allocator), srid); break; } case ObGeoType::POLYGON: { - tmp_geo = OB_NEWx(PY, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(PY, (&allocator), srid); break; } case ObGeoType::MULTIPOINT: { - tmp_geo = OB_NEWx(MPT, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(MPT, (&allocator), srid); break; } case ObGeoType::MULTILINESTRING: { - tmp_geo = OB_NEWx(MLN, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(MLN, (&allocator), srid); break; } case ObGeoType::MULTIPOLYGON: { - tmp_geo = OB_NEWx(MPY, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(MPY, (&allocator), srid); break; } case ObGeoType::GEOMETRYCOLLECTION: { - tmp_geo = OB_NEWx(GC, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(GC, (&allocator), srid); break; } default: { @@ -525,7 +559,7 @@ int ObGeoTypeUtil::create_geo_tree_by_type(ObIAllocator &allocator, switch(geo_type) { case ObGeoType::POINT: { - tmp_geo = OB_NEWx(PT, (&allocator), srid, (&allocator)); + tmp_geo = OB_NEWx(PT, (&allocator), srid); break; } case ObGeoType::LINESTRING: { @@ -570,6 +604,334 @@ int ObGeoTypeUtil::create_geo_tree_by_type(ObIAllocator &allocator, return ret; } +template +int ObGeoTypeUtil::simplify_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator) +{ + // e.g. MULTILINESTRING((0 0, 1 1)) -> LINESTRING(0 0, 1 1) + int ret= OB_SUCCESS; + switch (geo->type()) { + case ObGeoType::MULTILINESTRING: { + typename GcType::sub_ml_type *mp = reinterpret_cast(geo); + if (OB_ISNULL(mp)) { + ret = OB_ERR_GIS_INVALID_DATA; + OB_LOG(WARN, "invalid null pointer", K(ret)); + } else if (mp->size() == 1) { + geo = &(mp->front()); + } + break; + } + case ObGeoType::MULTIPOINT: { + typename GcType::sub_mpt_type *mpt = reinterpret_cast(geo); + if (OB_ISNULL(mpt)) { + ret = OB_ERR_GIS_INVALID_DATA; + OB_LOG(WARN, "invalid null pointer", K(ret)); + } else if (mpt->size() == 1) { + typename GcType::sub_pt_type *p = OB_NEWx(typename GcType::sub_pt_type, &allocator, geo->get_srid()); + if (OB_ISNULL(p)) { + ret = OB_ERR_GIS_INVALID_DATA; + OB_LOG(WARN, "invalid null pointer", K(ret)); + } else { + p->set_data(mpt->front()); + geo = p; + } + } + break; + } + case ObGeoType::MULTIPOLYGON: { + typename GcType::sub_mp_type *mp = reinterpret_cast(geo); + if (OB_ISNULL(mp)) { + ret = OB_ERR_GIS_INVALID_DATA; + OB_LOG(WARN, "invalid null pointer", K(ret)); + } else if (mp->size() == 1) { + geo = &(mp->front()); + } + break; + } + case ObGeoType::GEOMETRYCOLLECTION: { + GcType *mp = reinterpret_cast(geo); + if (OB_ISNULL(mp)) { + ret = OB_ERR_GIS_INVALID_DATA; + OB_LOG(WARN, "invalid null pointer", K(ret)); + } else if (mp->size() > 0) { + for (uint32_t i = 0; i < mp->size() && OB_SUCC(ret); i++) { + bool in_res_geo = false; + ObGeometry *cur_geo = &(*mp)[i]; + if (OB_FAIL(simplify_multi_geo(cur_geo, allocator))) { + OB_LOG(WARN, "fail to remove dupilicate multi geometry", K(ret)); + } else if (OB_FAIL(mp->set(i, cur_geo))) { + OB_LOG(WARN, "fail to set geometry", K(ret), K(i), KP(cur_geo)); + } + } + if (mp->size() == 1) { + geo = &(mp->front()); + } + } + break; + } + default: { + break; // do nothing + } + } + return ret; +} + +// for geo tree +template +int ObGeoTypeUtil::simplify_geo_collection(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs) +{ + int ret = OB_SUCCESS; + if (geo->type() != ObGeoType::GEOMETRYCOLLECTION) { + // do nothing + } else { + GcTreeType *&geo_coll = reinterpret_cast(geo); + ObGeoType front_type; + bool need_simplify = true; + if (geo_coll->size() < 2) { + need_simplify = false; + } else { + front_type = geo_coll->front().type(); + for (uint32_t i = 1; need_simplify && i < geo_coll->size(); ++i) { + if (((*geo_coll)[i]).type() != front_type) { + need_simplify = false; + } + } + } + if (need_simplify) { + switch(front_type) { + case ObGeoType::POINT: { + typename GcTreeType::sub_mpt_type *res_geo = OB_NEWx(typename GcTreeType::sub_mpt_type, &allocator, geo->get_srid(), allocator); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "fail to alloc memory", K(ret)); + } + for (uint32_t i = 0; OB_SUCC(ret) && i < geo_coll->size(); ++i) { + typename GcTreeType::sub_pt_type &geo_point = reinterpret_cast((*geo_coll)[i]); + if (OB_FAIL(res_geo->push_back(geo_point))) { + OB_LOG(WARN, "failed to add point to multipoint", K(ret)); + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + case ObGeoType::LINESTRING: { + typename GcTreeType::sub_ml_type *res_geo = OB_NEWx(typename GcTreeType::sub_ml_type, &allocator, geo->get_srid(), allocator); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "fail to alloc memory", K(ret)); + } + for (uint32_t i = 0; OB_SUCC(ret) && i < geo_coll->size(); ++i) { + if (OB_FAIL(res_geo->push_back((*geo_coll)[i]))) { + OB_LOG(WARN, "failed to add linestring to multilinestring", K(ret)); + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + case ObGeoType::POLYGON: { + typename GcTreeType::sub_mp_type *res_geo = OB_NEWx(typename GcTreeType::sub_mp_type, &allocator, geo->get_srid(), allocator); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "fail to alloc memory", K(ret)); + } + for (uint32_t i = 0; OB_SUCC(ret) && i < geo_coll->size(); ++i) { + if (OB_FAIL(res_geo->push_back((*geo_coll)[i]))) { + OB_LOG(WARN, "failed to add polygon to multipolygon", K(ret)); + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + default: { + // do nothing + break; + } + } + } + } + return ret; +} + +// for geo tree +template +int ObGeoTypeUtil::remove_duplicate_multi_geo(ObGeometry *&geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs) +{ + int ret = OB_SUCCESS; + ObArenaAllocator &allocator = mem_ctx->get_arena_allocator(); + switch (geo->type()) { + case ObGeoType::POINT: + case ObGeoType::LINESTRING: + case ObGeoType::POLYGON: { + break; + } + case ObGeoType::MULTIPOINT: { + typename GcTreeType::sub_mpt_type *res_geo = OB_NEWx(typename GcTreeType::sub_mpt_type, &allocator, geo->get_srid(), allocator); + typename GcTreeType::sub_mpt_type &sp_geo = reinterpret_cast(*geo); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); + } + for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret); i++) { + bool in_res_geo = false; + for (int32_t j = 0; j < res_geo->size() && OB_SUCC(ret) && !in_res_geo; j++) { + if ((sp_geo[i].template get<0>() == sp_geo[j].template get<0>()) + && (sp_geo[i].template get<1>() == sp_geo[j].template get<1>())) { + in_res_geo = true; + } + } + if (OB_SUCC(ret) && !in_res_geo) { + typename GcTreeType::sub_pt_type pt(sp_geo[i].template get<0>(), sp_geo[i].template get<1>()); + if (OB_FAIL(res_geo->push_back(pt))) { + OB_LOG(WARN, "fail to push back geometry", K(ret)); + } + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + case ObGeoType::MULTILINESTRING: { + typename GcTreeType::sub_ml_type *res_geo = OB_NEWx(typename GcTreeType::sub_ml_type, &allocator, geo->get_srid(), allocator); + typename GcTreeType::sub_ml_type &sp_geo = reinterpret_cast(*geo); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); + } + for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret); i++) { + bool in_res_geo = false; + if (OB_FAIL(is_in_geometry(mem_ctx, sp_geo[i], *res_geo, srs, in_res_geo))) { + OB_LOG(WARN, "fail to check is in geometry", K(ret)); + } else if (!in_res_geo && OB_FAIL(res_geo->push_back(sp_geo[i]))) { + OB_LOG(WARN, "fail to push back geometry", K(ret)); + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + case ObGeoType::MULTIPOLYGON: { + typename GcTreeType::sub_mp_type *res_geo = OB_NEWx(typename GcTreeType::sub_mp_type, &allocator, geo->get_srid(), allocator); + typename GcTreeType::sub_mp_type &sp_geo = reinterpret_cast(*geo); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); + } + for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret); i++) { + bool in_res_geo = false; + if (OB_FAIL(is_in_geometry(mem_ctx, sp_geo[i], *res_geo, srs, in_res_geo))) { + OB_LOG(WARN, "fail to check is in geometry", K(ret)); + } else if (!in_res_geo && OB_FAIL(res_geo->push_back(sp_geo[i]))) { + OB_LOG(WARN, "fail to push back geometry", K(ret)); + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + case ObGeoType::GEOMETRYCOLLECTION: { + GcTreeType *res_geo = OB_NEWx(GcTreeType, &allocator, geo->get_srid(), allocator); + GcTreeType *&sp_geo = reinterpret_cast(geo); + if (OB_ISNULL(res_geo)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "failt to allocate memory for geometry", K(ret), K(geo->type())); + } + for (int32_t i = 0; i < sp_geo->size() && OB_SUCC(ret); i++) { + bool in_res_geo = false; + ObGeometry *cur_geo = &(*sp_geo)[i]; + if (OB_FAIL(remove_duplicate_multi_geo(cur_geo, mem_ctx, srs))) { + OB_LOG(WARN, "fail to remove dupilicate multi geometry", K(ret)); + } else if (OB_FAIL(is_in_geometry(mem_ctx, *cur_geo, *res_geo, srs, in_res_geo))) { + OB_LOG(WARN, "fail to check is in geometry", K(ret)); + } else if (!in_res_geo && OB_FAIL(res_geo->push_back(*cur_geo))) { + OB_LOG(WARN, "fail to push back geometry", K(ret)); + } + } + if (OB_SUCC(ret)) { + geo = res_geo; + } + break; + } + default: { + ret = OB_NOT_SUPPORTED; + OB_LOG(WARN, "geometry type not supported", K(ret), K(geo->type())); + break; + } + } + return ret; +} + +template +int ObGeoTypeUtil::check_if_geo_duplicate(ObGeometry *geo, lib::MemoryContext &mem_ctx, + const ObSrsItem *srs, bool &is_duplicate) +{ + INIT_SUCC(ret); + ObArenaAllocator &allocator = mem_ctx->get_arena_allocator(); + is_duplicate = false; + switch (geo->type()) { + case ObGeoType::POINT: + case ObGeoType::LINESTRING: + case ObGeoType::POLYGON: { + break; + } + case ObGeoType::MULTIPOINT: { + typename GcTreeType::sub_mpt_type &sp_geo = reinterpret_cast(*geo); + for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret) && !is_duplicate; i++) { + for (int32_t j = i + 1; j < sp_geo.size() && OB_SUCC(ret) && !is_duplicate; j++) { + if ((sp_geo[i].template get<0>() == sp_geo[j].template get<0>()) + && (sp_geo[i].template get<1>() == sp_geo[j].template get<1>())) { + is_duplicate = true; + } + } + } + break; + } + case ObGeoType::MULTILINESTRING: { + typename GcTreeType::sub_ml_type &sp_geo = reinterpret_cast(*geo); + for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret) && !is_duplicate; i++) { + if (OB_FAIL(is_in_geometry(mem_ctx, sp_geo[i], sp_geo, srs, is_duplicate, i + 1))) { + OB_LOG(WARN, "fail to check is in geometry", K(ret)); + } + } + break; + } + case ObGeoType::MULTIPOLYGON: { + typename GcTreeType::sub_mp_type &sp_geo = reinterpret_cast(*geo); + for (int32_t i = 0; i < sp_geo.size() && OB_SUCC(ret) && !is_duplicate; i++) { + if (OB_FAIL(is_in_geometry(mem_ctx, sp_geo[i], sp_geo, srs, is_duplicate, i + 1))) { + OB_LOG(WARN, "fail to check is in geometry", K(ret)); + } + } + break; + } + case ObGeoType::GEOMETRYCOLLECTION: { + GcTreeType *&sp_geo = reinterpret_cast(geo); + for (int32_t i = 0; i < sp_geo->size() && OB_SUCC(ret) && !is_duplicate; i++) { + ObGeometry *cur_geo = &(*sp_geo)[i]; + if (OB_FAIL(check_if_geo_duplicate(cur_geo, mem_ctx, srs, is_duplicate))) { + OB_LOG(WARN, "fail to remove dupilicate multi geometry", K(ret)); + } else if (!is_duplicate && OB_FAIL(is_in_geometry(mem_ctx, *cur_geo, *sp_geo, srs, is_duplicate))) { + OB_LOG(WARN, "fail to check is in geometry", K(ret)); + } + } + break; + } + default: { + ret = OB_NOT_SUPPORTED; + OB_LOG(WARN, "geometry type not supported", K(ret), K(geo->type())); + break; + } + } + return ret; +} + // only support PLINESTRING/MULTILINESTRING in catesian bin (ObWkbGeom) template int ObGeoBoxUtil::fast_box(const GeometryType *g, ObGeogBox &box, bool &has_fast_box) diff --git a/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.cpp b/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.cpp index 8057452c0..cb3201975 100644 --- a/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.cpp @@ -19,14 +19,31 @@ namespace common { template int ObGeoZoomInVisitor::zoom_in_point(T_Point *geo) { - uint32_t count = 0; - while (count++ < zoom_in_value_) { - double longti = geo->x(); - double lati = geo->y(); - longti *= 10; - lati *= 10; - geo->x(longti); - geo->y(lati); + if (!is_calc_zoom_) { + uint32_t count = 0; + while (count++ < zoom_in_value_) { + double longti = geo->x(); + double lati = geo->y(); + longti *= 10; + lati *= 10; + geo->x(longti); + geo->y(lati); + } + } else { + uint32_t count = 0; + double nx_tmp = geo->x(); + double ny_tmp = geo->y(); + while (nx_tmp != 0.0 && std::fabs(nx_tmp) < ZOOM_IN_THRESHOLD) { + nx_tmp *= 10; + count++; + } + zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; + count = 0; + while (ny_tmp != 0.0 && std::fabs(ny_tmp) < ZOOM_IN_THRESHOLD) { + ny_tmp *= 10; + count++; + } + zoom_in_value_ = count > zoom_in_value_ ? count : zoom_in_value_; } return OB_SUCCESS; } diff --git a/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.h b/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.h index 92063dfd8..9b9f26767 100644 --- a/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.h +++ b/deps/oblib/src/lib/geo/ob_geo_zoom_in_visitor.h @@ -25,7 +25,8 @@ namespace common class ObGeoZoomInVisitor : public ObEmptyGeoVisitor { public: - ObGeoZoomInVisitor(uint32_t zoom_in_value) : zoom_in_value_(zoom_in_value) {} + ObGeoZoomInVisitor(uint32_t zoom_in_value, bool is_calc_zoom = false) + : zoom_in_value_(zoom_in_value), is_calc_zoom_(is_calc_zoom) {} virtual ~ObGeoZoomInVisitor() {} bool prepare(ObGeometry *geo) { UNUSED(geo); return true; } int visit(ObGeometry *geo) override { UNUSED(geo); return OB_SUCCESS; } @@ -33,11 +34,17 @@ public: int visit(ObIWkbGeogPoint *geo); int visit(ObCartesianPoint *geo); int visit(ObIWkbGeomPoint *geo); + uint32_t get_zoom_in_value() { return zoom_in_value_; } + void set_zoom_in_value(uint32_t zoom_in_value) { zoom_in_value_ = zoom_in_value;} + void set_is_calc_zoom(bool is_calc_zoom) { is_calc_zoom_ = is_calc_zoom;} + private: + static constexpr double ZOOM_IN_THRESHOLD = 0.00000001; template int zoom_in_point(T_Point *geo); uint32_t zoom_in_value_; + bool is_calc_zoom_; DISALLOW_COPY_AND_ASSIGN(ObGeoZoomInVisitor); }; diff --git a/deps/oblib/src/lib/geo/ob_geometry_cast.cpp b/deps/oblib/src/lib/geo/ob_geometry_cast.cpp index 3bfa7923a..8accaa3e7 100644 --- a/deps/oblib/src/lib/geo/ob_geometry_cast.cpp +++ b/deps/oblib/src/lib/geo/ob_geometry_cast.cpp @@ -1027,7 +1027,7 @@ int ObGeomcollectionTypeCast::cast(const ObGeometry &src, } else { double x = iter->template get<0>(); double y = iter->template get<1>(); - P *point = new (buf) P (x, y, src.get_srid(), allocator); + P *point = new (buf) P (x, y, src.get_srid()); if (OB_FAIL(res.push_back(*point))) { LOG_WARN("fail to push back point", K(ret)); } diff --git a/deps/oblib/src/lib/geo/ob_s2adapter.cpp b/deps/oblib/src/lib/geo/ob_s2adapter.cpp index e008e5af4..03b51535f 100644 --- a/deps/oblib/src/lib/geo/ob_s2adapter.cpp +++ b/deps/oblib/src/lib/geo/ob_s2adapter.cpp @@ -295,20 +295,21 @@ int64_t ObS2Adapter::get_mbr(ObSpatialMBR &mbr) mbr.x_max_ = rect.lng_hi().degrees(); } } else { - ObCartesianBox box; - ObArenaAllocator tmp_allocator; - ObGeoEvalCtx gis_context(&tmp_allocator, NULL); - if (OB_FAIL(gis_context.append_geo_arg(geo_))) { - LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); - } else if (OB_FAIL(ObGeoFuncEnvelope::eval(gis_context, box))) { - LOG_WARN("get mbr box failed", K(ret)); - } else if (box.is_empty()) { - LOG_DEBUG("It's might be empty geometry collection", K(geo_->type()), K(geo_->is_empty())); - } else { - mbr.x_min_ = box.min_corner().get<0>(); - mbr.y_min_ = box.min_corner().get<1>(); - mbr.x_max_ = box.max_corner().get<0>(); - mbr.y_max_ = box.max_corner().get<1>(); + CREATE_WITH_TEMP_CONTEXT(lib::ContextParam().set_mem_attr(MTL_ID(), "GISModule", ObCtxIds::DEFAULT_CTX_ID)) { + ObCartesianBox box; + ObGeoEvalCtx gis_context(CURRENT_CONTEXT, NULL); + if (OB_FAIL(gis_context.append_geo_arg(geo_))) { + LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFuncEnvelope::eval(gis_context, box))) { + LOG_WARN("get mbr box failed", K(ret)); + } else if (box.is_empty()) { + LOG_DEBUG("It's might be empty geometry collection", K(geo_->type()), K(geo_->is_empty())); + } else { + mbr.x_min_ = box.min_corner().get<0>(); + mbr.y_min_ = box.min_corner().get<1>(); + mbr.x_max_ = box.max_corner().get<0>(); + mbr.y_max_ = box.max_corner().get<1>(); + } } } } diff --git a/deps/oblib/src/lib/geo/ob_sdo_geo_object.cpp b/deps/oblib/src/lib/geo/ob_sdo_geo_object.cpp index 3b65ce5c6..b2414ebb4 100644 --- a/deps/oblib/src/lib/geo/ob_sdo_geo_object.cpp +++ b/deps/oblib/src/lib/geo/ob_sdo_geo_object.cpp @@ -51,14 +51,14 @@ int ObSdoPoint::to_text(ObStringBuffer &buf) } else if ((len = snprintf(number_buf, 128, format_str_x.ptr(), x_)) < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret), K(x_)); - } else if (OB_FAIL(buf.append(number_buf, len))) { + } else if (OB_FAIL(buf.append(number_buf, len, 0))) { LOG_WARN("fail to print gtype", K(ret)); } else if (OB_FAIL(buf.append(", "))) { LOG_WARN("fail to print ,", K(ret)); } else if ((len = snprintf(number_buf, 128, format_str_y.ptr(), y_)) < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret), K(y_)); - } else if (OB_FAIL(buf.append(number_buf, len))) { + } else if (OB_FAIL(buf.append(number_buf, len, 0))) { LOG_WARN("fail to print gtype", K(ret)); } else if (OB_FAIL(buf.append(", "))) { LOG_WARN("fail to print ,", K(ret)); @@ -66,7 +66,7 @@ int ObSdoPoint::to_text(ObStringBuffer &buf) if ((len = snprintf(number_buf, 128, format_str_z.ptr(), z_)) < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret), K(x_)); - } else if (OB_FAIL(buf.append(number_buf, len))) { + } else if (OB_FAIL(buf.append(number_buf, len, 0))) { LOG_WARN("fail to print gtype", K(ret)); } else if (OB_FAIL(buf.append(")"))){ LOG_WARN("fail to print (", K(ret)); @@ -94,7 +94,7 @@ int ObSdoGeoObject::to_text(ObStringBuffer &buf) } else if ((len = snprintf(number_buf, 128, "%lu", gtype_num)) < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret)); - } else if (OB_FAIL(buf.append(number_buf, len))) { + } else if (OB_FAIL(buf.append(number_buf, len, 0))) { LOG_WARN("fail to print gtype", K(ret)); } else if (OB_FAIL(buf.append(", "))) { LOG_WARN("fail to print ,", K(ret)); @@ -102,7 +102,7 @@ int ObSdoGeoObject::to_text(ObStringBuffer &buf) LOG_WARN("fail to print srid", K(ret)); } else if (srid_ != UINT32_MAX && ((len = snprintf(number_buf, 128, "%u", srid_)) < 0 || - OB_FAIL(buf.append(number_buf, len)))) { + OB_FAIL(buf.append(number_buf, len, 0)))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret), K(len)); } else if (OB_FAIL(buf.append(", "))) { @@ -125,7 +125,7 @@ int ObSdoGeoObject::to_text(ObStringBuffer &buf) if ((len = snprintf(number_buf, 128, "%lu", elem_info_.at(i))) < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret)); - } else if (OB_FAIL(buf.append(number_buf, len))) { + } else if (OB_FAIL(buf.append(number_buf, len, 0))) { LOG_WARN("fail to print gtype", K(ret)); } else if (i + 1 != elem_info_.count() && OB_FAIL(buf.append(", "))) { LOG_WARN("fail to print ,", K(ret)); @@ -152,7 +152,7 @@ int ObSdoGeoObject::to_text(ObStringBuffer &buf) if ((len = snprintf(number_buf, 128, format_str.ptr(), ordinates_.at(i))) < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to val to string", K(ret)); - } else if (OB_FAIL(buf.append(number_buf, len))) { + } else if (OB_FAIL(buf.append(number_buf, len, 0))) { LOG_WARN("fail to print gtype", K(ret)); } else if (i + 1 != ordinates_.count() && OB_FAIL(buf.append(", "))) { LOG_WARN("fail to print ,", K(ret)); diff --git a/deps/oblib/src/lib/geo/ob_sdo_geo_object.h b/deps/oblib/src/lib/geo/ob_sdo_geo_object.h index a7e61ee01..61f6b2d9a 100644 --- a/deps/oblib/src/lib/geo/ob_sdo_geo_object.h +++ b/deps/oblib/src/lib/geo/ob_sdo_geo_object.h @@ -67,13 +67,22 @@ private: class ObSdoGeoObject { public: - ObSdoGeoObject(ObGeoType gtype, ObSdoPoint point, uint32_t srid = UINT32_MAX) - : gtype_(gtype), point_(point), srid_(srid) {} + ObSdoGeoObject(ObGeoType gtype, ObSdoPoint point, ObIAllocator &allocator, uint32_t srid = UINT32_MAX) + : gtype_(gtype), point_(point), srid_(srid), + elem_info_(OB_MALLOC_NORMAL_BLOCK_SIZE, ModulePageAllocator(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR)), + ordinates_(DEFAULT_PAGE_SIZE_ORDINATES, ModulePageAllocator(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR)) + {} ObSdoGeoObject(ObGeoType gtype, ObArray elem_info, - ObArray ordinates, uint32_t srid = UINT32_MAX) - : gtype_(gtype), elem_info_(elem_info), ordinates_(ordinates), srid_(srid) + ObArray ordinates, ObIAllocator &allocator, uint32_t srid = UINT32_MAX) + : gtype_(gtype), srid_(srid), + elem_info_(OB_MALLOC_NORMAL_BLOCK_SIZE, ModulePageAllocator(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR)), + ordinates_(DEFAULT_PAGE_SIZE_ORDINATES, ModulePageAllocator(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR)) {} + ObSdoGeoObject(ObIAllocator &allocator) : gtype_(ObGeoType::GEOTYPEMAX), srid_(UINT32_MAX), + elem_info_(OB_MALLOC_NORMAL_BLOCK_SIZE, ModulePageAllocator(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR)), + ordinates_(DEFAULT_PAGE_SIZE_ORDINATES, ModulePageAllocator(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR)) + {} ObSdoGeoObject() : gtype_(ObGeoType::GEOTYPEMAX), srid_(UINT32_MAX) {} ~ObSdoGeoObject() {} @@ -96,13 +105,14 @@ public: TO_STRING_KV(K_(gtype), K_(srid), K_(point), K_(elem_info), K_(ordinates)); private: + static const int64_t DEFAULT_PAGE_SIZE_ORDINATES = 1024; // 1KB bool need_sci_format(double num) { return num <= -1e9 || num >= 1e10; } ObGeoType gtype_; ObSdoPoint point_; + uint32_t srid_; ObArray elem_info_; ObArray ordinates_; - uint32_t srid_; DISALLOW_COPY_AND_ASSIGN(ObSdoGeoObject); }; } // namespace common diff --git a/deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.cpp b/deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.cpp new file mode 100644 index 000000000..c32140fbf --- /dev/null +++ b/deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.cpp @@ -0,0 +1,1095 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "lib/ob_errno.h" +#include +#define USING_LOG_PREFIX LIB +#include "ob_wkb_to_json_bin_visitor.h" +#include "lib/geo/ob_geo_func_register.h" +#include "lib/geo/ob_wkb_to_json_visitor.h" + +namespace oceanbase { +namespace common { + +enum TypeNameMap +{ + Point = 0, + MultiPoint = 1, + LineString = 2, + MultiLineString = 3, + Polygon = 4, + MultiPolygon = 5, + GeometryCollection = 6 +}; +const ObString type_name_table[] +{ + "Point", + "MultiPoint", + "LineString", + "MultiLineString", + "Polygon", + "MultiPolygon", + "GeometryCollection" +}; +enum KeyNameMap +{ + crs = 0, + bbox = 1, + type = 2, + geometries = 3, + coordinates = 4, + properties = 5, + name = 6 +}; +const ObString key_name_table[] +{ + "crs", + "bbox", + "type", + "geometries", + "coordinates", + "properties", + "name" +}; +ObWkbToJsonBinVisitor::ObWkbToJsonBinVisitor( + ObIAllocator *allocator, + uint32_t max_dec_digits, + uint8_t flag, + const ObGeoSrid srid) + : json_buf_(allocator), + flag_(flag), + srid_(srid), + allocator_(allocator), + max_dec_digits_(max_dec_digits), + is_appendCrs(false) +{ +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogPoint *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL(appendPointObj(geo, type_name_table[TypeNameMap::Point]))) { + LOG_WARN("fail to append point", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomPoint *geo) +{ + INIT_SUCC(ret); + ObString type_name(type_name_table[0]); //"Point" + if (OB_FAIL(appendPointObj(geo, type_name))) { + LOG_WARN("fail to append point", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogMultiPoint *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendLineObj(geo, type_name_table[TypeNameMap::MultiPoint])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomMultiPoint *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendLineObj(geo, type_name_table[TypeNameMap::MultiPoint])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogLineString *geo) +{ + INIT_SUCC(ret); + // ObString type_name(type_name_table[2]); //"LineString" + if (OB_FAIL((appendLineObj(geo, type_name_table[TypeNameMap::LineString])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomLineString *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendLineObj(geo, type_name_table[TypeNameMap::LineString])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogMultiLineString *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendMultiLineObj< + ObIWkbGeogMultiLineString, + ObWkbGeogMultiLineString, + ObWkbGeogLineString>(geo, type_name_table[TypeNameMap::MultiLineString])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomMultiLineString *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendMultiLineObj< + ObIWkbGeomMultiLineString, + ObWkbGeomMultiLineString, + ObWkbGeomLineString>(geo, type_name_table[TypeNameMap::MultiLineString])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogPolygon *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendPolygonObj< + ObIWkbGeogPolygon, + ObWkbGeogPolygon, + ObWkbGeogLinearRing, + ObWkbGeogPolygonInnerRings>(geo, type_name_table[TypeNameMap::Polygon])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomPolygon *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendPolygonObj< + ObIWkbGeomPolygon, + ObWkbGeomPolygon, + ObWkbGeomLinearRing, + ObWkbGeomPolygonInnerRings>(geo, type_name_table[TypeNameMap::Polygon])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogMultiPolygon *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendMultiPolygonObj< + ObIWkbGeogMultiPolygon, + ObWkbGeogMultiPolygon, + ObWkbGeogPolygon, + ObWkbGeogLinearRing, + ObWkbGeogPolygonInnerRings>(geo, type_name_table[TypeNameMap::MultiPolygon])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomMultiPolygon *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendMultiPolygonObj< + ObIWkbGeomMultiPolygon, + ObWkbGeomMultiPolygon, + ObWkbGeomPolygon, + ObWkbGeomLinearRing, + ObWkbGeomPolygonInnerRings>(geo, type_name_table[TypeNameMap::MultiPolygon])))) { + LOG_WARN("fail to append line", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeogCollection *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendCollectionObj< + ObIWkbGeogCollection, + ObWkbGeogCollection>(geo, type_name_table[TypeNameMap::GeometryCollection])))) { + LOG_WARN("fail to append collection", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::visit(ObIWkbGeomCollection *geo) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendCollectionObj< + ObIWkbGeomCollection, + ObWkbGeomCollection>(geo, type_name_table[TypeNameMap::GeometryCollection])))) { + LOG_WARN("fail to append collection", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::to_jsonbin(ObGeometry *geo, ObString &geojsonbin) +{ + INIT_SUCC(ret); + json_buf_.reset(); + if (OB_FAIL(json_buf_.reserve(geo->length() * 2))) { + LOG_WARN("fail to reserve json_buf_", K(ret), K(geo->length() * 2)); + } else if (OB_FAIL(ObJsonBin::add_doc_header_v0(json_buf_))) { + LOG_WARN("fail to add doc header", K(ret)); + } else if (OB_FAIL(geo->do_visit(*this))) { + LOG_WARN("fail to geo->do_visit", K(ret)); + } else if (OB_FAIL(ObJsonBin::set_doc_header_v0(json_buf_, json_buf_.length()))) { + LOG_WARN("fail to set doc header", K(ret)); + } else if (OB_FAIL(json_buf_.get_result_string(geojsonbin))) { + LOG_WARN("fail to get_result_string", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor:: appendCoordinatePoint( + double x, + double y, + ObJsonBin &bin, + uint64_t start_pos, + uint64_t &val_idx) +{ + INIT_SUCC(ret); + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_ARRAY); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else { + uint64_t array_pos = 0; + ObJsonBin array_bin; + uint64_t array_idx = 0; + if (OB_FAIL(appendMeta(array_bin, array_pos, 1, 2, 0))) { + LOG_WARN("fail to appendMeta", K(ret), K(array_pos)); + } else if (OB_FAIL(appendDouble(x, array_bin, array_pos, array_idx))) { + LOG_WARN("fail to appendDouble", K(ret), K(x), K(array_pos), K(array_idx)); + } else if (OB_FAIL(appendDouble(y, array_bin, array_pos, array_idx))) { + LOG_WARN("fail to appendDouble", K(ret), K(y), K(array_pos), K(array_idx)); + } else if (OB_FAIL(fillHeaderSize(array_bin, array_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret), K(array_pos)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendPointObj(T_IBIN *geo, const ObString &type_name) +{ + // { "type": "Point", "coordinates": [x, y] } + INIT_SUCC(ret); + ObJsonBin bin; + uint64_t start_pos = 0; + uint64_t val_idx = 0; + if (OB_FAIL(appendJsonCommon(type_name, geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendJsonCommon", K(ret), K(type_name)); + } else if (OB_FAIL(appendCoordinatePoint(geo->x(), geo->y(), bin, start_pos, val_idx))) { + LOG_WARN("fail to appendCoordinatePoint", K(ret), K(geo->x()), K(geo->y())); + } else if (OB_FAIL(fillHeaderSize(bin, start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendLine(const T_BIN *line, ObJsonBin &bin, uint64_t &start_pos, uint64_t &val_idx) +{ + INIT_SUCC(ret); + typename T_BIN::iterator iter = line->begin(); + uint64_t line_size = line->iter_idx_max(); + ObJsonBin line_bin; + uint64_t line_val_idx = 0; + uint64_t line_start_pos = 0; + if (OB_FAIL(appendArrayHeader(bin, start_pos, val_idx, line_size, line_bin, line_start_pos))) { + LOG_WARN("fail to appendArrayHeader", K(ret), K(start_pos), K(val_idx)); + } else { + for (; OB_SUCC(ret) && iter != line->end(); iter++) { + if(OB_FAIL(appendCoordinatePoint( + iter->template get<0>(), + iter->template get<1>(), + line_bin, + line_start_pos, + line_val_idx))) { + LOG_WARN("fail to appendCoordinatePoint", K(ret), K(iter->template get<0>()), K(iter->template get<1>())); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(line_bin, line_start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendLineObj(T_IBIN *geo, const ObString &type_name) +{ + INIT_SUCC(ret); + ObJsonBin bin; + uint64_t start_pos = 0; + uint64_t val_idx = 0; + const T_BIN *line = reinterpret_cast(geo->val()); + if (OB_FAIL(appendJsonCommon(type_name, geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendJsonCommon", K(ret), K(type_name)); + } else if (OB_FAIL(appendLine(line, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendLine", K(ret), K(start_pos), K(val_idx)); + } else if (OB_FAIL(fillHeaderSize(bin, start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendMultiLineObj(T_IBIN *geo, const ObString &type_name) +{ + INIT_SUCC(ret); + ObJsonBin bin; + uint64_t start_pos = 0; + uint64_t val_idx = 0; + if (OB_FAIL(appendJsonCommon(type_name, geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendJsonCommon", K(ret), K(type_name)); + } else { + const T_BIN *multi_line = reinterpret_cast(geo->val()); + typename T_BIN::iterator line = multi_line->begin(); + uint64_t multi_size = multi_line->iter_idx_max(); + ObJsonBin multi_bin; + uint64_t multi_val_idx = 0; + uint64_t multi_start_pos = 0; + if (OB_FAIL(appendArrayHeader(bin, start_pos, val_idx, multi_size, multi_bin, multi_start_pos))) { + LOG_WARN("fail to appendArrayHeader", K(ret), K(start_pos), K(val_idx)); + } else { + for (; OB_SUCC(ret) && line != multi_line->end(); line++) { + if (OB_FAIL(appendLine(&(*line), multi_bin, multi_start_pos, multi_val_idx))) { + LOG_WARN("fail to appendLine", K(ret), K(multi_start_pos), K(multi_val_idx)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(multi_bin, multi_start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(bin, start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendPolygon(const T_BIN *poly, ObJsonBin &bin, uint64_t &start_pos, uint64_t &val_idx) +{ + INIT_SUCC(ret); + uint64_t poly_size = poly->size(); + const T_BIN_RING& exterior = poly->exterior_ring(); + const T_BIN_INNER_RING &inner_rings = poly->inner_rings(); + ObJsonBin poly_bin; + uint64_t poly_val_idx = 0; + uint64_t poly_start_pos = 0; + if (OB_FAIL(appendArrayHeader(bin, start_pos, val_idx, poly_size, poly_bin, poly_start_pos))) { + LOG_WARN("fail to appendArrayHeader", K(ret), K(start_pos), K(val_idx)); + } else { + if (poly_size > 0) { + // exterior poly + if (OB_FAIL(appendLine(&exterior, poly_bin, poly_start_pos, poly_val_idx))) { + LOG_WARN("fail to appendLine", K(ret), K(poly_start_pos), K(poly_val_idx)); + } + } + // interior poly + typename T_BIN_INNER_RING::iterator iterInnerRing = inner_rings.begin(); + for (; OB_SUCC(ret) && iterInnerRing != inner_rings.end(); iterInnerRing++) { + if (OB_FAIL(appendLine(&(*iterInnerRing), poly_bin, poly_start_pos, poly_val_idx))) { + LOG_WARN("fail to appendLine", K(ret), K(poly_start_pos), K(poly_val_idx)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(poly_bin, poly_start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendPolygonObj(T_IBIN *geo, const ObString &type_name) +{ + INIT_SUCC(ret); + ObJsonBin bin; + uint64_t start_pos = 0; + uint64_t val_idx = 0; + const T_BIN *poly = reinterpret_cast(geo->val()); + if (OB_FAIL(appendJsonCommon(type_name, geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendJsonCommon", K(ret), K(type_name)); + } else if (OB_FAIL((appendPolygon< + T_BIN, + T_BIN_RING, + T_BIN_INNER_RING>(poly, bin, start_pos, val_idx)))) { + LOG_WARN("appendPolygon fail", K(ret), K(start_pos), K(val_idx)); + } else if (OB_FAIL(fillHeaderSize(bin, start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendMultiPolygonObj(T_IBIN *geo, const ObString &type_name) +{ + INIT_SUCC(ret); + ObJsonBin bin; + uint64_t start_pos = 0; + uint64_t val_idx = 0; + if (OB_FAIL(appendJsonCommon(type_name, geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendJsonCommon", K(ret), K(type_name)); + } else { + const T_BIN *multi_poly = reinterpret_cast(geo->val()); + typename T_BIN::iterator poly = multi_poly->begin(); + uint64_t multi_size = multi_poly->iter_idx_max(); + ObJsonBin multi_bin; + uint64_t multi_val_idx = 0; + uint64_t multi_start_pos = 0; + if (OB_FAIL(appendArrayHeader(bin, start_pos, val_idx, multi_size, multi_bin, multi_start_pos))) { + LOG_WARN("fail to appendArrayHeader", K(ret), K(start_pos), K(val_idx)); + } else { + for (; OB_SUCC(ret) && poly != multi_poly->end(); poly++) { + if (OB_FAIL((appendPolygon(&(*poly), multi_bin, multi_start_pos, multi_val_idx)))) { + LOG_WARN("fail to appendPolygon", K(ret), K(multi_start_pos), K(multi_val_idx)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(multi_bin, multi_start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(bin, start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendCollectionSub( + typename T_COLLC::const_pointer sub_ptr, + const T_COLLC *collection, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx) +{ + INIT_SUCC(ret); + ObGeoType sub_type = collection->get_sub_type(sub_ptr); + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_OBJECT); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else { + switch (sub_type) { + case ObGeoType::POINT : { + const T_POINT* geo = reinterpret_cast(sub_ptr); + T_IPOINT igeo; + ObString data(sizeof(T_POINT), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL(appendPointObj(&igeo, type_name_table[TypeNameMap::Point]))) { + LOG_WARN("fail to append point", K(ret)); + } + break; + } + case ObGeoType::MULTIPOINT : { + const T_MULTIPOINT* geo = reinterpret_cast(sub_ptr); + T_IMULTIPOINT igeo; + ObString data(sizeof(T_MULTIPOINT), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL((appendLineObj(&igeo, type_name_table[TypeNameMap::MultiPoint])))) { + LOG_WARN("fail to append multi_point", K(ret)); + } + break; + } + case ObGeoType::LINESTRING : { + const T_LINE* geo = reinterpret_cast(sub_ptr); + T_ILINE igeo; + ObString data(sizeof(T_LINE), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL((appendLineObj(&igeo, type_name_table[TypeNameMap::LineString])))) { + LOG_WARN("fail to append line", K(ret)); + } + break; + } + case ObGeoType::MULTILINESTRING : { + const T_MULTILINE* geo = reinterpret_cast(sub_ptr); + T_IMULTILINE igeo; + ObString data(sizeof(T_MULTILINE), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL((appendMultiLineObj< + T_IMULTILINE, + T_MULTILINE, + T_LINE>(&igeo, type_name_table[TypeNameMap::MultiLineString])))) { + LOG_WARN("fail to append multi_line", K(ret)); + } + break; + } + case ObGeoType::POLYGON : { + const T_POLY* geo = reinterpret_cast(sub_ptr); + T_IPOLY igeo; + ObString data(sizeof(T_POLY), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL((appendPolygonObj< + T_IPOLY, + T_POLY, + T_LINEARRING, + T_INNERRING>(&igeo, type_name_table[TypeNameMap::Polygon])))) { + LOG_WARN("fail to append polygon", K(ret)); + } + break; + } + case ObGeoType::MULTIPOLYGON : { + const T_MULTIPOLY* geo = reinterpret_cast(sub_ptr); + T_IMULTIPOLY igeo; + ObString data(sizeof(T_MULTIPOLY), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL((appendMultiPolygonObj< + T_IMULTIPOLY, + T_MULTIPOLY, + T_POLY, + T_LINEARRING, + T_INNERRING>(&igeo, type_name_table[TypeNameMap::MultiPolygon])))) { + LOG_WARN("fail to append multi_polygon", K(ret)); + } + break; + } + case ObGeoType::GEOMETRYCOLLECTION : { + const T_COLLC* geo = reinterpret_cast(sub_ptr); + T_ICOLLC igeo; + ObString data(sizeof(T_COLLC), reinterpret_cast(geo)); + igeo.set_data(data); + if (OB_FAIL((appendCollectionObj(&igeo, type_name_table[TypeNameMap::GeometryCollection])))) { + LOG_WARN("fail to append collection", K(ret)); + } + break; + } + default : { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid geo type", K(ret), K(sub_type)); + break; + } + } // switch end + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendCollectionSubWrapper( + ObWkbGeogCollection::const_pointer sub_ptr, + const ObWkbGeogCollection *collection, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendCollectionSub< + ObIWkbGeogPoint, + ObIWkbGeogMultiPoint, + ObIWkbGeogLineString, + ObIWkbGeogMultiLineString, + ObIWkbGeogPolygon, + ObIWkbGeogMultiPolygon, + ObIWkbGeogCollection, + ObWkbGeogPoint, + ObWkbGeogMultiPoint, + ObWkbGeogLineString, + ObWkbGeogMultiLineString, + ObWkbGeogPolygon, + ObWkbGeogLinearRing, + ObWkbGeogPolygonInnerRings, + ObWkbGeogMultiPolygon, + ObWkbGeogCollection>( + sub_ptr, + collection, + bin, + start_pos, + val_idx)))) { + LOG_WARN("fail to appendJsonCommon", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendCollectionSubWrapper( + ObWkbGeomCollection::const_pointer sub_ptr, + const ObWkbGeomCollection *collection, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx) +{ + INIT_SUCC(ret); + if (OB_FAIL((appendCollectionSub< + ObIWkbGeomPoint, + ObIWkbGeomMultiPoint, + ObIWkbGeomLineString, + ObIWkbGeomMultiLineString, + ObIWkbGeomPolygon, + ObIWkbGeomMultiPolygon, + ObIWkbGeomCollection, + ObWkbGeomPoint, + ObWkbGeomMultiPoint, + ObWkbGeomLineString, + ObWkbGeomMultiLineString, + ObWkbGeomPolygon, + ObWkbGeomLinearRing, + ObWkbGeomPolygonInnerRings, + ObWkbGeomMultiPolygon, + ObWkbGeomCollection>( + sub_ptr, + collection, + bin, + start_pos, + val_idx)))) { + LOG_WARN("fail to appendJsonCommon", K(ret)); + } + return ret; +} + +template +int ObWkbToJsonBinVisitor::appendCollectionObj(T_IBIN *geo, const ObString &type_name) +{ + INIT_SUCC(ret); + ObJsonBin bin; + uint64_t start_pos = 0; + uint64_t val_idx = 0; + if (OB_FAIL(appendJsonCommon(type_name, geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendJsonCommon", K(ret), K(type_name)); + } else { + const T_BIN *collection = reinterpret_cast(geo->val()); + typename T_BIN::iterator collection_iter = collection->begin(); + uint64_t collection_size = collection->iter_idx_max(); + ObJsonBin collection_bin; + uint64_t collection_val_idx = 0; + uint64_t collection_start_pos = 0; + if (OB_FAIL(appendArrayHeader( + bin, + start_pos, + val_idx, + collection_size, + collection_bin, + collection_start_pos))) { + LOG_WARN("fail to appendArrayHeader", K(ret), K(start_pos), K(val_idx)); + } else { + for (; OB_SUCC(ret) && collection_iter != collection->end(); collection_iter++) { + typename T_BIN::const_pointer sub_ptr = collection_iter.operator->(); + if (OB_FAIL(appendCollectionSubWrapper( + sub_ptr, + collection, + collection_bin, + collection_start_pos, + collection_val_idx))) { + LOG_WARN("fail to appendCollectionSub", K(ret), K(collection_start_pos), K(collection_val_idx)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(collection_bin, collection_start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(fillHeaderSize(bin, start_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendJsonCommon( + const ObString type_name, + ObGeometry *geo, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx) +{ + INIT_SUCC(ret); + uint64_t key_count = 2; // minimun count is 2 + int key_idx = 0; + ObGeoType type = geo->type(); + if (type <= ObGeoType::GEOMETRY || type >= ObGeoType::GEOTYPEMAX) { + int ret = OB_ERR_GIS_INVALID_DATA; + LOG_WARN("invalid geo type", K(ret), K(type)); + } + // append obj meta + if (OB_FAIL(ret)) { + } else if (!is_appendCrs && srid_ != 0 + && ((flag_ & ObGeoJsonFormat::SHORT_SRID) || (flag_ & ObGeoJsonFormat::LONG_SRID))) { + key_count++; + } + if (OB_FAIL(ret)) { + } else if (flag_ & ObGeoJsonFormat::BBOX && !geo->is_empty()) { + key_count++; + } + // append obj key + if (OB_FAIL(ret)) { + } else if (OB_FAIL(appendMeta(bin, start_pos, 0, key_count))) { + LOG_WARN("fail to appendMeta", K(ret), K(start_pos), K(key_count)); + } else if (!is_appendCrs && srid_ != 0 + && ((flag_ & ObGeoJsonFormat::SHORT_SRID) || (flag_ & ObGeoJsonFormat::LONG_SRID)) + && OB_FAIL(appendObjKey(key_name_table[KeyNameMap::crs], bin, start_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::crs]), K(start_pos), K(key_idx)); + } else if (flag_ & ObGeoJsonFormat::BBOX && !geo->is_empty() + && OB_FAIL(appendObjKey(key_name_table[KeyNameMap::bbox], bin, start_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::bbox]), K(start_pos), K(key_idx)); + } else if (OB_FAIL(appendObjKey(key_name_table[KeyNameMap::type], bin, start_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::type]), K(start_pos), K(key_idx)); + } else if (geo->type() == ObGeoType::GEOMETRYCOLLECTION + && OB_FAIL(appendObjKey(key_name_table[KeyNameMap::geometries], bin, start_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::geometries]), K(start_pos), K(key_idx)); + } else if (geo->type() != ObGeoType::GEOMETRYCOLLECTION + && OB_FAIL(appendObjKey(key_name_table[KeyNameMap::coordinates], bin, start_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::coordinates]), K(start_pos), K(key_idx)); + } + // append obj value + if (OB_FAIL(ret)) { + } else if (OB_FAIL(appendCrs(bin, start_pos, val_idx))) { + LOG_WARN("fail to appendCrs", K(ret), K(start_pos), K(val_idx)); + } else if (OB_FAIL(appendBbox(geo, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendBbox", K(ret), K(start_pos), K(val_idx)); + } else if (OB_FAIL(appendString(type_name, bin, start_pos, val_idx))) { + LOG_WARN("fail to appendString", K(ret), K(type_name), K(start_pos), K(val_idx)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendObjKey(const ObString key_str, ObJsonBin &bin, uint64_t &start_pos, int &key_idx) +{ + INIT_SUCC(ret); + uint64_t key_offset = json_buf_.length() - start_pos; + uint64_t key_len = key_str.length(); + if (OB_FAIL(bin.set_key_entry(key_idx, key_offset, key_len, false))) { + LOG_WARN("fail to set_key_entry", K(ret), K(key_idx), K(key_offset), K(key_len)); + } else if (OB_FAIL(json_buf_.append(key_str, 0))) { + LOG_WARN("fail to append key", K(ret), K(key_str)); + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + key_idx++; + } + return ret; +} + + +int ObWkbToJsonBinVisitor::appendMeta(ObJsonBin &bin, uint64_t &start_pos, int type_flag, uint64_t element_count, uint64_t size_size) +{ + INIT_SUCC(ret); + ObJsonBinMeta meta; + ObJBVerType vertype = J_NULL_V0; + if (type_flag == 0) { + vertype = ObJsonBin::get_object_vertype(); + } else if (type_flag == 1) { + vertype = ObJsonBin::get_array_vertype(); + } + start_pos = json_buf_.length(); + meta.set_type(vertype, false); + meta.set_element_count(element_count); + meta.set_element_count_var_type(ObJsonVar::get_var_type(element_count)); + meta.set_obj_size_var_type(size_size); + meta.set_entry_var_type(meta.obj_size_var_type()); + meta.set_is_continuous(true); + meta.calc_entry_array(); + if (OB_FAIL(meta.to_header(json_buf_))) { + LOG_WARN("meta to_header failed", K(ret)); + } else if (OB_FAIL(bin.reset(json_buf_.string(), start_pos, nullptr))) { + LOG_WARN("init bin with meta failed", K(ret), K(meta)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::fillHeaderSize(ObJsonBin &bin, uint64_t start_pos) +{ + INIT_SUCC(ret); + uint64_t real_obj_size = static_cast(json_buf_.length() - start_pos); + if (OB_FAIL(bin.set_obj_size(real_obj_size))) { + LOG_WARN("fail to set_obj_size", K(ret), K(real_obj_size)); + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendCrs(ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx) +{ + INIT_SUCC(ret); + if (!is_appendCrs && srid_ != 0 && ((flag_ & ObGeoJsonFormat::SHORT_SRID) || (flag_ & ObGeoJsonFormat::LONG_SRID))) { + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_OBJECT); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else { + // {"crs": {"type": "name", "properties": {"name": "EPSG:4269"}} + // {"crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:EPSG::4269"}} + ObJsonBin crs_bin; + uint64_t crs_pos = 0; + uint64_t crs_idx = 0; + int key_idx = 0; + if (OB_FAIL(appendMeta(crs_bin, crs_pos, 0, 2, 0))) { + LOG_WARN("fail to appendMeta", K(ret), K(crs_pos)); + } else if (OB_FAIL(appendObjKey(key_name_table[KeyNameMap::type], crs_bin, crs_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::type]), K(crs_pos), K(key_idx)); + } else if (OB_FAIL(appendObjKey(key_name_table[KeyNameMap::properties], crs_bin, crs_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::properties]), K(crs_pos), K(key_idx)); + } else if (OB_FAIL(appendString(key_name_table[KeyNameMap::name], crs_bin, crs_pos, crs_idx))) { + LOG_WARN("fail to appendString", K(ret), K(crs_pos)); + } else if (OB_FAIL(appendCrsProp(crs_bin, crs_pos, crs_idx))){ + LOG_WARN("fail to appendCrsProp", K(ret), K(crs_pos)); + } else if (OB_FAIL(fillHeaderSize(crs_bin, crs_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("j_bin_.set_current fail", K(ret)); + } else { + val_idx++; + is_appendCrs = true; + } + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendCrsProp( + ObJsonBin &bin, + uint64_t start_pos, + uint64_t &val_idx) +{ + INIT_SUCC(ret); + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_OBJECT); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else { + ObJsonBin prop_bin; + uint64_t prop_pos = 0; + uint64_t prop_idx = 0; + int key_idx = 0; + char srid_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; + uint64_t srid_len = ObFastFormatInt::format_signed(srid_, srid_buf); + ObStringBuffer prop_value_buf(allocator_); + ObString prop_value; + if (flag_ & ObGeoJsonFormat::LONG_SRID) { + // {"name": "urn:ogc:def:crs:EPSG::[SRID]"} + if (OB_FAIL(prop_value_buf.append("urn:ogc:def:crs:EPSG::"))) { + LOG_WARN("fail to append long srid string", K(ret)); + } + } else { + // {"name": "EPSG:[SRID]"} + if (OB_FAIL(prop_value_buf.append("EPSG:"))) { + LOG_WARN("fail to append short srid string", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(prop_value_buf.append(srid_buf, srid_len, 0))) { + LOG_WARN("fail to append srid", K(ret), K(srid_)); + } else if (OB_FAIL(prop_value_buf.get_result_string(prop_value))) { + LOG_WARN("fail to get prop_value stringd", K(ret)); + } + + // append object + if (OB_FAIL(ret)) { + } else if (OB_FAIL(appendMeta(prop_bin, prop_pos, 0, 1, 0))) { + LOG_WARN("fail to appendMeta", K(ret), K(prop_pos)); + } else if (OB_FAIL(appendObjKey(key_name_table[KeyNameMap::name], prop_bin, prop_pos, key_idx))) { + LOG_WARN("fail to appendObjKey", K(ret), K(key_name_table[KeyNameMap::name]), K(prop_pos), K(key_idx)); + } else if (OB_FAIL(appendString(prop_value, prop_bin, prop_pos, prop_idx))) { + LOG_WARN("fail to appendString", K(ret), K(prop_pos)); + } else if (OB_FAIL(fillHeaderSize(prop_bin, prop_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret), K(prop_pos)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendBbox(ObGeometry *geo, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx) +{ + INIT_SUCC(ret); + if ((flag_ & ObGeoJsonFormat::BBOX) && !geo->is_empty()) { + // [xmin, ymin, xmax, ymax] + ObGeogBox *box = nullptr; + ObArenaAllocator tmp_allocator; + ObGeometry *box_geo = nullptr; + if (geo->crs() == ObGeoCRS::Geographic) { + if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(tmp_allocator, geo->type(), false, true, box_geo, geo->get_srid()))) { + LOG_WARN("fail to create geo by type", K(ret), K(geo->type())); + } else { + box_geo->set_data(geo->val()); + } + } else { + box_geo = geo; + } + CREATE_WITH_TEMP_CONTEXT(lib::ContextParam().set_mem_attr(MTL_ID(), "GISModule", ObCtxIds::DEFAULT_CTX_ID)) { + ObGeoEvalCtx geo_ctx(CURRENT_CONTEXT); + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(geo_ctx.append_geo_arg(box_geo))) { + LOG_WARN("build gis context failed", K(ret)); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(geo_ctx, box))) { + LOG_WARN("failed to do box functor failed", K(ret)); + } else { + // append Bbox + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_ARRAY); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else { + uint64_t array_pos = 0; + ObJsonBin array_bin; + uint64_t array_idx = 0; + if (OB_FAIL(appendMeta(array_bin, array_pos, 1, 4, 0))) { + LOG_WARN("fail to appendMeta", K(ret), K(array_pos)); + } else if (OB_FAIL(appendDouble(box->xmin, array_bin, array_pos, array_idx))) { + LOG_WARN("fail to appendDouble", K(ret), K(box->xmin), K(array_pos), K(array_idx)); + } else if (OB_FAIL(appendDouble(box->ymin, array_bin, array_pos, array_idx))) { + LOG_WARN("fail to appendDouble", K(ret), K(box->ymin), K(array_pos), K(array_idx)); + } else if (OB_FAIL(appendDouble(box->xmax, array_bin, array_pos, array_idx))) { + LOG_WARN("fail to appendDouble", K(ret), K(box->xmax), K(array_pos), K(array_idx)); + } else if (OB_FAIL(appendDouble(box->ymax, array_bin, array_pos, array_idx))) { + LOG_WARN("fail to appendDouble", K(ret), K(box->ymax), K(array_pos), K(array_idx)); + } else if (OB_FAIL(fillHeaderSize(array_bin, array_pos))) { + LOG_WARN("fail to fillHeaderSize", K(ret), K(array_pos)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + } + } + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendString(const ObString &str, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx) +{ + INIT_SUCC(ret); + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_STRING); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else if (OB_FAIL(ObJsonBinSerializer::serialize_json_string(ObJBVerType::J_STRING_V0, str, json_buf_))) { + LOG_WARN("failed to serialize json string", K(ret), K(str)); + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("fail to set_current", K(ret), K(start_pos)); + } else { + val_idx++; + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendDouble(double value, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx) +{ + INIT_SUCC(ret); + double dec_value = value; + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_DOUBLE); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else if (max_dec_digits_ < INT_MAX32 + && OB_FALSE_IT(dec_value = ObGeoTypeUtil::round_double(value, max_dec_digits_, false))) { + } else if (OB_FAIL(ObJsonBinSerializer::serialize_json_double(dec_value, json_buf_))) { + LOG_WARN("failed to append double to json_buf_", K(ret), K(dec_value), K(value)); + } else if (OB_FAIL(bin.set_current(json_buf_.string(), start_pos))) { + LOG_WARN("failed to set_current", K(ret)); + } else { + val_idx++; + } + return ret; +} + +int ObWkbToJsonBinVisitor::appendArrayHeader( + ObJsonBin &bin, + uint64_t start_pos, + uint64_t val_idx, + uint64_t size, + ObJsonBin &array_bin, + uint64_t &array_start_pos) +{ + INIT_SUCC(ret); + uint64_t value_offset = json_buf_.length() - start_pos; + uint8_t value_type = static_cast(ObJsonNodeType::J_ARRAY); + if (OB_FAIL(bin.set_value_entry(val_idx, value_offset, value_type, false))) { + LOG_WARN("fail to set value entry", K(ret), K(value_offset), K(value_type)); + } else if (OB_FAIL(appendMeta(array_bin, array_start_pos, 1, size))) { + LOG_WARN("fail to appendMeta", K(ret), K(array_start_pos), K(size)); + } + return ret; +} + +void ObWkbToJsonBinVisitor::reset() +{ + json_buf_.reset(); + flag_ = 0; + srid_ = 0; + max_dec_digits_ = UINT_MAX32; + is_appendCrs = false; +} + +} // namespace common +} // namespace oceanbase diff --git a/deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.h b/deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.h new file mode 100644 index 000000000..ef068ba8e --- /dev/null +++ b/deps/oblib/src/lib/geo/ob_wkb_to_json_bin_visitor.h @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_LIB_GEO_OB_GEO_TO_JSON_BIN_VISITOR_ +#define OCEANBASE_LIB_GEO_OB_GEO_TO_JSON_BIN_VISITOR_ +#include "lib/geo/ob_geo_visitor.h" +#include "lib/geo/ob_geo_utils.h" +#include "lib/json_type/ob_json_bin.h" +#include "lib/xml/ob_multi_mode_bin.h" + +namespace oceanbase +{ +namespace common +{ +class ObWkbToJsonBinVisitor : public ObEmptyGeoVisitor +{ +public: + static const int MAX_DIGITS_IN_DOUBLE = 25; + explicit ObWkbToJsonBinVisitor( + ObIAllocator *allocator, + uint32_t max_dec_digits = UINT_MAX32, + uint8_t flag = 0, + const ObGeoSrid srid = 0); + + ~ObWkbToJsonBinVisitor() {} + bool prepare(ObGeometry *geo) { UNUSED(geo); return true; } + int visit(ObIWkbGeogPoint *geo); + int visit(ObIWkbGeomPoint *geo); + int visit(ObIWkbGeogLineString *geo); + int visit(ObIWkbGeomLineString *geo); + int visit(ObIWkbGeogMultiPoint *geo); + int visit(ObIWkbGeomMultiPoint *geo); + int visit(ObIWkbGeogMultiLineString *geo); + int visit(ObIWkbGeomMultiLineString *geo); + int visit(ObIWkbGeogPolygon *geo); + int visit(ObIWkbGeomPolygon *geo); + int visit(ObIWkbGeogMultiPolygon *geo); + int visit(ObIWkbGeomMultiPolygon *geo); + int visit(ObIWkbGeogCollection *geo); + int visit(ObIWkbGeomCollection *geo); + + bool is_end(ObGeometry *geo) { UNUSED(geo); return true; } + int to_jsonbin(ObGeometry *geo, ObString &geojsonbin); + + void reset(); +private: + // for Point + int appendCoordinatePoint(double x, double y, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx); + template + int appendPointObj(T_IBIN *geo, const ObString &type_name); + // for LineString + template + int appendLine(const T_BIN *line, ObJsonBin &bin, uint64_t &start_pos, uint64_t &val_idx); + template + int appendLineObj(T_IBIN *geo, const ObString &type_name); + template + int appendMultiLineObj(T_IBIN *geo, const ObString &type_name); + // for Polygon + template + int appendPolygon(const T_BIN *poly, ObJsonBin &bin, uint64_t &start_pos, uint64_t &val_idx); + template + int appendPolygonObj(T_IBIN *geo, const ObString &type_name); + template + int appendMultiPolygonObj(T_IBIN *geo, const ObString &type_name); + // for Collection + template< + typename T_IPOINT, + typename T_IMULTIPOINT, + typename T_ILINE, + typename T_IMULTILINE, + typename T_IPOLY, + typename T_IMULTIPOLY, + typename T_ICOLLC, + typename T_POINT, + typename T_MULTIPOINT, + typename T_LINE, + typename T_MULTILINE, + typename T_POLY, + typename T_LINEARRING, + typename T_INNERRING, + typename T_MULTIPOLY, + typename T_COLLC> + int appendCollectionSub( + typename T_COLLC::const_pointer sub_ptr, + const T_COLLC *collection, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx); + + int appendCollectionSubWrapper( + ObWkbGeogCollection::const_pointer sub_ptr, + const ObWkbGeogCollection *collection, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx); + int appendCollectionSubWrapper( + ObWkbGeomCollection::const_pointer sub_ptr, + const ObWkbGeomCollection *collection, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx); + template + int appendCollectionObj(T_IBIN *geo, const ObString &type_name); + // common + int appendJsonCommon( + const ObString type_name, + ObGeometry *geo, + ObJsonBin &bin, + uint64_t &start_pos, + uint64_t &val_idx); + int appendMeta(ObJsonBin &bin, uint64_t &start_pos, int type_flag, uint64_t element_count, uint64_t size_size = 3); + int appendObjKey(const ObString key_str, ObJsonBin &bin, uint64_t &start_pos, int &key_idx); + int fillHeaderSize(ObJsonBin &bin, uint64_t start_pos); + int appendCrs(ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx); + int appendCrsProp(ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx); + int appendBbox(ObGeometry *geo, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx); + int appendString(const ObString &str, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx); + int appendDouble(double value, ObJsonBin &bin, uint64_t start_pos, uint64_t &val_idx); + int appendArrayHeader( + ObJsonBin &bin, + uint64_t start_pos, + uint64_t val_idx, + uint64_t size, + ObJsonBin &array_bin, + uint64_t &array_start_pos); + + ObJsonBuffer json_buf_; + uint8_t flag_; + ObGeoSrid srid_; + ObIAllocator *allocator_; + uint32_t max_dec_digits_; + bool is_appendCrs; + + DISALLOW_COPY_AND_ASSIGN(ObWkbToJsonBinVisitor); +}; + +} // namespace common +} // namespace oceanbase + +#endif \ No newline at end of file diff --git a/deps/oblib/src/lib/geo/ob_wkb_to_json_visitor.cpp b/deps/oblib/src/lib/geo/ob_wkb_to_json_visitor.cpp index 559bb4a36..8ac8b0577 100644 --- a/deps/oblib/src/lib/geo/ob_wkb_to_json_visitor.cpp +++ b/deps/oblib/src/lib/geo/ob_wkb_to_json_visitor.cpp @@ -23,6 +23,7 @@ #include "lib/geo/ob_geo_func_register.h" #include "lib/utility/ob_fast_convert.h" #include "rpc/obmysql/ob_mysql_global.h" +#include "share/rc/ob_tenant_base.h" namespace oceanbase { namespace common { @@ -696,17 +697,19 @@ int ObWkbToJsonVisitor::appendMySQLFlagInfo(ObGeometry *geo) } else { box_geo = geo; } - ObGeoEvalCtx geo_ctx(allocator_); - if (OB_FAIL(ret)) { - // do nothing - } else if (OB_FAIL(geo_ctx.append_geo_arg(box_geo))) { - LOG_WARN("build gis context failed", K(ret)); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(geo_ctx, box))) { - LOG_WARN("failed to do box functor failed", K(ret)); - } else if (OB_FAIL(appendBox(*box))) { - LOG_WARN("fail to append bbox field", K(ret)); - } else if (OB_FAIL(buffer_.append(", "))) { - LOG_WARN("fail to append comma", K(ret)); + CREATE_WITH_TEMP_CONTEXT(lib::ContextParam().set_mem_attr(MTL_ID(), "GISModule", ObCtxIds::DEFAULT_CTX_ID)) { + ObGeoEvalCtx geo_ctx(CURRENT_CONTEXT); + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(geo_ctx.append_geo_arg(box_geo))) { + LOG_WARN("build gis context failed", K(ret)); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(geo_ctx, box))) { + LOG_WARN("failed to do box functor failed", K(ret)); + } else if (OB_FAIL(appendBox(*box))) { + LOG_WARN("fail to append bbox field", K(ret)); + } else if (OB_FAIL(buffer_.append(", "))) { + LOG_WARN("fail to append comma", K(ret)); + } } } return ret; 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 4d98a6d10..15255cdbc 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -23,6 +23,7 @@ #include "rpc/obmysql/ob_mysql_global.h" // DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE #include "lib/charset/ob_charset.h" // for strntod #include "common/ob_smart_var.h" // for SMART_VAR +#include "common/ob_smart_call.h" namespace oceanbase { namespace common { @@ -1689,7 +1690,7 @@ int ObIJsonBase::find_string_method(ObIAllocator* allocator, ObSeekParentInfo &p } } else if (!str_only) { ObJsonBuffer j_buf(allocator); - if (OB_FAIL(print(j_buf, true, false, 0))) { + if (OB_FAIL(print(j_buf, true, 0, false, 0))) { trans_fail = true; } else { ObJsonString* tmp_ans = static_cast (allocator->alloc(sizeof(ObJsonString))); @@ -1773,7 +1774,7 @@ int ObIJsonBase::find_trans_method(ObIAllocator* allocator, ObSeekParentInfo &pa src = ObString(get_data_length(), get_data()); } else if (type != ObJsonNodeType::J_NULL) { ObJsonBuffer j_buf(allocator); - if (OB_FAIL(print(j_buf, true, false, 0))) { + if (OB_FAIL(print(j_buf, true, 0, false, 0))) { trans_fail = true; } else { src = ObString(j_buf.length(), j_buf.ptr()); @@ -3200,7 +3201,7 @@ int ObIJsonBase::get_str_comp_result(ObIAllocator* allocator, ObSeekParentInfo & right_str = ObString(var->get_data_length(), var->get_data()); } else { ObJsonBuffer j_buf(allocator); - if (OB_FAIL(var->print(j_buf, true, false, 0))) { + if (OB_FAIL(var->print(j_buf, true, 0, false, 0))) { LOG_WARN("fail to get string of sql_var.", K(ret)); } else { right_str = ObString(j_buf.length(), j_buf.ptr()); @@ -3566,7 +3567,7 @@ int ObIJsonBase::print_array(ObJsonBuffer &j_buf, uint64_t depth, bool is_pretty jb_ptr = &j_bin; if (OB_FAIL(get_array_element(i, jb_ptr))) { LOG_WARN("fail to get array element", K(ret), K(depth), K(i)); - } else if (OB_FAIL(jb_ptr->print(j_buf, true, is_pretty, depth))) { + } else if (OB_FAIL(jb_ptr->print(j_buf, true, 0, is_pretty, depth))) { LOG_WARN("fail to print json value to string", K(ret), K(i), K(is_pretty), K(depth)); } } @@ -3631,7 +3632,7 @@ int ObIJsonBase::print_object(ObJsonBuffer &j_buf, uint64_t depth, bool is_prett jb_ptr = &j_bin; if (OB_FAIL(get_object_value(i, jb_ptr))) { LOG_WARN("fail to get object value", K(ret), K(i), K(is_pretty), K(depth)); - } else if (OB_FAIL(jb_ptr->print(j_buf, true, is_pretty, depth))) { // value + } else if (OB_FAIL(jb_ptr->print(j_buf, true, 0, is_pretty, depth))) { // value LOG_WARN("fail to print json value to string", K(ret), K(i), K(is_pretty), K(depth)); } } @@ -3823,7 +3824,7 @@ int ObIJsonBase::print_opaque(ObJsonBuffer &j_buf, uint64_t depth, bool is_quote // base64::typeXX: if (OB_FAIL(base64_buf.append("base64:type"))) { LOG_WARN("fail to append \" base64:type \"", K(ret), K(depth)); - } else if (OB_FAIL(base64_buf.append(field_buf, field_len))) { + } else if (OB_FAIL(base64_buf.append(field_buf, field_len, 0))) { LOG_WARN("fail to append field type", K(ret), K(depth), K(f_type)); } else if (OB_FAIL(base64_buf.append(":"))) { LOG_WARN("fail to append \":\"", K(ret), K(depth)); @@ -3847,7 +3848,7 @@ int ObIJsonBase::print_opaque(ObJsonBuffer &j_buf, uint64_t depth, bool is_quote base64_buf.length()))) { LOG_WARN("fail to add double quote", K(ret), K(depth), K(f_type), K(base64_buf)); } - } else if (OB_FAIL(j_buf.append(base64_buf.ptr(), base64_buf.length()))) { + } else if (OB_FAIL(j_buf.append(base64_buf.ptr(), base64_buf.length(), 0))) { LOG_WARN("fail to append base64_buf", K(ret), K(depth), K(f_type), K(base64_buf)); } } @@ -3858,138 +3859,141 @@ int ObIJsonBase::print_opaque(ObJsonBuffer &j_buf, uint64_t depth, bool is_quote return ret; } -int ObIJsonBase::print(ObJsonBuffer &j_buf, bool is_quoted, bool is_pretty, uint64_t depth) const +int ObIJsonBase::print(ObJsonBuffer &j_buf, bool is_quoted, uint64_t reserve_len, bool is_pretty, uint64_t depth) const { INIT_SUCC(ret); ObJsonNodeType j_type = json_type(); - - // consistent with mysql 5.7 - // in mysql 8.0, varstring is handled as json string, obvarchartype is considered as varstring. - switch (j_type) { - case ObJsonNodeType::J_DATE: - case ObJsonNodeType::J_TIME: - case ObJsonNodeType::J_DATETIME: - case ObJsonNodeType::J_TIMESTAMP: - case ObJsonNodeType::J_ORACLEDATE: - case ObJsonNodeType::J_ODATE: - case ObJsonNodeType::J_OTIMESTAMP: - case ObJsonNodeType::J_OTIMESTAMPTZ: { - if (OB_FAIL(print_jtime(j_buf, is_quoted))) { - LOG_WARN("fail to change jtime to string", K(ret), K(is_quoted), K(is_pretty), K(depth)); - } - break; - } - - case ObJsonNodeType::J_ARRAY: { - ++depth; - if (OB_FAIL(SMART_CALL(print_array(j_buf, depth, is_pretty)))) { - LOG_WARN("fail to change jarray to string", K(ret), K(is_quoted), K(is_pretty), K(depth)); - } - break; - } - - case ObJsonNodeType::J_OBJECT: { - ++depth; - if (OB_FAIL(SMART_CALL(print_object(j_buf, depth, is_pretty)))) { - LOG_WARN("fail to print object to string", K(ret), K(depth), K(j_type), K(is_pretty)); - } - break; - } - - case ObJsonNodeType::J_BOOLEAN: { - if (get_boolean() ? OB_FAIL(j_buf.append("true", sizeof("true") - 1)) : - OB_FAIL(j_buf.append("false", sizeof("false") - 1))) { - LOG_WARN("fail to append boolean", K(ret), K(get_boolean()), K(j_type)); - } - break; - } - - case ObJsonNodeType::J_DECIMAL: - case ObJsonNodeType::J_ODECIMAL: { - if (OB_FAIL(print_decimal(j_buf))) { - LOG_WARN("fail to print decimal to string", K(ret), K(depth), K(j_type)); - } - break; - } - - case ObJsonNodeType::J_DOUBLE: - case ObJsonNodeType::J_ODOUBLE: { - if (OB_FAIL(print_double(j_buf))) { - LOG_WARN("fail to print double to string", K(ret), K(depth), K(j_type)); - } - break; - } - - case ObJsonNodeType::J_OFLOAT: { - if (OB_FAIL(print_float(j_buf))) { - LOG_WARN("fail to print float to string", K(ret), K(depth), K(j_type)); - } - break; - } - - case ObJsonNodeType::J_NULL: { - if (!(this)->is_real_json_null(this) && OB_FAIL(j_buf.append("", 0))) { - LOG_WARN("fail to append NULL upper string to buffer", K(ret), K(j_type)); - } else if ((this)->is_real_json_null(this) && OB_FAIL(j_buf.append("null", sizeof("null") - 1))) { - LOG_WARN("fail to append null string to buffer", K(ret), K(j_type)); - } - break; - } - - case ObJsonNodeType::J_OPAQUE: { - if (OB_FAIL(print_opaque(j_buf, depth, is_quoted))) { - LOG_WARN("fail to print opaque to string", K(ret), K(depth), K(j_type), K(is_quoted)); - } - break; - } - - case ObJsonNodeType::J_STRING: - case ObJsonNodeType::J_OBINARY: - case ObJsonNodeType::J_OOID: - case ObJsonNodeType::J_ORAWHEX: - case ObJsonNodeType::J_ORAWID: - case ObJsonNodeType::J_ODAYSECOND: - case ObJsonNodeType::J_OYEARMONTH: { - uint64_t data_len = get_data_length(); - const char *data = get_data(); - if (is_quoted && data_len == 0) { - if (OB_FAIL(j_buf.append("\"\"", 2))) { - LOG_WARN("fail to append empty string", K(ret), K(j_type), K(is_quoted)); + if (reserve_len > 0 && OB_FAIL(j_buf.reserve(reserve_len * 1.2))) { + LOG_WARN("failed to reserve j_str", K(ret), K(reserve_len)); + } else { + // consistent with mysql 5.7 + // in mysql 8.0, varstring is handled as json string, obvarchartype is considered as varstring. + switch (j_type) { + case ObJsonNodeType::J_DATE: + case ObJsonNodeType::J_TIME: + case ObJsonNodeType::J_DATETIME: + case ObJsonNodeType::J_TIMESTAMP: + case ObJsonNodeType::J_ORACLEDATE: + case ObJsonNodeType::J_ODATE: + case ObJsonNodeType::J_OTIMESTAMP: + case ObJsonNodeType::J_OTIMESTAMPTZ: { + if (OB_FAIL(print_jtime(j_buf, is_quoted))) { + LOG_WARN("fail to change jtime to string", K(ret), K(is_quoted), K(is_pretty), K(depth)); } - } else if (OB_ISNULL(data) && data_len != 0) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("data is null", K(ret), K(data_len)); - } else if (OB_FAIL(ObJsonBaseUtil::append_string(j_buf, is_quoted, data, data_len))) { - // if data is null, data_len is 0, it is an empty string - LOG_WARN("fail to append string", K(ret), K(j_type), K(is_quoted)); + break; } - break; - } - case ObJsonNodeType::J_INT: - case ObJsonNodeType::J_OINT: { - char tmp_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; - int64_t len = ObFastFormatInt::format_signed(get_int(), tmp_buf); - if (OB_FAIL(j_buf.append(tmp_buf, len))) { - LOG_WARN("fail to append json int to buffer", K(ret), K(get_int()), K(len), K(j_type)); + case ObJsonNodeType::J_ARRAY: { + ++depth; + if (OB_FAIL(SMART_CALL(print_array(j_buf, depth, is_pretty)))) { + LOG_WARN("fail to change jarray to string", K(ret), K(is_quoted), K(is_pretty), K(depth)); + } + break; } - break; - } - case ObJsonNodeType::J_UINT: - case ObJsonNodeType::J_OLONG: { - char tmp_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; - int64_t len = ObFastFormatInt::format_unsigned(get_uint(), tmp_buf); - if (OB_FAIL(j_buf.append(tmp_buf, len))) { - LOG_WARN("fail to append json uint to buffer", K(ret), K(get_uint()), K(len), K(j_type)); + case ObJsonNodeType::J_OBJECT: { + ++depth; + if (OB_FAIL(SMART_CALL(print_object(j_buf, depth, is_pretty)))) { + LOG_WARN("fail to print object to string", K(ret), K(depth), K(j_type), K(is_pretty)); + } + break; } - break; - } - default: { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("undefined json node type", K(ret), K(j_type)); - break; + case ObJsonNodeType::J_BOOLEAN: { + if (get_boolean() ? OB_FAIL(j_buf.append("true", sizeof("true") - 1, 0)) : + OB_FAIL(j_buf.append("false", sizeof("false") - 1, 0))) { + LOG_WARN("fail to append boolean", K(ret), K(get_boolean()), K(j_type)); + } + break; + } + + case ObJsonNodeType::J_DECIMAL: + case ObJsonNodeType::J_ODECIMAL: { + if (OB_FAIL(print_decimal(j_buf))) { + LOG_WARN("fail to print decimal to string", K(ret), K(depth), K(j_type)); + } + break; + } + + case ObJsonNodeType::J_DOUBLE: + case ObJsonNodeType::J_ODOUBLE: { + if (OB_FAIL(print_double(j_buf))) { + LOG_WARN("fail to print double to string", K(ret), K(depth), K(j_type)); + } + break; + } + + case ObJsonNodeType::J_OFLOAT: { + if (OB_FAIL(print_float(j_buf))) { + LOG_WARN("fail to print float to string", K(ret), K(depth), K(j_type)); + } + break; + } + + case ObJsonNodeType::J_NULL: { + if (!(this)->is_real_json_null(this) && OB_FAIL(j_buf.append("", 0, 0))) { + LOG_WARN("fail to append NULL upper string to buffer", K(ret), K(j_type)); + } else if ((this)->is_real_json_null(this) && OB_FAIL(j_buf.append("null", sizeof("null") - 1, 0))) { + LOG_WARN("fail to append null string to buffer", K(ret), K(j_type)); + } + break; + } + + case ObJsonNodeType::J_OPAQUE: { + if (OB_FAIL(print_opaque(j_buf, depth, is_quoted))) { + LOG_WARN("fail to print opaque to string", K(ret), K(depth), K(j_type), K(is_quoted)); + } + break; + } + + case ObJsonNodeType::J_STRING: + case ObJsonNodeType::J_OBINARY: + case ObJsonNodeType::J_OOID: + case ObJsonNodeType::J_ORAWHEX: + case ObJsonNodeType::J_ORAWID: + case ObJsonNodeType::J_ODAYSECOND: + case ObJsonNodeType::J_OYEARMONTH: { + uint64_t data_len = get_data_length(); + const char *data = get_data(); + if (is_quoted && data_len == 0) { + if (OB_FAIL(j_buf.append("\"\"", 2, 0))) { + LOG_WARN("fail to append empty string", K(ret), K(j_type), K(is_quoted)); + } + } else if (OB_ISNULL(data) && data_len != 0) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("data is null", K(ret), K(data_len)); + } else if (OB_FAIL(ObJsonBaseUtil::append_string(j_buf, is_quoted, data, data_len))) { + // if data is null, data_len is 0, it is an empty string + LOG_WARN("fail to append string", K(ret), K(j_type), K(is_quoted)); + } + break; + } + + case ObJsonNodeType::J_INT: + case ObJsonNodeType::J_OINT: { + char tmp_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; + int64_t len = ObFastFormatInt::format_signed(get_int(), tmp_buf); + if (OB_FAIL(j_buf.append(tmp_buf, len, 0))) { + LOG_WARN("fail to append json int to buffer", K(ret), K(get_int()), K(len), K(j_type)); + } + break; + } + + case ObJsonNodeType::J_UINT: + case ObJsonNodeType::J_OLONG: { + char tmp_buf[ObFastFormatInt::MAX_DIGITS10_STR_SIZE] = {0}; + int64_t len = ObFastFormatInt::format_unsigned(get_uint(), tmp_buf); + if (OB_FAIL(j_buf.append(tmp_buf, len, 0))) { + LOG_WARN("fail to append json uint to buffer", K(ret), K(get_uint()), K(len), K(j_type)); + } + break; + } + + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("undefined json node type", K(ret), K(j_type)); + break; + } } } @@ -4809,26 +4813,6 @@ int ObIJsonBase::compare(const ObIJsonBase &other, int &res, bool is_path) const } -uint32_t ObIJsonBase::depth() -{ - INIT_SUCC(ret); - uint32_t depth = 0; - - if (is_bin()) { - ObArenaAllocator allocator; - ObIJsonBase *j_tree = NULL; - if (OB_FAIL(ObJsonBaseFactory::transform(&allocator, this, ObJsonInType::JSON_TREE, j_tree))) { - LOG_WARN("fail to transform to tree", K(ret)); - } else { - depth = j_tree->depth(); - } - } else { - depth = static_cast(this)->depth(); - } - - return depth; -} - int ObIJsonBase::get_location(ObJsonBuffer &path) { INIT_SUCC(ret); @@ -6297,15 +6281,16 @@ int ObJsonBaseUtil::append_newline_and_indent(ObJsonBuffer &j_buf, uint64_t leve { // Append newline and two spaces per indentation level. INIT_SUCC(ret); + uint64_t reserve_size = level << 1; if (OB_FAIL(j_buf.append("\n"))) { LOG_WARN("fail to append newline to buffer", K(ret), K(level)); - } else if (OB_FAIL(j_buf.reserve(level * 2))) { + } else if (OB_FAIL(j_buf.reserve(reserve_size))) { LOG_WARN("fail to reserve memory for buffer", K(ret), K(level)); } else { - char str[level * 2]; - MEMSET(str, ' ', level * 2); - if (OB_FAIL(j_buf.append(str, level * 2))) { + char str[reserve_size]; + MEMSET(str, ' ', reserve_size); + if (OB_FAIL(j_buf.append(str, reserve_size, 0))) { LOG_WARN("fail to append space to buffer", K(ret), K(level)); } } @@ -6359,7 +6344,7 @@ int ObJsonBaseUtil::escape_character(char c, ObJsonBuffer &j_buf) case '"': case '\\': { char str[1] = {c}; - if (OB_FAIL(j_buf.append(str, 1))) { + if (OB_FAIL(j_buf.append(str, 1, 0))) { LOG_WARN("fail to append c to j_buf", K(ret), K(c)); } break; @@ -6371,11 +6356,11 @@ int ObJsonBaseUtil::escape_character(char c, ObJsonBuffer &j_buf) static char _dig_vec_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; char high[1] = {_dig_vec_lower[(c & 0xf0) >> 4]}; char low[1] = {_dig_vec_lower[(c & 0x0f)]}; - if (OB_FAIL(j_buf.append("u00", 3))) { + if (OB_FAIL(j_buf.append("u00", 3, 0))) { LOG_WARN("fail to append \"u00\" to j_buf", K(ret)); - } else if (OB_FAIL(j_buf.append(high, 1))) { + } else if (OB_FAIL(j_buf.append(high, 1, 0))) { LOG_WARN("fail to append four high bits to j_buf", K(ret)); - } else if (OB_FAIL(j_buf.append(low, 1))) { + } else if (OB_FAIL(j_buf.append(low, 1, 0))) { LOG_WARN("fail to append four low bits to j_buf", K(ret)); } break; @@ -6416,7 +6401,7 @@ int ObJsonBaseUtil::add_double_quote(ObJsonBuffer &j_buf, const char *cptr, uint // Most characters do not need to be escaped. // Append the characters that do not need to be escaped - if (OB_FAIL(j_buf.append(cptr, next_special - cptr))) { + if (OB_FAIL(j_buf.append(cptr, next_special - cptr, 0))) { LOG_WARN("fail to append common segments to j_buf", K(ret), K(length), K(next_special - cptr)); break; @@ -6452,7 +6437,7 @@ int ObJsonBaseUtil::append_string(ObJsonBuffer &j_buf, bool is_quoted, LOG_WARN("fail to add double quote", K(ret), K(length)); } } else { - if (OB_FAIL(j_buf.append(data, length))) { + if (OB_FAIL(j_buf.append(data, length, 0))) { LOG_WARN("fail to append data", K(ret), K(length)); } } 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 d0fdca0da..f87191e87 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.h +++ b/deps/oblib/src/lib/json_type/ob_json_base.h @@ -309,7 +309,7 @@ public: // @param [in] is_pretty Whether from JSON_PRETTY function or not. // @param [in] depth The depth of json tree. // @return Returns OB_SUCCESS on success, error code otherwise. - virtual int print(ObJsonBuffer &j_buf, bool is_quoted, + virtual int print(ObJsonBuffer &j_buf, bool is_quoted, uint64_t reserve_len = 0, bool is_pretty = false, uint64_t depth = 0) const; // calculate json hash value @@ -330,7 +330,7 @@ public: // Get depth of current json document. // // @return uint32_t. - virtual uint32_t depth(); + virtual uint32_t depth() const = 0; // Returns a string in json path form from the root node to the current location. // 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 1f4a52468..354875d3f 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_bin.cpp @@ -653,6 +653,37 @@ int ObJsonBinSerializer::serialize_json_decimal(ObJsonDecimal *json_dec, ObJsonB return ret; } +int ObJsonBinSerializer::serialize_json_double(double value, ObJsonBuffer &result) +{ + INIT_SUCC(ret); + if (isnan(value) || isinf(value)) { + ret = OB_INVALID_NUMERIC; + LOG_WARN("invalid float value", K(ret), K(value)); + } else if (OB_FAIL(result.append(reinterpret_cast(&value), sizeof(double), 0))) { + LOG_WARN("failed to append float json obj", K(ret)); + } + return ret; +} + +int ObJsonBinSerializer::serialize_json_string(ObJBVerType vertype, const ObString &value, ObJsonBuffer &result) +{ + INIT_SUCC(ret); + int64_t str_len_size = serialization::encoded_length_vi64(value.length()); + int64_t pos = result.length() + sizeof(uint8_t); + if (OB_FAIL(result.append(reinterpret_cast(&vertype), sizeof(uint8_t), 0))) { + LOG_WARN("failed to serialize type for str json obj", K(ret), K(str_len_size)); + } else if (OB_FAIL(result.reserve(str_len_size))) { + LOG_WARN("failed to reserver serialize size for str json obj", K(ret), K(str_len_size)); + } else if (OB_FAIL(serialization::encode_vi64(result.ptr(), result.capacity(), pos, value.length()))) { + LOG_WARN("failed to serialize for str json obj", K(ret), K(pos), K(value.length())); + } else if (OB_FAIL(result.set_length(pos))) { + LOG_WARN("failed to update len for str json obj", K(ret), K(pos)); + } else if (OB_FAIL(result.append(value.ptr(), value.length(), 0))) { + LOG_WARN("failed to append string json obj value", K(ret)); + } + return ret; +} + int ObJsonBinSerializer::serialize_json_value(ObJsonNode *json_tree, ObJsonBuffer &result) { INIT_SUCC(ret); @@ -693,11 +724,8 @@ int ObJsonBinSerializer::serialize_json_value(ObJsonNode *json_tree, ObJsonBuffe case ObJsonNodeType::J_ODOUBLE: { const ObJsonDouble *d = static_cast(json_tree); double value = d->value(); - 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)); + if (OB_FAIL(ObJsonBinSerializer::serialize_json_double(value, result))) { + LOG_WARN("failed to serialize json double", K(ret), K(value)); } break; } @@ -720,19 +748,9 @@ int ObJsonBinSerializer::serialize_json_value(ObJsonNode *json_tree, ObJsonBuffe case ObJsonNodeType::J_OYEARMONTH: case ObJsonNodeType::J_STRING: { // [type][length][string] const ObJsonString *sub_obj = static_cast(json_tree); - int64_t ser_len = serialization::encoded_length_vi64(sub_obj->length()); - int64_t pos = result.length() + sizeof(uint8_t); ObJBVerType vertype = ObJsonVerType::get_json_vertype(json_tree->json_type()); - if (OB_FAIL(result.append(reinterpret_cast(&vertype), sizeof(uint8_t)))) { - LOG_WARN("failed to serialize type for str json obj", K(ret), K(ser_len)); - } else if (OB_FAIL(result.reserve(ser_len))) { - LOG_WARN("failed to reserver serialize size for str json obj", K(ret), K(ser_len)); - } else if (OB_FAIL(serialization::encode_vi64(result.ptr(), result.capacity(), pos, sub_obj->length()))) { - LOG_WARN("failed to serialize for str json obj", K(ret), K(ser_len)); - } else if (OB_FAIL(result.set_length(pos))) { - LOG_WARN("failed to update len for str json obj", K(ret), K(pos)); - } else if (OB_FAIL(result.append(sub_obj->value().ptr(), sub_obj->length()))) { - LOG_WARN("failed to append string json obj value", K(ret)); + if (OB_FAIL(ObJsonBinSerializer::serialize_json_string(vertype, sub_obj->value(), result))) { + LOG_WARN("failed to serialize json string", K(ret), K(sub_obj->value())); } break; } @@ -950,7 +968,7 @@ int ObJsonBinSerializer::serialize(ObJsonNode *json_tree, ObString &data) if (root_type == ObJsonNodeType::J_ARRAY || root_type == ObJsonNodeType::J_OBJECT) { if (OB_FAIL(ObJsonBin::add_doc_header_v0(result))) { LOG_WARN("add_doc_header_v0 fail", K(ret)); - } else if (OB_FAIL(serialize_json_value(json_tree, result))) { + } else if (OB_FAIL(SMART_CALL(serialize_json_value(json_tree, result)))) { LOG_WARN("serialize json tree fail", K(ret), K(root_type)); } else if (OB_FAIL(ObJsonBin::set_doc_header_v0(result, result.length()))) { LOG_WARN("set_doc_header_v0 fail", K(ret)); @@ -960,7 +978,7 @@ int ObJsonBinSerializer::serialize(ObJsonNode *json_tree, ObString &data) if (!ObJsonVerType::is_opaque_or_string(ver_type) && OB_FAIL(result.append(reinterpret_cast(&ver_type), sizeof(uint8_t)))) { LOG_WARN("failed to serialize json tree at append used size", K(ret), K(result.length())); - } else if (OB_FAIL(serialize_json_value(json_tree, result))) { // do recursion + } else if (OB_FAIL(SMART_CALL(serialize_json_value(json_tree, result)))) { // do recursion LOG_WARN("failed to serialize json tree at recursion", K(ret)); } } @@ -1458,7 +1476,7 @@ int ObJsonBin::deserialize_json_object_v0(ObJsonObject *object) LOG_WARN("ob_write_string fail", K(ret), K(i), K(ori_key)); } else if (OB_FAIL(get_value(i, child_bin))) { LOG_WARN("get child value fail", K(ret)); - } else if (OB_FAIL(child_bin.deserialize_json_value(node))) { + } else if (OB_FAIL(SMART_CALL(child_bin.deserialize_json_value(node)))) { LOG_WARN("deserialize child node fail", K(ret), K(i), K(child_bin)); } else if (OB_FAIL(object->add(key, node, false, true, false, is_schema_))) { LOG_WARN("add node to obj fail", K(ret), K(i)); @@ -3782,6 +3800,28 @@ int ObJsonBin::reset() return ret; } +uint32_t ObJsonBin::depth() const +{ + INIT_SUCC(ret); + uint32_t max_child = 0; + if (is_json_scalar(meta_.json_type())) { + max_child = 0; + } else { + uint64_t count = meta_.element_count(); + uint64_t value_entry_start = meta_.value_offset_start_; + for (uint64_t i = 0; OB_SUCC(ret) && i < count; i++) { + ObJsonBin value(allocator_); + if (OB_FAIL(this->get_value(i, value))) { + LOG_WARN("get value failed.", K(ret), K(i), K(count)); + } else { + max_child = max(max_child, value.depth()); + } + } + } + + return max_child + 1; +} + int ObJsonBin::init_meta() { INIT_SUCC(ret); @@ -4334,22 +4374,22 @@ int ObJsonVar::append_var(uint64_t var, uint8_t type, ObJsonBuffer &result) switch (size) { case JBLS_UINT8: { uint8_t var_trans = static_cast(var); - ret = result.append(reinterpret_cast(&var_trans), sizeof(uint8_t)); + ret = result.append(reinterpret_cast(&var_trans), sizeof(uint8_t), 0); break; } case JBLS_UINT16: { uint16_t var_trans = static_cast(var); - ret = result.append(reinterpret_cast(&var_trans), sizeof(uint16_t)); + ret = result.append(reinterpret_cast(&var_trans), sizeof(uint16_t), 0); break; } case JBLS_UINT32: { uint32_t var_trans = static_cast(var); - ret = result.append(reinterpret_cast(&var_trans), sizeof(uint32_t)); + ret = result.append(reinterpret_cast(&var_trans), sizeof(uint32_t), 0); break; } case JBLS_UINT64: { uint64_t var_trans = static_cast(var); - ret = result.append(reinterpret_cast(&var_trans), sizeof(uint64_t)); + ret = result.append(reinterpret_cast(&var_trans), sizeof(uint64_t), 0); break; } default: { @@ -5149,7 +5189,7 @@ int ObJsonBinMeta::to_header(ObJsonBuffer &buffer) LOG_WARN("type not object or array", K(ret), "json type", json_type()); } else if (OB_FAIL(to_header(header))) { LOG_WARN("to_header fail", K(ret)); - } else if (OB_FAIL(buffer.append(reinterpret_cast(&header), sizeof(header)))) { + } else if (OB_FAIL(buffer.append(reinterpret_cast(&header), sizeof(header), 0))) { LOG_WARN("append header to buffer fail", K(ret)); } else if (OB_FAIL(ObJsonVar::append_var(element_count(), element_count_var_type(), buffer))) { LOG_WARN("failed to append array header member count", K(ret)); diff --git a/deps/oblib/src/lib/json_type/ob_json_bin.h b/deps/oblib/src/lib/json_type/ob_json_bin.h index 0fc7750f0..223f1e5f5 100644 --- a/deps/oblib/src/lib/json_type/ob_json_bin.h +++ b/deps/oblib/src/lib/json_type/ob_json_bin.h @@ -597,6 +597,12 @@ 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; + int set_key_entry(int index, uint64_t key_offset, uint64_t key_len, bool check=true); + int set_value_entry(int index, uint64_t value_offset, uint8_t value_type, bool check=true); + int set_current(const ObString &data, int64_t offset); + int set_obj_size(uint64_t obj_size); + static int add_doc_header_v0(ObJsonBuffer &buffer); + static int set_doc_header_v0(ObJsonBuffer &buffer,int64_t extend_seg_offset); public: static OB_INLINE ObJBVerType get_null_vertype() { return J_NULL_V0; } static OB_INLINE ObJBVerType get_decimal_vertype() { return J_DECIMAL_V0; } @@ -632,8 +638,6 @@ public: private: static OB_INLINE bool is_forward_v0(uint8_t type) { return J_FORWARD_V0 == type; } static OB_INLINE bool is_doc_header_v0(uint8_t type) { return J_DOC_HEADER_V0 == type; } - static int add_doc_header_v0(ObJsonBuffer &buffer); - static int set_doc_header_v0(ObJsonBuffer &buffer,int64_t extend_seg_offset); static int set_doc_header_v0(ObString &buffer, int64_t extend_seg_offset); public: TO_STRING_KV( @@ -838,6 +842,7 @@ public: // release resource void destroy(); void set_is_schema(bool is_schema) {is_schema_ = is_schema;} + OB_INLINE uint32_t depth() const override; virtual int reset(); OB_INLINE const ObILobCursor* get_cursor() const { return cursor_; } OB_INLINE ObILobCursor* get_cursor() { return cursor_; } @@ -986,15 +991,12 @@ private: int get_value_entry(int index, uint64_t &value_offset, uint8_t &value_type) const; int64_t get_value_entry_size() const; int get_value(int index, ObJsonBin &value) const; - int set_key_entry(int index, uint64_t key_offset, uint64_t key_len, bool check=true); - int set_value_entry(int index, uint64_t value_offset, uint8_t value_type, bool check=true); OB_INLINE uint64_t get_value_entry_offset(int index) const { return meta_.get_value_entry_offset(index); } OB_INLINE uint64_t get_key_entry_offset(int index) const { return meta_.get_key_entry_offset(index); } OB_INLINE uint8_t entry_var_type() const { return meta_.entry_var_type(); } OB_INLINE uint64_t entry_var_size() const { return meta_.entry_var_size(); } OB_INLINE uint64_t obj_size() const { return meta_.obj_size(); } - int set_obj_size(uint64_t obj_size); OB_INLINE uint64_t obj_size_var_size() const { return meta_.obj_size_var_size(); } OB_INLINE uint64_t get_obj_size_offset() const { return meta_.get_obj_size_offset(); } OB_INLINE uint8_t obj_size_var_type() const { return meta_.obj_size_var_type(); } @@ -1023,8 +1025,6 @@ private: int record_insert_offset(int index, int64_t value_offset, int64_t value_len, uint8_t value_type); int get_json_path_at_iter(int index, ObString &path) const; - int set_current(const ObString &data, int64_t offset); - int parse_type_(); int skip_type_byte_(); int parse_doc_header_(); @@ -1127,6 +1127,8 @@ public: public: static int serialize_json_integer(int64_t value, ObJsonBuffer &result); static int serialize_json_decimal(ObJsonDecimal *json_dec, ObJsonBuffer &result); + static int serialize_json_double(double value, ObJsonBuffer &result); + static int serialize_json_string(ObJBVerType vertype, const ObString &value, ObJsonBuffer &result); private: ObIAllocator *allocator_; diff --git a/deps/oblib/src/lib/ob_name_def.h b/deps/oblib/src/lib/ob_name_def.h index 9ac06ef8a..1c2c8c0e5 100644 --- a/deps/oblib/src/lib/ob_name_def.h +++ b/deps/oblib/src/lib/ob_name_def.h @@ -1098,8 +1098,11 @@ #define N_XML_ATTRIBUTES "xmlattributes" #define N_EXTRACTVALUE "extractvalue" #define N_EXTRACT_XML "extract_xml" +#define N_EXISTSNODE_XML "existsnode_xml" #define N_XMLSERIALIZE "xmlserialize" #define N_XMLCAST "xmlcast" +#define N_XML_CONCAT "xmlconcat" +#define N_XML_FOREST "xmlforest" #define N_UPDATEXML "updatexml" #define N_INSERTCHILDXML "insertchildxml" #define N_XMLSEQUENCE "xmlsequence" @@ -1189,4 +1192,6 @@ #define N_RB_SELECT "rb_select" #define N_GET_MYSQL_ROUTINE_PARAMETER_TYPE_STR "get_mysql_routine_parameter_type_str" #define N_ORA_LOGIN_USER "ora_login_user" +#define N_PRIV_ST_GEOHASH "_st_geohash" +#define N_PRIV_ST_MAKEPOINT "_st_makepoint" #endif //OCEANBASE_LIB_OB_NAME_DEF_H_ diff --git a/deps/oblib/src/lib/string/ob_string_buffer.cpp b/deps/oblib/src/lib/string/ob_string_buffer.cpp index 498d3cfb2..f194cdec7 100644 --- a/deps/oblib/src/lib/string/ob_string_buffer.cpp +++ b/deps/oblib/src/lib/string/ob_string_buffer.cpp @@ -58,10 +58,10 @@ int ObStringBuffer::get_result_string(ObString &buffer) int ObStringBuffer::append(const char *str) { - return append(str, NULL == str ? 0 : strlen(str)); + return append(str, NULL == str ? 0 : strlen(str), 0); } -int ObStringBuffer::append(const char *str, const uint64_t len, int8_t index) +int ObStringBuffer::append(const char *str, const uint64_t len, int8_t flag) { INIT_SUCC(ret); if (OB_ISNULL(allocator_)) { @@ -77,7 +77,7 @@ int ObStringBuffer::append(const char *str, const uint64_t len, int8_t index) if (need_len < len_) { ret = OB_SIZE_OVERFLOW; LOG_WARN("size over flow", K(ret), K(need_len), K(len_)); - } else if (OB_FAIL(reserve(index == -1 ? need_len : len))) { + } else if (OB_FAIL(reserve(flag == -1 ? need_len : len))) { LOG_WARN("reserve data failed", K(ret), K(need_len), K(len_)); } else { MEMCPY(data_ + len_, str, len); @@ -90,9 +90,9 @@ int ObStringBuffer::append(const char *str, const uint64_t len, int8_t index) return ret; } -int ObStringBuffer::append(const ObString &str) +int ObStringBuffer::append(const ObString &str, int8_t flag) { - return append(str.ptr(), str.length()); + return append(str.ptr(), str.length(), flag); } int ObStringBuffer::reserve(const uint64_t len) diff --git a/deps/oblib/src/lib/string/ob_string_buffer.h b/deps/oblib/src/lib/string/ob_string_buffer.h index d3a6107b2..11ddd97d4 100644 --- a/deps/oblib/src/lib/string/ob_string_buffer.h +++ b/deps/oblib/src/lib/string/ob_string_buffer.h @@ -36,8 +36,14 @@ public: int get_result_string(ObString &buffer); int append(const char *str); - int append(const char *str, const uint64_t len, int8_t index = -1); - int append(const ObString &str); + + // Append data later + // @param [in] flag reserves flag bits for other subsequent expansions + // @return Returns OB_SUCCESS on success, error code otherwise. + // When the flag is the default value -1, the size of len_*2 + len is used each time to expand the memory. + // If the data is large, the default value is not used, and the memory application size is len_ + len. + int append(const char *str, const uint64_t len, int8_t flag = -1); + int append(const ObString &str, int8_t flag = -1); int reserve(const uint64_t len); int extend(const uint64_t len); diff --git a/deps/oblib/src/lib/xml/ob_binary_aggregate.cpp b/deps/oblib/src/lib/xml/ob_binary_aggregate.cpp index 2cc8e820e..e05ffd951 100644 --- a/deps/oblib/src/lib/xml/ob_binary_aggregate.cpp +++ b/deps/oblib/src/lib/xml/ob_binary_aggregate.cpp @@ -231,7 +231,7 @@ int ObBinAggSerializer::add_element_xml(ObXmlBin *xml_bin) 0 : key_info_.at(current_count - 1)->offset_ + key_info_.at(current_count -1)->key_len_; if (OB_FAIL(key_info_.push_back(key_info))) { - LOG_WARN("failed to append key info.", K(ret)); + LOG_WARN("failed to push back key info into array.", K(ret), K(key_info)); } else if (OB_FAIL(key_.append(key.ptr(), key.length()))) { LOG_WARN("failed to append key into key_", K(ret), K(key)); } @@ -517,7 +517,9 @@ int ObBinAggSerializer::construct_header() int64_t buff_length = buff_.length(); if (type_ == AGG_XML) { buff_length = buff_.length(); - doc_header_.serialize(doc_header_buff); + if (OB_FAIL(doc_header_.serialize(doc_header_buff))) { + LOG_WARN("failed to serialize doc header.", K(ret)); + } } int64_t total_size = ObBinAggSerializer::estimate_total(value_len_ + key_len_, @@ -526,7 +528,8 @@ int ObBinAggSerializer::construct_header() static_cast(header_type_), total_size, count_); - if (OB_FAIL(header_serializer.serialize())) { + if (OB_FAIL(ret)) { + } else if (OB_FAIL(header_serializer.serialize())) { LOG_WARN("header serialize failed.", K(ret)); } else if (OB_FALSE_IT(header_str = header_serializer.buffer()->string())) { } else if (OB_FAIL(buff_.reserve(total_size))) { @@ -577,16 +580,24 @@ void ObBinAggSerializer::set_value_entry_for_json(int64_t entry_idx, uint8_t ty *reinterpret_cast(write_buf) = type; } -void ObBinAggSerializer::set_key(int64_t key_offset, int64_t key_len) +int ObBinAggSerializer::set_key(int64_t key_offset, int64_t key_len) { + INIT_SUCC(ret); char* write_buf = key_.ptr() + key_offset; - buff_.append(write_buf, key_len); + if (OB_FAIL(buff_.append(write_buf, key_len, 0))) { + LOG_WARN("failed to append buff.", K(ret), K(buff_.length()), K(key_len)); + } + return ret; } -void ObBinAggSerializer::set_value(int64_t value_offset, int64_t value_len) +int ObBinAggSerializer::set_value(int64_t value_offset, int64_t value_len) { + INIT_SUCC(ret); char* write_buf = value_.ptr() + value_offset; - buff_.append(write_buf, value_len, 0); + if (OB_FAIL(buff_.append(write_buf, value_len, 0))) { + LOG_WARN("failed to append buff.", K(ret), K(buff_.length()), K(value_len)); + } + return ret; } void ObBinAggSerializer::set_xml_decl(ObString version, ObString encoding, uint16_t standalone) @@ -812,31 +823,35 @@ int ObBinAggSerializer::deal_last_unparsed() return ret; } -void ObBinAggSerializer::construct_key_and_value() +int ObBinAggSerializer::construct_key_and_value() { + INIT_SUCC(ret); if (!is_json_array()) { - for (int64_t i = 0; i < key_info_.count(); i++) { + for (int64_t i = 0; OB_SUCC(ret) && i < key_info_.count(); i++) { ObAggBinKeyInfo *key_info = key_info_.at(i); if ((has_unique_flag() && key_info->unparsed_)) { // do nothing - } else { - set_key(key_info->offset_, key_info->key_len_); + } else if (OB_FAIL(set_key(key_info->offset_, key_info->key_len_))) { + LOG_WARN("failed to set key.", K(ret), K(key_info->offset_), K(key_info->key_len_)); } } } if (!has_unique_flag()) { - buff_.append(value_.ptr(), value_.length(), 0); + if (OB_FAIL(buff_.append(value_.ptr(), value_.length(), 0))) { + LOG_WARN("failed to append value into buff_.", K(ret), K(value_.length())); + } } else { - for (int64_t i = 0; i < key_info_.count(); i++) { + for (int64_t i = 0; OB_SUCC(ret) && i < key_info_.count(); i++) { ObAggBinKeyInfo *key_info = key_info_.at(i); if (key_info->unparsed_) { // do nothing - } else { - set_value(key_info->value_offset_, key_info->value_len_); + } else if (OB_FAIL(set_value(key_info->value_offset_, key_info->value_len_))) { + LOG_WARN("failed to set value", K(ret), K(key_info->value_offset_), K(key_info->value_len_)); } } } + return ret; } int ObBinAggSerializer::copy_and_reset(ObIAllocator* new_allocator, @@ -912,7 +927,7 @@ int ObBinAggSerializer::serialize() LOG_WARN("failed to construct header.", K(ret)); } else if (OB_FAIL(construct_meta())) { // construct meta_ LOG_WARN("failed to construct meta.", K(ret)); - } else if (OB_FALSE_IT(construct_key_and_value())) { // merge key_ and value_ + } else if (OB_FAIL(construct_key_and_value())) { // merge key_ and value_ } else if (OB_FAIL(rewrite_total_size())) { // write total LOG_WARN("failed to rewrite total size.", K(ret)); } diff --git a/deps/oblib/src/lib/xml/ob_binary_aggregate.h b/deps/oblib/src/lib/xml/ob_binary_aggregate.h index e6e16eddf..ed82ee150 100644 --- a/deps/oblib/src/lib/xml/ob_binary_aggregate.h +++ b/deps/oblib/src/lib/xml/ob_binary_aggregate.h @@ -87,7 +87,7 @@ public: private: int construct_meta(); - void construct_key_and_value(); + int construct_key_and_value(); int rewrite_total_size(); @@ -128,8 +128,8 @@ private: ObIAllocator* get_array_allocator() { return arr_allocator_ == nullptr ? allocator_ : arr_allocator_; } void set_value_entry_for_json(int64_t entry_idx, uint8_t type, int64_t value_offset); - void set_key(int64_t key_offset, int64_t key_len); - void set_value(int64_t value_offset, int64_t value_len); + int set_key(int64_t key_offset, int64_t key_len); + int set_value(int64_t value_offset, int64_t value_len); static int64_t estimate_total(int64_t base_length, int64_t count, int32_t type, int64_t xml_header_size = 4); static int text_serialize(ObString value, ObStringBuffer &res); static int text_deserialize(ObString value, ObStringBuffer &res); diff --git a/deps/oblib/src/lib/xml/ob_multi_mode_interface.cpp b/deps/oblib/src/lib/xml/ob_multi_mode_interface.cpp index aea88c252..332da1e11 100644 --- a/deps/oblib/src/lib/xml/ob_multi_mode_interface.cpp +++ b/deps/oblib/src/lib/xml/ob_multi_mode_interface.cpp @@ -174,6 +174,23 @@ int64_t ObIMulModeBase::get_serialize_size() return 0; } +int ObIMulModeBase::get_bin_size(uint64_t &size) +{ + INIT_SUCC(ret); + if (is_binary() && meta_.data_type_ == OB_XML_TYPE) { + ObXmlBin *bin = nullptr; + if (OB_ISNULL(bin = static_cast(this))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to cast to bin.", K(ret)); + } else if (bin->meta_.len_ != 0) { + size = bin->meta_.len_; + } else if (OB_NOT_NULL(bin->buffer_.get_allocator())) { + size = bin->buffer_.length(); + } + } + return ret; +} + int ObIMulModeBase::print(ObStringBuffer& x_buf, uint32_t format_flag, uint64_t depth, uint64_t size, ObCollationType charset) { INIT_SUCC(ret); @@ -313,7 +330,7 @@ int ObIMulModeBase::print_attr(ObStringBuffer& x_buf, uint32_t format_flag) if (OB_FAIL(ObXmlParserUtils::escape_xml_text(value, x_buf))) { LOG_WARN("fail to print text with escape char", K(ret), K(value)); } - } else if (OB_FAIL(x_buf.append(value))) { + } else if (OB_FAIL(x_buf.append(value, 0))) { LOG_WARN("fail to print value in attr", K(ret), K(value)); } @@ -348,7 +365,7 @@ int ObIMulModeBase::print_ns(ObStringBuffer& x_buf, uint32_t format_flag) if (OB_FAIL(ObXmlParserUtils::escape_xml_text(value, x_buf))) { LOG_WARN("fail to print text with escape char", K(ret), K(value)); } - } else if (OB_FAIL(x_buf.append(value))) { + } else if (OB_FAIL(x_buf.append(value, 0))) { LOG_WARN("fail to print value in ns", K(ret), K(value)); } @@ -372,12 +389,12 @@ int ObIMulModeBase::print_pi(ObStringBuffer& x_buf, uint32_t format_flag) LOG_WARN("fail to print =\" in attr", K(ret)); } else if (OB_FAIL(x_buf.append(" 0 && OB_FAIL(x_buf.reserve(reserve_size))) { + LOG_WARN("failed to reserve x_buf.", K(ret), K(reserve_size)); + } else if (!(format_flag & ObXmlFormatType::HIDE_PROLOG) && has_flags(XML_DECL_FLAG)) { if (OB_FAIL(x_buf.append(" 0 && OB_FAIL(x_buf.reserve(reserve_size))) { + LOG_WARN("failed to reserve x_buf.", K(ret), K(reserve_size)); + } else if (!(format_flag & ObXmlFormatType::HIDE_PROLOG) && has_flags(XML_DECL_FLAG)) { if (OB_FAIL(x_buf.append(" 0 && OB_FAIL(x_buf.reserve(reserve_size))) { + LOG_WARN("failed to reserve x_buf.", K(ret), K(reserve_size)); + } else if (with_encoding || with_version) { if (OB_FAIL(x_buf.append(""))) { LOG_WARN("fail to print ]]> in attr", K(ret)); @@ -668,7 +699,7 @@ int ObIMulModeBase::print_comment(ObStringBuffer& x_buf, uint32_t format_flag) LOG_WARN("fail to get value.", K(ret)); } else if (OB_FAIL(x_buf.append(""))) { LOG_WARN("fail to print --> in attr", K(ret)); @@ -686,7 +717,7 @@ int ObIMulModeBase::print_text(ObStringBuffer& x_buf, uint32_t format_flag) if (OB_FAIL(ObXmlParserUtils::escape_xml_text(value, x_buf))) { LOG_WARN("fail to print text with escape char", K(ret), K(value)); } - } else if (OB_FAIL(x_buf.append(value))) { + } else if (OB_FAIL(x_buf.append(value, 0))) { LOG_WARN("fail to print text", K(ret), K(value)); } return ret; diff --git a/deps/oblib/src/lib/xml/ob_multi_mode_interface.h b/deps/oblib/src/lib/xml/ob_multi_mode_interface.h index 8b6f15171..2faee7203 100644 --- a/deps/oblib/src/lib/xml/ob_multi_mode_interface.h +++ b/deps/oblib/src/lib/xml/ob_multi_mode_interface.h @@ -135,6 +135,7 @@ enum ObNodeDataType: int8_t { }; class ObIMulModeBase; +class ObXmlNode; struct ObNodeMetaData { ObNodeMetaData(ObNodeMemType m_type, ObNodeDataType data_type) : m_type_(m_type), @@ -371,6 +372,7 @@ public: * node type, json xml together enum */ virtual ObMulModeNodeType type() const = 0; + virtual int clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) { return OB_NOT_SUPPORTED; } bool is_binary() const { return meta_.m_type_ == BINARY_TYPE; } @@ -601,6 +603,8 @@ public: * virtual int to_time(int64_t &value) const = 0; * virtual int to_bit(uint64_t &value) const = 0; **/ +private: + int get_bin_size(uint64_t &size); protected: ObNodeMetaData meta_; diff --git a/deps/oblib/src/lib/xml/ob_xml_bin.cpp b/deps/oblib/src/lib/xml/ob_xml_bin.cpp index 6c2769bac..cfdcb2cca 100644 --- a/deps/oblib/src/lib/xml/ob_xml_bin.cpp +++ b/deps/oblib/src/lib/xml/ob_xml_bin.cpp @@ -49,10 +49,12 @@ int ObXmlElementBinHeader::serialize(ObStringBuffer& buffer) *reinterpret_cast(data + pos) = flags_; pos += sizeof(uint8_t); - buffer.set_length(pos); + if (OB_FAIL(buffer.set_length(pos))) { + LOG_WARN("failed to set length.", K(ret), K(pos)); + } uint32_t left = header_len - sizeof(uint8_t); - if (is_prefix_) { + if (OB_SUCC(ret) && is_prefix_) { if (OB_FAIL(serialization::encode_vi64(data, pos + left, pos, prefix_len_))) { LOG_WARN("failed to serialize for str xml obj", K(ret), K(prefix_len_size_)); } else if (OB_FAIL(buffer.set_length(pos))) { @@ -61,7 +63,9 @@ int ObXmlElementBinHeader::serialize(ObStringBuffer& buffer) LOG_WARN("failed to append string obj value", K(ret)); } else { pos += prefix_len_; - buffer.set_length(pos); + if (OB_FAIL(buffer.set_length(pos))) { + LOG_WARN("failed to set length.", K(ret), K(pos)); + } } } } @@ -138,7 +142,9 @@ int ObXmlAttrBinHeader::serialize(ObStringBuffer* buffer) LOG_WARN("failed to append string obj value", K(ret)); } } else { - buffer->set_length(pos); + if (OB_FAIL(buffer->set_length(pos))) { + LOG_WARN("failed to set length.", K(ret), K(pos)); + } } } @@ -408,8 +414,8 @@ int ObXmlTextSerializer::serialize() LOG_WARN("failed to reserver serialize size for str obj", K(ret), K(ser_len)); } else if (OB_FAIL(ObMulModeVar::set_var(type_, ObMulModeBinLenSize::MBL_UINT8, buffer_->ptr() + buffer_->length()))) { LOG_WARN("failed to set var", K(ret), K(type_)); - } else { - buffer_->set_length(buffer_->length() + header_len); + } else if (OB_FAIL(buffer_->set_length(buffer_->length() + header_len))) { + LOG_WARN("failed to set length.", K(ret), K(buffer_->length()), K(header_len)); } int64_t pos = buffer_->length(); @@ -542,21 +548,28 @@ ObXmlElementSerializer::ObXmlElementSerializer(ObIMulModeBase* root, ObStringBuf key_start_ = (value_entry_size_ + sizeof(uint8_t)) * size() + value_entry_start_; } -void ObXmlElementSerializer::set_index_entry(int64_t origin_index, int64_t sort_index) +int ObXmlElementSerializer::set_index_entry(int64_t origin_index, int64_t sort_index) { + INIT_SUCC(ret); int64_t offset = index_start_ + origin_index * header_.get_count_var_size(); char* write_buf = header_.buffer()->ptr() + offset; - ObMulModeVar::set_var(sort_index, header_.get_count_var_size_type(), write_buf); + return ObMulModeVar::set_var(sort_index, header_.get_count_var_size_type(), write_buf); } -void ObXmlElementSerializer::set_key_entry(int64_t entry_idx, int64_t key_offset, int64_t key_len) +int ObXmlElementSerializer::set_key_entry(int64_t entry_idx, int64_t key_offset, int64_t key_len) { + INIT_SUCC(ret); int64_t offset = key_entry_start_ + entry_idx * (header_.get_entry_var_size() * 2); char* write_buf = header_.buffer()->ptr() + offset; - ObMulModeVar::set_var(key_offset, header_.get_entry_var_size_type(), write_buf); - - write_buf += header_.get_entry_var_size(); - ObMulModeVar::set_var(key_len, header_.get_entry_var_size_type(), write_buf); + if (OB_FAIL(ObMulModeVar::set_var(key_offset, header_.get_entry_var_size_type(), write_buf))) { + LOG_WARN("failed to set var.", K(ret), K(key_offset)); + } else { + write_buf += header_.get_entry_var_size(); + if (OB_FAIL(ObMulModeVar::set_var(key_len, header_.get_entry_var_size_type(), write_buf))) { + LOG_WARN("failed to set var.", K(ret), K(key_len)); + } + } + return ret; } int ObXmlElementSerializer::reserve_meta() @@ -568,18 +581,19 @@ int ObXmlElementSerializer::reserve_meta() uint32_t reserve_size = key_start_ - index_start_; if (OB_FAIL(buffer.reserve(reserve_size))) { LOG_WARN("failed to reserve buffer.", K(ret), K(reserve_size), K(header_.start())); - } else { - buffer.set_length(pos + reserve_size); + } else if (OB_FAIL(buffer.set_length(pos + reserve_size))) { + LOG_WARN("failed to set length.", K(ret), K(pos + reserve_size)); } return ret; } -void ObXmlElementSerializer::set_value_entry(int64_t entry_idx, uint8_t type, int64_t value_offset) +int ObXmlElementSerializer::set_value_entry(int64_t entry_idx, uint8_t type, int64_t value_offset) { + INIT_SUCC(ret); int64_t offset = value_entry_start_ + entry_idx * (header_.get_entry_var_size() + sizeof(uint8_t)); char* write_buf = header_.buffer()->ptr() + offset; *reinterpret_cast(write_buf) = type; - ObMulModeVar::set_var(value_offset, header_.get_entry_var_size_type(), write_buf + sizeof(uint8_t)); + return ObMulModeVar::set_var(value_offset, header_.get_entry_var_size_type(), write_buf + sizeof(uint8_t)); } int ObXmlElementSerializer::serialize_child_key(const ObString& key, int64_t idx) @@ -590,9 +604,8 @@ int ObXmlElementSerializer::serialize_child_key(const ObString& key, int64_t idx if (OB_FAIL(buffer.append(key.ptr(), key.length()))) { LOG_WARN("failed to append key string.", K(ret), K(buffer.length()), K(key.length())); - } else { - // idx fill later - set_key_entry(idx, key_offset, key.length()); + } else if (OB_FAIL(set_key_entry(idx, key_offset, key.length()))) { // idx fill later + LOG_WARN("failed to set key entry", K(key_offset), K(key.length())); } return ret; @@ -628,8 +641,8 @@ int ObXmlElementSerializer::serialize_key(int arr_idx, int64_t depth) case M_CDATA: { if (OB_FAIL(serialize_child_key(cur->get_key(), g_idx))) { LOG_WARN("failed to serialize key string.", K(ret), K(cur->get_key().length()), K(buffer.length())); - } else { - set_index_entry( cur->get_index() + child_arr_[arr_idx].g_start_, g_idx); + } else if (OB_FAIL(set_index_entry( cur->get_index() + child_arr_[arr_idx].g_start_, g_idx))) { + LOG_WARN("failed to set index entry.", K(ret)); } break; } @@ -672,8 +685,8 @@ int ObXmlElementSerializer::serialize_value(int arr_idx, int64_t depth) ObXmlElementSerializer ele_serializer(cur, header_.buffer()); if (OB_FAIL(ele_serializer.serialize(depth + 1))) { LOG_WARN("failed to serialize element child", K(ret), K(buffer.length())); - } else { - set_value_entry(g_idx, cur_type, value_start); + } else if (OB_FAIL(set_value_entry(g_idx, cur_type, value_start))) { + LOG_WARN("failed to set value entry.", K(ret), K(value_start)); } break; } @@ -683,8 +696,8 @@ int ObXmlElementSerializer::serialize_value(int arr_idx, int64_t depth) ObXmlAttributeSerializer attr_serializer(cur, buffer); if (OB_FAIL(attr_serializer.serialize())) { LOG_WARN("failed to serialize attribute.", K(ret), K(cur_type), K(buffer.length())); - } else { - set_value_entry(g_idx, cur_type, value_start); + } else if (OB_FAIL(set_value_entry(g_idx, cur_type, value_start))) { + LOG_WARN("failed to set value entry.", K(ret), K(value_start)); } break; } @@ -694,8 +707,8 @@ int ObXmlElementSerializer::serialize_value(int arr_idx, int64_t depth) ObXmlTextSerializer serializer(cur, buffer); if (OB_FAIL(serializer.serialize())) { LOG_WARN("failed to serialize text.", K(ret), K(cur_type), K(buffer.length())); - } else { - set_value_entry(g_idx, cur_type, value_start); + } else if (OB_FAIL(set_value_entry(g_idx, cur_type, value_start))) { + LOG_WARN("failed to set value entry.", K(ret), K(value_start)); } break; } @@ -949,11 +962,12 @@ int ObXmlElementSerializer::serialize(int64_t depth) if (serialize_try_time_ >= MAX_RETRY_TIME) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to serialize as meta info not match.", K(ret), K(total_size), K(children_num), K(header_)); + } else if (OB_FAIL(buffer.set_length(start))) { + LOG_WARN("failed to set length.", K(ret), K(start)); } else { int64_t delta = total_size - header_.get_obj_size(); ele->set_delta_serialize_size(delta); serialize_try_time_++; - buffer.set_length(start); new (this) ObXmlElementSerializer(root_, &buffer); if (OB_FAIL(serialize(depth))) { LOG_WARN("failed to serialize.", K(ret), K(buffer.length())); @@ -3144,8 +3158,8 @@ int ObXmlBinMerge::reserve_meta(ObMulBinHeaderSerializer& header) uint32_t reserve_size = merge_meta_.key_start_ - merge_meta_.index_start_; if (OB_FAIL(merge_meta_.header_->buffer_->reserve(reserve_size))) { LOG_WARN("failed to reserve buffer.", K(ret), K(reserve_size)); - } else { - header.buffer_->set_length(pos + reserve_size); + } else if (OB_FAIL(header.buffer_->set_length(pos + reserve_size))) { + LOG_WARN("failed to set length.", K(ret), K(pos + reserve_size)); } } return ret; diff --git a/deps/oblib/src/lib/xml/ob_xml_bin.h b/deps/oblib/src/lib/xml/ob_xml_bin.h index 153cbd7c8..49e91d78b 100644 --- a/deps/oblib/src/lib/xml/ob_xml_bin.h +++ b/deps/oblib/src/lib/xml/ob_xml_bin.h @@ -258,12 +258,12 @@ public: int serialize(int64_t depth); int deserialize(ObIMulModeBase*& node); int reserve_meta(); - void set_key_entry(int64_t entry_idx, int64_t key_offset, int64_t key_len); - void set_index_entry(int64_t origin_index, int64_t sort_index); + int set_key_entry(int64_t entry_idx, int64_t key_offset, int64_t key_len); + int set_index_entry(int64_t origin_index, int64_t sort_index); int64_t size() { return attr_count_ + child_count_; } int serialize_child_key(const ObString& key, int64_t idx); - void set_value_entry(int64_t entry_idx, uint8_t type, int64_t value_offset); + int set_value_entry(int64_t entry_idx, uint8_t type, int64_t value_offset); struct MemberArray { int64_t g_start_; diff --git a/deps/oblib/src/lib/xml/ob_xml_tree.cpp b/deps/oblib/src/lib/xml/ob_xml_tree.cpp index e023d507e..f8a6f001c 100644 --- a/deps/oblib/src/lib/xml/ob_xml_tree.cpp +++ b/deps/oblib/src/lib/xml/ob_xml_tree.cpp @@ -276,6 +276,62 @@ int ObXmlElement::get_attribute_pos(ObMulModeNodeType xml_type, const ObString& return ret; } +int ObXmlElement::clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) +{ + INIT_SUCC(ret); + ObXmlElement *ele = nullptr; + ObXmlNode *origin_node = nullptr; + node = ObXmlUtil::clone_new_node(ctx->allocator_, type(), ctx); + if (OB_ISNULL(node)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocator xml text node.", K(ret)); + } else if (OB_ISNULL(ele = static_cast(node)) || + OB_ISNULL(origin_node = static_cast(this))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("clone new node cast to element is null", K(ret)); + } else { + ele->set_prefix(prefix_); + ele->set_xml_key(tag_info_); + ele->set_standalone(standalone_); + ele->set_has_xml_decl(has_xml_decl_); + ele->set_empty(is_empty_); + ele->set_unparse(is_unparse_); + ele->set_encoding_flag(encoding_val_empty_); + + int64_t child_size = size(); + int64_t attr_count = attribute_size(); + for (int64_t i = 0; OB_SUCC(ret) && i < attr_count; i++) { + ObXmlAttribute *attr = nullptr; + ObXmlNode *clone_node = nullptr; + if (OB_FAIL(get_attribute(attr, i))) { + LOG_WARN("failed to get attribute.", K(ret), K(i)); + } else if (OB_ISNULL(attr)) { + ret =OB_ERR_UNEXPECTED; + LOG_WARN("get attribute is null.", K(ret), K(i)); + } else if (OB_FAIL(attr->clone(ctx, clone_node))) { + LOG_WARN("failed to clone attribute.", K(ret), KP(attr)); + } else if (OB_FAIL(ele->add_attribute(clone_node))) { + LOG_WARN("failed to add attribute.", K(ret), K(i), KP(clone_node)); + } + } + + for (int64_t i = 0; OB_SUCC(ret) && i < child_size; i++) { + ObXmlNode *child_node = nullptr; + ObXmlNode *clone_node = nullptr; + if (OB_ISNULL(child_node = origin_node->at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get child node.", K(ret), K(i), KP(origin_node)); + } else if (OB_FAIL(child_node->clone(ctx, clone_node))) { + LOG_WARN("failed to clone child_node.", K(ret), KP(child_node)); + } else if (OB_FAIL(ele->add_element(clone_node, false, i))) { + LOG_WARN("failed to add xmlnode into element.", K(ret), K(i), KP(child_node), KP(origin_node)); + } + } + } + + return ret; +} + ObXmlAttribute* ObXmlElement::get_attribute_by_name(const ObString& ns_value, const ObString& name) // get attr by name { ObXmlAttribute* res_node = NULL; @@ -988,6 +1044,43 @@ int64_t ObXmlDocument::get_serialize_size() return res; } +int ObXmlDocument::clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) +{ + INIT_SUCC(ret); + ObXmlDocument *doc = nullptr; + ObXmlNode *origin_node = nullptr; + node = ObXmlUtil::clone_new_node(ctx->allocator_, type(), ctx); + if (OB_ISNULL(node)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocator xml text node.", K(ret)); + } else if (OB_ISNULL(doc = static_cast(node)) || + OB_ISNULL(origin_node = static_cast(this))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("clone new node cast to document is null", K(ret)); + } else { + doc->set_version(version_); + doc->set_encoding(encoding_); + doc->set_extSubset(extSubset_); + doc->set_inSubset(intSubset_); + + int64_t child_size = size(); + for (int64_t i = 0; OB_SUCC(ret) && i < child_size; i++) { + ObXmlNode *child_node = nullptr; + ObXmlNode *clone_node = nullptr; + if (OB_ISNULL(child_node = origin_node->at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get child node.", K(ret), K(i), KP(origin_node)); + } else if (OB_FAIL(child_node->clone(ctx, clone_node))) { + LOG_WARN("failed to clone child_node.", K(ret), KP(child_node)); + } else if (OB_FAIL(doc->add_element(clone_node, false, i))) { + LOG_WARN("failed to add xmlnode into element.", K(ret), K(i), KP(child_node), KP(origin_node)); + } + } + } + + return ret; +} + int ObXmlElement::remove_attribute(int pos) { INIT_SUCC(ret); @@ -1213,6 +1306,37 @@ int ObXmlText::compare(const ObString& key, int& res) return ret; } +int ObXmlText::clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) +{ + INIT_SUCC(ret); + node = ObXmlUtil::clone_new_node(ctx->allocator_, type(), ctx); + if (OB_ISNULL(node)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocator xml text node.", K(ret)); + } else { + node->set_value(text_); + } + return ret; +} + +int ObXmlAttribute::clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) +{ + INIT_SUCC(ret); + node = ObXmlUtil::clone_new_node(ctx->allocator_, type(), ctx); + if (OB_ISNULL(node)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocator xml attributes node.", K(ret)); + } else { + ObXmlAttribute *attr = static_cast(node); + attr->set_prefix(prefix_); + attr->set_ns(ns_); + attr->set_xml_key(name_); + attr->set_value(value_); + attr->set_attr_decl(attr_decl_); + } + return ret; +} + int64_t ObXmlAttribute::get_serialize_size() { int64_t res = 0; diff --git a/deps/oblib/src/lib/xml/ob_xml_tree.h b/deps/oblib/src/lib/xml/ob_xml_tree.h index 50aaf8697..2ec804134 100644 --- a/deps/oblib/src/lib/xml/ob_xml_tree.h +++ b/deps/oblib/src/lib/xml/ob_xml_tree.h @@ -177,6 +177,7 @@ public: virtual int get_value(ObIArray &value, const ObString& key_name) { return 0; } // compare virtual int compare(const ObIMulModeBase &other, int &res) { return 0; } + virtual int clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) override { return OB_NOT_SUPPORTED; } virtual int set_flag_by_descandant(); @@ -336,6 +337,7 @@ public: virtual int get_attribute(ObIArray& res, ObMulModeNodeType filter_type, int32_t flags = 0); virtual int get_attribute(ObIMulModeBase*& res, ObMulModeNodeType filter_type, const ObString& key1, const ObString &key2 = ObString()); virtual bool check_if_defined_ns(); + int clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) override; private: // namespace prefix ObString prefix_; @@ -390,6 +392,7 @@ public: ObXmlNode* get_extSubset() { return extSubset_; } int64_t get_serialize_size(); + int clone(ObMulModeMemCtx *ctx, ObXmlNode *&node); protected: // xml prolog @@ -465,6 +468,7 @@ class ObXmlAttribute : public ObXmlNode // ObXmlNode *clone(ObIAllocator* allocator) const; virtual int compare(const ObString& key, int& res); int64_t get_serialize_size(); + int clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) override; protected: // namespace prefix ObString prefix_; @@ -517,6 +521,7 @@ public: bool is_space() { return is_space_; } void set_is_space(bool is_space) { is_space_ = is_space; } int64_t get_serialize_size(); + int clone(ObMulModeMemCtx *ctx, ObXmlNode *&node) override; protected: ObString text_; int64_t length_; diff --git a/deps/oblib/src/lib/xml/ob_xml_util.cpp b/deps/oblib/src/lib/xml/ob_xml_util.cpp index 0172e6639..7268f503c 100644 --- a/deps/oblib/src/lib/xml/ob_xml_util.cpp +++ b/deps/oblib/src/lib/xml/ob_xml_util.cpp @@ -1544,5 +1544,21 @@ int ObXmlUtil::restore_ns_vec(ObNsSortedVector* element_ns_vec, ObVector +ObXmlNode* ObXmlUtil::clone_new_node(ObIAllocator* allocator, Args &&... args) +{ + void *buf = allocator->alloc(sizeof(T)); + T *new_node = NULL; + + if (OB_ISNULL(buf)) { + LOG_WARN_RET(OB_ALLOCATE_MEMORY_FAILED, "fail to alloc memory for ObXmlNode"); + } else { + new_node = new(buf)T(std::forward(args)...); + } + + return static_cast(new_node); + +} + } // namespace common } // namespace oceanbase diff --git a/deps/oblib/src/lib/xml/ob_xml_util.h b/deps/oblib/src/lib/xml/ob_xml_util.h index 0466f7665..40974437b 100644 --- a/deps/oblib/src/lib/xml/ob_xml_util.h +++ b/deps/oblib/src/lib/xml/ob_xml_util.h @@ -535,6 +535,8 @@ public: static bool is_xml_doc_over_depth(uint64_t depth); static int revert_escape_character(ObIAllocator &allocator, ObString &input_str, ObString &output_str); + template + static ObXmlNode* clone_new_node(ObIAllocator* allocator, Args &&... args); }; class ObMulModeFactory diff --git a/deps/oblib/src/lib/xml/ob_xpath.cpp b/deps/oblib/src/lib/xml/ob_xpath.cpp index ae438a255..2871f7353 100644 --- a/deps/oblib/src/lib/xml/ob_xpath.cpp +++ b/deps/oblib/src/lib/xml/ob_xpath.cpp @@ -2157,6 +2157,41 @@ ObIMulModeBase* ObPathExprIter::get_cur_res_parent() return path_ctx_.ancestor_record_.size() > 0 ? path_ctx_.ancestor_record_.top() : nullptr; } +int ObPathExprIter::get_node_exists(bool &is_exists) +{ + INIT_SUCC(ret); + is_exists = false; + if (!is_inited_ || OB_ISNULL(path_node_)) { + ret = OB_INIT_FAIL; + LOG_WARN("should be inited", K(ret)); + } else { + ObSeekResult path_res; + while (OB_SUCC(ret) && !is_exists) { + if (OB_FAIL(path_node_->eval_node(path_ctx_, path_res))) { + if (ret != OB_ITER_END) { + LOG_WARN("fail to seek", K(ret)); + } + } else if (path_res.is_scalar_) { + if (OB_ISNULL(path_res.result_.scalar_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("xpath result scalar is null", K(ret)); + } else if (path_res.result_.scalar_->node_type_.get_arg_type() == ObArgType::PN_BOOLEAN + && !path_res.result_.scalar_->arg_.boolean_) { + // do nothing, keep seeking + } else { + is_exists = true; + } + } else { + is_exists = true; + } + } // end while + if (ret == OB_ITER_END) { + ret = OB_SUCCESS; + } + } + return ret; +} + int ObPathExprIter::get_next_node(ObIMulModeBase*& res) { INIT_SUCC(ret); diff --git a/deps/oblib/src/lib/xml/ob_xpath.h b/deps/oblib/src/lib/xml/ob_xpath.h index 5fb93b44b..5428b8e5f 100644 --- a/deps/oblib/src/lib/xml/ob_xpath.h +++ b/deps/oblib/src/lib/xml/ob_xpath.h @@ -934,6 +934,7 @@ public: int init(ObMulModeMemCtx* ctx, ObString& path, ObString& default_ns, ObIMulModeBase* doc, ObPathVarObject* pass_var, bool add_namespace = true); int open(); // begin to parse and seek int get_next_node(ObIMulModeBase*& res); + int get_node_exists(bool &is_exists); int get_first_node(ObPathNode*& loc); int get_first_axis(ObPathNodeAxis& first_axis); diff --git a/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp b/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp index d8fce1f75..e73f78799 100644 --- a/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp +++ b/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp @@ -1138,7 +1138,7 @@ int ObMySQLUtil::json_cell_str(uint64_t tenant_id, char *buf, const int64_t len, } } else if (OB_FAIL(j_bin.reset_iter())) { OB_LOG(WARN, "fail to reset json bin iter", K(ret), K(val)); - } else if (OB_FAIL(j_base->print(jbuf, true))) { + } else if (OB_FAIL(j_base->print(jbuf, true, val.length()))) { OB_LOG(WARN, "json binary to string failed in mysql mode", K(ret), K(val), K(*j_base)); } else { int64_t new_length = jbuf.length(); diff --git a/src/pl/ob_pl_interface_pragma.h b/src/pl/ob_pl_interface_pragma.h index 53670f1df..33cb43dc8 100644 --- a/src/pl/ob_pl_interface_pragma.h +++ b/src/pl/ob_pl_interface_pragma.h @@ -481,6 +481,8 @@ INTERFACE_DEF(INTERFACE_XML_TYPE_TRANSFORM, "XML_TYPE_TRANSFORM", (ObXmlType::transform)) INTERFACE_DEF(INTERFACE_XML_TYPE_GETCLOBVAL, "XML_TYPE_GETCLOBVAL", (ObXmlType::getclobval)) INTERFACE_DEF(INTERFACE_XML_TYPE_GETSTRINGVAL, "XML_TYPE_GETSTRINGVAL", (ObXmlType::getstringval)) + INTERFACE_DEF(INTERFACE_XML_TYPE_EXISTSNODE, "XML_TYPE_EXISTSNODE", (ObXmlType::existsnode)) + INTERFACE_DEF(INTERFACE_XML_TYPE_EXTRACT, "XML_TYPE_EXTRACT", (ObXmlType::extract)) INTERFACE_DEF(INTERFACE_XML_TYPE_CREATEXML, "XML_TYPE_CREATEXML", (ObXmlType::createxml)) INTERFACE_DEF(INTERFACE_XML_TYPE_CONSTRUCTOR, "XML_TYPE_CONSTRUCTOR", (ObXmlType::constructor)) //end of xmltype diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index 4638631d4..e696a75bb 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -8586,7 +8586,7 @@ static int json_raw(const ObObjType expect_type, ObObjCastParams ¶ms, ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); - } else if (CAST_FAIL(j_base->print(j_buf, true))) { + } else if (CAST_FAIL(j_base->print(j_buf, true, j_bin_str.length()))) { 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); @@ -8658,7 +8658,7 @@ static int json_string(const ObObjType expect_type, ObObjCastParams ¶ms, ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); - } else if (CAST_FAIL(j_base->print(j_buf, true))) { + } else if (CAST_FAIL(j_base->print(j_buf, true, j_bin_str.length()))) { 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); @@ -8727,7 +8727,7 @@ static int common_json_string(const ObObjType expect_type, ObString j_str; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); - } else if (CAST_FAIL(j_base->print(j_buf, true))) { + } else if (CAST_FAIL(j_base->print(j_buf, true, j_bin_str.length()))) { 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); diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index 7d6e3c534..d2f11b84f 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -2105,6 +2105,9 @@ DEF_INT(max_partition_num, OB_TENANT_PARAMETER, "8192", "[8192, 65536]", DEF_INT(json_document_max_depth, OB_TENANT_PARAMETER, "100", "[100,1024]", "maximum nesting depth allowed in a JSON document", ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_INT(_multimodel_memory_trace_level, OB_TENANT_PARAMETER, "0", "[0,100)", + "Multi-mode memory tracking mechanism", + ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); ERRSIM_DEF_INT(errsim_backup_task_batch_size, OB_CLUSTER_PARAMETER, "0", "[0,)", "the batch size backup task receive in errsim mode" "Range: [0,) in integer", diff --git a/src/sql/CMakeLists.txt b/src/sql/CMakeLists.txt index 1045e7edf..14c20ac75 100644 --- a/src/sql/CMakeLists.txt +++ b/src/sql/CMakeLists.txt @@ -553,6 +553,7 @@ ob_set_subtarget(ob_sql engine_expr engine/expr/ob_expr_insert_child_xml.cpp engine/expr/ob_expr_xml_delete_xml.cpp engine/expr/ob_expr_xml_sequence.cpp + engine/expr/ob_expr_existsnode_xml.cpp engine/expr/ob_expr_sql_udt_utils.cpp engine/expr/ob_expr_temp_table_ssid.cpp engine/expr/ob_expr_collection_construct.cpp @@ -574,8 +575,11 @@ ob_set_subtarget(ob_sql engine_expr engine/expr/ob_expr_prefix_pattern.cpp engine/expr/ob_expr_sys_makexml.cpp engine/expr/ob_expr_xml_func_helper.cpp + engine/expr/ob_expr_multi_mode_func_helper.cpp engine/expr/ob_expr_xmlparse.cpp engine/expr/ob_expr_xml_element.cpp + engine/expr/ob_expr_xml_concat.cpp + engine/expr/ob_expr_xml_forest.cpp engine/expr/ob_expr_xml_attributes.cpp engine/expr/ob_expr_xml_serialize.cpp engine/expr/ob_expr_priv_xml_binary.cpp @@ -591,6 +595,8 @@ ob_set_subtarget(ob_sql engine_expr engine/expr/ob_expr_st_geomfromewkt.cpp engine/expr/ob_expr_priv_st_geogfromtext.cpp engine/expr/ob_expr_priv_st_geographyfromtext.cpp + engine/expr/ob_expr_priv_st_geohash.cpp + engine/expr/ob_expr_priv_st_makepoint.cpp engine/expr/ob_expr_st_asewkt.cpp engine/expr/ob_expr_st_srid.cpp engine/expr/ob_expr_st_distance.cpp diff --git a/src/sql/engine/aggregate/ob_aggregate_processor.cpp b/src/sql/engine/aggregate/ob_aggregate_processor.cpp index f80b3c74a..aff4365b1 100644 --- a/src/sql/engine/aggregate/ob_aggregate_processor.cpp +++ b/src/sql/engine/aggregate/ob_aggregate_processor.cpp @@ -7865,16 +7865,14 @@ int ObAggregateProcessor::get_ora_json_arrayagg_result(const ObAggrInfo &aggr_in } else if (ob_is_string_type(rsp_type) || ob_is_raw(rsp_type)) { ObIJsonBase *j_base = NULL; ObStringBuffer *buff = bin_agg.get_buffer(); - if (OB_FAIL(string_buffer.reserve(buff->length()))) { - LOG_WARN("fail to reserve string.", K(ret), K(buff->length())); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_alloc, + if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_alloc, buff->string(), ObJsonInType::JSON_BIN, ObJsonInType::JSON_BIN, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { LOG_WARN("fail to get real data.", K(ret), K(buff)); - } else if (OB_FAIL(j_base->print(string_buffer, true, false))) { + } else if (OB_FAIL(j_base->print(string_buffer, true, buff->length(), false))) { LOG_WARN("failed: get json string text", K(ret)); } else if (rsp_type == ObVarcharType && string_buffer.length() > rsp_len) { char res_ptr[OB_MAX_DECIMAL_PRECISION] = {0}; @@ -8086,7 +8084,8 @@ int ObAggregateProcessor::get_ora_xmlagg_result(const ObAggrInfo &aggr_info, int ret = OB_SUCCESS; #ifdef OB_BUILD_ORACLE_PL ObString result; - common::ObArenaAllocator tmp_alloc(ObModIds::OB_SQL_AGGR_FUNC, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); + common::ObArenaAllocator tmp_allocator(ObModIds::OB_SQL_AGGR_FUNC, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); + MultimodeAlloctor tmp_alloc(tmp_allocator, T_FUN_ORA_XMLAGG, MTL_ID(), ret); ObXmlDocument *content = NULL; ObXmlDocument* doc = NULL; ObString blob_locator; @@ -8315,6 +8314,7 @@ int ObAggregateProcessor::get_ora_xmlagg_result(const ObAggrInfo &aggr_info, } else if (OB_FAIL(ObXMLExprHelper::pack_binary_res(*aggr_info.expr_, eval_ctx_, bin_agg.get_buffer()->string(), blob_locator))) { LOG_WARN("pack binary res failed", K(ret)); } else { + tmp_alloc.set_baseline_size_and_flag(bin_agg.get_buffer()->length()); concat_result.set_string(blob_locator.ptr(), blob_locator.length()); } } @@ -8477,16 +8477,14 @@ int ObAggregateProcessor::get_ora_json_objectagg_result(const ObAggrInfo &aggr_i } else if (OB_FALSE_IT(buff = bin_agg.get_buffer())) { } else if (ob_is_string_type(rsp_type) || ob_is_raw(rsp_type)) { ObIJsonBase *j_base = NULL; - if (OB_FAIL(string_buffer.reserve(buff->length()))) { - LOG_WARN("fail to reserve string.", K(ret), K(buff->length())); - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_alloc, + if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_alloc, buff->string(), ObJsonInType::JSON_BIN, ObJsonInType::JSON_BIN, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { LOG_WARN("fail to get real data.", K(ret), K(buff)); - } else if (OB_FAIL(j_base->print(string_buffer, true, false))) { + } else if (OB_FAIL(j_base->print(string_buffer, true, buff->length(), false))) { LOG_WARN("failed: get json string text", K(ret)); } else if (rsp_type == ObVarcharType && string_buffer.length() > rsp_len) { char res_ptr[OB_MAX_DECIMAL_PRECISION] = {0}; diff --git a/src/sql/engine/basic/ob_json_table_op.cpp b/src/sql/engine/basic/ob_json_table_op.cpp index 9af61d57c..5aba0916a 100644 --- a/src/sql/engine/basic/ob_json_table_op.cpp +++ b/src/sql/engine/basic/ob_json_table_op.cpp @@ -22,6 +22,7 @@ #include "sql/session/ob_sql_session_info.h" #include "sql/engine/ob_physical_plan.h" #include "sql/engine/expr/ob_expr_json_func_helper.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" #include "sql/engine/expr/ob_expr_json_value.h" #include "sql/engine/expr/ob_expr_json_query.h" #include "sql/engine/expr/ob_expr_json_exists.h" @@ -669,15 +670,20 @@ int ObJsonTableOp::reset_variable() jt_ctx_.is_cover_error_ = false; jt_ctx_.error_code_ = 0; jt_ctx_.is_need_end_ = 0; - - if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&jt_ctx_.row_alloc_, jt_ctx_.mem_ctx_))) { - LOG_WARN("fail to create tree memory context", K(ret)); + MultimodeAlloctor *tmp_allocator = nullptr; + if (OB_ISNULL(tmp_allocator = static_cast(jt_ctx_.row_alloc_.alloc(sizeof(MultimodeAlloctor))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate Multimode alloc buf", K(ret)); + } else { + new (tmp_allocator)MultimodeAlloctor(jt_ctx_.row_alloc_, T_XML_TABLE_EXPRESSION, ret); } if (OB_FAIL(ret)) { } else if (MY_SPEC.value_exprs_.empty()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to open iter, value expr is null.", K(ret)); + } else if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(tmp_allocator, jt_ctx_.mem_ctx_))) { + LOG_WARN("fail to create tree memory context", K(ret)); } else if (OB_FAIL(root_->reset(&jt_ctx_))) { LOG_WARN("failed to open table func xml column node.", K(ret)); } else { @@ -696,6 +702,7 @@ int ObJsonTableOp::switch_iterator() int ObJsonTableOp::init() { INIT_SUCC(ret); + uint64_t tenant_id = -1; if (!is_inited_) { const ObJsonTableSpec* spec_ptr = reinterpret_cast(&spec_); jt_ctx_.spec_ptr_ = const_cast(spec_ptr); @@ -703,7 +710,6 @@ int ObJsonTableOp::init() LOG_WARN("fail to init json table op, as generate exec tree occur error.", K(ret)); } else { const sql::ObSQLSessionInfo *session = get_exec_ctx().get_my_session(); - uint64_t tenant_id = -1; if (OB_ISNULL(session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is NULL", K(ret)); @@ -758,7 +764,15 @@ int ObJsonTableOp::init() jt_ctx_.is_cover_error_ = false; jt_ctx_.error_code_ = 0; jt_ctx_.is_need_end_ = 0; - if (OB_SUCC(ret) && OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&jt_ctx_.row_alloc_, jt_ctx_.mem_ctx_))) { + MultimodeAlloctor *tmp_allocator = nullptr; + if (OB_ISNULL(tmp_allocator = static_cast(jt_ctx_.row_alloc_.alloc(sizeof(MultimodeAlloctor))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate Multimode alloc buf", K(ret)); + } else { + new (tmp_allocator)MultimodeAlloctor(jt_ctx_.row_alloc_, T_XML_TABLE_EXPRESSION, ret); + } + + if (OB_SUCC(ret) && OB_FAIL(ObXmlUtil::create_mulmode_tree_context(tmp_allocator, jt_ctx_.mem_ctx_))) { LOG_WARN("fail to create tree memory context", K(ret)); } return ret; @@ -2947,6 +2961,7 @@ int JsonTableFunc::eval_input(ObJsonTableOp &jt, JtScanCtx& ctx, ObEvalCtx &eval ObString j_str; bool is_null = false; ObIJsonBase* in = NULL; + MultimodeAlloctor tmp_allocator(ctx.row_alloc_, T_JSON_TABLE_EXPRESSION, ret); if (doc_type == ObNullType) { ret = OB_ITER_END; @@ -2959,11 +2974,12 @@ int JsonTableFunc::eval_input(ObJsonTableOp &jt, JtScanCtx& ctx, ObEvalCtx &eval } else { jt.reset_columns(); if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(ctx.spec_ptr_->value_exprs_.at(0), eval_ctx, - ctx.row_alloc_, j_str, is_null))) { + tmp_allocator, j_str, is_null))) { ret = OB_ERR_INPUT_JSON_TABLE; LOG_WARN("get real data failed", K(ret)); } else if (is_null) { ret = OB_ITER_END; + } else if (OB_FALSE_IT(tmp_allocator.set_baseline_size(j_str.length()))) { } else if ((ob_is_string_type(doc_type) || doc_type == ObLobType) && (doc_cs_type != CS_TYPE_BINARY) && (ObCharset::charset_type_by_coll(doc_cs_type) != CHARSET_UTF8MB4)) { @@ -2973,7 +2989,7 @@ int JsonTableFunc::eval_input(ObJsonTableOp &jt, JtScanCtx& ctx, ObEvalCtx &eval int64_t buf_len = j_str.length() * factor; uint32_t result_len = 0; - if (OB_ISNULL(buf = static_cast(ctx.row_alloc_.alloc(buf_len)))) { + if (OB_ISNULL(buf = static_cast(tmp_allocator.alloc(buf_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret)); } else if (OB_FAIL(ObCharset::charset_convert(doc_cs_type, j_str.ptr(), @@ -2994,7 +3010,7 @@ int JsonTableFunc::eval_input(ObJsonTableOp &jt, JtScanCtx& ctx, ObEvalCtx &eval if (OB_FAIL(ret)) { - } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&ctx.row_alloc_, j_str, j_in_type, expect_type, in, parse_flag, ObJsonExprHelper::get_json_max_depth_config())) + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&tmp_allocator, j_str, j_in_type, expect_type, in, parse_flag, ObJsonExprHelper::get_json_max_depth_config())) || (in->json_type() != ObJsonNodeType::J_ARRAY && in->json_type() != ObJsonNodeType::J_OBJECT)) { if (OB_FAIL(ret) || (is_ensure_json)) { in= nullptr; diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index 4b7e9ee8f..567e08839 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -2636,7 +2636,7 @@ static int common_json_string(const ObExpr &expr, // get json string if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); - } else if (CAST_FAIL(j_base->print(j_buf, true))) { + } else if (CAST_FAIL(j_base->print(j_buf, true, j_bin_str.length()))) { LOG_WARN("fail to convert json to string", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); @@ -8625,7 +8625,7 @@ CAST_FUNC_NAME(json, raw) if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); - } else if (CAST_FAIL(j_base->print(j_buf, true))) { + } else if (CAST_FAIL(j_base->print(j_buf, true, j_bin_str.length()))) { LOG_WARN("fail to convert json to string", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); @@ -8675,7 +8675,7 @@ CAST_FUNC_NAME(json, string) if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); - } else if (CAST_FAIL(j_base->print(j_buf, true))) { + } else if (CAST_FAIL(j_base->print(j_buf, true, j_bin_str.length()))) { LOG_WARN("fail to convert json to string", K(ret), K(j_bin_str)); 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_expr_eval_functions.cpp b/src/sql/engine/expr/ob_expr_eval_functions.cpp index 836937d66..f59ec3161 100644 --- a/src/sql/engine/expr/ob_expr_eval_functions.cpp +++ b/src/sql/engine/expr/ob_expr_eval_functions.cpp @@ -325,12 +325,15 @@ #include "ob_expr_xml_attributes.h" #include "ob_expr_extract_value.h" #include "ob_expr_extract_xml.h" +#include "ob_expr_existsnode_xml.h" #include "ob_expr_xml_serialize.h" #include "ob_expr_xmlcast.h" #include "ob_expr_update_xml.h" #include "ob_expr_insert_child_xml.h" #include "ob_expr_xml_delete_xml.h" #include "ob_expr_xml_sequence.h" +#include "ob_expr_xml_concat.h" +#include "ob_expr_xml_forest.h" #include "ob_expr_generator_func.h" #include "ob_expr_random.h" #include "ob_expr_randstr.h" @@ -406,6 +409,8 @@ #include "ob_expr_can_access_trigger.h" #include "ob_expr_split_part.h" #include "ob_expr_get_mysql_routine_parameter_type_str.h" +#include "ob_expr_priv_st_geohash.h" +#include "ob_expr_priv_st_makepoint.h" namespace oceanbase { @@ -1169,9 +1174,9 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = { eval_questionmark_decint2decint_eqcast, /* 659 */ eval_questionmark_decint2decint_normalcast, /* 660 */ ObExprExtractExpiredTime::eval_extract_cert_expired_time, /* 661 */ - NULL, //ObExprXmlConcat::eval_xml_concat, /* 662 */ - NULL, //ObExprXmlForest::eval_xml_forest, /* 663 */ - NULL, //ObExprExistsNodeXml::eval_existsnode_xml, /* 664 */ + ObExprXmlConcat::eval_xml_concat, /* 662 */ + ObExprXmlForest::eval_xml_forest, /* 663 */ + ObExprExistsNodeXml::eval_existsnode_xml, /* 664 */ ObExprPassword::eval_password, /* 665 */ ObExprDocID::generate_doc_id, /* 666 */ ObExprWordSegment::generate_fulltext_column, /* 667 */ @@ -1186,8 +1191,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = { ObExprIs::json_is_false, /* 676 */ ObExprCurrentRole::eval_current_role, /* 677 */ ObExprMod::mod_decimalint, /* 678 */ - NULL, // ObExprPrivSTGeoHash::eval_priv_st_geohash, /* 679 */ - NULL, // ObExprPrivSTMakePoint::eval_priv_st_makepoint, /* 680 */ + ObExprPrivSTGeoHash::eval_priv_st_geohash, /* 679 */ + ObExprPrivSTMakePoint::eval_priv_st_makepoint, /* 680 */ ObExprGetLock::get_lock, /* 681 */ ObExprIsFreeLock::is_free_lock, /* 682 */ ObExprIsUsedLock::is_used_lock, /* 683 */ diff --git a/src/sql/engine/expr/ob_expr_existsnode_xml.cpp b/src/sql/engine/expr/ob_expr_existsnode_xml.cpp new file mode 100644 index 000000000..b1e41bbd7 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_existsnode_xml.cpp @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file is for func existsnode(xml). + */ + +#include "ob_expr_existsnode_xml.h" +#include "lib/xml/ob_xml_parser.h" +#include "lib/xml/ob_xml_util.h" +#include "sql/engine/expr/ob_expr_xml_func_helper.h" +#include "sql/engine/ob_exec_context.h" + +#define USING_LOG_PREFIX SQL_ENG + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace sql +{ + +ObExprExistsNodeXml::ObExprExistsNodeXml(common::ObIAllocator &alloc) + : ObFuncExprOperator( + alloc, + T_FUN_SYS_XML_EXISTSNODE, + N_EXISTSNODE_XML, + MORE_THAN_ONE, + VALID_FOR_GENERATED_COL, + NOT_ROW_DIMENSION) +{ +} + +ObExprExistsNodeXml::~ObExprExistsNodeXml() {} + +int ObExprExistsNodeXml::calc_result_typeN( + ObExprResType &type, + ObExprResType *types, + int64_t param_num, + common::ObExprTypeCtx &type_ctx) const +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(param_num != 3)) { + ret = OB_ERR_PARAM_SIZE; + LOG_WARN("invalid argument number", K(ret), K(param_num)); + } else if (!is_called_in_sql()) { + ret = OB_ERR_SP_LILABEL_MISMATCH; + LOG_WARN("expr call in pl semantics disallowed", K(ret), K(N_EXISTSNODE_XML)); + LOG_USER_ERROR(OB_ERR_SP_LILABEL_MISMATCH, static_cast(strlen(N_EXISTSNODE_XML)), N_EXISTSNODE_XML); + } else { + ObObjType in_type = types[0].get_type(); + if (types[0].is_ext() && types[0].get_udt_id() == T_OBJ_XML) { + types[0].get_calc_meta().set_sql_udt(ObXMLSqlType); + } else if (!ob_is_xml_sql_type(in_type, types[0].get_subschema_id())) { + ret = OB_ERR_INVALID_XML_DATATYPE; + LOG_USER_ERROR(OB_ERR_INVALID_XML_DATATYPE, "-", "-"); + LOG_WARN("inconsistent datatypes", K(ret), K(ob_obj_type_str(in_type))); + } + for (int8_t i = 1; i < param_num && OB_SUCC(ret); i++) { + ObObjType param_type = types[i].get_type(); + if (param_type == ObNullType) { + if (i == 1) { + ret = OB_ERR_INVALID_XPATH_EXPRESSION; + LOG_WARN("invalid xpath expression", K(ret)); + } + } else if (ob_is_string_type(param_type)) { + if (types[i].get_charset_type() != CHARSET_UTF8MB4) { + types[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + } else { + ret = OB_ERR_INVALID_XPATH_EXPRESSION; + LOG_WARN("invalid xpath expression", K(ret)); + } + } + + if (OB_SUCC(ret)) { + type.set_int32(); + } + } + return ret; +} + +int ObExprExistsNodeXml::eval_existsnode_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) +{ + INIT_SUCC(ret); + bool is_exists = false; + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + ObDatum *xml_datum = NULL; + ObIMulModeBase *xml_doc = NULL; + ObMulModeNodeType node_type = M_MAX_TYPE; + ObString xpath_str; + ObPathExprIter xpath_iter(&allocator); + ObString namespace_str; + ObString default_ns; + ObPathVarObject prefix_ns(allocator); + ObMulModeMemCtx* mem_ctx = nullptr; + + // Check and read param + CK(OB_NOT_NULL(ctx.exec_ctx_.get_my_session())); + OZ(ObXmlUtil::create_mulmode_tree_context(&allocator, mem_ctx)); + CK(expr.arg_cnt_ == 3); + OZ(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum), expr.args_[0]); + if (OB_FAIL(ret)) { + } else if (expr.args_[1]->datum_meta_.type_ == ObNullType) { + ret = OB_ERR_INVALID_XPATH_EXPRESSION; + LOG_WARN("invalid xpath expression", K(ret), K(expr.args_[1]->datum_meta_.type_ )); + } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[1], ctx, xpath_str, allocator))) { + LOG_WARN("fail to get xpath str", K(ret), K(expr.args_[1])); + } else if (expr.args_[2]->datum_meta_.type_ == ObNullType){ + // do noting + } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[2], ctx, namespace_str, allocator))) { + LOG_WARN("fail to get namespace str", K(ret), K(expr.args_[2])); + } + + // process xmltype and xpath + OZ(ObXMLExprHelper::get_xml_base( + mem_ctx, xml_datum, + ObCollationType::CS_TYPE_INVALID, + ObNodeMemType::BINARY_TYPE, + xml_doc, + node_type, + ObGetXmlBaseType::OB_SHOULD_CHECK)); + OZ(ObXMLExprHelper::construct_namespace_params(namespace_str, default_ns, prefix_ns, allocator)); + if (OB_FAIL(ret)) { + } else if (OB_FAIL(xpath_iter.init(mem_ctx, xpath_str, default_ns, xml_doc, &prefix_ns))) { + LOG_WARN("fail to init xpath iterator", K(xpath_str), K(default_ns), K(ret)); + ObXMLExprHelper::replace_xpath_ret_code(ret); + } else if (OB_FAIL(xpath_iter.open())) { + LOG_WARN("fail to open xpath iterator", K(ret)); + ObXMLExprHelper::replace_xpath_ret_code(ret); + } else if (OB_FAIL(xpath_iter.get_node_exists(is_exists))) { + LOG_WARN("fail to get node exists", K(ret)); + } + + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = xpath_iter.close())) { + LOG_WARN("fail to close xpath iter", K(tmp_ret)); + ret = COVER_SUCC(tmp_ret); + } + if (OB_FAIL(ret)) { + } else if (is_exists) { + res.set_int(1); + } else { + res.set_int(0); + } + return ret; +} + +int ObExprExistsNodeXml::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const +{ + UNUSED(expr_cg_ctx); + UNUSED(raw_expr); + rt_expr.eval_func_ = eval_existsnode_xml; + return OB_SUCCESS; +} + +} // sql +} // oceanbase \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_existsnode_xml.h b/src/sql/engine/expr/ob_expr_existsnode_xml.h new file mode 100644 index 000000000..335db8086 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_existsnode_xml.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file is for func existsnode(xml). + */ + +#ifndef OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_EXISTSNODE_XML_H +#define OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_EXISTSNODE_XML_H + +#include "sql/engine/expr/ob_expr_operator.h" +#include "lib/xml/ob_xpath.h" +namespace oceanbase +{ + +namespace sql +{ +class ObExprExistsNodeXml : public ObFuncExprOperator +{ + public: + explicit ObExprExistsNodeXml(common::ObIAllocator &alloc); + virtual ~ObExprExistsNodeXml(); + virtual int calc_result_typeN( + ObExprResType &type, + ObExprResType *types, + int64_t param_num, + common::ObExprTypeCtx &type_ctx) const override; + static int eval_existsnode_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); + virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; + +private: + DISALLOW_COPY_AND_ASSIGN(ObExprExistsNodeXml); +}; + +} // sql +} // oceanbase + + +#endif //OCEANBASE_SQL_ENGINE_EXPR_OB_EXPR_EXISTSNODE_XML_H \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_extract_value.cpp b/src/sql/engine/expr/ob_expr_extract_value.cpp index 771967bfd..0f562d92b 100644 --- a/src/sql/engine/expr/ob_expr_extract_value.cpp +++ b/src/sql/engine/expr/ob_expr_extract_value.cpp @@ -124,7 +124,8 @@ int ObExprExtractValue::eval_extract_value(const ObExpr &expr, ObEvalCtx &ctx, O { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObDatum *xml_datum = NULL; ObString xpath_str; ObString namespace_str; @@ -136,7 +137,7 @@ int ObExprExtractValue::eval_extract_value(const ObExpr &expr, ObEvalCtx &ctx, O ObString xml_res; ObCollationType cs_type = CS_TYPE_INVALID; ObMulModeMemCtx* xml_mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -146,7 +147,7 @@ int ObExprExtractValue::eval_extract_value(const ObExpr &expr, ObEvalCtx &ctx, O } else if (OB_UNLIKELY(expr.arg_cnt_ != 2 && expr.arg_cnt_ != 3)) { ret = OB_ERR_PARAM_SIZE; LOG_WARN("invalid arg_cnt_", K(ret), K(expr.arg_cnt_)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum, allocator))) { LOG_WARN("fail to get xml str", K(ret)); } else if (ObNullType == expr.args_[1]->datum_meta_.type_) { ret = OB_ERR_INVALID_XPATH_EXPRESSION; @@ -179,7 +180,8 @@ int ObExprExtractValue::eval_mysql_extract_value(const ObExpr &expr, ObEvalCtx & { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObTextStringDatumResult output_result(expr.datum_meta_.type_, &expr, &ctx, &res); ObString xml_frag; ObString xpath_expr; @@ -188,11 +190,8 @@ int ObExprExtractValue::eval_mysql_extract_value(const ObExpr &expr, ObEvalCtx & ObStringBuffer xml_res(&allocator); ObMulModeMemCtx* xml_mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); - if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get session failed.", K(ret)); - } else if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&allocator, xml_mem_ctx))) { + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); + if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&allocator, xml_mem_ctx))) { LOG_WARN("fail to create tree memory context", K(ret)); } else if (expr.arg_cnt_ != 2) { ret = OB_ERR_PARAM_SIZE; @@ -204,6 +203,7 @@ int ObExprExtractValue::eval_mysql_extract_value(const ObExpr &expr, ObEvalCtx & LOG_WARN("get xml frag string failed", K(ret)); } else if (xml_frag.empty()) { // do nothing + } else if (OB_FALSE_IT(allocator.set_baseline_size(xml_frag.length()))) { } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[1], ctx, xpath_expr, allocator))) { LOG_WARN("get xpath expr failed.", K(ret)); } else if (OB_FAIL(ObMulModeFactory::get_xml_base(xml_mem_ctx, xml_frag, ObNodeMemType::TREE_TYPE, ObNodeMemType::BINARY_TYPE, xml_base, M_DOCUMENT))) { diff --git a/src/sql/engine/expr/ob_expr_extract_xml.cpp b/src/sql/engine/expr/ob_expr_extract_xml.cpp index ac401d517..5cec74528 100644 --- a/src/sql/engine/expr/ob_expr_extract_xml.cpp +++ b/src/sql/engine/expr/ob_expr_extract_xml.cpp @@ -82,7 +82,8 @@ int ObExprExtractXml::eval_extract_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDat { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObDatum *xml_datum = NULL; ObString xpath_str; ObString namespace_str; @@ -91,15 +92,15 @@ int ObExprExtractXml::eval_extract_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObPathExprIter xpath_iter(&allocator); ObString default_ns; ObPathVarObject prefix_ns(allocator); - ObString xml_res; - ObXmlDocument *root = nullptr; + ObString bin_str; ObMulModeNodeType node_type = M_MAX_TYPE; - ObString input_str; ObCollationType cs_type = CS_TYPE_INVALID; + bool is_null_res = false; + ObString blob_locator; // eval arg ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -109,7 +110,7 @@ int ObExprExtractXml::eval_extract_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (OB_UNLIKELY(expr.arg_cnt_ != 3)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid arg_cnt_", K(ret), K(expr.arg_cnt_)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum, allocator))) { LOG_WARN("fail to get xmltype value", K(ret)); } else if (ObNullType == expr.args_[1]->datum_meta_.type_) { ret = OB_ERR_INVALID_XPATH_EXPRESSION; @@ -129,138 +130,18 @@ int ObExprExtractXml::eval_extract_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (OB_FAIL(xpath_iter.init(mem_ctx, xpath_str, default_ns, xml_doc, &prefix_ns))) { LOG_WARN("fail to init xpath iterator", K(xpath_str), K(default_ns), K(ret)); ObXMLExprHelper::replace_xpath_ret_code(ret); - } else if (OB_FAIL(concat_xpath_result(expr, ctx, xpath_iter, cs_type, res, node_type, mem_ctx))) { + } else if (OB_FAIL(ObXMLExprHelper::concat_xpath_result(mem_ctx, xpath_iter, bin_str, is_null_res))) { LOG_WARN("fail to concat xpath result", K(ret)); } - return ret; -} -int ObExprExtractXml::concat_xpath_result(const ObExpr &expr, - ObEvalCtx &eval_ctx, - ObPathExprIter &xpath_iter, - ObCollationType cs_type, - ObDatum &res, - ObMulModeNodeType &node_type, - ObMulModeMemCtx* mem_ctx) -{ - int ret = OB_SUCCESS; - ObStringBuffer buff(mem_ctx->allocator_); - ObIMulModeBase *node = NULL; - int64_t append_node_num = 0; - int element_count = 0; - int text_count = 0; - ObString version; - ObString encoding; - uint16_t standalone; - ObString blob_locator; - bool first_is_doc = false; - ObIMulModeBase* last_parent = nullptr; - common::hash::ObHashMap ns_map; - - if (OB_FAIL(xpath_iter.open())) { - LOG_WARN("fail to open xpath iterator", K(ret)); - ObXMLExprHelper::replace_xpath_ret_code(ret); - } else if (OB_FAIL(ns_map.create(10, lib::ObMemAttr(MTL_ID(), "XMLModule")))) { - LOG_WARN("ns map create failed", K(ret)); - } - - ObBinAggSerializer bin_agg(mem_ctx->allocator_, ObBinAggType::AGG_XML, static_cast(M_CONTENT)); - - while (OB_SUCC(ret)) { - ObIMulModeBase* tmp = nullptr; - ObXmlBin extend; - if (OB_FAIL(xpath_iter.get_next_node(node))) { - if (ret != OB_ITER_END) { - LOG_WARN("fail to get next xml node", K(ret)); - } - } else if (OB_ISNULL(node)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("xpath result node is null", K(ret)); - } else if (node->is_tree() && OB_FAIL(ObMulModeFactory::transform(mem_ctx, node, BINARY_TYPE, node))) { - LOG_WARN("fail to transform to tree", K(ret)); - } else { - ObXmlBin *bin = nullptr; - if (OB_ISNULL(bin = static_cast(node))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get bin failed", K(ret)); - } else if (bin->meta_.len_ == 0) { - // do nothing - } else if (bin->check_extend()) { - bool conflict = false; - // check key conflict - if (OB_FAIL(bin->get_extend(extend))) { - LOG_WARN("fail to get extend", K(ret)); - } else if (OB_FAIL(ObXmlUtil::check_ns_conflict(xpath_iter.get_cur_res_parent(), last_parent, &extend, ns_map, conflict))) { - LOG_WARN("fail to check conflict", K(ret)); - } else if (conflict) { - // if conflict, merge bin - if (OB_FAIL(bin->merge_extend(extend))) { - LOG_WARN("fail to merge extend", K(ret)); - } else { - bin = &extend; - } - } else if (OB_FAIL(bin->remove_extend())) { // if not conflict, erase extend - LOG_WARN("fail to remove extend", K(ret)); - } - } - if (OB_FAIL(ret)) { - } else if (OB_FAIL(bin_agg.append_key_and_value(bin))) { - LOG_WARN("failed to append binary", K(ret)); - } else { - ObMulModeNodeType type = node->type(); - if (append_node_num == 0 && type == ObMulModeNodeType::M_DOCUMENT) { - version = node->get_version(); - encoding = node->get_encoding(); - standalone = node->get_standalone(); - first_is_doc = version.empty() ? false : true; - } - - if (type == ObMulModeNodeType::M_ELEMENT || type == ObMulModeNodeType::M_DOCUMENT) { - element_count++; - } else if (type == ObMulModeNodeType::M_TEXT || type == ObMulModeNodeType::M_CDATA) { - text_count++; - } else if (type == ObMulModeNodeType::M_CONTENT) { - append_node_num += bin->count() - 1; - } - append_node_num++; - } - } - } - - if (ret == OB_ITER_END) { - ret = OB_SUCCESS; - if (element_count > 1 || element_count == 0) { - node_type = ObMulModeNodeType::M_CONTENT; - } else if (element_count == 1 && text_count > 0) { - node_type = ObMulModeNodeType::M_CONTENT; - } else if (append_node_num == 0) { - // do nothing - } else { - node_type = ObMulModeNodeType::M_DOCUMENT; - } - - bin_agg.set_header_type(node_type); - if (first_is_doc && append_node_num == 1) { - bin_agg.set_xml_decl(version, encoding, standalone); - } - } - - int tmp_ret = OB_SUCCESS; - if (OB_SUCCESS != (tmp_ret = xpath_iter.close())) { - LOG_WARN("fail to close xpath iter", K(tmp_ret)); - ret = COVER_SUCC(tmp_ret); - } else if (append_node_num == 0) { + if (OB_FAIL(ret)) { + } else if (is_null_res) { res.set_null(); - } else if (OB_FAIL(bin_agg.serialize())) { - LOG_WARN("failed to serialize binary.", K(ret)); - } else if (ns_map.size() > 0 && OB_FAIL(ObXmlUtil::ns_to_extend(mem_ctx, ns_map, bin_agg.get_buffer()))) { - LOG_WARN("failed to serialize extend.", K(ret)); - } else if (OB_FAIL(ObXMLExprHelper::pack_binary_res(expr, eval_ctx, bin_agg.get_buffer()->string(), blob_locator))) { + } else if (OB_FAIL(ObXMLExprHelper::pack_binary_res(expr, ctx, bin_str, blob_locator))) { LOG_WARN("failed to pack binary res.", K(ret)); } else { res.set_string(blob_locator.ptr(), blob_locator.length()); } - ns_map.clear(); return ret; } diff --git a/src/sql/engine/expr/ob_expr_extract_xml.h b/src/sql/engine/expr/ob_expr_extract_xml.h index 5cbfdd969..93b311090 100644 --- a/src/sql/engine/expr/ob_expr_extract_xml.h +++ b/src/sql/engine/expr/ob_expr_extract_xml.h @@ -36,13 +36,6 @@ class ObExprExtractXml : public ObFuncExprOperator ObExpr &rt_expr) const override; private: - static int concat_xpath_result(const ObExpr &expr, - ObEvalCtx &eval_ctx, - ObPathExprIter &xpath_iter, - ObCollationType cs_type, - ObDatum &res, - ObMulModeNodeType &node_type, - ObMulModeMemCtx* ctx); static int check_and_set_res(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res, diff --git a/src/sql/engine/expr/ob_expr_insert_child_xml.cpp b/src/sql/engine/expr/ob_expr_insert_child_xml.cpp index eca1bf08b..2f91c27c1 100644 --- a/src/sql/engine/expr/ob_expr_insert_child_xml.cpp +++ b/src/sql/engine/expr/ob_expr_insert_child_xml.cpp @@ -103,7 +103,8 @@ int ObExprInsertChildXml::eval_insert_child_xml(const ObExpr &expr, ObEvalCtx &c { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObDatum *xml_datum = NULL; ObIMulModeBase *xml_tree = NULL; ObString xpath_str; @@ -118,7 +119,7 @@ int ObExprInsertChildXml::eval_insert_child_xml(const ObExpr &expr, ObEvalCtx &c bool is_insert_attributes = false; ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), "XMLModule")); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&allocator, mem_ctx))) { LOG_WARN("fail to create tree memory context", K(ret)); } else if (OB_UNLIKELY(expr.arg_cnt_ != 5)) { @@ -127,7 +128,7 @@ int ObExprInsertChildXml::eval_insert_child_xml(const ObExpr &expr, ObEvalCtx &c } else if (ObNullType == expr.args_[1]->datum_meta_.type_) { ret = OB_ERR_INVALID_XPATH_EXPRESSION; LOG_WARN("invalid xpath expression", K(ret)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum, allocator))) { LOG_WARN("fail to get xmltype value", K(ret)); } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[1], ctx, xpath_str, allocator))) { LOG_WARN("fail to get xpath str", K(ret)); @@ -204,7 +205,7 @@ int ObExprInsertChildXml::eval_insert_child_xml(const ObExpr &expr, ObEvalCtx &c int ObExprInsertChildXml::insert_child_xml(const ObExpr &expr, ObEvalCtx &ctx, ObMulModeMemCtx* mem_ctx, - ObArenaAllocator &allocator, + MultimodeAlloctor &allocator, ObPathExprIter &xpath_iter, ObString child_str, ObString value_str, @@ -219,7 +220,8 @@ int ObExprInsertChildXml::insert_child_xml(const ObExpr &expr, uint64_t ele_index = 0; ObDatum *value_datum = NULL; CK(OB_NOT_NULL(expr.args_[3])); - if (expr.args_[3]->datum_meta_.type_ == ObUserDefinedSQLType) { + ObObjType type = expr.args_[3]->datum_meta_.type_; + if (type == ObUserDefinedSQLType) { if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[3], ctx, value_datum))) { LOG_WARN("fail to get xmltype value", K(ret)); } else if (OB_FAIL(ObXMLExprHelper::get_xml_base(mem_ctx, value_datum, CS_TYPE_INVALID, ObNodeMemType::TREE_TYPE, value_doc))) { @@ -280,6 +282,17 @@ int ObExprInsertChildXml::insert_child_xml(const ObExpr &expr, ret = OB_SUCCESS; } + if (OB_FAIL(ret)) { + } else if (type == ObUserDefinedSQLType) { + if (OB_FAIL(allocator.add_baseline_size(value_datum, true, res_array.size()))) { + LOG_WARN("failed to add base line size", K(ret)); + } + } else { + if (OB_FAIL(allocator.add_baseline_size(expr.args_[3], ctx, res_array.size()))) { + LOG_WARN("failed to add base line size", K(ret)); + } + } + for (int i = 0; OB_SUCC(ret) && i < res_array.size(); i++) { ObIMulModeBase* insert_node = res_array[i]; if (OB_ISNULL(insert_node)) { @@ -290,10 +303,13 @@ int ObExprInsertChildXml::insert_child_xml(const ObExpr &expr, LOG_WARN("fail to insert attributes node", K(ret), K(child_str), K(value_str)); } } else { - ObIMulModeBase *value_doc = NULL; - if (OB_FAIL(ObXMLExprHelper::get_xml_base(mem_ctx, value_datum, CS_TYPE_INVALID, ObNodeMemType::TREE_TYPE, value_doc))) { - LOG_WARN("fail to parse xml doc", K(ret)); - } else if (OB_FAIL(insert_element_node(allocator, insert_node, value_doc->at(ele_index)))) { + ObXmlNode *value_clone = nullptr; + if (OB_ISNULL(value_doc->at(ele_index))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get index is null", K(ret), K(ele_index), KP(value_doc)); + } else if (OB_FAIL(value_doc->at(ele_index)->clone(mem_ctx, value_clone))) { + LOG_WARN("failed to clone.", K(ret), K(value_doc)); + } else if (OB_FAIL(insert_element_node(allocator, insert_node, value_clone))) { LOG_WARN("fail to insert element node", K(ret)); } } @@ -308,7 +324,7 @@ int ObExprInsertChildXml::insert_child_xml(const ObExpr &expr, return ret; } -int ObExprInsertChildXml::insert_element_node(ObArenaAllocator &allocator, +int ObExprInsertChildXml::insert_element_node(ObIAllocator &allocator, ObIMulModeBase *insert_node, ObIMulModeBase *value_node) { @@ -389,7 +405,7 @@ int ObExprInsertChildXml::insert_attributes_node(ObString key_str, int ObExprInsertChildXml::check_child_expr(const ObExpr &expr, ObEvalCtx &ctx, - ObArenaAllocator &allocator, + ObIAllocator &allocator, ObMulModeMemCtx* mem_ctx, ObString &child_str, ObString &value_str, diff --git a/src/sql/engine/expr/ob_expr_insert_child_xml.h b/src/sql/engine/expr/ob_expr_insert_child_xml.h index c5824216d..c2eefeabc 100644 --- a/src/sql/engine/expr/ob_expr_insert_child_xml.h +++ b/src/sql/engine/expr/ob_expr_insert_child_xml.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/xml/ob_xpath.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" namespace oceanbase { @@ -41,7 +42,7 @@ private: static int insert_child_xml(const ObExpr &expr, ObEvalCtx &ctx, ObMulModeMemCtx* mem_ctx, - ObArenaAllocator &allocator, + MultimodeAlloctor &allocator, ObPathExprIter &xpath_iter, ObString child_str, ObString value_str, @@ -49,14 +50,14 @@ private: static int check_child_expr(const ObExpr &expr, ObEvalCtx &ctx, - ObArenaAllocator &allocator, + ObIAllocator &allocator, ObMulModeMemCtx* mem_ctx, ObString &child_str, ObString &value_str, bool &is_insert_attributes); static bool is_first_char_attribute(ObString child_str); - static int insert_element_node(ObArenaAllocator &allocator, ObIMulModeBase *insert_node, ObIMulModeBase *value_node); + static int insert_element_node(ObIAllocator &allocator, ObIMulModeBase *insert_node, ObIMulModeBase *value_node); static int insert_attributes_node(ObString key_str, ObString value_str, diff --git a/src/sql/engine/expr/ob_expr_is_json.cpp b/src/sql/engine/expr/ob_expr_is_json.cpp index 26de2b656..bbf8fc0f5 100644 --- a/src/sql/engine/expr/ob_expr_is_json.cpp +++ b/src/sql/engine/expr/ob_expr_is_json.cpp @@ -82,7 +82,7 @@ int ObExprIsJson::calc_result_typeN(ObExprResType& type, int ObExprIsJson::check_is_json(const ObExpr &expr, ObEvalCtx &ctx, const ObDatum &data, ObObjType type, - ObCollationType cs_type, ObArenaAllocator &allocator, + ObCollationType cs_type, MultimodeAlloctor &allocator, uint8_t strict_opt, uint8_t scalar_opt, uint8_t unique_opt, bool check_for_is_json, ObDatum &res) { @@ -275,7 +275,9 @@ int ObExprIsJson::eval_is_json(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) LOG_WARN("eval json arg failed", K(ret)); } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); if (OB_FAIL(check_is_json(expr, ctx, *json_datum, json_arg->datum_meta_.type_, cs_type, temp_allocator, diff --git a/src/sql/engine/expr/ob_expr_is_json.h b/src/sql/engine/expr/ob_expr_is_json.h index 4137a92e6..e1be27d31 100644 --- a/src/sql/engine/expr/ob_expr_is_json.h +++ b/src/sql/engine/expr/ob_expr_is_json.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "sql/engine/expr/ob_expr_lob_utils.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" namespace oceanbase { @@ -33,7 +34,7 @@ public: static int get_is_json_option(const ObExpr &expr, ObEvalCtx &ctx, int64_t idx, uint8_t& is_json_mode); static int check_is_json(const ObExpr &expr, ObEvalCtx &ctx, const ObDatum &data, ObObjType type, - ObCollationType cs_type, ObArenaAllocator &allocator, + ObCollationType cs_type, MultimodeAlloctor &allocator, uint8_t strict_opt, uint8_t scalar_opt, uint8_t unique_opt, bool check_for_is_json, ObDatum &res); static int eval_is_json(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); diff --git a/src/sql/engine/expr/ob_expr_json_array.cpp b/src/sql/engine/expr/ob_expr_json_array.cpp index d99ca799b..481285801 100644 --- a/src/sql/engine/expr/ob_expr_json_array.cpp +++ b/src/sql/engine/expr/ob_expr_json_array.cpp @@ -144,8 +144,8 @@ int ObExprJsonArray::eval_ora_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObD INIT_SUCC(ret); ObDatum *json_datum = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); uint32_t max_val_idx = expr.arg_cnt_ - 3; int64_t opt_array[OPT_MAX_ID] = {0}; int64_t& opt_strict = opt_array[OPT_STRICT_ID]; @@ -154,7 +154,7 @@ int ObExprJsonArray::eval_ora_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObD ObDatum *opt_datum = NULL; ObExpr *opt_expr = expr.args_[i]; ObObjType val_type = opt_expr->datum_meta_.type_; - if (OB_UNLIKELY(OB_FAIL(opt_expr->eval(ctx, opt_datum)))) { + if (OB_FAIL(temp_allocator.eval_arg(opt_expr, ctx, opt_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || opt_datum->is_null()) { } else if (!ob_is_integer_type(val_type)) { @@ -187,7 +187,7 @@ int ObExprJsonArray::eval_ora_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObD ObObjType val_type = opt_expr->datum_meta_.type_; bool is_format_json = false; ObIJsonBase* j_val = nullptr; - if (OB_UNLIKELY(OB_FAIL(opt_expr->eval(ctx, opt_format)))) { + if (OB_FAIL(temp_allocator.eval_arg(opt_expr, ctx, opt_format))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || opt_format->is_null()) { } else if (!ob_is_integer_type(val_type)) { @@ -221,7 +221,7 @@ int ObExprJsonArray::eval_ora_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObD } else { if (OB_FAIL(string_buffer.reserve(j_arr.get_serialize_size()))) { LOG_WARN("fail to reserve string.", K(ret), K(j_arr.get_serialize_size())); - } else if (OB_FAIL(j_arr.print(string_buffer, true, false))) { + } else if (OB_FAIL(j_arr.print(string_buffer, true, 0, false))) { LOG_WARN("failed: get json string text", K(ret)); } else { ObCollationType in_cs_type = CS_TYPE_UTF8MB4_BIN; @@ -262,7 +262,9 @@ int ObExprJsonArray::eval_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObDatum INIT_SUCC(ret); ObDatum *json_datum = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonArray j_arr(&temp_allocator); ObIJsonBase *j_base = &j_arr; @@ -273,7 +275,10 @@ int ObExprJsonArray::eval_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObDatum for (uint32_t i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; i++) { ObIJsonBase *j_val; - if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i, j_val))) { + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i], ctx))) { + LOG_WARN("failed to add baselien size", K(ret), K(i)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i, j_val))) { + ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_WARN("failed: get_json_val failed", K(ret)); } else if (OB_FAIL(j_base->array_append(j_val))) { LOG_WARN("failed: json array append json value", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_json_array_append.cpp b/src/sql/engine/expr/ob_expr_json_array_append.cpp index 5d359a29f..8612eee4c 100644 --- a/src/sql/engine/expr/ob_expr_json_array_append.cpp +++ b/src/sql/engine/expr/ob_expr_json_array_append.cpp @@ -95,7 +95,9 @@ int ObExprJsonArrayAppend::eval_json_array_append(const ObExpr &expr, ObEvalCtx { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObIJsonBase *j_base = NULL; bool is_null = false; ObJsonSeekResult hit; @@ -119,7 +121,7 @@ int ObExprJsonArrayAppend::eval_json_array_append(const ObExpr &expr, ObEvalCtx ObExpr *arg = expr.args_[i]; ObDatum *json_datum = NULL; hit.reset(); - if (OB_FAIL(expr.args_[i]->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, json_datum))) { LOG_WARN("failed: eval json path datum.", K(ret)); } else if (arg->datum_meta_.type_ == ObNullType || json_datum->is_null()) { is_null = true; @@ -136,7 +138,9 @@ int ObExprJsonArrayAppend::eval_json_array_append(const ObExpr &expr, ObEvalCtx // do nothing } else { ObIJsonBase *j_val = NULL; - if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i+1], ctx))) { + LOG_WARN("failed to add baselien size", K(ret), K(i + 1)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_WARN("failed: get_json_val.", K(ret), K(i)); } else { 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 e13ee3468..47804de35 100644 --- a/src/sql/engine/expr/ob_expr_json_array_insert.cpp +++ b/src/sql/engine/expr/ob_expr_json_array_insert.cpp @@ -81,7 +81,8 @@ int ObExprJsonArrayInsert::eval_json_array_insert(const ObExpr &expr, ObEvalCtx { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObIJsonBase *j_base = NULL; bool is_null = false; ObJsonSeekResult hit; @@ -104,7 +105,7 @@ int ObExprJsonArrayInsert::eval_json_array_insert(const ObExpr &expr, ObEvalCtx hit.reset(); ObExpr *arg = expr.args_[i]; ObDatum *json_datum = NULL; - if (OB_FAIL(expr.args_[i]->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, json_datum))) { LOG_WARN("failed: eval json path datum.", K(ret)); } else if (json_datum->is_null() || arg->datum_meta_.type_ == ObNullType) { is_null = true; @@ -129,7 +130,9 @@ int ObExprJsonArrayInsert::eval_json_array_insert(const ObExpr &expr, ObEvalCtx ObIJsonBase *j_pos_node = hit[0]; if (j_pos_node->json_type() == ObJsonNodeType::J_ARRAY) { ObIJsonBase *j_val = NULL; - if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i+1], ctx))) { + LOG_WARN("failed to add baselien size", K(ret), K(i + 1)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_WARN("failed: get_json_val", K(ret)); } else { diff --git a/src/sql/engine/expr/ob_expr_json_contains.cpp b/src/sql/engine/expr/ob_expr_json_contains.cpp index 37873ba82..cd0e0907a 100644 --- a/src/sql/engine/expr/ob_expr_json_contains.cpp +++ b/src/sql/engine/expr/ob_expr_json_contains.cpp @@ -74,7 +74,8 @@ int ObExprJsonContains::eval_json_contains(const ObExpr &expr, ObEvalCtx &ctx, O ObIJsonBase *json_candidate = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 0, json_target, is_null_result))) { LOG_WARN("get_json_doc failed", K(ret)); @@ -95,7 +96,7 @@ int ObExprJsonContains::eval_json_contains(const ObExpr &expr, ObEvalCtx &ctx, O path_cache = ((path_cache != NULL) ? path_cache : &ctx_cache); ObDatum *path_data = NULL; - if (OB_FAIL(expr.args_[2]->eval(ctx, path_data))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[2], ctx, path_data))) { LOG_WARN("eval json path datum failed", K(ret)); } else if (expr.args_[2]->datum_meta_.type_ == ObNullType || path_data->is_null()) { is_null_result = true; diff --git a/src/sql/engine/expr/ob_expr_json_contains_path.cpp b/src/sql/engine/expr/ob_expr_json_contains_path.cpp index 4cb1dbaca..f9bd1e655 100644 --- a/src/sql/engine/expr/ob_expr_json_contains_path.cpp +++ b/src/sql/engine/expr/ob_expr_json_contains_path.cpp @@ -79,7 +79,8 @@ int ObExprJsonContainsPath::eval_json_contains_path(const ObExpr &expr, ObIJsonBase *json_target = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 0, json_target, is_null_result, false))) { LOG_WARN("get_json_doc failed", K(ret)); } else { @@ -88,7 +89,7 @@ int ObExprJsonContainsPath::eval_json_contains_path(const ObExpr &expr, ObDatum *json_datum = NULL; ObExpr *json_arg = expr.args_[1]; ObObjType val_type = json_arg->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { is_null_result = true; @@ -115,7 +116,7 @@ int ObExprJsonContainsPath::eval_json_contains_path(const ObExpr &expr, for (int64_t i = 2; OB_SUCC(ret) && i < expr.arg_cnt_ && !is_null_result; i++) { ObJsonSeekResult hit; ObDatum *path_data = NULL; - if (OB_FAIL(expr.args_[i]->eval(ctx, path_data))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, path_data))) { LOG_WARN("eval json path datum failed", K(ret)); } else if (expr.args_[i]->datum_meta_.type_ == ObNullType || path_data->is_null()) { is_null_result = true; diff --git a/src/sql/engine/expr/ob_expr_json_depth.cpp b/src/sql/engine/expr/ob_expr_json_depth.cpp index 418104761..f7db4e609 100644 --- a/src/sql/engine/expr/ob_expr_json_depth.cpp +++ b/src/sql/engine/expr/ob_expr_json_depth.cpp @@ -59,13 +59,14 @@ int ObExprJsonDepth::eval_json_depth(const ObExpr &expr, ObEvalCtx &ctx, ObDatum bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { is_null_result = true; } else if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 0, - json_doc, is_null_result))) { + json_doc, is_null_result, false))) { LOG_WARN("get_json_doc failed", K(ret)); } else { // do nothing diff --git a/src/sql/engine/expr/ob_expr_json_equal.cpp b/src/sql/engine/expr/ob_expr_json_equal.cpp index 0f82e7e0b..70402d2f3 100644 --- a/src/sql/engine/expr/ob_expr_json_equal.cpp +++ b/src/sql/engine/expr/ob_expr_json_equal.cpp @@ -86,7 +86,8 @@ int ObExprJsonEqual::eval_json_equal(const ObExpr &expr, ObEvalCtx &ctx, ObDatum ObIJsonBase *json_candidate = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); int compare_res = -1; bool is_equal = false; uint8_t option_on_error = 0; @@ -128,7 +129,7 @@ int ObExprJsonEqual::eval_json_equal(const ObExpr &expr, ObEvalCtx &ctx, ObDatum ret = OB_SUCCESS; val_type = json_arg->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObIntType) { int64_t option = json_datum->get_int(); diff --git a/src/sql/engine/expr/ob_expr_json_exists.cpp b/src/sql/engine/expr/ob_expr_json_exists.cpp index e2e9b0e3b..4b39c6204 100644 --- a/src/sql/engine/expr/ob_expr_json_exists.cpp +++ b/src/sql/engine/expr/ob_expr_json_exists.cpp @@ -135,7 +135,7 @@ int ObExprJsonExists::calc_result_typeN(ObExprResType& type, } int ObExprJsonExists::get_path(const ObExpr &expr, ObEvalCtx &ctx, - ObJsonPath* &j_path, common::ObArenaAllocator &allocator, + ObJsonPath* &j_path, common::ObIAllocator &allocator, ObJsonPathCache &ctx_cache, ObJsonPathCache* &path_cache) { INIT_SUCC(ret); @@ -177,7 +177,7 @@ int ObExprJsonExists::get_path(const ObExpr &expr, ObEvalCtx &ctx, return ret; } -int ObExprJsonExists::get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObArenaAllocator &allocator, +int ObExprJsonExists::get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObIAllocator &allocator, uint16_t index, ObIJsonBase*& j_base) { INIT_SUCC(ret); @@ -242,7 +242,7 @@ int ObExprJsonExists::get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::O } int ObExprJsonExists::get_passing(const ObExpr &expr, ObEvalCtx &ctx, PassingMap &pass_map, - uint32_t param_num, ObArenaAllocator& temp_allocator) + uint32_t param_num, ObIAllocator& temp_allocator) { INIT_SUCC(ret); ObExpr *json_arg = nullptr; @@ -415,7 +415,9 @@ int ObExprJsonExists::eval_json_exists(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObIJsonBase *json_data = NULL; bool is_null_json = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonPathCache ctx_cache(&temp_allocator); ObJsonPathCache* path_cache = nullptr; ObJsonPath* j_path = nullptr; diff --git a/src/sql/engine/expr/ob_expr_json_exists.h b/src/sql/engine/expr/ob_expr_json_exists.h index c505ca00c..a44744f73 100644 --- a/src/sql/engine/expr/ob_expr_json_exists.h +++ b/src/sql/engine/expr/ob_expr_json_exists.h @@ -34,15 +34,15 @@ public: common::ObExprTypeCtx& type_ctx) const override; virtual bool need_rt_ctx() const override { return true; } static int get_path(const ObExpr &expr, ObEvalCtx &ctx, ObJsonPath* &j_path, - common::ObArenaAllocator &allocator, + common::ObIAllocator &allocator, ObJsonPathCache &ctx_cache, ObJsonPathCache* &path_cache); - static int get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObArenaAllocator &allocator, + static int get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObIAllocator &allocator, uint16_t index, ObIJsonBase*& j_base); - static int get_json_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObArenaAllocator &allocator, + static int get_json_data(const ObExpr &expr, ObEvalCtx &ctx, common::ObIAllocator &allocator, uint16_t index, ObIJsonBase*& j_base, bool &is_null, bool need_to_tree, bool need_quote); static int get_passing(const ObExpr &expr, ObEvalCtx &ctx, PassingMap &pass_map, - uint32_t param_num, common::ObArenaAllocator &temp_allocator); + uint32_t param_num, common::ObIAllocator &temp_allocator); static int get_error_or_empty(const ObExpr &expr, ObEvalCtx &ctx, uint32_t idx, uint8_t &result); static int get_error_option(int8_t option_on_error, bool& res_val); static int get_empty_option(int8_t option_on_empty, bool& res_val); diff --git a/src/sql/engine/expr/ob_expr_json_extract.cpp b/src/sql/engine/expr/ob_expr_json_extract.cpp index 4b3c34dd2..dda8de0b1 100644 --- a/src/sql/engine/expr/ob_expr_json_extract.cpp +++ b/src/sql/engine/expr/ob_expr_json_extract.cpp @@ -106,11 +106,12 @@ int ObExprJsonExtract::eval_json_extract(const ObExpr &expr, ObEvalCtx &ctx, ObD bool is_null_result = false; bool may_match_many = (expr.arg_cnt_ > 2); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (expr.datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("invalid out put charset", K(ret), K(expr.datum_meta_.cs_type_)); - } else if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, json_datum)))) { + } else if (OB_FAIL(allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (json_datum->is_null()) { is_null_result = true; // mysql return NULL result @@ -124,6 +125,7 @@ int ObExprJsonExtract::eval_json_extract(const ObExpr &expr, ObEvalCtx &ctx, ObD ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type); if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, allocator, j_str, is_null_result))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (OB_FALSE_IT(allocator.set_baseline_size(j_str.length()))) { } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_str, j_in_type, j_in_type, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { LOG_WARN("fail to get json base", K(ret), K(j_in_type)); ret = OB_ERR_INVALID_JSON_TEXT; @@ -150,7 +152,7 @@ int ObExprJsonExtract::eval_json_extract(const ObExpr &expr, ObEvalCtx &ctx, ObD for (int64_t i = 1; OB_SUCC(ret) && (!is_null_result) && i < expr.arg_cnt_; i++) { hit.reset(); ObDatum *path_data = NULL; - if (OB_FAIL(expr.args_[i]->eval(ctx, path_data))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[i], ctx, path_data))) { LOG_WARN("eval json path datum failed", K(ret)); } else if (path_data->is_null()) { is_null_result = true; 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 d39b87559..c96f3027f 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -91,6 +91,30 @@ int ObJsonExprHelper::ensure_collation(ObObjType type, ObCollationType cs_type) return ret; } +int ObJsonExprHelper::get_json_or_str_data(ObExpr *expr, ObEvalCtx &ctx, + MultimodeAlloctor &allocator, + ObString& str, bool& is_null) +{ + INIT_SUCC(ret); + ObDatum *json_datum = NULL; + ObObjType val_type = expr->datum_meta_.type_; + if (OB_FAIL(allocator.eval_arg(expr, ctx, json_datum))) { + LOG_WARN("eval json arg failed", K(ret)); + } else if (json_datum->is_null() || val_type == ObNullType) { + is_null = true; + } else if (!ob_is_extend(val_type) + && !ob_is_json(val_type) + && !ob_is_raw(val_type) + && !ob_is_string_type(val_type)) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("input type error", K(val_type)); + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, *json_datum, + expr->datum_meta_, expr->obj_meta_.has_lob_header(), str))) { + LOG_WARN("fail to get real data.", K(ret), K(str)); + } + return ret; +} + int ObJsonExprHelper::get_json_or_str_data(ObExpr *expr, ObEvalCtx &ctx, common::ObIAllocator &allocator, ObString& str, bool& is_null) @@ -116,7 +140,7 @@ int ObJsonExprHelper::get_json_or_str_data(ObExpr *expr, ObEvalCtx &ctx, } int ObJsonExprHelper::get_json_schema(const ObExpr &expr, ObEvalCtx &ctx, - common::ObArenaAllocator &allocator, + MultimodeAlloctor &allocator, uint16_t index, ObIJsonBase*& j_schema, bool &is_null) { @@ -126,7 +150,7 @@ int ObJsonExprHelper::get_json_schema(const ObExpr &expr, ObEvalCtx &ctx, ObExpr *schema_arg = expr.args_[index]; ObObjType type = schema_arg->datum_meta_.type_; ObCollationType cs_type = schema_arg->datum_meta_.cs_type_; - if (OB_FAIL(schema_arg->eval(ctx, schema_datum))) { + if (OB_FAIL(allocator.eval_arg(schema_arg, ctx, schema_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (type == ObNullType || schema_datum->is_null()) { is_null = true; @@ -140,6 +164,7 @@ int ObJsonExprHelper::get_json_schema(const ObExpr &expr, ObEvalCtx &ctx, if (OB_FAIL(get_json_or_str_data(schema_arg, ctx, allocator, j_str, is_null))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); } else if (is_null) { + } else if (OB_FALSE_IT(allocator.add_baseline_size(j_str.length()))) { } else { ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); ObJsonSchemaCache* schema_cache = ObJsonExprHelper::get_schema_cache_ctx(expr.expr_ctx_id_, &ctx.exec_ctx_); @@ -153,8 +178,9 @@ int ObJsonExprHelper::get_json_schema(const ObExpr &expr, ObEvalCtx &ctx, return ret; } +/* int ObJsonExprHelper::get_json_doc(const ObExpr &expr, ObEvalCtx &ctx, - common::ObArenaAllocator &allocator, + common::ObIAllocator &allocator, uint16_t index, ObIJsonBase*& j_base, bool &is_null, bool need_to_tree, bool relax, bool preserve_dup) @@ -211,6 +237,67 @@ int ObJsonExprHelper::get_json_doc(const ObExpr &expr, ObEvalCtx &ctx, } return ret; } +*/ + +int ObJsonExprHelper::get_json_doc(const ObExpr &expr, ObEvalCtx &ctx, + MultimodeAlloctor &allocator, + uint16_t index, ObIJsonBase*& j_base, + bool &is_null, bool need_to_tree, + bool relax, bool preserve_dup) +{ + INIT_SUCC(ret); + ObDatum *json_datum = NULL; + ObExpr *json_arg = expr.args_[index]; + ObObjType val_type = json_arg->datum_meta_.type_; + ObCollationType cs_type = json_arg->datum_meta_.cs_type_; + bool is_oracle = lib::is_oracle_mode(); + bool allow_partial_update = false; + + if (OB_UNLIKELY(OB_FAIL(allocator.eval_arg(json_arg, ctx, json_datum)))) { + LOG_WARN("eval json arg failed", K(ret)); + } else if (val_type == ObNullType || json_datum->is_null()) { + is_null = true; + } else if (val_type != ObJsonType && !ob_is_string_type(val_type)) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("input type error", K(val_type)); + } else if (lib::is_mysql_mode() && OB_FAIL(ObJsonExprHelper::ensure_collation(val_type, cs_type))) { + LOG_WARN("fail to ensure collation", K(ret), K(val_type), K(cs_type)); + } else if (ob_is_json(val_type) + && OB_FAIL(ObJsonExprHelper::is_allow_partial_update(expr, ctx, json_datum->get_string(), allow_partial_update))) { + LOG_WARN("get partial updaet setting fail", K(ret)); + } else if (allow_partial_update) { + if (OB_FAIL(get_json_for_partial_update(expr, *json_arg, ctx, allocator, *json_datum, j_base))) { + LOG_WARN("get_json_for_partial_update fail", K(ret), K(val_type)); + } + } else { + ObString j_str; + if (OB_FAIL(get_json_or_str_data(json_arg, ctx, allocator, j_str, is_null))) { + LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (is_null) { + } else if (OB_FALSE_IT(allocator.add_baseline_size(j_str.length()))) { + } else { + ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type); + + ObJsonInType expect_type = need_to_tree ? ObJsonInType::JSON_TREE : j_in_type; + bool relax_json = (lib::is_oracle_mode() && relax); + uint32_t parse_flag = relax_json ? ObJsonParser::JSN_RELAXED_FLAG : 0; + ADD_FLAG_IF_NEED(preserve_dup, parse_flag, ObJsonParser::JSN_PRESERVE_DUP_FLAG); + if (is_oracle && j_str.length() == 0) { + is_null = true; + } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_str, j_in_type, + expect_type, j_base, parse_flag))) { + LOG_WARN("fail to get json base", K(ret), K(j_in_type)); + if (is_oracle) { + ret = OB_ERR_JSON_SYNTAX_ERROR; + } else { + ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; + LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT_IN_PARAM); + } + } + } + } + return ret; +} int ObJsonExprHelper::get_const_json_schema(const common::ObObj &data, const char* func_name, common::ObIAllocator *allocator, ObIJsonBase*& j_schema) @@ -519,7 +606,7 @@ int ObJsonExprHelper::cast_to_json_tree(ObString &text, common::ObIAllocator *al LOG_WARN("get json tree fail", K(ret)); } else { ObJsonBuffer jbuf(allocator); - if (OB_FAIL(j_tree->print(jbuf, true, false, 0))) { + if (OB_FAIL(j_tree->print(jbuf, true, 0, false, 0))) { LOG_WARN("json binary to string failed", K(ret)); } else if (jbuf.empty()) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -631,7 +718,11 @@ int ObJsonExprHelper::get_json_val(const ObExpr &expr, ObEvalCtx &ctx, ObDatum *json_datum = NULL; ObExpr *json_arg = expr.args_[index]; ObObjType val_type = json_arg->datum_meta_.type_; - if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, json_datum)))) { + MultimodeAlloctor *alloc = nullptr; + if (OB_ISNULL(alloc = static_cast(allocator))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null alloc.", K(ret)); + } else if (OB_FAIL(alloc->eval_arg(json_arg, 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)); @@ -698,7 +789,7 @@ int ObJsonExprHelper::get_json_val(const ObExpr &expr, ObEvalCtx &ctx, int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, ObEvalCtx &ctx, - common::ObIAllocator *allocator, + MultimodeAlloctor *allocator, ObIJsonBase*& j_base, bool is_format_json, bool is_strict, @@ -710,8 +801,10 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, ObExpr *json_arg = expr; bool is_bool_data_type = (json_arg->is_boolean_ || json_arg->datum_meta_.type_ == ObTinyIntType); - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(allocator->eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret), K(json_arg->datum_meta_)); + } else if (OB_FAIL(allocator->add_baseline_size(json_datum, json_arg->obj_meta_.has_lob_header()))) { + LOG_WARN("failed to add baselien size", K(ret)); } else if ((json_datum->is_null() || ob_is_null(json_arg->obj_meta_.get_type())) && is_absent_null) { } else if (OB_FAIL(oracle_datum2_json_val(json_datum, 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 54db07caf..aad707324 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.h +++ b/src/sql/engine/expr/ob_expr_json_func_helper.h @@ -28,6 +28,8 @@ #include "lib/json_type/ob_json_diff.h" #include "sql/engine/expr/ob_expr_result_type_util.h" #include "storage/lob/ob_lob_util.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" +#include "sql/engine/ob_exec_context.h" using namespace oceanbase::common; @@ -203,6 +205,9 @@ public: static int get_json_or_str_data(ObExpr *expr, ObEvalCtx &ctx, common::ObIAllocator &allocator, ObString& str, bool& is_null); + static int get_json_or_str_data(ObExpr *expr, ObEvalCtx &ctx, + MultimodeAlloctor &allocator, + ObString& str, bool& is_null); /* get json doc to JsonBase in static_typing_engine @param[in] expr the input arguments @@ -214,12 +219,12 @@ public: @return Returns OB_SUCCESS on success, error code otherwise. */ static int get_json_doc(const ObExpr &expr, ObEvalCtx &ctx, - common::ObArenaAllocator &allocator, + MultimodeAlloctor &allocator, uint16_t index, ObIJsonBase*& j_base, bool &is_null, bool need_to_tree=true, bool relax = true, bool preserve_dup = false); static int get_json_schema(const ObExpr &expr, ObEvalCtx &ctx, - common::ObArenaAllocator &allocator, + MultimodeAlloctor &allocator, uint16_t index, ObIJsonBase*& j_base, bool &is_null); @@ -295,7 +300,7 @@ public: ObBasicSessionInfo *session, ObIJsonBase*& j_base, bool is_bool_data_type, bool format_json = false, bool is_strict = false, bool is_bin = false); - static int eval_oracle_json_val(ObExpr *expr, ObEvalCtx &ctx, common::ObIAllocator *allocator, + static int eval_oracle_json_val(ObExpr *expr, ObEvalCtx &ctx, MultimodeAlloctor *allocator, ObIJsonBase*& j_base, bool format_json = false, bool is_strict = false, bool is_bin = false, bool is_absent_null = false); /* diff --git a/src/sql/engine/expr/ob_expr_json_insert.cpp b/src/sql/engine/expr/ob_expr_json_insert.cpp index 6cf2941ce..2763e20a5 100644 --- a/src/sql/engine/expr/ob_expr_json_insert.cpp +++ b/src/sql/engine/expr/ob_expr_json_insert.cpp @@ -84,7 +84,9 @@ int ObExprJsonInsert::eval_json_insert(const ObExpr &expr, ObEvalCtx &ctx, ObDat { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObIJsonBase *j_base = NULL; ObDatum *json_datum = NULL; bool is_null = false; @@ -107,7 +109,7 @@ int ObExprJsonInsert::eval_json_insert(const ObExpr &expr, ObEvalCtx &ctx, ObDat for (int32 i = 1; OB_SUCC(ret) && i < expr.arg_cnt_ && !is_null; i += 2) { ObExpr *arg = expr.args_[i]; json_datum = NULL; - if (OB_FAIL(expr.args_[i]->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, json_datum))) { LOG_WARN("failed: eval json path datum.", K(ret)); } else if (arg->datum_meta_.type_ == ObNullType || json_datum->is_null()) { is_null = true; @@ -133,7 +135,9 @@ int ObExprJsonInsert::eval_json_insert(const ObExpr &expr, ObEvalCtx &ctx, ObDat // do nothing } else { ObIJsonBase *j_val; - if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i+1], ctx))) { + LOG_WARN("add baseline size failed.", K(ret), K(i + 1)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_WARN("failed: get_json_val.", K(ret)); } else { diff --git a/src/sql/engine/expr/ob_expr_json_keys.cpp b/src/sql/engine/expr/ob_expr_json_keys.cpp index 23c3115e0..433bf64a8 100644 --- a/src/sql/engine/expr/ob_expr_json_keys.cpp +++ b/src/sql/engine/expr/ob_expr_json_keys.cpp @@ -101,7 +101,8 @@ int ObExprJsonKeys::eval_json_keys(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ObIJsonBase *json_doc = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (expr.datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("invalid out put charset", K(ret), K(expr.datum_meta_.cs_type_)); @@ -119,7 +120,7 @@ int ObExprJsonKeys::eval_json_keys(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ObDatum *path_data = NULL; if (expr.args_[1]->datum_meta_.type_ == ObNullType) { is_null_result = true; - } else if (OB_FAIL(expr.args_[1]->eval(ctx, path_data))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, path_data))) { LOG_WARN("eval json path datum failed", K(ret)); } else { ObJsonSeekResult sub_json_targets; diff --git a/src/sql/engine/expr/ob_expr_json_length.cpp b/src/sql/engine/expr/ob_expr_json_length.cpp index 9749e5598..2bda71f7e 100644 --- a/src/sql/engine/expr/ob_expr_json_length.cpp +++ b/src/sql/engine/expr/ob_expr_json_length.cpp @@ -63,7 +63,7 @@ int ObExprJsonLength::calc_result_typeN(ObExprResType& type, int ObExprJsonLength::calc(ObEvalCtx &ctx, const ObDatum &data1, ObDatumMeta meta1, bool has_lob_header1, const ObDatum *data2, ObDatumMeta meta2, bool has_lob_header2, - ObIAllocator *allocator, ObDatum &res, + MultimodeAlloctor *allocator, ObDatum &res, ObJsonPathCache* path_cache) { INIT_SUCC(ret); @@ -88,6 +88,7 @@ int ObExprJsonLength::calc(ObEvalCtx &ctx, const ObDatum &data1, ObDatumMeta met LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, data1, meta1, has_lob_header1, j_doc))) { LOG_WARN("fail to get real data.", K(ret), K(j_doc)); + } else if (OB_FALSE_IT(allocator->add_baseline_size(j_doc.length()))) { } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_doc, j_in_type, j_in_type, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { @@ -147,16 +148,17 @@ int ObExprJsonLength::eval_json_length(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObDatum *datum0 = NULL; ObExpr *arg0 = expr.args_[0]; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); - if (OB_FAIL(arg0->eval(ctx, datum0))) { // json doc + if (OB_FAIL(tmp_allocator.eval_arg(arg0, ctx, datum0))) { // json doc LOG_WARN("fail to eval json arg", K(ret), K(arg0->datum_meta_)); } else { if (expr.arg_cnt_ > 1) { // json path ObExpr *arg1 = expr.args_[1]; meta1 = arg1->datum_meta_; has_lob_header1 = arg1->obj_meta_.has_lob_header(); - if (OB_FAIL(arg1->eval(ctx, datum1))) { + if (OB_FAIL(tmp_allocator.eval_arg(arg1, ctx, datum1))) { LOG_WARN("fail to eval path arg", K(ret), K(meta1)); } } diff --git a/src/sql/engine/expr/ob_expr_json_length.h b/src/sql/engine/expr/ob_expr_json_length.h index 3fe0432f6..e01a58ebb 100644 --- a/src/sql/engine/expr/ob_expr_json_length.h +++ b/src/sql/engine/expr/ob_expr_json_length.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/json_type/ob_json_path.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; @@ -35,7 +36,7 @@ public: static int calc(ObEvalCtx &ctx, const ObDatum &data1, ObDatumMeta meta1, bool has_lob_header1, const ObDatum *data2, ObDatumMeta meta2, bool has_lob_header2, - ObIAllocator *allocator, ObDatum &res, + MultimodeAlloctor *allocator, ObDatum &res, ObJsonPathCache* path_cache); static int eval_json_length(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, 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 152239775..f2ede5609 100644 --- a/src/sql/engine/expr/ob_expr_json_member_of.cpp +++ b/src/sql/engine/expr/ob_expr_json_member_of.cpp @@ -90,16 +90,20 @@ int ObExprJsonMemberOf::eval_json_member_of(const ObExpr &expr, ObEvalCtx &ctx, ObIJsonBase *json_a = NULL; ObIJsonBase *json_b = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); bool is_null_result = (expr.args_[0]->datum_meta_.type_ == ObNullType); if (!is_null_result) { ObDatum *json_datum = NULL; ObExpr *json_arg = expr.args_[0]; ObObjType type2 = expr.args_[1]->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (json_datum->is_null()) { is_null_result = true; + } else if (OB_FAIL(temp_allocator.add_baseline_size(json_datum, json_arg->obj_meta_.has_lob_header()))) { + LOG_WARN("failed to add baselien size", K(ret)); } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, 0, json_a))) { LOG_WARN("get_json_value failed", K(ret)); } else if (!ObJsonExprHelper::is_convertible_to_json(type2)) { 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 da5ecba56..467faf194 100644 --- a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp +++ b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp @@ -110,7 +110,9 @@ int ObExprJsonMergePatch::eval_json_merge_patch(const ObExpr &expr, ObEvalCtx &c { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObIJsonBase *j_base = NULL; ObIJsonBase *j_patch_node = NULL; bool has_null = false; @@ -185,7 +187,9 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); bool is_cover_error = false; int err_code = 0; @@ -197,7 +201,7 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt ObExpr *opt_expr = expr.args_[i]; ObObjType val_type = opt_expr->datum_meta_.type_; ObCollationType cs_type = opt_expr->datum_meta_.cs_type_; - if (OB_UNLIKELY(OB_FAIL(opt_expr->eval(ctx, opt_datum)))) { + if (OB_FAIL(temp_allocator.eval_arg(opt_expr, ctx, opt_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || opt_datum->is_null()) { } else if (!ob_is_integer_type(val_type)) { @@ -311,7 +315,7 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt ObString result_str; bool is_quote = j_base->json_type() == ObJsonNodeType::J_STRING; - if (OB_FAIL(j_base->print(*jbuf, is_quote, is_pretty > 0))) { + if (OB_FAIL(j_base->print(*jbuf, is_quote, 0, is_pretty > 0))) { LOG_WARN("json binary to string failed", K(ret)); } else if (jbuf->empty()) { ret = OB_ERR_UNEXPECTED; 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 38c884804..e88be975e 100644 --- a/src/sql/engine/expr/ob_expr_json_merge_preserve.cpp +++ b/src/sql/engine/expr/ob_expr_json_merge_preserve.cpp @@ -72,7 +72,9 @@ int ObExprJsonMergePreserve::eval_json_merge_preserve(const ObExpr &expr, ObEval INIT_SUCC(ret); ObDatum *json_datum = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObIJsonBase *j_base = NULL; ObIJsonBase *j_patch_node = NULL; bool has_null = false; @@ -82,7 +84,10 @@ int ObExprJsonMergePreserve::eval_json_merge_preserve(const ObExpr &expr, ObEval } for (int32 i = 0; OB_SUCC(ret) && i < expr.arg_cnt_ && !has_null; i++) { - if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, i, j_patch_node, has_null))) { + ObIJsonBase *j_res = NULL; + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i], ctx))) { + LOG_WARN("failed to add baseline size.", K(ret)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, i, j_patch_node, has_null))) { LOG_WARN("get_json_doc failed", K(ret)); } else if (has_null) { // do nothing diff --git a/src/sql/engine/expr/ob_expr_json_object.cpp b/src/sql/engine/expr/ob_expr_json_object.cpp index 1d88e620f..f87d2d459 100644 --- a/src/sql/engine/expr/ob_expr_json_object.cpp +++ b/src/sql/engine/expr/ob_expr_json_object.cpp @@ -193,7 +193,9 @@ int ObExprJsonObject::eval_json_object(const ObExpr &expr, ObEvalCtx &ctx, ObDat { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonObject j_obj(&temp_allocator); ObIJsonBase *j_base = &j_obj; @@ -205,7 +207,7 @@ int ObExprJsonObject::eval_json_object(const ObExpr &expr, ObEvalCtx &ctx, ObDat for (int32 i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; i += 2) { ObExpr *arg = expr.args_[i]; ObDatum *json_datum = NULL; - if (OB_FAIL(arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(arg, ctx, json_datum))) { LOG_WARN("failed: eval json args datum failed", K(ret)); } else if (json_datum->is_null()) { ret = OB_ERR_JSON_DOCUMENT_NULL_KEY; @@ -217,6 +219,9 @@ int ObExprJsonObject::eval_json_object(const ObExpr &expr, ObEvalCtx &ctx, ObDat bool is_null = false; if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(arg, ctx, temp_allocator, key, is_null))) { LOG_WARN("fail to get real data.", K(ret), K(key)); + } else if (OB_FALSE_IT(temp_allocator.add_baseline_size(key.length()))) { + } else if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i+1], ctx))) { + LOG_WARN("failed to add baseline size.", K(ret), K(i+1)); } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, j_val))) { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT_IN_PARAM); @@ -250,7 +255,9 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonBuffer string_buffer(&temp_allocator); ObObjType val_type; ObCollationType value_cs_type; @@ -273,7 +280,7 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O int64_t opt_res_type = 0; ObDatum *datum_res_type = nullptr; if (OB_FAIL(ret)) { - } else if (OB_UNLIKELY(OB_FAIL(expr.args_[expr.arg_cnt_ - 3]->eval(ctx, datum_res_type)))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[expr.arg_cnt_ - 3], ctx, datum_res_type))) { LOG_WARN("eval json arg failed", K(ret)); } else { opt_res_type = datum_res_type->get_int(); @@ -313,7 +320,7 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O ObObjType value_data_type = arg_value->datum_meta_.type_; ObDatum *datum_key = nullptr; - if (OB_FAIL(arg_key->eval(ctx, datum_key))) { + if (OB_FAIL(temp_allocator.eval_arg(arg_key, ctx, datum_key))) { LOG_WARN("failed: eval json args datum failed", K(ret)); } else if (datum_key->is_null() || key_data_type == ObNullType) { ret = OB_ERR_JSON_DOCUMENT_NULL_KEY; @@ -333,6 +340,7 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O ObIJsonBase *j_val = nullptr; ObString key = datum_key->get_string(); bool is_format_json = format_type > 0; + temp_allocator.add_baseline_size(key.length()); if (OB_FAIL(ObJsonExprHelper::eval_oracle_json_val( arg_value, ctx, &temp_allocator, j_val, is_format_json, is_strict, false, is_null_absent))) { @@ -369,7 +377,7 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O if (OB_FAIL(string_buffer.reserve(j_obj.get_serialize_size()))) { LOG_WARN("fail to reserve string.", K(ret), K(j_obj.get_serialize_size())); - } else if (OB_FAIL(j_base->print(string_buffer, false, false))) { + } else if (OB_FAIL(j_base->print(string_buffer, false, 0, false))) { LOG_WARN("fail to transform to string.", K(ret), K(string_buffer.length())); } else { ObCollationType in_cs_type = CS_TYPE_UTF8MB4_BIN; @@ -447,22 +455,6 @@ int ObExprJsonObject::set_result(ObObjType dst_type, ObString str_res, common::O return ret; } -int ObExprJsonObject::get_ora_json_doc(const ObExpr &expr, ObEvalCtx &ctx, - uint16_t index, ObDatum*& j_datum, - bool &is_null) -{ - INIT_SUCC(ret); - ObExpr *json_arg = expr.args_[index]; - j_datum = NULL; - ObObjType val_type = json_arg->datum_meta_.type_; - if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, j_datum)))) { - LOG_WARN("eval json arg failed", K(ret), K(val_type)); - } else if (j_datum->is_null()) { - is_null = true; - } - return ret; -} - int ObExprJsonObject::eval_option_clause_value(ObExpr *expr, ObEvalCtx &ctx, uint8_t &type, diff --git a/src/sql/engine/expr/ob_expr_json_object.h b/src/sql/engine/expr/ob_expr_json_object.h index fae3c1619..ca61f85af 100644 --- a/src/sql/engine/expr/ob_expr_json_object.h +++ b/src/sql/engine/expr/ob_expr_json_object.h @@ -60,9 +60,6 @@ private: uint8_t &type, int64_t size_para); - static int get_ora_json_doc(const ObExpr &expr, ObEvalCtx &ctx, - uint16_t index, ObDatum*& j_datum, - bool &is_null); private: DISALLOW_COPY_AND_ASSIGN(ObExprJsonObject); diff --git a/src/sql/engine/expr/ob_expr_json_overlaps.cpp b/src/sql/engine/expr/ob_expr_json_overlaps.cpp index 6bce6d119..d11c428a3 100644 --- a/src/sql/engine/expr/ob_expr_json_overlaps.cpp +++ b/src/sql/engine/expr/ob_expr_json_overlaps.cpp @@ -66,7 +66,8 @@ int ObExprJsonOverlaps::eval_json_overlaps(const ObExpr &expr, ObEvalCtx &ctx, O ObIJsonBase *json_b = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (!ObJsonExprHelper::is_convertible_to_json(expr.args_[0]->datum_meta_.type_)) { ret = OB_ERR_INVALID_TYPE_FOR_JSON; diff --git a/src/sql/engine/expr/ob_expr_json_pretty.cpp b/src/sql/engine/expr/ob_expr_json_pretty.cpp index 0251f5aa5..943ebe4e2 100644 --- a/src/sql/engine/expr/ob_expr_json_pretty.cpp +++ b/src/sql/engine/expr/ob_expr_json_pretty.cpp @@ -55,7 +55,7 @@ int ObExprJsonPretty::calc_result_type1(ObExprResType &type, } int ObExprJsonPretty::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObJsonBuffer &j_buf, bool &is_null) + MultimodeAlloctor *allocator, ObJsonBuffer &j_buf, bool &is_null) { INIT_SUCC(ret); ObObjType type = meta.type_; @@ -76,6 +76,7 @@ int ObExprJsonPretty::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta LOG_WARN("fail to ensure collation", K(ret), K(type), K(cs_type)); } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, data, meta, has_lob_header, j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (OB_FALSE_IT(allocator->add_baseline_size(j_str.length()))) { } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { @@ -83,7 +84,7 @@ int ObExprJsonPretty::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta 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, 0))) { + } else if (OB_FAIL(j_base->print(j_buf, true, j_str.length(), true, 0))) { LOG_WARN("fail to print json", K(ret), K(type), K(j_str), K(j_in_type)); } @@ -95,13 +96,15 @@ int ObExprJsonPretty::eval_json_pretty(const ObExpr &expr, ObEvalCtx &ctx, ObDat { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObExpr *arg = expr.args_[0]; ObDatum *j_datum = NULL; ObJsonBuffer j_buf(&tmp_allocator); bool is_null = false; - if (OB_FAIL(arg->eval(ctx, j_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(arg, ctx, j_datum))) { ret = OB_ERR_INVALID_DATATYPE; LOG_WARN("error, eval json args datum failed", K(ret)); } else if (OB_FAIL(calc(ctx, *j_datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &tmp_allocator, j_buf, is_null))) { diff --git a/src/sql/engine/expr/ob_expr_json_pretty.h b/src/sql/engine/expr/ob_expr_json_pretty.h index 992decc3a..0c531e700 100644 --- a/src/sql/engine/expr/ob_expr_json_pretty.h +++ b/src/sql/engine/expr/ob_expr_json_pretty.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/json_type/ob_json_common.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; @@ -30,7 +31,7 @@ public: virtual ~ObExprJsonPretty(); static int calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObJsonBuffer &j_buf, bool &is_null); + MultimodeAlloctor *allocator, ObJsonBuffer &j_buf, bool &is_null); int calc_result_type1(ObExprResType &type, ObExprResType &type1, common::ObExprTypeCtx &type_ctx) const override; diff --git a/src/sql/engine/expr/ob_expr_json_query.cpp b/src/sql/engine/expr/ob_expr_json_query.cpp index a3edf57a7..dc3aec139 100644 --- a/src/sql/engine/expr/ob_expr_json_query.cpp +++ b/src/sql/engine/expr/ob_expr_json_query.cpp @@ -218,7 +218,9 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum bool is_null_result = false; uint8_t is_type_mismatch = 0; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonBin st_json(&temp_allocator); ObIJsonBase *j_base = &st_json; ObIJsonBase *jb_empty = NULL; diff --git a/src/sql/engine/expr/ob_expr_json_quote.cpp b/src/sql/engine/expr/ob_expr_json_quote.cpp index f208f8f4e..9bb615d3d 100644 --- a/src/sql/engine/expr/ob_expr_json_quote.cpp +++ b/src/sql/engine/expr/ob_expr_json_quote.cpp @@ -58,7 +58,7 @@ int ObExprJsonQuote::calc_result_type1(ObExprResType &type, } -int ObExprJsonQuote::calc(ObEvalCtx &ctx, ObIAllocator &temp_allocator, const ObDatum &data, +int ObExprJsonQuote::calc(ObEvalCtx &ctx, MultimodeAlloctor &temp_allocator, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, ObJsonBuffer &j_buf, bool &is_null) { INIT_SUCC(ret); @@ -88,6 +88,7 @@ int ObExprJsonQuote::calc(ObEvalCtx &ctx, ObIAllocator &temp_allocator, const Ob if (OB_FAIL(j_buf.append("\"\"", 2))) { LOG_WARN("failed: jbuf append", K(ret)); } + } else if (OB_FALSE_IT(temp_allocator.add_baseline_size(j_buf.length()))) { } else if (OB_FAIL(ObJsonPathUtil::double_quote(json_val, &j_buf))) { LOG_WARN("failed: add double quote", K(ret), K(json_val)); } @@ -100,13 +101,15 @@ int ObExprJsonQuote::eval_json_quote(const ObExpr &expr, ObEvalCtx &ctx, ObDatum { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonBuffer j_buf(&temp_allocator); ObExpr *arg = expr.args_[0]; ObDatum* json_datum = NULL; bool is_null = false; - if (OB_FAIL(arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(arg, ctx, json_datum))) { LOG_WARN("failed: eval json args datum.", K(ret)); } else if (OB_FAIL(calc(ctx, temp_allocator, *json_datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), j_buf, is_null))) { diff --git a/src/sql/engine/expr/ob_expr_json_quote.h b/src/sql/engine/expr/ob_expr_json_quote.h index 536dfceb5..9e17cec5d 100644 --- a/src/sql/engine/expr/ob_expr_json_quote.h +++ b/src/sql/engine/expr/ob_expr_json_quote.h @@ -17,6 +17,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/json_type/ob_json_tree.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; @@ -30,7 +31,7 @@ public: explicit ObExprJsonQuote(common::ObIAllocator &alloc); virtual ~ObExprJsonQuote(); - static int calc(ObEvalCtx &ctx, ObIAllocator &temp_allocator, const ObDatum &data, + static int calc(ObEvalCtx &ctx, MultimodeAlloctor &temp_allocator, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, ObJsonBuffer &j_buf, bool &is_null); int calc_result_type1(ObExprResType &type, ObExprResType &type1, diff --git a/src/sql/engine/expr/ob_expr_json_remove.cpp b/src/sql/engine/expr/ob_expr_json_remove.cpp index de71ae045..c11ce6038 100644 --- a/src/sql/engine/expr/ob_expr_json_remove.cpp +++ b/src/sql/engine/expr/ob_expr_json_remove.cpp @@ -90,7 +90,8 @@ int ObExprJsonRemove::eval_json_remove(const ObExpr &expr, ObEvalCtx &ctx, ObDat bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (expr.datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("invalid out put charset", K(ret), K(expr.datum_meta_.cs_type_)); @@ -112,7 +113,7 @@ int ObExprJsonRemove::eval_json_remove(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObDatum *path_data = NULL; if (expr.args_[i]->datum_meta_.type_ == ObNullType) { is_null_result = true; - } else if (OB_FAIL(expr.args_[i]->eval(ctx, path_data))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, path_data))) { ret = OB_ERR_INVALID_JSON_PATH; LOG_USER_ERROR(OB_ERR_INVALID_JSON_PATH); } else { diff --git a/src/sql/engine/expr/ob_expr_json_replace.cpp b/src/sql/engine/expr/ob_expr_json_replace.cpp index f63e85061..f9bd6493c 100644 --- a/src/sql/engine/expr/ob_expr_json_replace.cpp +++ b/src/sql/engine/expr/ob_expr_json_replace.cpp @@ -66,7 +66,8 @@ int ObExprJsonReplace::eval_json_replace(const ObExpr &expr, ObEvalCtx &ctx, ObD ObIJsonBase *json_doc = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (expr.datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("invalid out put charset", K(ret), K(expr.datum_meta_.cs_type_)); @@ -88,7 +89,7 @@ int ObExprJsonReplace::eval_json_replace(const ObExpr &expr, ObEvalCtx &ctx, ObD if (expr.args_[i]->datum_meta_.type_ == ObNullType) { is_null_result = true; break; - } else if (OB_FAIL(expr.args_[i]->eval(ctx, path_data))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, path_data))) { LOG_WARN("eval json path datum failed", K(ret)); } else { ObString path_val = path_data->get_string(); @@ -107,7 +108,9 @@ int ObExprJsonReplace::eval_json_replace(const ObExpr &expr, ObEvalCtx &ctx, ObD if (OB_SUCC(ret) && !is_null_result) { ObIJsonBase *json_val = NULL; - if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i+1], ctx))) { + LOG_WARN("failed to add baselien size", K(ret), K(i + 1)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, json_val))) { LOG_WARN("get_json_val failed", K(ret)); } diff --git a/src/sql/engine/expr/ob_expr_json_schema_valid.cpp b/src/sql/engine/expr/ob_expr_json_schema_valid.cpp index 14cdec685..9a5f02ef5 100644 --- a/src/sql/engine/expr/ob_expr_json_schema_valid.cpp +++ b/src/sql/engine/expr/ob_expr_json_schema_valid.cpp @@ -93,8 +93,9 @@ int ObExprJsonSchemaValid::eval_json_schema_valid(const ObExpr &expr, ObEvalCtx ObIJsonBase* j_doc = nullptr; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObJsonBin j_schema_bin; + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_ISNULL(info)) { // schema is not const if (OB_FAIL(ObJsonExprHelper::get_json_schema(expr, ctx, temp_allocator, 0, diff --git a/src/sql/engine/expr/ob_expr_json_schema_validation_report.cpp b/src/sql/engine/expr/ob_expr_json_schema_validation_report.cpp index 2c94cae0d..d929873a1 100644 --- a/src/sql/engine/expr/ob_expr_json_schema_validation_report.cpp +++ b/src/sql/engine/expr/ob_expr_json_schema_validation_report.cpp @@ -105,7 +105,9 @@ int ObExprJsonSchemaValidationReport::eval_json_schema_validation_report(const O ObIJsonBase* j_doc = nullptr; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonBin j_schema_bin; if (OB_ISNULL(info)) { // schema is not const diff --git a/src/sql/engine/expr/ob_expr_json_search.cpp b/src/sql/engine/expr/ob_expr_json_search.cpp index b8a2fa011..1c185fa36 100644 --- a/src/sql/engine/expr/ob_expr_json_search.cpp +++ b/src/sql/engine/expr/ob_expr_json_search.cpp @@ -251,7 +251,8 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat bool is_null = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (expr.datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("invalid out put charset", K(ret), K(expr.datum_meta_.cs_type_)); @@ -265,7 +266,7 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat if (OB_SUCC(ret) && !is_null) { json_arg = expr.args_[1]; val_type = json_arg->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { is_null = true; @@ -299,7 +300,7 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat if (OB_SUCC(ret) && expr.arg_cnt_ >= 4 && !is_null) { json_arg = expr.args_[3]; val_type = json_arg->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { // do nothing, null type use default escape @@ -338,7 +339,7 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat if (OB_SUCC(ret) && !is_null) { json_arg = expr.args_[2]; val_type = json_arg->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { is_null = true; @@ -379,7 +380,7 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat for (uint64_t i = 4; OB_SUCC(ret) && !is_null && i < expr.arg_cnt_; i++) { json_arg = expr.args_[i]; val_type = json_arg->datum_meta_.type_; - if (OB_FAIL(json_arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(json_arg, ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { is_null = true; diff --git a/src/sql/engine/expr/ob_expr_json_set.cpp b/src/sql/engine/expr/ob_expr_json_set.cpp index 2ad1df6b8..94e8c9de7 100644 --- a/src/sql/engine/expr/ob_expr_json_set.cpp +++ b/src/sql/engine/expr/ob_expr_json_set.cpp @@ -148,7 +148,8 @@ int ObExprJsonSet::eval_json_set(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re ObIJsonBase *json_doc = NULL; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (expr.datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("invalid out put charset", K(ret), K(expr.datum_meta_.cs_type_)); @@ -171,7 +172,7 @@ int ObExprJsonSet::eval_json_set(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re if (expr.args_[i]->datum_meta_.type_ == ObNullType) { is_null_result = true; break; - } else if (OB_FAIL(expr.args_[i]->eval(ctx, path_data))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[i], ctx, path_data))) { LOG_WARN("eval json path datum failed", K(ret)); } else { ObString path_val = path_data->get_string(); @@ -186,7 +187,9 @@ int ObExprJsonSet::eval_json_set(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re if (OB_SUCC(ret) && !is_null_result) { ObIJsonBase *json_val = NULL; - if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, json_val))) { + if (OB_FAIL(temp_allocator.add_baseline_size(expr.args_[i+1], ctx))) { + LOG_WARN("failed to add baseline size.", K(ret)); + } else if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i+1, json_val))) { LOG_WARN("get_json_val failed", K(ret)); } else if (OB_FAIL(set_value(hit, json_doc, json_val, json_path, &temp_allocator))) { LOG_WARN("set_json_value failed", K(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 3fd349cb1..b4b9cbdf5 100644 --- a/src/sql/engine/expr/ob_expr_json_storage_free.cpp +++ b/src/sql/engine/expr/ob_expr_json_storage_free.cpp @@ -56,7 +56,7 @@ int ObExprJsonStorageFree::calc_result_type1(ObExprResType &type, } int ObExprJsonStorageFree::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, - bool has_lob_header, ObIAllocator *allocator, ObDatum &res) + bool has_lob_header, MultimodeAlloctor *allocator, ObDatum &res) { INIT_SUCC(ret); ObObjType type = meta.type_; @@ -79,6 +79,7 @@ int ObExprJsonStorageFree::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, data, meta, has_lob_header, j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (OB_FALSE_IT(allocator->add_baseline_size(j_str.length()))) { } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { @@ -111,7 +112,8 @@ int ObExprJsonStorageFree::eval_json_storage_free(const ObExpr &expr, ObEvalCtx LOG_WARN("eval json arg failed", K(ret)); } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObIAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_FAIL(calc(ctx, *datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &tmp_allocator, res))) { LOG_WARN("fail to calc json free result", K(ret), K(arg->datum_meta_)); } diff --git a/src/sql/engine/expr/ob_expr_json_storage_free.h b/src/sql/engine/expr/ob_expr_json_storage_free.h index 84bc117ac..2da896623 100644 --- a/src/sql/engine/expr/ob_expr_json_storage_free.h +++ b/src/sql/engine/expr/ob_expr_json_storage_free.h @@ -15,6 +15,7 @@ #define OCEANBASE_SQL_OB_EXPR_JSON_STORAGE_FREE_H_ #include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; @@ -33,7 +34,7 @@ public: const override; static int calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObDatum &res); + MultimodeAlloctor *allocator, ObDatum &res); static int eval_json_storage_free(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_storage_size.cpp b/src/sql/engine/expr/ob_expr_json_storage_size.cpp index 4abd6a431..63a453788 100644 --- a/src/sql/engine/expr/ob_expr_json_storage_size.cpp +++ b/src/sql/engine/expr/ob_expr_json_storage_size.cpp @@ -55,7 +55,7 @@ int ObExprJsonStorageSize::calc_result_type1(ObExprResType &type, } int ObExprJsonStorageSize::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, - bool has_lob_header, ObIAllocator *allocator, ObDatum &res) + bool has_lob_header, MultimodeAlloctor *allocator, ObDatum &res) { INIT_SUCC(ret); ObObjType type = meta.type_; @@ -91,6 +91,7 @@ int ObExprJsonStorageSize::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, data, meta, has_lob_header, j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (OB_FALSE_IT(allocator->add_baseline_size(j_str.length()))) { } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, j_in_type, j_base, 0, ObJsonExprHelper::get_json_max_depth_config()))) { @@ -120,7 +121,8 @@ int ObExprJsonStorageSize::eval_json_storage_size(const ObExpr &expr, ObEvalCtx LOG_WARN("eval json arg failed", K(ret)); } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObIAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_FAIL(calc(ctx, *datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &tmp_allocator, res))) { LOG_WARN("fail to calc json storage free result", K(ret), K(arg->datum_meta_)); } diff --git a/src/sql/engine/expr/ob_expr_json_storage_size.h b/src/sql/engine/expr/ob_expr_json_storage_size.h index 8bf910ade..f0f7c8900 100644 --- a/src/sql/engine/expr/ob_expr_json_storage_size.h +++ b/src/sql/engine/expr/ob_expr_json_storage_size.h @@ -15,6 +15,7 @@ #define OCEANBASE_SQL_OB_EXPR_JSON_STORAGE_SIZE_H_ #include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; @@ -33,7 +34,7 @@ public: const override; static int calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObDatum &res); + MultimodeAlloctor *allocator, ObDatum &res); static int eval_json_storage_size(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_type.cpp b/src/sql/engine/expr/ob_expr_json_type.cpp index ea3ed05a6..b2fbc4e26 100644 --- a/src/sql/engine/expr/ob_expr_json_type.cpp +++ b/src/sql/engine/expr/ob_expr_json_type.cpp @@ -200,8 +200,11 @@ int ObExprJsonType::eval_json_type(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & uint32_t type_idx = 0; bool is_null = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObIAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(calc(ctx, *datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &tmp_allocator, type_idx, is_null))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + if (OB_FAIL(tmp_allocator.add_baseline_size(datum, arg->obj_meta_.has_lob_header()))) { + LOG_WARN("failed to add baseline size.", K(ret)); + } else if (OB_FAIL(calc(ctx, *datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &tmp_allocator, type_idx, is_null))) { LOG_WARN("fail to calc json type result", K(ret), K(arg->datum_meta_)); } else if (is_null) { res.set_null(); diff --git a/src/sql/engine/expr/ob_expr_json_unquote.cpp b/src/sql/engine/expr/ob_expr_json_unquote.cpp index 978c48405..f702795f7 100644 --- a/src/sql/engine/expr/ob_expr_json_unquote.cpp +++ b/src/sql/engine/expr/ob_expr_json_unquote.cpp @@ -60,7 +60,7 @@ int ObExprJsonUnquote::calc_result_type1(ObExprResType &type, } int ObExprJsonUnquote::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObJsonBuffer &j_buf, bool &is_null) + MultimodeAlloctor *allocator, ObJsonBuffer &j_buf, bool &is_null) { INIT_SUCC(ret); ObIJsonBase *j_base = NULL; @@ -89,8 +89,11 @@ int ObExprJsonUnquote::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta met ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(type); if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, data, meta, has_lob_header, j_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); + } else if (OB_FALSE_IT(allocator->add_baseline_size(j_str.length()))) { } else if (ob_is_string_type(type) && (j_str.length() < 2 || j_str[0] != '"' || j_str[j_str.length() - 1] != '"')) { - if (OB_FAIL(j_buf.append(j_str))) { + if (OB_FAIL(j_buf.reserve(j_str.length()))) { + LOG_WARN("failed to reserve j_buf", K(ret), K(j_str.length())); + } else if (OB_FAIL(j_buf.append(j_str, 0))) { LOG_WARN("failed: copy original string", K(ret), K(j_str)); } } else if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, j_in_type, @@ -117,11 +120,12 @@ int ObExprJsonUnquote::eval_json_unquote(const ObExpr &expr, ObEvalCtx &ctx, ObD ObExpr *arg = expr.args_[0]; ObDatum* json_datum = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObJsonBuffer j_buf(&temp_allocator); bool is_null = false; - if (OB_FAIL(arg->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(arg, ctx, json_datum))) { ret = OB_ERR_INVALID_DATATYPE; LOG_WARN("error, eval json args datum failed", K(ret)); } else if (OB_FAIL(calc(ctx, *json_datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &temp_allocator, j_buf, is_null))) { diff --git a/src/sql/engine/expr/ob_expr_json_unquote.h b/src/sql/engine/expr/ob_expr_json_unquote.h index 3fde8204e..51961fc51 100644 --- a/src/sql/engine/expr/ob_expr_json_unquote.h +++ b/src/sql/engine/expr/ob_expr_json_unquote.h @@ -17,6 +17,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/json_type/ob_json_tree.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; namespace oceanbase @@ -30,7 +31,7 @@ public: virtual ~ObExprJsonUnquote(); static int calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObJsonBuffer &j_buf, bool &is_null); + MultimodeAlloctor *allocator, ObJsonBuffer &j_buf, bool &is_null); virtual int calc_result_type1(ObExprResType &type, ObExprResType &type1, diff --git a/src/sql/engine/expr/ob_expr_json_utils.cpp b/src/sql/engine/expr/ob_expr_json_utils.cpp index 08be32713..05b0a8c06 100644 --- a/src/sql/engine/expr/ob_expr_json_utils.cpp +++ b/src/sql/engine/expr/ob_expr_json_utils.cpp @@ -825,7 +825,7 @@ int cast_to_string(common::ObIAllocator *allocator, LOG_WARN("allocator is null", K(ret)); } else { ObJsonBuffer j_buf(allocator); - if (CAST_FAIL(j_base->print(j_buf, cast_param.is_quote_, cast_param.is_pretty_))) { + if (CAST_FAIL(j_base->print(j_buf, cast_param.is_quote_, 0, cast_param.is_pretty_))) { is_type_mismatch = 1; LOG_WARN("fail to_string as json", K(ret)); } else { @@ -1753,7 +1753,7 @@ int ObJsonUtil::get_json_path(ObExpr* expr, ObEvalCtx &ctx, bool &is_null_result, ObJsonParamCacheCtx *¶m_ctx, - common::ObIAllocator &temp_allocator, + MultimodeAlloctor &temp_allocator, bool &is_cover_by_error) { INIT_SUCC(ret); @@ -1768,7 +1768,7 @@ int ObJsonUtil::get_json_path(ObExpr* expr, && OB_NOT_NULL(path_cache)) { } else { type = expr->datum_meta_.type_; - if (OB_FAIL(expr->eval(ctx, json_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr, ctx, json_datum))) { is_cover_by_error = false; LOG_WARN("eval json arg failed", K(ret)); } else if (type == ObNullType || json_datum->is_null()) { @@ -1812,7 +1812,7 @@ int ObJsonUtil::get_json_path(ObExpr* expr, int ObJsonUtil::get_json_doc(ObExpr *expr, ObEvalCtx &ctx, - common::ObIAllocator &allocator, + MultimodeAlloctor &allocator, ObIJsonBase*& j_base, bool &is_null, bool & is_cover_by_error, bool relax) @@ -1824,7 +1824,7 @@ int ObJsonUtil::get_json_doc(ObExpr *expr, bool is_oracle = lib::is_oracle_mode(); - if (OB_UNLIKELY(OB_FAIL(expr->eval(ctx, json_datum)))) { + if (OB_FAIL(allocator.eval_arg(expr, ctx, json_datum))) { is_cover_by_error = false; LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || json_datum->is_null()) { @@ -1839,6 +1839,7 @@ int ObJsonUtil::get_json_doc(ObExpr *expr, if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(expr, ctx, allocator, j_str, is_null))) { LOG_WARN("fail to get real data.", K(ret), K(j_str)); } else if (is_null) { + } else if (OB_FALSE_IT(allocator.add_baseline_size(j_str.length()))) { } else { ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type); ObJsonInType expect_type = j_in_type; diff --git a/src/sql/engine/expr/ob_expr_json_utils.h b/src/sql/engine/expr/ob_expr_json_utils.h index 43787cce2..a14537d55 100644 --- a/src/sql/engine/expr/ob_expr_json_utils.h +++ b/src/sql/engine/expr/ob_expr_json_utils.h @@ -218,11 +218,11 @@ public: ObEvalCtx &ctx, bool &is_null_result, ObJsonParamCacheCtx *¶m_ctx, - common::ObIAllocator &temp_allocator, + MultimodeAlloctor &temp_allocator, bool &is_cover_by_error); static int get_json_doc(ObExpr *expr, ObEvalCtx &ctx, - common::ObIAllocator &allocator, + MultimodeAlloctor &allocator, ObIJsonBase*& j_base, bool &is_null, bool & is_cover_by_error, bool relax = false); diff --git a/src/sql/engine/expr/ob_expr_json_valid.cpp b/src/sql/engine/expr/ob_expr_json_valid.cpp index 62dd06c39..6bef6dfa6 100644 --- a/src/sql/engine/expr/ob_expr_json_valid.cpp +++ b/src/sql/engine/expr/ob_expr_json_valid.cpp @@ -68,7 +68,7 @@ int ObExprJsonValid::calc_result_type1(ObExprResType &type, } int ObExprJsonValid::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, - bool has_lob_header, ObIAllocator *allocator, ObDatum &res) + bool has_lob_header, MultimodeAlloctor *allocator, ObDatum &res) { INIT_SUCC(ret); ObObjType type = meta.type_; @@ -93,6 +93,7 @@ int ObExprJsonValid::calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, } else { is_invalid = true; } + } else if (OB_FALSE_IT(allocator->add_baseline_size(j_str.length()))) { } else if (type == ObJsonType) { // json bin ObIJsonBase *j_bin = NULL; if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, ObJsonInType::JSON_BIN, @@ -136,7 +137,8 @@ int ObExprJsonValid::eval_json_valid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum ret = OB_SUCCESS; } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObIAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_FAIL(calc(ctx, *datum, arg->datum_meta_, arg->obj_meta_.has_lob_header(), &tmp_allocator, res))) { LOG_WARN("fail to calc json valid result", K(ret), K(arg->datum_meta_)); } diff --git a/src/sql/engine/expr/ob_expr_json_valid.h b/src/sql/engine/expr/ob_expr_json_valid.h index dbb620653..5f5bb40b5 100644 --- a/src/sql/engine/expr/ob_expr_json_valid.h +++ b/src/sql/engine/expr/ob_expr_json_valid.h @@ -15,6 +15,7 @@ #define OCEANBASE_SQL_OB_EXPR_JSON_VALID_H_ #include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" using namespace oceanbase::common; @@ -32,7 +33,7 @@ public: common::ObExprTypeCtx &type_ctx) const override; static int calc(ObEvalCtx &ctx, const ObDatum &data, ObDatumMeta meta, bool has_lob_header, - ObIAllocator *allocator, ObDatum &res); + MultimodeAlloctor *allocator, ObDatum &res); static int eval_json_valid(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_value.cpp b/src/sql/engine/expr/ob_expr_json_value.cpp index ac98cfc3f..9a8f81b0e 100644 --- a/src/sql/engine/expr/ob_expr_json_value.cpp +++ b/src/sql/engine/expr/ob_expr_json_value.cpp @@ -228,7 +228,9 @@ int ObExprJsonValue::eval_json_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum uint8_t is_type_mismatch = 0; ObDatum *return_val = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonBin st_json(&temp_allocator); ObIJsonBase *j_base = &st_json; ObJsonSeekResult hits; @@ -319,7 +321,9 @@ int ObExprJsonValue::eval_ora_json_value(const ObExpr &expr, ObEvalCtx &ctx, ObD uint8_t is_type_mismatch = 0; ObDatum *return_val = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "JSONModule")); ObJsonBin st_json(&temp_allocator); ObIJsonBase *j_base = &st_json; ObJsonSeekResult hits; @@ -331,8 +335,12 @@ int ObExprJsonValue::eval_ora_json_value(const ObExpr &expr, ObEvalCtx &ctx, ObD if (OB_ISNULL(param_ctx)) { param_ctx = &ctx_cache; } - // init flag - if (param_ctx->is_first_exec_ && OB_FAIL(init_ctx_var(expr, param_ctx))) { + + // add version protection, as lower version has handle input in a defference way + if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_2_2_0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("json value raw expr number has change in 4.2.2 version", K(ret)); + } else if (param_ctx->is_first_exec_ && OB_FAIL(init_ctx_var(expr, param_ctx))) { is_cover_by_error = false; LOG_WARN("fail to init param ctx", K(ret)); } else if (OB_ISNULL(param_ctx->json_param_.json_path_) // parse json path diff --git a/src/sql/engine/expr/ob_expr_lob_utils.h b/src/sql/engine/expr/ob_expr_lob_utils.h index afac73299..875c9c516 100644 --- a/src/sql/engine/expr/ob_expr_lob_utils.h +++ b/src/sql/engine/expr/ob_expr_lob_utils.h @@ -314,6 +314,43 @@ public: return read_real_string_data(allocator, type, CS_TYPE_BINARY, has_lob_header, str, exec_ctx); } + // return str is copy of inrow/outrow lob + static int read_real_string_data_with_copy(ObIAllocator &allocator, const ObDatum &datum, const ObDatumMeta &meta, + bool has_lob_header, ObString &str) + { + int ret = OB_SUCCESS; + str = datum.get_string(); + bool need_copy = false; + if (datum.is_null()) { + str.reset(); + } else if (is_lob_storage(meta.type_)) { + uint64_t tenant_id = MTL_ID(); + ObArenaAllocator *tmp_alloc_ptr = nullptr; + ObArenaAllocator tmp_allocator("ObLobRRSD", OB_MALLOC_NORMAL_BLOCK_SIZE, tenant_id); + if (tenant_id != OB_INVALID_TENANT_ID) { + tmp_alloc_ptr = &tmp_allocator; + } + ObTextStringIter str_iter(meta.type_, meta.cs_type_, str, has_lob_header); + if (OB_FAIL(str_iter.init(0, NULL, &allocator, tmp_alloc_ptr))) { + COMMON_LOG(WARN, "Lob: str iter init failed ", K(ret), K(str_iter)); + } else if (OB_FAIL(str_iter.get_full_data(str))) { + COMMON_LOG(WARN, "Lob: str iter get full data failed ", K(ret), K(str_iter)); + } else if (!str_iter.is_outrow_lob()) { + need_copy = true; + } + } else { + need_copy = true; + } + if (OB_SUCC(ret) && need_copy) { + ObString str_cpy; + if (OB_FAIL(ob_write_string(allocator, str, str_cpy))) { + COMMON_LOG(WARN, "fail to copy inrow data"); + } else { + str = str_cpy; + } + } + return ret; + }; // get outrow lob prefix or inrow/string tc full data static int read_prefix_string_data(ObEvalCtx &ctx, diff --git a/src/sql/engine/expr/ob_expr_multi_mode_func_helper.cpp b/src/sql/engine/expr/ob_expr_multi_mode_func_helper.cpp new file mode 100644 index 000000000..15a9e9480 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_multi_mode_func_helper.cpp @@ -0,0 +1,439 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file is for implement of func multimode expr helper + */ + +#define USING_LOG_PREFIX SQL_ENG +#include "lib/ob_errno.h" +#include "ob_expr_multi_mode_func_helper.h" + +using namespace oceanbase::common; +using namespace oceanbase::sql; + +namespace oceanbase +{ +namespace sql +{ + +uint64_t ObMultiModeExprHelper::get_tenant_id(ObSQLSessionInfo *session) +{ + uint64_t tenant_id = 0; + if (OB_ISNULL(session)) { + // If the session is not obtained, 500 tenant memory will be temporarily used, + // but it will not affect subsequent execution. + tenant_id = OB_SERVER_TENANT_ID; + int ret = OB_ERR_UNEXPECTED; + LOG_ERROR("failed to get session, set tenant_id 500.", K(ret), K(lbt())); + } else if (session->get_ddl_info().is_ddl_check_default_value()) { + tenant_id = OB_SERVER_TENANT_ID; + } else { + tenant_id = session->get_effective_tenant_id(); + } + return tenant_id; +} + +MultimodeAlloctor::MultimodeAlloctor(ObArenaAllocator &arena, uint64_t type, int64_t tenant_id, int &ret, const char *func_name/* = ""*/) + : arena_(arena), + baseline_size_(0), + type_(type), + mem_threshold_flag_(0), + check_level_(0), + func_name_(func_name), + children_used_(used()), + expect_threshold_(0), + ret_(ret), + ext_used_(0) +{ + uint64_t alloc_tenant = arena.get_arena().get_tenant_id(); + if (alloc_tenant != tenant_id) { + INIT_SUCC(ret); + LOG_WARN("[Multi-mode ALARM] different tenants", K(ret), K(alloc_tenant), K(tenant_id)); + } else { + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(alloc_tenant)); + if (tenant_config.is_valid()) { + check_level_ = tenant_config->_multimodel_memory_trace_level; + if (check_level_ > 2) { + check_level_ = 0; + } + } + } +} + +MultimodeAlloctor::MultimodeAlloctor(ObArenaAllocator &arena, uint64_t type, int &ret) + : arena_(arena), + baseline_size_(0), + type_(type), + mem_threshold_flag_(0), + check_level_(0), + func_name_(""), + children_used_(used()), + expect_threshold_(0), + ret_(ret), + ext_used_(0) +{ + uint64_t alloc_tenant = arena.get_arena().get_tenant_id(); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(alloc_tenant)); + if (tenant_config.is_valid()) { + check_level_ = tenant_config->_multimodel_memory_trace_level; + if (check_level_ > 2) { + check_level_ = 0; + } + } +} + +MultimodeAlloctor::~MultimodeAlloctor() +{ + if (ret_ == OB_SUCCESS && check_level_ > 0 && has_reached_threshold()) { + INIT_SUCC(ret); + LOG_ERROR("[Multi-mode ALARM ERROR] Allocator has reached threshold.", K(*this), K(ext_used_), K(lbt())); + } +} + +void MultimodeAlloctor::set_baseline_size(uint64_t baseline_size) +{ + baseline_size_ = baseline_size; + expect_threshold_ = baseline_size_ * get_expected_multiple(type_); +} + +void MultimodeAlloctor::set_baseline_size_and_flag(uint64_t baseline_size) +{ + baseline_size_ = baseline_size; + expect_threshold_ = baseline_size_ * get_expected_multiple(type_); + if (has_reached_specified_threshold(1.0)) { + set_reached_threshold(); + } +} + +void MultimodeAlloctor::add_baseline_size(uint64_t add_size) +{ + baseline_size_ += add_size; + expect_threshold_ = baseline_size_ * get_expected_multiple(type_); +} + +int MultimodeAlloctor::add_baseline_size(ObDatum *datum, bool has_lob_header, uint32_t multiple) +{ + INIT_SUCC(ret); + int64_t byte_len = datum->len_; + if (has_lob_header) { + ObLobLocatorV2 locator(datum->get_string()); + if (OB_FAIL(locator.get_lob_data_byte_len(byte_len))) { + LOG_WARN("get lob data byte length failed", K(ret)); + } else { + add_baseline_size(byte_len * multiple); + } + } else { + add_baseline_size(byte_len * multiple); + } + + return ret; +} + +int MultimodeAlloctor::add_baseline_size(const ObExpr *expr, ObEvalCtx &ctx, uint32_t multiple) +{ + INIT_SUCC(ret); + ObDatum *datum = nullptr; + ObObjType val_type; + int64_t byte_len = 0; + if (OB_ISNULL(expr)) { + } else if (OB_FALSE_IT(val_type = expr->datum_meta_.type_)) { + } else if (OB_FAIL(eval_arg(expr, ctx, datum))) { + LOG_WARN("eval json arg failed", K(ret), K(val_type)); + } else if (OB_FAIL(add_baseline_size(datum, ob_is_user_defined_sql_type(val_type) || expr->obj_meta_.has_lob_header(), multiple))) { + LOG_WARN("failed to add base line size.", K(ret), K(val_type), KPC(datum)); + } + + return ret; +} + +void MultimodeAlloctor::mem_check(float multiple) +{ + INIT_SUCC(ret); + if (has_reached_specified_threshold(multiple)) { + LOG_INFO("[Multi-mode ALARM] Allocator has reached level.", K(ret), K(*this), K(multiple), K(expect_threshold_), K(lbt())); + } +} + +uint64_t MultimodeAlloctor::get_expected_multiple(uint64_t type) +{ + uint64_t expected_multiple = 0; + switch (type) { + case T_FUN_SYS_JSON_OBJECT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_EXTRACT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_CONTAINS: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_CONTAINS_PATH: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_DEPTH: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_KEYS: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_ARRAY: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_QUOTE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_UNQUOTE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_OVERLAPS: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_REMOVE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_SEARCH: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_VALID: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_ARRAY_APPEND: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_ARRAY_INSERT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_REPLACE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_TYPE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_LENGTH: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_INSERT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_STORAGE_SIZE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_STORAGE_FREE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_MERGE_PRESERVE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_MERGE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_MERGE_PATCH: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_PRETTY: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_SET: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_MEMBER_OF: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_VALUE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_JSON_ARRAYAGG: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_JSON_OBJECTAGG: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_IS_JSON: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_EQUAL: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_QUERY: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_ORA_JSON_ARRAYAGG: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_ORA_JSON_OBJECTAGG: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_MAKEXML: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XML_ELEMENT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XMLPARSE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_ORA_XMLAGG: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XML_ATTRIBUTES: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XML_EXTRACTVALUE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XML_EXTRACT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XML_SERIALIZE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XMLCAST: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_UPDATE_XML: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_PRIV_MAKE_XML_BINARY: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_EXISTS: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_OBJECT_WILD_STAR: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_SCHEMA_VALID: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_SCHEMA_VALIDATION_REPORT: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_JSON_APPEND: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_INSERTCHILDXML: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_DELETEXML: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_XMLSEQUENCE: + expected_multiple = ObMultiModeDefaultMagnification; + break; + case T_FUN_SYS_ST_ASTEXT: + case T_FUN_SYS_ST_ASWKT: + case T_FUN_SYS_PRIV_ST_ASEWKT: + expected_multiple = ObMultiModeSingleMagnification; + break; + + default: + expected_multiple = ObMultiModeDefaultMagnification; + } + + return expected_multiple; +} + +const double MultimodeAlloctor::MEM_THRESHOLD_LEVEL[LEVEL_NUMBERS][LEVEL_CLASS] = +{ + // level = 0 + { + 0, + 0, + 0 + }, + // level = 1 + { + 0.2, + 0.6, + 0.8 + }, + // level = 2 + { + 0.4, + 0.8, + 1.2 + } +}; + +bool MultimodeAlloctor::has_reached_specified_threshold(double threshold) +{ + double current_threshold = (double)expect_threshold_ * threshold; + return (double)cur_func_used() > current_threshold; +} + +void MultimodeAlloctor::memory_usage_check_if_need() +{ + if (is_open_trace() && baseline_size_ > 0 && cur_func_used() > OB_MEM_TRACK_MIN_FOOT) { + memory_usage_check(); + } +} + +void MultimodeAlloctor::memory_usage_check() +{ + INIT_SUCC(ret); + bool has_reached = true; + for (uint8_t i = 0; has_reached && i < LEVEL_CLASS; i++) { + if (!has_level_mem_threshold(i)) { + if (has_reached_specified_threshold(MEM_THRESHOLD_LEVEL[check_level_][i])) { + set_level_mem_threshold(i); + LOG_INFO("[Multi-mode ALARM] Allocator has reached level.", K(ret), K(i), + K(*this), K(expect_threshold_), K(lbt())); + } else { + has_reached = false; + } + } + } + + if (!has_reached_threshold() && has_reached_specified_threshold(1.0)) { + set_reached_threshold(); + LOG_INFO("[Multi-mode ALARM] Allocator has reached threshold.", K(ret), K(3), + K(*this), K(expect_threshold_), K(lbt())); + } +} + +void *MultimodeAlloctor::alloc(const int64_t sz) +{ + void* ptr = arena_.alloc(sz); + memory_usage_check_if_need(); + return ptr; +} + +void *MultimodeAlloctor::alloc(const int64_t size, const ObMemAttr &attr) +{ + void* ptr = arena_.alloc(size, attr); + memory_usage_check_if_need(); + return ptr; +} + + +int MultimodeAlloctor::eval_arg(const ObExpr *arg, ObEvalCtx &ctx, common::ObDatum *&datum) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(arg)) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("invalid null expr argument", K(ret), K(arg)); + } else { + int64_t last_used = used(); + if (OB_FAIL(arg->eval(ctx, datum))) { + LOG_WARN("eval geo arg failed", K(ret)); + } else { + children_used_ += used() - last_used; + } + } + return ret; +} + +void MultimodeAlloctor::add_ext_used(uint64_t add) { + ext_used_ += add; + memory_usage_check_if_need(); +} + +}; +}; diff --git a/src/sql/engine/expr/ob_expr_multi_mode_func_helper.h b/src/sql/engine/expr/ob_expr_multi_mode_func_helper.h new file mode 100644 index 000000000..63af8a8d4 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_multi_mode_func_helper.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file is for implement of func multimode expr helper + */ + +#ifndef OCEANBASE_SQL_OB_EXPR_MULTI_MODE_FUNC_HELPER_H_ +#define OCEANBASE_SQL_OB_EXPR_MULTI_MODE_FUNC_HELPER_H_ + +#include "sql/session/ob_sql_session_info.h" +#include "lib/allocator/page_arena.h" +#include "objit/common/ob_item_type.h" + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace sql +{ + +#define ObMultiModeDefaultMagnification 3 +#define ObMultiModeSingleMagnification 1 +#define ObMultiModeDoubleMagnification 2 +#define ObMultiModeTripleMagnification 3 +#define ObMultiModeFourMagnification 4 +#define ObMultiModeFiveMagnification 5 +#define ObMultiModeSixMagnification 6 + +static const int32_t FIRST_MEM_THRESHOLD = 0x1; +static const int32_t SECOND_MEM_THRESHOLD = 0x2; +static const int32_t THIRD_MEM_THRESHOLD = 0x4; +static const int32_t MEM_EXCEED_THRESHOLD = 0x8; + +enum ObMultiModeType +{ + T_PL_FUNC_XML_TRANSFORM = 0, + T_PL_FUNC_XML_CREATE_XML = 1, + T_PL_FUNC_XML_CONSTRUCTOR = 2, + T_PL_FUNC_XML_GETVAL = 3, + T_PL_FUNC_XML_MAX = 100, // reserve [0, 99] for xml func + T_PL_FUNC_GIS_GET_WKB = 101, + T_PL_FUNC_GIS_GET_WKT = 102, + T_PL_FUNC_GIS_ST_ISVALID = 103, + T_PL_FUNC_GIS_GET_GEOJSON = 104, + T_PL_FUNC_GIS_CONTRUCTOR = 105, + T_PL_FUNC_GIS_CAST = 106, + T_PL_FUNC_GIS_MAX = 200, +}; + +class ObMultiModeExprHelper final +{ +public: + static uint64_t get_tenant_id(ObSQLSessionInfo *session); // json and xml get tenant_id public function +}; + + + +class MultimodeAlloctor : public ObIAllocator +{ +public: + MultimodeAlloctor(ObArenaAllocator &arena, uint64_t type, int &ret); + MultimodeAlloctor(ObArenaAllocator &arena, uint64_t type, int64_t tenant_id, int &ret, const char *func_name = ""); + ~MultimodeAlloctor(); + +public: + virtual void *alloc(const int64_t sz); + void *alloc(const int64_t size, const ObMemAttr &attr); + virtual void *realloc(void *ptr, const int64_t oldsz, const int64_t newsz) { return arena_.realloc(ptr, oldsz, newsz); } + virtual void free(void *ptr) { arena_.free(ptr); } + int64_t used() const { return arena_.used(); } + int64_t total() const { return arena_.total(); } + void reset() { arena_.reset(); } + void reuse() override { arena_.reuse(); } + void set_attr(const ObMemAttr &attr) override + { + arena_.set_attr(attr); + } + + void mem_check(float multiple); + void set_baseline_size(uint64_t baseline_size); + void add_baseline_size(uint64_t add_size); + void set_baseline_size_and_flag(uint64_t baseline_size); + void set_children_used(uint64_t children_used) { children_used_ = children_used; } + int add_baseline_size(const ObExpr *expr, ObEvalCtx &ctx, uint32_t multiple = 1); + int add_baseline_size(ObDatum *datum, bool has_lob_header, uint32_t multiple = 1); + bool is_open_trace() { return check_level_ > 0; } + int64_t cur_func_used() const { return used() - children_used_ + ext_used_; } + int eval_arg(const ObExpr *arg, ObEvalCtx &ctx, common::ObDatum *&datum); + void add_ext_used(uint64_t add); + void memory_usage_check_if_need(); + TO_STRING_KV(K_(ret), K_(baseline_size), K_(type), K_(func_name), + K_(mem_threshold_flag), K_(check_level), K(cur_func_used()), K(ext_used_)); +private: + static uint64_t get_expected_multiple(uint64_t type); + bool has_reached_threshold() { return static_cast(MEM_EXCEED_THRESHOLD & mem_threshold_flag_); } + bool has_first_mem_threshold() { return static_cast(FIRST_MEM_THRESHOLD & mem_threshold_flag_); } + bool has_second_mem_threshold() { return static_cast(SECOND_MEM_THRESHOLD & mem_threshold_flag_); } + bool has_third_mem_threshold() { return static_cast(THIRD_MEM_THRESHOLD & mem_threshold_flag_); } + bool has_level_mem_threshold(uint8_t level) { return static_cast((1 << level) & mem_threshold_flag_); } + bool has_reached_specified_threshold(double threshold); + void set_reached_threshold() { mem_threshold_flag_ |= MEM_EXCEED_THRESHOLD; } + void set_first_mem_threshold() { mem_threshold_flag_ |= FIRST_MEM_THRESHOLD; } + void set_second_mem_threshold() { mem_threshold_flag_ |= SECOND_MEM_THRESHOLD; } + void set_third_mem_threshold() { mem_threshold_flag_ |= THIRD_MEM_THRESHOLD; } + void set_level_mem_threshold(uint8_t level) { mem_threshold_flag_ |= (1 << level); } + void memory_usage_check(); + static constexpr int OB_MEM_TRACK_MIN_FOOT = 10 << 10; //ObMemoryTrackingMinimumFootprint + static const int32_t LEVEL_NUMBERS = 99; + static const int32_t LEVEL_CLASS = 3; + static const double MEM_THRESHOLD_LEVEL[LEVEL_NUMBERS][LEVEL_CLASS]; +private: + ObIAllocator &arena_; + uint64_t baseline_size_; + uint64_t type_; + int32_t mem_threshold_flag_; + int32_t check_level_; + const char* func_name_; + uint64_t children_used_; + uint64_t expect_threshold_; + int &ret_; + uint64_t ext_used_; +}; + + +}; +}; + +#endif // OCEANBASE_SQL_OB_EXPR_MULTI_MODE_FUNC_HELPER_H_ \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_operator_factory.cpp b/src/sql/engine/expr/ob_expr_operator_factory.cpp index 5d28d7a49..3b33f5460 100644 --- a/src/sql/engine/expr/ob_expr_operator_factory.cpp +++ b/src/sql/engine/expr/ob_expr_operator_factory.cpp @@ -405,9 +405,12 @@ #include "sql/engine/expr/ob_expr_priv_xml_binary.h" #include "sql/engine/expr/ob_expr_xmlparse.h" #include "sql/engine/expr/ob_expr_xml_element.h" +#include "sql/engine/expr/ob_expr_xml_forest.h" +#include "sql/engine/expr/ob_expr_xml_concat.h" #include "sql/engine/expr/ob_expr_xml_attributes.h" #include "sql/engine/expr/ob_expr_extract_value.h" #include "sql/engine/expr/ob_expr_extract_xml.h" +#include "sql/engine/expr/ob_expr_existsnode_xml.h" #include "sql/engine/expr/ob_expr_xml_serialize.h" #include "sql/engine/expr/ob_expr_xmlcast.h" #include "sql/engine/expr/ob_expr_update_xml.h" @@ -471,7 +474,8 @@ #include "sql/engine/expr/ob_expr_can_access_trigger.h" #include "sql/engine/expr/ob_expr_split_part.h" #include "sql/engine/expr/ob_expr_get_mysql_routine_parameter_type_str.h" - +#include "sql/engine/expr/ob_expr_priv_st_geohash.h" +#include "sql/engine/expr/ob_expr_priv_st_makepoint.h" using namespace oceanbase::common; namespace oceanbase @@ -1110,6 +1114,8 @@ void ObExprOperatorFactory::register_expr_operators() REG_OP(ObExprSTSymDifference); REG_OP(ObExprPrivSTAsMVTGeom); REG_OP(ObExprPrivSTMakeValid); + REG_OP(ObExprPrivSTGeoHash); + REG_OP(ObExprPrivSTMakePoint); REG_OP(ObExprCurrentRole); REG_OP(ObExprArray); /* vector index */ @@ -1474,9 +1480,12 @@ void ObExprOperatorFactory::register_expr_operators() REG_OP_ORCL(ObExprPrivXmlBinary); REG_OP_ORCL(ObExprXmlparse); REG_OP_ORCL(ObExprXmlElement); + REG_OP_ORCL(ObExprXmlConcat); + REG_OP_ORCL(ObExprXmlForest); REG_OP_ORCL(ObExprXmlAttributes); REG_OP_ORCL(ObExprExtractValue); REG_OP_ORCL(ObExprExtractXml); + REG_OP_ORCL(ObExprExistsNodeXml); REG_OP_ORCL(ObExprXmlSerialize); REG_OP_ORCL(ObExprXmlcast); REG_OP_ORCL(ObExprUpdateXml); diff --git a/src/sql/engine/expr/ob_expr_priv_attribute_access.cpp b/src/sql/engine/expr/ob_expr_priv_attribute_access.cpp index e5b0eac4c..025c46371 100644 --- a/src/sql/engine/expr/ob_expr_priv_attribute_access.cpp +++ b/src/sql/engine/expr/ob_expr_priv_attribute_access.cpp @@ -18,6 +18,7 @@ #include "lib/json_type/ob_json_base.h" #include "lib/geo/ob_sdo_geo_object.h" #include "lib/geo/ob_geo_utils.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" namespace oceanbase { @@ -114,22 +115,23 @@ int ObExprUDTAttributeAccess::eval_attr_access(const ObExpr &expr, ObEvalCtx &ct ObDatum *attr_datum = NULL; int32_t attr_idx = 0; int num_args = expr.arg_cnt_; + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_UDT_ATTR_ACCESS); if (num_args != 2) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected params number", K(ret), K(num_args)); - } else if (OB_FAIL(expr.args_[0]->eval(ctx, udt_datum))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, udt_datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (udt_datum->is_null()) { res.set_null(); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, attr_datum))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, attr_datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (attr_datum->is_null()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid attribute idx", K(ret)); } else { attr_idx = attr_datum->get_int(); - ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); const ObExprUdtAttrAccessInfo *info = static_cast(expr.extra_info_); ObSqlUDT sql_udt; @@ -143,6 +145,7 @@ int ObExprUDTAttributeAccess::eval_attr_access(const ObExpr &expr, ObEvalCtx &ct CS_TYPE_BINARY, true, raw_data))) { LOG_WARN("failed to get udt raw data", K(ret), K(info->udt_id_)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(raw_data.length()))) { } else if (expr.args_[0]->datum_meta_.type_ == ObGeometryType) { if (OB_FAIL(eval_sdo_geom_attr_access(temp_allocator, raw_data, attr_idx, res))) { LOG_WARN("failed to eval sdo_geometry attribute", K(ret), K(attr_idx)); @@ -189,7 +192,7 @@ int ObExprUDTAttributeAccess::eval_attr_access(const ObExpr &expr, ObEvalCtx &ct int ObExprUDTAttributeAccess::eval_sdo_geom_attr_access(ObIAllocator &allocator, const ObString &swkb, const int32_t attr_idx, ObDatum &res) { int ret = OB_SUCCESS; - ObSdoGeoObject sdo_geo; + ObSdoGeoObject sdo_geo(allocator); if (OB_FAIL(ObGeoTypeUtil::wkb_to_sdo_geo(swkb, sdo_geo, true))) { LOG_WARN("fail to wkb_to_sdo_geo", K(ret), K(swkb)); } else { diff --git a/src/sql/engine/expr/ob_expr_priv_st_asewkb.cpp b/src/sql/engine/expr/ob_expr_priv_st_asewkb.cpp index 4d33f75b2..39964fd4e 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_asewkb.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_asewkb.cpp @@ -73,7 +73,8 @@ int ObExprStPrivAsEwkb::eval_priv_st_as_ewkb(const ObExpr &expr, uint32_t arg_num = expr.arg_cnt_; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_ASEWKB); const ObSrsItem *srs = NULL; omt::ObSrsCacheGuard srs_guard; bool is_geog = false; @@ -81,7 +82,7 @@ int ObExprStPrivAsEwkb::eval_priv_st_as_ewkb(const ObExpr &expr, ObGeometry *geo = NULL; ObString wkb_str; - if (OB_FAIL(expr.args_[0]->eval(ctx, wkb_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, wkb_datum))) { LOG_WARN("fail to eval wkb datum", K(ret)); } else if (wkb_datum->is_null()) { is_null_result = true; @@ -89,6 +90,7 @@ int ObExprStPrivAsEwkb::eval_priv_st_as_ewkb(const ObExpr &expr, } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *wkb_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb_str))) { LOG_WARN("fail to get real data.", K(ret), K(wkb_str)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkb_str.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb_str, srs))) { LOG_WARN("fail to get srs item", K(ret), K(wkb_str)); } else if (OB_FAIL(ObGeoTypeUtil::create_geo_by_wkb(tmp_allocator, wkb_str, srs, geo, true, true, true))) { diff --git a/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.cpp b/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.cpp index 29004578a..e4aa6b943 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.cpp @@ -101,9 +101,31 @@ int ObExprPrivSTAsMVTGeom::calc_result_typeN(ObExprResType &type, ObExprResType return ret; } +int ObExprPrivSTAsMVTGeom::get_bounds(lib::MemoryContext &mem_ctx, ObGeometry &geo, ObGeogBox *&bounds) +{ + int ret = OB_SUCCESS; + ObGeoEvalCtx box_ctx(mem_ctx); + box_ctx.set_is_called_in_pg_expr(true); + if (OB_FAIL(box_ctx.append_geo_arg(&geo))) { + LOG_WARN("build gis context failed", K(ret), K(box_ctx.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(box_ctx, bounds))) { + LOG_WARN("failed to do box functor failed", K(ret)); + } else if ((bounds->xmax - bounds->xmin) <= 0 || ((bounds->ymax - bounds->ymin) <= 0)) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_ASMVTGEOM); + LOG_WARN("_ST_AsMVTGeom: Geometric bounds are too small", + K(ret), + K(bounds->xmin), + K(bounds->ymin), + K(bounds->ymax), + K(bounds->xmax)); + } + return ret; +} + int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx &ctx, - bool &is_null_res, ObGeometry *&geo1, ObGeogBox *&bounds, int32_t &extent, int32_t &buffer, - bool &clip_geom) + MultimodeAlloctor &allocator, bool &is_null_res, ObGeometry *&geo1, ObGeometry *&geo2, + int32_t &extent, int32_t &buffer, bool &clip_geom) { int ret = OB_SUCCESS; ObDatum *datum1 = nullptr; @@ -115,10 +137,6 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs1 = nullptr; const ObSrsItem *srs2 = nullptr; - ObEvalCtx::TempAllocGuard ctx_alloc_g(ctx); - common::ObArenaAllocator &ctx_allocator = ctx_alloc_g.get_allocator(); - // ObArenaAllocator tmp_allocator; - ObGeometry *geo2 = nullptr; // process two geometry if (ob_is_null(type1)) { @@ -126,7 +144,7 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx } else if (ob_is_null(type2)) { ret = OB_ERR_NULL_INPUT; LOG_WARN("_ST_AsMVTGeom: Geometric bounds cannot be null", K(ret)); - } else if (OB_FAIL(arg1->eval(ctx, datum1)) || OB_FAIL(arg2->eval(ctx, datum2))) { + } else if (OB_FAIL(allocator.eval_arg(arg1, ctx, datum1)) || OB_FAIL(allocator.eval_arg(arg2, ctx, datum2))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null()) { is_null_res = true; @@ -134,24 +152,21 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx ret = OB_ERR_NULL_INPUT; LOG_WARN("_ST_AsMVTGeom: Geometric bounds cannot be null", K(ret)); } else { - ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &ctx_allocator = tmp_alloc_g.get_allocator(); ObString wkb1 = datum1->get_string(); ObString wkb2 = datum2->get_string(); - ObGeoEvalCtx box_ctx(&ctx_allocator); - box_ctx.set_is_called_in_pg_expr(true); - if (OB_FAIL(ObTextStringHelper::read_real_string_data( - ctx_allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb1))) { + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( + allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN( "fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header()), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(ctx_allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *datum2, arg2->datum_meta_, arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN( "fail to read real string data", K(ret), K(arg2->obj_meta_.has_lob_header()), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs1, true, N_PRIV_ST_ASMVTGEOM)) || OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb2, srs2, true, N_PRIV_ST_ASMVTGEOM))) { if (ret == OB_ERR_SRS_NOT_FOUND) { @@ -159,19 +174,19 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_ASMVTGEOM); } LOG_WARN("fail to get srs item", K(ret), K(wkb1), K(wkb2)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(ctx_allocator, + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, wkb1, geo1, srs1, N_PRIV_ST_ASMVTGEOM, - ObGeoBuildFlag::GEO_NORMALIZE | ObGeoBuildFlag::GEO_CHECK_RING))) { + GEO_NORMALIZE | GEO_CHECK_RING | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(ctx_allocator, + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs2, N_PRIV_ST_ASMVTGEOM, - ObGeoBuildFlag::GEO_DEFAULT | ObGeoBuildFlag::GEO_CHECK_RING))) { + GEO_DEFAULT | GEO_CHECK_RING | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } else if (OB_NOT_NULL(srs1) && srs1->is_geographical_srs()) { ret = OB_ERR_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS; @@ -183,19 +198,6 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx LOG_USER_ERROR(OB_ERR_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS, N_PRIV_ST_ASMVTGEOM, ObGeoTypeUtil::get_geo_name_by_type(geo2->type())); LOG_WARN("Geometry in geographical srs can not be input", K(ret), K(srs2)); - } else if (OB_FAIL(box_ctx.append_geo_arg(geo2))) { - LOG_WARN("build gis context failed", K(ret), K(box_ctx.get_geo_count())); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(box_ctx, bounds))) { - LOG_WARN("failed to do box functor failed", K(ret)); - } else if ((bounds->xmax - bounds->xmin) <= 0 || ((bounds->ymax - bounds->ymin) <= 0)) { - ret = OB_ERR_GIS_INVALID_DATA; - LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_ASMVTGEOM); - LOG_WARN("_ST_AsMVTGeom: Geometric bounds are too small", - K(ret), - K(bounds->xmin), - K(bounds->ymin), - K(bounds->ymax), - K(bounds->xmax)); } } // process extent @@ -203,7 +205,7 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx extent = 4096; // default if (OB_SUCC(ret) && num_args >= 3) { ObDatum *datum = nullptr; - if (OB_FAIL(expr.args_[2]->eval(ctx, datum))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[2], ctx, datum))) { LOG_WARN("fail to eval second argument", K(ret)); } else if (datum->is_null()) { // use default value @@ -219,7 +221,7 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx buffer = 256; // default if (OB_SUCC(ret) && num_args >= 4) { ObDatum *datum = nullptr; - if (OB_FAIL(expr.args_[3]->eval(ctx, datum))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[3], ctx, datum))) { LOG_WARN("fail to eval second argument", K(ret)); } else if (datum->is_null()) { // use default value @@ -236,7 +238,7 @@ int ObExprPrivSTAsMVTGeom::process_input_geometry(const ObExpr &expr, ObEvalCtx int8_t clip_num = 0; if (OB_SUCC(ret) && num_args >= 5) { ObDatum *datum = nullptr; - if (OB_FAIL(expr.args_[4]->eval(ctx, datum))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[4], ctx, datum))) { LOG_WARN("fail to eval second argument", K(ret)); } else if (datum->is_null()) { // use default value @@ -315,10 +317,22 @@ int ObExprPrivSTAsMVTGeom::affine_to_tile_space( } int ObExprPrivSTAsMVTGeom::split_geo_to_basic_type( - ObGeometry *&geo, ObIAllocator &allocator, ObGeoType basic_type, ObGeometry *&split_geo) + ObGeometry &in_geo, ObIAllocator &allocator, ObGeoType basic_type, ObGeometry *&split_geo) { int ret = OB_SUCCESS; - if (geo->type() == ObGeoType::GEOMETRYCOLLECTION) { + ObGeometry *geo = nullptr; // tree + if (!in_geo.is_tree()) { + ObGeoToTreeVisitor tree_visitor(&allocator); + if (OB_FAIL(in_geo.do_visit(tree_visitor))) { + LOG_WARN("failed to transform gc to tree", K(ret)); + } else { + geo = tree_visitor.get_geometry(); + } + } else { + geo = &in_geo; + } + if (OB_FAIL(ret)) { + } else if (geo->type() == ObGeoType::GEOMETRYCOLLECTION) { ObCartesianMultipoint *mpt = NULL; ObCartesianMultilinestring *mls = NULL; ObCartesianMultipolygon *mpy = NULL; @@ -341,7 +355,7 @@ int ObExprPrivSTAsMVTGeom::split_geo_to_basic_type( split_geo = geo; } if (OB_SUCC(ret) - && OB_FAIL((ObGeoFuncUtils::simplify_multi_geo( + && OB_FAIL((ObGeoTypeUtil::simplify_multi_geo( split_geo, allocator)))) { LOG_WARN("fail to simplify multi geometry", K(ret)); } @@ -355,14 +369,14 @@ int ObExprPrivSTAsMVTGeom::snap_geometry_to_grid( ObGeoGrid grid = {0, 0, 0, 1, 1, 0}; if (OB_FAIL(ObGeoMVTUtil::snap_to_grid(geo, grid, use_floor))) { LOG_WARN("fail to do snap to grid", K(ret)); - } else if (OB_FAIL((ObGeoFuncUtils::simplify_multi_geo( + } else if (OB_FAIL((ObGeoTypeUtil::simplify_multi_geo( geo, allocator)))) { LOG_WARN("fail to simplify multi geometry", K(ret)); } return ret; } -int ObExprPrivSTAsMVTGeom::clip_geometry(ObGeometry *geo, ObIAllocator &allocator, +int ObExprPrivSTAsMVTGeom::clip_geometry(ObGeometry *geo, lib::MemoryContext &mem_ctx, ObGeoType basic_type, int32_t extent, int32_t buffer, bool clip_geom, bool &is_null_res, ObGeometry *&res_geo) { @@ -370,7 +384,8 @@ int ObExprPrivSTAsMVTGeom::clip_geometry(ObGeometry *geo, ObIAllocator &allocato ObGeometry *basic_geo = nullptr; ObGeogBox *clip_box = nullptr; bool is_geo_empty = false; - if (OB_FAIL(split_geo_to_basic_type(geo, allocator, ObGeoType::POLYGON, basic_geo))) { + ObArenaAllocator &allocator = mem_ctx->get_arena_allocator(); + if (OB_FAIL(split_geo_to_basic_type(*geo, allocator, ObGeoType::POLYGON, basic_geo))) { LOG_WARN("fail to split geo to basic type", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::check_empty(basic_geo, is_geo_empty))) { LOG_WARN("fail to check empty", K(ret)); @@ -387,7 +402,7 @@ int ObExprPrivSTAsMVTGeom::clip_geometry(ObGeometry *geo, ObIAllocator &allocato } else { clip_box->xmax = clip_box->ymax = extent + static_cast(buffer); clip_box->xmin = clip_box->ymin = -static_cast(buffer); - if (OB_FAIL(ObGeoBoxUtil::clip_by_box(*basic_geo, allocator, *clip_box, res_geo, true))) { + if (OB_FAIL(ObGeoBoxUtil::clip_by_box(*basic_geo, mem_ctx, *clip_box, res_geo, true))) { LOG_WARN("fail to do clip by box", K(ret)); } else if (OB_ISNULL(res_geo)) { is_null_res = true; @@ -404,7 +419,7 @@ int ObExprPrivSTAsMVTGeom::clip_geometry(ObGeometry *geo, ObIAllocator &allocato } else if (basic_geo->type() == ObGeoType::POLYGON || basic_geo->type() == ObGeoType::MULTIPOLYGON) { ObGeometry *valid_poly = nullptr; - if (OB_FAIL(ObGeoExprUtils::make_valid_polygon(res_geo, allocator, valid_poly))) { + if (OB_FAIL(ObGeoExprUtils::make_valid_polygon(res_geo, mem_ctx, valid_poly))) { LOG_WARN("fail to make polygon valid", K(ret)); } else { res_geo = valid_poly; @@ -424,25 +439,35 @@ int ObExprPrivSTAsMVTGeom::eval_priv_st_asmvtgeom(const ObExpr &expr, ObEvalCtx int ret = OB_SUCCESS; bool is_null_res = false; ObGeometry *geo1 = nullptr; + ObGeometry *geo2 = nullptr; bool is_geo_empty = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_ASMVTGEOM); ObGeogBox *bounds = nullptr; int32_t extent = 4096; int32_t buffer = 256; bool clip_geom = true; ObGeometry *res_geo = nullptr; ObString res_wkb; - if (OB_FAIL(process_input_geometry( - expr, ctx, is_null_res, geo1, bounds, extent, buffer, clip_geom))) { + expr, ctx, temp_allocator, is_null_res, geo1, geo2, extent, buffer, clip_geom))) { LOG_WARN("fail to process input geometry", K(ret), K(geo1), K(is_null_res)); - } else if (is_null_res) { - // do nothing + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || is_null_res) { } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo_empty))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo_empty) { is_null_res = true; + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else if (OB_FAIL(get_bounds(*mem_ctx, *geo2, bounds))) { + LOG_WARN("fail to get bounds", K(ret)); } else if (geo1->type() == ObGeoType::LINESTRING || geo1->type() == ObGeoType::MULTILINESTRING) { // pre-check ObGeogBox fast_box; @@ -462,17 +487,12 @@ int ObExprPrivSTAsMVTGeom::eval_priv_st_asmvtgeom(const ObExpr &expr, ObEvalCtx ObGeoType basic_type = ObGeoType::GEOTYPEMAX; // POINT/LINE/POLYGON ObGeometry *split_geo = nullptr; - ObGeometry *geo_tree = nullptr; - ObGeoToTreeVisitor tree_visitor(&temp_allocator); if (OB_FAIL(ret) || is_null_res) { // do nothing } else if (OB_FAIL(get_basic_type(geo1, basic_type))) { LOG_WARN("fail to get basic type", K(ret)); - } else if (OB_FAIL(geo1->do_visit(tree_visitor))) { - LOG_WARN("failed to transform gc to tree", K(ret)); - } else if (FALSE_IT(geo_tree = tree_visitor.get_geometry())) { } else if (OB_FAIL(split_geo_to_basic_type( - geo_tree, temp_allocator, basic_type, split_geo))) { // split_geo: ObCartesian* + *geo1, temp_allocator, basic_type, split_geo))) { // split_geo: ObCartesian* LOG_WARN("fail to split geometry to basic type", K(ret), K(basic_type)); } else if (OB_FAIL(ObGeoExprUtils::check_empty(split_geo, is_geo_empty))) { LOG_WARN("check geo empty failed", K(ret)); @@ -489,7 +509,7 @@ int ObExprPrivSTAsMVTGeom::eval_priv_st_asmvtgeom(const ObExpr &expr, ObEvalCtx } else if (is_geo_empty) { is_null_res = true; } else if (OB_FAIL(clip_geometry(split_geo, - temp_allocator, + *mem_ctx, basic_type, extent, buffer, @@ -497,7 +517,7 @@ int ObExprPrivSTAsMVTGeom::eval_priv_st_asmvtgeom(const ObExpr &expr, ObEvalCtx is_null_res, res_geo))) { LOG_WARN("fail to clip geometry", K(ret)); - } else if (OB_FAIL((ObGeoFuncUtils::simplify_multi_geo( + } else if (OB_FAIL((ObGeoTypeUtil::simplify_multi_geo( res_geo, temp_allocator)))) { LOG_WARN("fail to simplify multi geometry", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::check_empty(res_geo, is_geo_empty))) { @@ -522,6 +542,9 @@ int ObExprPrivSTAsMVTGeom::eval_priv_st_asmvtgeom(const ObExpr &expr, ObEvalCtx } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.h b/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.h index 5358cf3b3..6631110d2 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.h +++ b/src/sql/engine/expr/ob_expr_priv_st_asmvtgeom.h @@ -14,6 +14,7 @@ #define OCEANBASE_SQL_OB_EXPR_ST_ASMVTGEOM_ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_func_box.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -35,15 +36,16 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int clip_geometry(ObGeometry *geo, ObIAllocator &allocator, ObGeoType basic_type, + static int clip_geometry(ObGeometry *geo, lib::MemoryContext &mem_ctx, ObGeoType basic_type, int32_t extent, int32_t buffer, bool clip_geom, bool &is_null_res, ObGeometry *&res_geo); static int get_basic_type(ObGeometry *geo, ObGeoType &basic_type); static int snap_geometry_to_grid(ObGeometry *&geo, ObIAllocator &allocator, bool use_floor); static int split_geo_to_basic_type( - ObGeometry *&geo, ObIAllocator &allocator, ObGeoType basic_type, ObGeometry *&split_geo); + ObGeometry &in_geo, ObIAllocator &allocator, ObGeoType basic_type, ObGeometry *&split_geo); static int affine_to_tile_space(ObGeometry *&geo, const ObGeogBox *bounds, int32_t extent); - static int process_input_geometry(const ObExpr &expr, ObEvalCtx &ctx, bool &is_null_res, - ObGeometry *&geo1, ObGeogBox *&bounds, int32_t &extent, int32_t &buffer, bool &clip_geom); + static int process_input_geometry(const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, + bool &is_null_res, ObGeometry *&geo1, ObGeometry *&geo2, int32_t &extent, int32_t &buffer, bool &clip_geom); + static int get_bounds(lib::MemoryContext &mem_ctx, ObGeometry &geo, ObGeogBox *&bounds); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTAsMVTGeom); }; } // namespace sql diff --git a/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.cpp b/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.cpp index 1289ddb10..0eed5d34c 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.cpp @@ -62,7 +62,7 @@ int ObExprPrivSTClipByBox2D::calc_result_type2(ObExprResType &type, ObExprResTyp return ret; } -int ObExprPrivSTClipByBox2D::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, +int ObExprPrivSTClipByBox2D::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, bool &is_null_res, ObGeometry *&geo1, ObGeometry *&geo2, const ObSrsItem *&srs1, const ObSrsItem *&srs2) { @@ -76,7 +76,7 @@ int ObExprPrivSTClipByBox2D::process_input_geometry(omt::ObSrsCacheGuard &srs_gu if (ob_is_null(type1) || ob_is_null(type2)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum1)) || OB_FAIL(arg2->eval(ctx, datum2))) { + } else if (OB_FAIL(allocator.eval_arg(arg1, ctx, datum1)) || OB_FAIL(allocator.eval_arg(arg2, ctx, datum2))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null() || datum2->is_null()) { is_null_res = true; @@ -84,17 +84,18 @@ int ObExprPrivSTClipByBox2D::process_input_geometry(omt::ObSrsCacheGuard &srs_gu ObString wkb1 = datum1->get_string(); ObString wkb2 = datum2->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data( + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN( "fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header()), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *datum2, arg2->datum_meta_, arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN( "fail to read real string data", K(ret), K(arg2->obj_meta_.has_lob_header()), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item( ctx, srs_guard, wkb1, srs1, true, N_PRIV_ST_CLIPBYBOX2D))) { LOG_WARN("fail to get srs item", K(ret), K(wkb1)); @@ -102,10 +103,10 @@ int ObExprPrivSTClipByBox2D::process_input_geometry(omt::ObSrsCacheGuard &srs_gu ctx, srs_guard, wkb2, srs2, true, N_PRIV_ST_CLIPBYBOX2D))) { LOG_WARN("fail to get srs item", K(ret), K(wkb2)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry( - allocator, wkb1, geo1, nullptr, N_PRIV_ST_CLIPBYBOX2D))) { // ObIWkbGeom + allocator, wkb1, geo1, nullptr, N_PRIV_ST_CLIPBYBOX2D, GEO_DEFAULT | GEO_NOT_COPY_WKB))) { // ObIWkbGeom LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb1)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry( - allocator, wkb2, geo2, nullptr, N_PRIV_ST_CLIPBYBOX2D))) { // ObIWkbGeom + allocator, wkb2, geo2, nullptr, N_PRIV_ST_CLIPBYBOX2D, GEO_DEFAULT | GEO_NOT_COPY_WKB))) { // ObIWkbGeom LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb2)); } else if (OB_NOT_NULL(srs1) && srs1->is_geographical_srs()) { ret = OB_ERR_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS; @@ -135,14 +136,17 @@ int ObExprPrivSTClipByBox2D::eval_priv_st_clipbybox2d( const ObSrsItem *srs1 = nullptr; const ObSrsItem *srs2 = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_CLIPBYBOX2D); ObString res_wkb; omt::ObSrsCacheGuard srs_guard; if (OB_FAIL(process_input_geometry(srs_guard, expr, ctx, temp_allocator, is_null_res, geo1, geo2, srs1, srs2))) { LOG_WARN("fail to process input geometry", K(ret), K(geo1), K(geo2), K(is_null_res)); - } else if (is_null_res) { - // do nothing + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || is_null_res) { } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)) || OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) { LOG_WARN("check geo empty failed", K(ret)); @@ -151,8 +155,13 @@ int ObExprPrivSTClipByBox2D::eval_priv_st_clipbybox2d( } else if (is_geo1_empty) { // return empty when first geo argument is empty res_geo = geo1; + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoEvalCtx box_ctx(&temp_allocator); + ObGeoEvalCtx box_ctx(*mem_ctx); box_ctx.set_is_called_in_pg_expr(true); ObGeogBox *gbox = nullptr; // calculate 2d box of geo2, then convert the box to a rectangle geo @@ -160,7 +169,7 @@ int ObExprPrivSTClipByBox2D::eval_priv_st_clipbybox2d( LOG_WARN("build gis context failed", K(ret), K(box_ctx.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(box_ctx, gbox))) { LOG_WARN("failed to do box functor failed", K(ret)); - } else if (OB_FAIL(ObGeoBoxUtil::clip_by_box(*geo1, temp_allocator, *gbox, res_geo, true))) { + } else if (OB_FAIL(ObGeoBoxUtil::clip_by_box(*geo1, *mem_ctx, *gbox, res_geo, true))) { LOG_WARN("fail to do clip by box", K(ret)); } else if (OB_ISNULL(res_geo)) { is_null_res = true; @@ -178,6 +187,9 @@ int ObExprPrivSTClipByBox2D::eval_priv_st_clipbybox2d( } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.h b/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.h index 7816d7268..a2cfa707c 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.h +++ b/src/sql/engine/expr/ob_expr_priv_st_clipbybox2d.h @@ -35,7 +35,7 @@ public: virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, bool &is_null_res, ObGeometry *&geo1, + static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, bool &is_null_res, ObGeometry *&geo1, ObGeometry *&geo2, const ObSrsItem *&srs1, const ObSrsItem *&srs2); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTClipByBox2D); }; diff --git a/src/sql/engine/expr/ob_expr_priv_st_equals.cpp b/src/sql/engine/expr/ob_expr_priv_st_equals.cpp index ae67320a6..9757a87cc 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_equals.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_equals.cpp @@ -57,44 +57,37 @@ int ObExprPrivSTEquals::calc_result_type2(ObExprResType &type, ObExprResType &ty return ret; } -int ObExprPrivSTEquals::get_input_geometry(omt::ObSrsCacheGuard &srs_guard, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, bool &is_null_geo, +int ObExprPrivSTEquals::get_input_geometry(omt::ObSrsCacheGuard &srs_guard, MultimodeAlloctor &allocator, ObEvalCtx &ctx, ObExpr *gis_arg, ObDatum *gis_datum, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty) { int ret = OB_SUCCESS; - ObEvalCtx::TempAllocGuard ctx_alloc_g(ctx); - common::ObArenaAllocator &allocator = ctx_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg->eval(ctx, gis_datum))) { - LOG_WARN("eval geo args failed", K(ret)); - } else if (gis_datum->is_null()) { - is_null_geo = true; - } else { - ObString wkb = gis_datum->get_string(); - ObGeoType type = ObGeoType::GEOTYPEMAX; - uint32_t srid = -1; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, - *gis_datum, - gis_arg->datum_meta_, - gis_arg->obj_meta_.has_lob_header(), - wkb))) { - LOG_WARN("fail to get real string data", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb, type, srid))) { - if (ret == OB_ERR_GIS_INVALID_DATA) { - LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_EQUALS); - } - LOG_WARN("get type and srid from wkb failed", K(wkb), K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::get_srs_item( - ctx, srs_guard, wkb, srs, true, N_PRIV_ST_EQUALS))) { - LOG_WARN("fail to get srs item", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, - wkb, - geo, - srs, - N_PRIV_ST_EQUALS, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { - LOG_WARN("get first geo by wkb failed", K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo, is_geo_empty))) { - LOG_WARN("check geo empty failed", K(ret)); + ObString wkb = gis_datum->get_string(); + ObGeoType type = ObGeoType::GEOTYPEMAX; + uint32_t srid = -1; + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, + *gis_datum, + gis_arg->datum_meta_, + gis_arg->obj_meta_.has_lob_header(), + wkb))) { + LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(allocator.add_baseline_size(wkb.length()))) { + } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb, type, srid))) { + if (ret == OB_ERR_GIS_INVALID_DATA) { + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_EQUALS); } + LOG_WARN("get type and srid from wkb failed", K(wkb), K(ret)); + } else if (OB_FAIL(ObGeoExprUtils::get_srs_item( + ctx, srs_guard, wkb, srs, true, N_PRIV_ST_EQUALS))) { + LOG_WARN("fail to get srs item", K(ret), K(wkb)); + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, + wkb, + geo, + srs, + N_PRIV_ST_EQUALS, + GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { + LOG_WARN("get first geo by wkb failed", K(ret)); + } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo, is_geo_empty))) { + LOG_WARN("check geo empty failed", K(ret)); } return ret; } @@ -114,31 +107,39 @@ int ObExprPrivSTEquals::eval_priv_st_equals(const ObExpr &expr, ObEvalCtx &ctx, const ObSrsItem *srs1 = nullptr; const ObSrsItem *srs2 = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_EQUALS); ObDatum *gis_datum1 = nullptr; ObDatum *gis_datum2 = nullptr; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); - } else if (OB_FAIL(get_input_geometry(srs_guard, gis_datum1, ctx, gis_arg1, is_geo1_null, srs1, geo1, is_geo1_empty))) { + } else if (OB_FAIL(get_input_geometry(srs_guard, temp_allocator, ctx, gis_arg1, gis_datum1, srs1, geo1, is_geo1_empty))) { LOG_WARN("fail to get input geometry", K(ret)); - } else if (OB_FAIL(get_input_geometry(srs_guard, gis_datum2, ctx, gis_arg2, is_geo2_null, srs2, geo2, is_geo2_empty))) { + } else if (OB_FAIL(get_input_geometry(srs_guard, temp_allocator, ctx, gis_arg2, gis_datum2, srs2, geo2, is_geo2_empty))) { LOG_WARN("fail to get input geometry", K(ret)); } else { uint32_t srid1 = srs1 == nullptr ? 0 : srs1->get_srid(); uint32_t srid2 = srs2 == nullptr ? 0 : srs2->get_srid(); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (srid1 != srid2) { ret = OB_ERR_GIS_DIFFERENT_SRIDS; LOG_WARN("srid not the same", K(ret), K(srid1), K(srid2)); LOG_USER_ERROR(OB_ERR_GIS_DIFFERENT_SRIDS, N_PRIV_ST_EQUALS, srid1, srid2); } else if (is_geo1_empty || is_geo2_empty) { res.set_bool(is_geo1_empty && is_geo2_empty); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs1, *geo1, *geo2))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { bool result = false; - ObGeoEvalCtx gis_context(&temp_allocator, srs1); + ObGeoEvalCtx gis_context(*mem_ctx, srs1); if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, result))) { @@ -148,6 +149,9 @@ int ObExprPrivSTEquals::eval_priv_st_equals(const ObExpr &expr, ObEvalCtx &ctx, res.set_bool(result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_priv_st_equals.h b/src/sql/engine/expr/ob_expr_priv_st_equals.h index 81d18e4a3..f9f27205b 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_equals.h +++ b/src/sql/engine/expr/ob_expr_priv_st_equals.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "observer/omt/ob_tenant_srs.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -33,8 +34,8 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int get_input_geometry(omt::ObSrsCacheGuard &srs_guard, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, - bool &is_null_geo, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty); + static int get_input_geometry(omt::ObSrsCacheGuard &srs_guard, MultimodeAlloctor &allocator, ObEvalCtx &ctx, ObExpr *gis_arg, + ObDatum *gis_datum, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTEquals); }; } // namespace sql diff --git a/src/sql/engine/expr/ob_expr_priv_st_geogfromtext.cpp b/src/sql/engine/expr/ob_expr_priv_st_geogfromtext.cpp index 6faff3aa7..d5b5f0c81 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_geogfromtext.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_geogfromtext.cpp @@ -74,11 +74,12 @@ int ObExprPrivSTGeogFromText::eval_priv_st_geogfromtext_common(const ObExpr &exp { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, func_name); ObDatum *datum = NULL; // get wkt - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("eval wkt arg failed", K(ret)); } else if(datum->is_null()){ res.set_null(); @@ -93,6 +94,7 @@ int ObExprPrivSTGeogFromText::eval_priv_st_geogfromtext_common(const ObExpr &exp if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkt))) { LOG_WARN("fail to get real data.", K(ret), K(wkt)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkt.length()))) { } else if (OB_NOT_NULL(wkt.find(';'))) { ObString srid_str = wkt.split_on(';'); if (OB_FAIL(ObGeoExprUtils::parse_srid(srid_str, srid))) { diff --git a/src/sql/engine/expr/ob_expr_priv_st_geohash.cpp b/src/sql/engine/expr/ob_expr_priv_st_geohash.cpp new file mode 100644 index 000000000..14367399a --- /dev/null +++ b/src/sql/engine/expr/ob_expr_priv_st_geohash.cpp @@ -0,0 +1,344 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file contains implementation for _st_geohash. + */ + +#define USING_LOG_PREFIX SQL_ENG +#include "sql/engine/expr/ob_expr_priv_st_geohash.h" +#include "lib/geo/ob_geo_func_register.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" + +using namespace oceanbase::common; +using namespace oceanbase::sql; + +namespace oceanbase +{ +namespace sql +{ +ObExprPrivSTGeoHash::ObExprPrivSTGeoHash(common::ObIAllocator &alloc) + : ObFuncExprOperator(alloc, T_FUN_SYS_PRIV_ST_GEOHASH, N_PRIV_ST_GEOHASH, MORE_THAN_ZERO, + NOT_VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION) +{} + +ObExprPrivSTGeoHash::~ObExprPrivSTGeoHash() +{} + +int ObExprPrivSTGeoHash::calc_result_typeN( + ObExprResType &type, + ObExprResType *types, + int64_t param_num, + ObExprTypeCtx &type_ctx) const +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(param_num > 2)) { + ObString fun_name(get_name()); + ret = OB_ERR_PARAM_SIZE; + LOG_USER_ERROR(OB_ERR_PARAM_SIZE, fun_name.length(), fun_name.ptr()); + } else { + ObObjType type_geom = types[0].get_type(); + if (!ob_is_geometry(type_geom) && !ob_is_string_type(type_geom) && !ob_is_null(type_geom)) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_GEOHASH); + LOG_WARN("invalid geometry type", K(ret), K(type_geom)); + } else if (param_num == 2) { + ObObjType prec_type = types[1].get_type(); + if ((ob_is_integer_type(prec_type) && ObTinyIntType != prec_type) || ob_is_null(prec_type)) { + // do noting + } else if (ob_is_string_type(prec_type)) { + types[1].set_calc_type(ObIntType); + } else { + ret = OB_ERR_INVALID_TYPE_FOR_ARGUMENT; + LOG_WARN("invalid precision type", K(ret), K(prec_type)); + } + } + } + + if (OB_SUCC(ret)) { + ObCastMode cast_mode = type_ctx.get_cast_mode(); + cast_mode &= ~CM_WARN_ON_FAIL; // make cast return error when fail + type_ctx.set_cast_mode(cast_mode); // cast mode only do work in new sql engine cast frame. + type.set_varchar(); + type.set_collation_type(type_ctx.get_coll_type()); + type.set_collation_level(CS_LEVEL_IMPLICIT); + } + + return ret; +} + +int ObExprPrivSTGeoHash::calc_geohash(ObGeogBox *&gbox, int precision, ObStringBuffer &geohash_buf) +{ + int ret = OB_SUCCESS; + const char base32[] = "0123456789bcdefghjkmnpqrstuvwxyz"; + char bits_mask[] = {16,8,4,2,1}; + int bit = 0; + uint8 ch_index = 0; + double lon = gbox->xmin + (gbox->xmax - gbox->xmin) / 2; + double lat = gbox->ymin + (gbox->ymax - gbox->ymin) / 2; + double lon_range[2], lat_range[2], mid; + lon_range[0] = -180.0; + lon_range[1] = 180.0; + lat_range[0] = -90.0; + lat_range[1] = 90.0; + + for (int i = 0; OB_SUCC(ret) && i < precision * 5; i++) { + if (!(i & 1)) { + // process longitude + mid = (lon_range[0] + lon_range[1]) / 2; + if (lon >= mid) { + // for compatibility,not using "ObGeoBoxUtil::is_float_gteq" here + ch_index |= bits_mask[bit]; + lon_range[0] = mid; + } else { + lon_range[1] = mid; + } + } else { + // process latitute + mid = (lat_range[0] + lat_range[1]) / 2; + if (lat >= mid) { + // for compatibility,not using "ObGeoBoxUtil::is_float_gteq" here + ch_index |= bits_mask[bit]; + lat_range[0] = mid; + } else { + lat_range[1] = mid; + } + } + if (bit < 4) { + bit++; + } else if (OB_FAIL(geohash_buf.append(&base32[ch_index], 1))) { + LOG_WARN("char append failed", K(ret), K(ch_index)); + } else { + bit = 0; + ch_index = 0; + } + } + return ret; +} + +int ObExprPrivSTGeoHash::calc_precision(ObGeogBox *&gbox, ObGeogBox *&bounds, int &precision) +{ + int ret = OB_SUCCESS; + bool finish_calc = false; + double minx, miny, maxx, maxy; + double latmax, latmin, lonmax, lonmin; + double lonwidth, latwidth; + double latmaxadjust, lonmaxadjust, latminadjust, lonminadjust; + minx = gbox->xmin; + maxx = gbox->xmax; + miny = gbox->ymin; + maxy = gbox->ymax; + + if (ObGeoBoxUtil::is_float_equal(minx, maxx) && ObGeoBoxUtil::is_float_equal(miny, maxy)) { + // it's a point + precision = 20; + } else { + lonmin = -180.0; + lonmax = 180.0; + latmin = -90.0; + latmax = 90.0; + int prec_calc = 0; + while(!finish_calc) { + lonwidth = lonmax - lonmin; + latwidth = latmax - latmin; + latmaxadjust = lonmaxadjust = latminadjust = lonminadjust = 0.0; + if (ObGeoBoxUtil::is_float_gt(minx, lonmin + lonwidth / 2.0)) { + lonminadjust = lonwidth / 2.0; + } else if (ObGeoBoxUtil::is_float_lt(maxx, lonmax - lonwidth / 2.0)) { + lonmaxadjust = -1 * lonwidth / 2.0; + } + if (lonminadjust || lonmaxadjust) { + lonmin += lonminadjust; + lonmax += lonmaxadjust; + prec_calc++; + } else { + finish_calc = true; + } + if (!finish_calc) { + if (ObGeoBoxUtil::is_float_gt(miny, latmin + latwidth / 2.0)) { + latminadjust = latwidth / 2.0; + } else if (ObGeoBoxUtil::is_float_lt(maxy, latmax - latwidth / 2.0)) { + latmaxadjust = -1 * latwidth / 2.0; + } + if (latminadjust || latmaxadjust) { + latmin += latminadjust; + latmax += latmaxadjust; + prec_calc++; + } else { + finish_calc = true; + } + } + } + // record bounds for future use + bounds->xmin = lonmin; + bounds->xmax = lonmax; + bounds->ymin = latmin; + bounds->ymax = latmax; + precision = prec_calc / 5; + } + return ret; +} + +int ObExprPrivSTGeoHash::get_gbox(lib::MemoryContext &mem_ctx, ObGeometry *&geo, ObGeogBox *&gbox) +{ + int ret = OB_SUCCESS; + ObGeoEvalCtx box_ctx(mem_ctx); + box_ctx.set_is_called_in_pg_expr(true); + + if (OB_FAIL(box_ctx.append_geo_arg(geo))) { + LOG_WARN("build gis context failed", K(ret), K(box_ctx.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(box_ctx, gbox))) { + LOG_WARN("failed to do box functor failed", K(ret)); + } else if (ObGeoBoxUtil::is_float_gt(gbox->xmin, gbox->xmax) + || ObGeoBoxUtil::is_float_gt(gbox->ymin , gbox->ymax)) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_GEOHASH); + LOG_WARN("Geometric bounds invalid", K(ret), K(gbox->xmin), K(gbox->xmax), K(gbox->ymin), K(gbox->ymax)); + } else if (ObGeoBoxUtil::is_float_lt(gbox->xmin, -180.0) || ObGeoBoxUtil::is_float_gt(gbox->xmax, 180.0)) { + ret = OB_OPERATE_OVERFLOW; + LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "longitude", N_PRIV_ST_GEOHASH); + LOG_WARN("longitude is out of range", K(ret), K(gbox->xmin), K(gbox->xmax)); + } else if (ObGeoBoxUtil::is_float_lt(gbox->ymin, -90.0) || ObGeoBoxUtil::is_float_gt(gbox->ymax, 90.0)) { + ret = OB_OPERATE_OVERFLOW; + LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "latitude", N_PRIV_ST_GEOHASH); + LOG_WARN("latitude is out of range", K(ret), K(gbox->xmin), K(gbox->xmax)); + } + return ret; +} + +int ObExprPrivSTGeoHash::process_input_geometry( + const ObExpr &expr, + ObEvalCtx &ctx, + MultimodeAlloctor &allocator, + bool &is_null_res, + ObGeometry *&geo, + int &precision) +{ + int ret = OB_SUCCESS; + ObDatum *geo_datum = nullptr; + ObExpr *geo_arg = expr.args_[0]; + ObGeoType geo_type; + uint32_t geo_srid; + bool is_geo_empty = true; + + if (OB_FAIL(geo_arg->eval(ctx, geo_datum))) { + LOG_WARN("fail to eval args", K(ret)); + } else if (geo_datum->is_null()) { + is_null_res = true; + } else { + ObString geo_wkb = geo_datum->get_string(); + omt::ObSrsCacheGuard srs_guard; + const ObSrsItem *geo_srs = nullptr; + + if (OB_FAIL(ObTextStringHelper::read_real_string_data( + allocator, + *geo_datum, + geo_arg->datum_meta_, + geo_arg->obj_meta_.has_lob_header(), + geo_wkb))) { + LOG_WARN("fail to read real string data", K(ret), K(geo_arg->obj_meta_.has_lob_header()), K(geo_wkb)); + } else if (geo_wkb.empty()) { + is_null_res = true; + } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(geo_wkb, geo_type, geo_srid))) { + if (ret == OB_ERR_GIS_INVALID_DATA) { + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_GEOHASH); + } + } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, geo_wkb, geo_srs, true, N_PRIV_ST_GEOHASH))) { + LOG_WARN("fail to get srs item", K(ret), K(geo_wkb)); + } else if (OB_FAIL(ObGeoExprUtils::build_geometry( + allocator, + geo_wkb, + geo, + nullptr, + N_PRIV_ST_GEOHASH, + ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { // ObIWkbGeom + LOG_WARN("fail to build geometry from wkb", K(ret), K(geo_wkb)); + } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo, is_geo_empty))) { + LOG_WARN("check geo empty failed", K(ret)); + } else if (is_geo_empty) { + is_null_res = true; + } + } + + if (OB_SUCC(ret) && !is_null_res && expr.arg_cnt_ == 2) { + ObExpr *prec_arg = expr.args_[1]; + ObDatum *prec_datum = nullptr; + if (ob_is_null(prec_arg->datum_meta_.type_)) { + precision = 0; + } else if (OB_FAIL(prec_arg->eval(ctx, prec_datum))) { + LOG_WARN("fail to eval args", K(ret)); + } else if (prec_datum->is_null()) { + precision = 0; + } else { + int64_t tmp_prec = prec_datum->get_int(); + if (tmp_prec > INT32_MAX || tmp_prec < INT32_MIN) { + ret = OB_OPERATE_OVERFLOW; + LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "precision", N_PRIV_ST_GEOHASH); + LOG_WARN("precision is not in range", K(ret), K(tmp_prec)); + } else { + precision = static_cast(tmp_prec); + } + } + } + return ret; +} + +int ObExprPrivSTGeoHash::eval_priv_st_geohash(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) +{ + int ret = OB_SUCCESS; + bool is_null_res = false; + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_GEOHASH); + ObGeometry *geo = nullptr; + ObString geohash_res; + ObGeogBox *gbox = nullptr; + ObGeogBox *bounds = nullptr; + ObStringBuffer geohash_buf(&temp_allocator); + int precision = 0; + + if (OB_FAIL(process_input_geometry(expr, ctx, temp_allocator, is_null_res, geo, precision))) { + LOG_WARN("fail to process input geometry", K(ret), K(is_null_res), K(geo), K(precision)); + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret)) { + } else if (is_null_res) { + res.set_null(); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else if (OB_FAIL(get_gbox(*mem_ctx, geo, gbox))) { + LOG_WARN("fail to calculate geometry gbox", K(ret)); + } else if (OB_ISNULL(bounds = OB_NEWx(ObGeogBox, &temp_allocator))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret), KP(bounds)); + } else if (precision <= 0 && OB_FAIL(calc_precision(gbox, bounds, precision))) { + LOG_WARN("fail to calculate precision", K(ret)); + } else if (OB_FAIL(calc_geohash(gbox, precision, geohash_buf))) { + LOG_WARN("fail to calculate geohash", K(ret)); + } else { + res.set_string(geohash_buf.ptr(), geohash_buf.length()); + } + + return ret; +} + +int ObExprPrivSTGeoHash::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const +{ + UNUSED(expr_cg_ctx); + UNUSED(raw_expr); + rt_expr.eval_func_ = eval_priv_st_geohash; + return OB_SUCCESS; +} + +} // namespace sql +} // namespace oceanbase \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_priv_st_geohash.h b/src/sql/engine/expr/ob_expr_priv_st_geohash.h new file mode 100644 index 000000000..825808080 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_priv_st_geohash.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file contains implementation for _st_geohash. + */ + +#ifndef OCEANBASE_SQL_OB_EXPR_ST_GEOHASH_ +#define OCEANBASE_SQL_OB_EXPR_ST_GEOHASH_ + +#include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace sql +{ +class ObExprPrivSTGeoHash : public ObFuncExprOperator +{ +public: + explicit ObExprPrivSTGeoHash(common::ObIAllocator &alloc); + virtual ~ObExprPrivSTGeoHash(); + virtual int calc_result_typeN( + ObExprResType &type, + ObExprResType *types, + int64_t param_num, + ObExprTypeCtx &type_ctx) const override; + static int eval_priv_st_geohash(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); + virtual int cg_expr( + ObExprCGCtx &expr_cg_ctx, + const ObRawExpr &raw_expr, + ObExpr &rt_expr) const override; +private: + static int process_input_geometry( + const ObExpr &expr, + ObEvalCtx &ctx, + MultimodeAlloctor &allocator, + bool &is_null_res, + ObGeometry *&geo, + int &precision); + static int get_gbox(lib::MemoryContext &mem_ctx, ObGeometry *&geo, ObGeogBox *&gbox); + static int calc_precision(ObGeogBox *&gbox, ObGeogBox *&bounds, int &precision); + static int calc_geohash(ObGeogBox *&gbox, int precision, ObStringBuffer &geohash_buf); + + DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTGeoHash); +}; +} // namespace sql +} // namespace oceanbase +#endif // OCEANBASE_SQL_OB_EXPR_ST_GEOHASH_ \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_priv_st_geometrytype.cpp b/src/sql/engine/expr/ob_expr_priv_st_geometrytype.cpp index dff378fc2..5b98491f7 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_geometrytype.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_geometrytype.cpp @@ -17,6 +17,7 @@ #include "lib/geo/ob_geo_utils.h" #include "lib/json_type/ob_json_base.h" #include "sql/engine/expr/ob_expr_lob_utils.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -64,12 +65,13 @@ int ObExprPrivSTGeometryType::eval_priv_st_geometrytype(const ObExpr &expr, ObEv ObExpr *arg1 = expr.args_[0]; ObObjType type1 = arg1->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_GEOMETRYTYPE); ObString res_type; if (ob_is_null(type1)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum1))) { + } else if (OB_FAIL(temp_allocator.eval_arg(arg1, ctx, datum1))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null()) { is_null_res = true; @@ -80,6 +82,7 @@ int ObExprPrivSTGeometryType::eval_priv_st_geometrytype(const ObExpr &expr, ObEv if (OB_FAIL(ObTextStringHelper::read_real_string_data( temp_allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header())); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_from_wkb(wkb, gtype))) { LOG_WARN("fail to get geo type from wkb", K(ret), K(gtype)); } else if (OB_FAIL(ObGeoTypeUtil::get_st_geo_name_by_type(gtype, res_type))) { diff --git a/src/sql/engine/expr/ob_expr_priv_st_iscollection.cpp b/src/sql/engine/expr/ob_expr_priv_st_iscollection.cpp index bb8b306f7..36fe96b84 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_iscollection.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_iscollection.cpp @@ -65,12 +65,13 @@ int ObExprPrivSTIsCollection::eval_priv_st_iscollection( ObExpr *arg1 = expr.args_[0]; ObObjType type1 = arg1->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_ISCOLLECTION); bool bres = true; if (ob_is_null(type1)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum1))) { + } else if (OB_FAIL(temp_allocator.eval_arg(arg1, ctx, datum1))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null()) { is_null_res = true; @@ -79,15 +80,16 @@ int ObExprPrivSTIsCollection::eval_priv_st_iscollection( ObGeoType gtype = ObGeoType::GEOTYPEMAX; ObGeometry *geo = nullptr; - if (OB_FAIL(ObTextStringHelper::read_real_string_data( + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( temp_allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header())); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, geo, nullptr, N_PRIV_ST_ISCOLLECTION, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { // ObIWkbGeom + GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { // ObIWkbGeom LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb)); } else if ((geo->type() <= ObGeoType::GEOMETRY) || (geo->type() >= ObGeoType::GEOTYPEMAX)) { ret = OB_ERR_INVALID_GEOMETRY_TYPE; diff --git a/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.cpp b/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.cpp index a23e60174..93e302b7d 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.cpp @@ -16,7 +16,6 @@ #include "sql/session/ob_sql_session_info.h" #include "lib/geo/ob_geo_func_register.h" #include "lib/geo/ob_geo_utils.h" -#include "share/object/ob_obj_cast_util.h" #include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; @@ -78,35 +77,6 @@ int ObExprPrivSTMakeEnvelope::calc_result_typeN( return ret; } -// ob_obj_cast.cpp string_double does not return error -// when empty string is converted to double in mysql mode -int ObExprPrivSTMakeEnvelope::string_to_double(const common::ObString &in_str, ObCollationType cs_type, double &res) -{ - int ret = OB_SUCCESS; - - if (in_str.empty()) { - ret = OB_ERR_DOUBLE_TRUNCATED; - LOG_WARN("input string is empty", K(ret), K(in_str)); - } else { - int err = 0; - char *endptr = NULL; - double out_val = ObCharset::strntodv2(in_str.ptr(), in_str.length(), &endptr, &err); - if (EOVERFLOW == err && (-DBL_MAX == out_val || DBL_MAX == out_val)) { - ret = OB_DATA_OUT_OF_RANGE; - LOG_WARN("value is out of range", K(ret), K(out_val)); - } else { - if (OB_FAIL(check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err, cs_type))) { - LOG_WARN("fail to check convert str err", K(ret), K(in_str), K(out_val), K(err)); - ret = OB_ERR_DOUBLE_TRUNCATED; - } else { - res = out_val; - } - } - } - - return ret; -} - int ObExprPrivSTMakeEnvelope::read_args(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObSEArray &coords, ObGeoSrid &srid, bool &is_null_result, const ObSrsItem *&srs_item) { @@ -131,7 +101,7 @@ int ObExprPrivSTMakeEnvelope::read_args(omt::ObSrsCacheGuard &srs_guard, const O is_null_result = true; } else if (!ob_is_string_type(type)) { coord = type == ObTinyIntType ? datum->get_tinyint() : datum->get_double(); - } else if (OB_FAIL(string_to_double(datum->get_string(), arg->datum_meta_.cs_type_, coord))) { + } else if (OB_FAIL(ObGeoExprUtils::string_to_double(datum->get_string(), arg->datum_meta_.cs_type_, coord))) { LOG_WARN("fail to get x", K(ret), K(datum->get_string()), K(arg->datum_meta_.cs_type_)); } diff --git a/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.h b/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.h index c1c0edff3..78166ea5b 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.h +++ b/src/sql/engine/expr/ob_expr_priv_st_makeenvelope.h @@ -35,7 +35,6 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int string_to_double(const common::ObString &in_str, ObCollationType cs_type, double &res); static int read_args(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObSEArray &coords, ObGeoSrid &srid, bool &is_null_result, const ObSrsItem *&srs_item); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTMakeEnvelope); diff --git a/src/sql/engine/expr/ob_expr_priv_st_makepoint.cpp b/src/sql/engine/expr/ob_expr_priv_st_makepoint.cpp new file mode 100644 index 000000000..e56dd27da --- /dev/null +++ b/src/sql/engine/expr/ob_expr_priv_st_makepoint.cpp @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file contains implementation for _st_makepoint. + */ + +#define USING_LOG_PREFIX SQL_ENG +#include "sql/engine/expr/ob_expr_priv_st_makepoint.h" +#include "sql/session/ob_sql_session_info.h" +#include "lib/geo/ob_geo_func_common.h" +#include "lib/geo/ob_geo_common.h" +#include "lib/geo/ob_geo_utils.h" +#include "lib/geo/ob_geo_bin.h" +#include "lib/geo/ob_geo.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" + + +using namespace oceanbase::common; +using namespace oceanbase::sql; + +namespace oceanbase +{ +namespace sql +{ +ObExprPrivSTMakePoint::ObExprPrivSTMakePoint(common::ObIAllocator &alloc) + : ObFuncExprOperator(alloc, T_FUN_SYS_PRIV_ST_MAKEPOINT, N_PRIV_ST_MAKEPOINT, TWO_OR_THREE, NOT_VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION) +{ +} + +ObExprPrivSTMakePoint::~ObExprPrivSTMakePoint() +{ +} + +int ObExprPrivSTMakePoint::calc_result_typeN( + ObExprResType& type, + ObExprResType* types_stack, + int64_t param_num, + ObExprTypeCtx& type_ctx) const +{ + int ret = OB_SUCCESS; + UNUSED(type_ctx); + for (int i = 0; OB_SUCC(ret) && i < param_num; i++) { + ObObjType type = types_stack[i].get_type(); + if (ob_is_null(type) || ob_is_double_type(type) || type == ObTinyIntType || ob_is_string_type(type)) { + // do nothing + } else if (ob_is_numeric_type(type)) { + types_stack[i].set_calc_type(ObDoubleType); + } else { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("invalid input type", K(ret), K(i), K(type)); + } + } + + if (OB_SUCC(ret)) { + ObCastMode cast_mode = type_ctx.get_cast_mode(); + cast_mode &= ~CM_WARN_ON_FAIL; // make cast return error when fail + cast_mode |= CM_STRING_INTEGER_TRUNC; // make cast check range when string to int + type_ctx.set_cast_mode(cast_mode); // cast mode only do work in new sql engine cast frame. + type.set_geometry(); + type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObGeometryType]).get_length()); + } + + return ret; +} + +int ObExprPrivSTMakePoint::eval_priv_st_makepoint( + const ObExpr &expr, + ObEvalCtx &ctx, + ObDatum &res) +{ + int ret = OB_SUCCESS; + bool is_null_result = false; + int num_args = expr.arg_cnt_; + ObDatum *datum[3] = {nullptr}; + double p[3] = {0.0}; + ObGeoSrid srid = 0; + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_ASMVTGEOM); + ObWkbBuffer res_wkb_buf(temp_allocator); + + for(int i = 0; OB_SUCC(ret) && i < num_args; i++) { + if (expr.args_[i]->is_boolean_) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("invalid type", K(ret), K(i), K(expr.args_[i]->is_boolean_)); + } else if(ob_is_null(expr.args_[i]->datum_meta_.type_)) { + is_null_result = true; + } else if (OB_FAIL(expr.args_[i]->eval(ctx, datum[i]))) { + LOG_WARN("fail to eval arg", K(ret), K(expr.args_[i]->datum_meta_.type_)); + } else if (datum[i]->is_null()) { + is_null_result = true; + } else if (ob_is_string_type(expr.args_[i]->datum_meta_.type_)) { + if (OB_FAIL(ObGeoExprUtils::string_to_double(datum[i]->get_string(), expr.args_[i]->datum_meta_.cs_type_, p[i]))) { + LOG_WARN("fail to get arg", K(ret), K(expr.args_[i]->datum_meta_.type_)); + } + } else { + p[i] = datum[i]->get_double(); + } + } + + if (OB_FAIL(ret) || is_null_result) { + } else if (OB_FAIL(res_wkb_buf.append(srid))) { + LOG_WARN("fail to append srid to makepoint wkb buf", K(ret), K(srid)); + } else if (OB_FAIL(res_wkb_buf.append(static_cast(ENCODE_GEO_VERSION(GEO_VESION_1))))) { + LOG_WARN("fail to append version to makepoint wkb buf", K(ret)); + } else if (OB_FAIL(res_wkb_buf.append(static_cast(ObGeoWkbByteOrder::LittleEndian)))) { + LOG_WARN("fail to append little endian byte order to makepoint wkb buf", K(ret)); + } else if (num_args == 2 && OB_FAIL(res_wkb_buf.append(static_cast(ObGeoType::POINT)))) { + LOG_WARN("fail to append 2D point type to makepoint wkb buf", K(ret)); + } else if (num_args == 3 && OB_FAIL(res_wkb_buf.append(static_cast(ObGeoType::POINTZ)))) { + LOG_WARN("fail to append 3D point type to makepoint wkb buf", K(ret)); + } else if (OB_FAIL(res_wkb_buf.append(p[0]))) { + LOG_WARN("fail to append x to makepoint wkb buf", K(ret), K(p[0])); + } else if (OB_FAIL(res_wkb_buf.append(p[1]))) { + LOG_WARN("fail to append y to makepoint wkb buf", K(ret), K(p[1])); + } else if (num_args > 2 && OB_FAIL(res_wkb_buf.append(p[2]))) { + LOG_WARN("fail to append z to makepoint wkb buf", K(ret), K(p[2])); + } + + if (OB_SUCC(ret)) { + if (is_null_result) { + res.set_null(); + } else if (OB_FAIL(ObGeoExprUtils::pack_geo_res(expr, ctx, res, res_wkb_buf.string()))) { + LOG_WARN("fail to pack geo res", K(ret)); + } + } + + return ret; +} + +int ObExprPrivSTMakePoint::cg_expr( + ObExprCGCtx &expr_cg_ctx, + const ObRawExpr &raw_expr, + ObExpr &rt_expr) const +{ + UNUSED(expr_cg_ctx); + UNUSED(raw_expr); + rt_expr.eval_func_ = eval_priv_st_makepoint; + return OB_SUCCESS; +} + +} // namespace sql +} // namespace oceanbase \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_priv_st_makepoint.h b/src/sql/engine/expr/ob_expr_priv_st_makepoint.h new file mode 100644 index 000000000..96df0ae64 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_priv_st_makepoint.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * This file contains implementation for _st_makepoint. + */ + +#ifndef OCEANBASE_SQL_OB_EXPR_PRIV_ST_MAKEPOINT_ +#define OCEANBASE_SQL_OB_EXPR_PRIV_ST_MAKEPOINT_ + +#include "sql/engine/expr/ob_expr_operator.h" + +using namespace oceanbase::common; + +namespace oceanbase +{ +namespace sql +{ +class ObExprPrivSTMakePoint : public ObFuncExprOperator +{ +public: + explicit ObExprPrivSTMakePoint(common::ObIAllocator &alloc); + virtual ~ObExprPrivSTMakePoint(); + virtual int calc_result_typeN( + ObExprResType& type, + ObExprResType* types, + int64_t param_num, + common::ObExprTypeCtx& type_ctx) + const override; + static int eval_priv_st_makepoint(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); + virtual int cg_expr( + ObExprCGCtx &expr_cg_ctx, + const ObRawExpr &raw_expr, + ObExpr &rt_expr) const override; +private: + DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTMakePoint); +}; + +} // sql +} // oceanbase +#endif // OCEANBASE_SQL_OB_EXPR_PRIV_ST_MAKEPOINT_ \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_priv_st_makevalid.cpp b/src/sql/engine/expr/ob_expr_priv_st_makevalid.cpp index c52afb71b..8a75620d9 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_makevalid.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_makevalid.cpp @@ -64,27 +64,37 @@ int ObExprPrivSTMakeValid::eval_priv_st_makevalid(const ObExpr &expr, ObEvalCtx int ret = OB_SUCCESS; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_MAKEVALID); ObDatum *gis_datum1 = nullptr; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = nullptr; ObGeometry *geo = NULL; - if (OB_FAIL(expr.args_[0]->eval(ctx, gis_datum1))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, gis_datum1))) { LOG_WARN("eval geo args failed", K(ret)); + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret)) { } else if (gis_datum1->is_null()) { res.set_null(); - } else if (OB_FAIL(ObGeoExprUtils::get_input_geometry(tmp_allocator, gis_datum1, ctx, - expr.args_[0], srs_guard, N_PRIV_ST_MAKEVALID, srs, geo))) { + } else if (OB_FAIL(ObGeoExprUtils::get_input_geometry(N_PRIV_ST_MAKEVALID, tmp_allocator, gis_datum1, ctx, + expr.args_[0], srs_guard, srs, geo))) { LOG_WARN("eval geo args failed", K(ret)); } else if (geo->crs() != ObGeoCRS::Cartesian) { ret = OB_ERR_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS; LOG_USER_ERROR(OB_ERR_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS, N_PRIV_ST_MAKEVALID, ObGeoTypeUtil::get_geo_name_by_type(geo->type())); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { bool isvalid_res = false; int correct_result; ObGeoNormalVal reason; - ObGeoEvalCtx gis_context(&tmp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo))) { LOG_WARN("build geo gis context failed", K(ret)); } else if (OB_FAIL(gis_context.append_val_arg(reason))) { @@ -98,7 +108,7 @@ int ObExprPrivSTMakeValid::eval_priv_st_makevalid(const ObExpr &expr, ObEvalCtx if (OB_FAIL(geo->do_visit(to_tree))) { LOG_WARN("fail to transfer geo1 to tree", K(ret)); } else { - if (OB_FAIL(ObGeoExprUtils::make_valid_polygon(to_tree.get_geometry(), tmp_allocator, valid_geo))) { + if (OB_FAIL(ObGeoExprUtils::make_valid_polygon(to_tree.get_geometry(), *mem_ctx, valid_geo))) { LOG_WARN("make polygon valid failed", K(ret)); } else if (OB_NOT_NULL(valid_geo) && !valid_geo->is_empty()) { geo = valid_geo; @@ -122,6 +132,9 @@ int ObExprPrivSTMakeValid::eval_priv_st_makevalid(const ObExpr &expr, ObEvalCtx } } } + if (mem_ctx != nullptr) { + tmp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_priv_st_numinteriorrings.cpp b/src/sql/engine/expr/ob_expr_priv_st_numinteriorrings.cpp index a2d68613a..912f7a750 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_numinteriorrings.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_numinteriorrings.cpp @@ -63,12 +63,13 @@ int ObExprPrivSTNumInteriorRings::eval_priv_st_numinteriorrings( ObExpr *arg1 = expr.args_[0]; ObObjType type1 = arg1->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_NUMINTERIORRINGS); uint32_t res_num = 0; if (ob_is_null(type1)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum1))) { + } else if (OB_FAIL(temp_allocator.eval_arg(arg1, ctx, datum1))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null()) { is_null_res = true; @@ -77,15 +78,16 @@ int ObExprPrivSTNumInteriorRings::eval_priv_st_numinteriorrings( ObGeoType gtype = ObGeoType::GEOTYPEMAX; ObGeometry *geo = nullptr; - if (OB_FAIL(ObTextStringHelper::read_real_string_data( + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( temp_allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header())); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, geo, nullptr, N_PRIV_ST_NUMINTERIORRINGS, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { // ObIWkbGeom + GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { // ObIWkbGeom LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb)); } else if (geo->type() != ObGeoType::POLYGON) { is_null_res = true; diff --git a/src/sql/engine/expr/ob_expr_priv_st_point.cpp b/src/sql/engine/expr/ob_expr_priv_st_point.cpp index 56cb87490..036c4732b 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_point.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_point.cpp @@ -15,7 +15,6 @@ #include "sql/engine/expr/ob_expr_priv_st_point.h" #include "observer/omt/ob_tenant_srs.h" #include "sql/session/ob_sql_session_info.h" -#include "share/object/ob_obj_cast_util.h" #include "lib/geo/ob_geo_func_common.h" #include "lib/geo/ob_geo_common.h" #include "lib/geo/ob_geo_utils.h" @@ -101,34 +100,6 @@ int ObExprPrivSTPoint::calc_result_typeN(ObExprResType& type, return ret; } -int ObExprPrivSTPoint::string_to_double(const common::ObString &in_str, ObCollationType cs_type, - double &res) -{ - int ret = OB_SUCCESS; - - if (in_str.empty()) { - ret = OB_ERR_DOUBLE_TRUNCATED; - LOG_WARN("input string is empty", K(ret), K(in_str)); - } else { - int err = 0; - char *endptr = NULL; - double out_val = ObCharset::strntodv2(in_str.ptr(), in_str.length(), &endptr, &err); - if (EOVERFLOW == err && (-DBL_MAX == out_val || DBL_MAX == out_val)) { - ret = OB_DATA_OUT_OF_RANGE; - LOG_WARN("value is out of range", K(ret), K(out_val)); - } else { - if (OB_FAIL(check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err, cs_type))) { - LOG_WARN("fail to check convert str err", K(ret), K(in_str), K(out_val), K(err)); - ret = OB_ERR_DOUBLE_TRUNCATED; - } else { - res = out_val; - } - } - } - - return ret; -} - int ObExprPrivSTPoint::eval_priv_st_point(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) @@ -200,9 +171,9 @@ int ObExprPrivSTPoint::eval_priv_st_point(const ObExpr &expr, if (!ob_is_string_type(type_y)) { y = datum_y->get_double(); } - if (ob_is_string_type(type_x) && OB_FAIL(string_to_double(datum_x->get_string(), arg_x->datum_meta_.cs_type_, x))) { + if (ob_is_string_type(type_x) && OB_FAIL(ObGeoExprUtils::string_to_double(datum_x->get_string(), arg_x->datum_meta_.cs_type_, x))) { LOG_WARN("fail to get x", K(ret), K(type_x)); - } else if (ob_is_string_type(type_y) && OB_FAIL(string_to_double(datum_y->get_string(), arg_y->datum_meta_.cs_type_, y))) { + } else if (ob_is_string_type(type_y) && OB_FAIL(ObGeoExprUtils::string_to_double(datum_y->get_string(), arg_y->datum_meta_.cs_type_, y))) { LOG_WARN("fail to get y", K(ret), K(type_y)); } else if (OB_FAIL(res_wkb_buf.append(srid))) { LOG_WARN("fail to append srid to point wkb buf", K(ret), K(srid)); diff --git a/src/sql/engine/expr/ob_expr_priv_st_point.h b/src/sql/engine/expr/ob_expr_priv_st_point.h index 3dc664f1e..e8c803d7c 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_point.h +++ b/src/sql/engine/expr/ob_expr_priv_st_point.h @@ -39,7 +39,6 @@ public: const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int string_to_double(const common::ObString &in_str, ObCollationType cs_type, double &res); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTPoint); }; diff --git a/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.cpp b/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.cpp index 42ead9d45..5e142e2e2 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.cpp @@ -57,7 +57,7 @@ int ObExprPrivSTPointOnSurface::calc_result_type1( } int ObExprPrivSTPointOnSurface::process_input_geometry( - const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, bool &is_null_res, ObGeometry *&geo1) + const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, bool &is_null_res, ObGeometry *&geo1) { int ret = OB_SUCCESS; ObDatum *datum1 = nullptr; @@ -66,7 +66,7 @@ int ObExprPrivSTPointOnSurface::process_input_geometry( if (ob_is_null(type1)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum1))) { + } else if (OB_FAIL(allocator.eval_arg(arg1, ctx, datum1))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null()) { is_null_res = true; @@ -75,13 +75,14 @@ int ObExprPrivSTPointOnSurface::process_input_geometry( omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs1 = nullptr; - if (OB_FAIL(ObTextStringHelper::read_real_string_data( + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header()), K(wkb1)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs1, true, N_PRIV_ST_POINTONSURFACE))) { LOG_WARN("fail to get srs item", K(ret), K(wkb1)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry( - allocator, wkb1, geo1, nullptr, N_PRIV_ST_POINTONSURFACE))) { // ObIWkbGeom + allocator, wkb1, geo1, nullptr, N_PRIV_ST_POINTONSURFACE, GEO_DEFAULT | GEO_NOT_COPY_WKB))) { // ObIWkbGeom LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb1)); } else if (OB_NOT_NULL(srs1) && srs1->is_geographical_srs()) { ret = OB_ERR_NOT_IMPLEMENTED_FOR_GEOGRAPHIC_SRS; @@ -102,15 +103,23 @@ int ObExprPrivSTPointOnSurface::eval_priv_st_pointonsurface(const ObExpr &expr, ObGeometry *res_geo = NULL; ObGeometry *interior_point = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_POINTONSURFACE); ObString res_wkb; if (OB_FAIL(process_input_geometry(expr, ctx, temp_allocator, is_null_res, geo1))) { LOG_WARN("fail to process input geometry", K(ret), K(geo1), K(is_null_res)); - } else if (is_null_res) { - // do nothing + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || is_null_res) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoInteriorPointVisitor inter_point_visitor(&temp_allocator); + ObGeoInteriorPointVisitor inter_point_visitor(*mem_ctx); if (OB_FAIL(geo1->do_visit(inter_point_visitor))) { LOG_WARN("fail to do interior point visitor", K(ret)); } else if (OB_FAIL(inter_point_visitor.get_interior_point(interior_point))) { @@ -129,6 +138,9 @@ int ObExprPrivSTPointOnSurface::eval_priv_st_pointonsurface(const ObExpr &expr, } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.h b/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.h index 919cbcb83..a47515ba6 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.h +++ b/src/sql/engine/expr/ob_expr_priv_st_pointonsurface.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; @@ -34,7 +35,7 @@ public: private: static int process_input_geometry( - const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, bool &is_null_res, ObGeometry *&geo1); + const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, bool &is_null_res, ObGeometry *&geo1); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTPointOnSurface); }; } // namespace sql diff --git a/src/sql/engine/expr/ob_expr_priv_st_touches.cpp b/src/sql/engine/expr/ob_expr_priv_st_touches.cpp index 255045c2d..00472ead8 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_touches.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_touches.cpp @@ -58,7 +58,7 @@ int ObExprPrivSTTouches::calc_result_type2(ObExprResType &type, ObExprResType &t } // an invalid type and a nullptr type will return nullptr // an invalid type and a valid type return error - if (null_types == 0 && unexpected_types > 0) { + if (unexpected_types > 0) { ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_TOUCHES); LOG_WARN("invalid type", K(ret)); @@ -71,44 +71,37 @@ int ObExprPrivSTTouches::calc_result_type2(ObExprResType &type, ObExprResType &t return ret; } -int ObExprPrivSTTouches::get_input_geometry(omt::ObSrsCacheGuard &srs_guard, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, - bool &is_null_geo, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty) +int ObExprPrivSTTouches::get_input_geometry(omt::ObSrsCacheGuard &srs_guard, MultimodeAlloctor &temp_allocator, ObEvalCtx &ctx, ObExpr *gis_arg, + ObDatum *gis_datum, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty) { int ret = OB_SUCCESS; - ObEvalCtx::TempAllocGuard ctx_alloc_g(ctx); - common::ObArenaAllocator &allocator = ctx_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg->eval(ctx, gis_datum))) { - LOG_WARN("eval geo args failed", K(ret)); - } else if (gis_datum->is_null()) { - is_null_geo = true; - } else { - ObString wkb = gis_datum->get_string(); - ObGeoType type = ObGeoType::GEOTYPEMAX; - uint32_t srid = -1; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, - *gis_datum, - gis_arg->datum_meta_, - gis_arg->obj_meta_.has_lob_header(), - wkb))) { - LOG_WARN("fail to get real string data", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb, type, srid))) { - if (ret == OB_ERR_GIS_INVALID_DATA) { - LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_TOUCHES); - } - LOG_WARN("get type and srid from wkb failed", K(wkb), K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::get_srs_item( - ctx, srs_guard, wkb, srs, true, N_PRIV_ST_TOUCHES))) { - LOG_WARN("fail to get srs item", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, - wkb, - geo, - srs, - N_PRIV_ST_TOUCHES, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { - LOG_WARN("get first geo by wkb failed", K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo, is_geo_empty))) { - LOG_WARN("check geo empty failed", K(ret)); + ObString wkb = gis_datum->get_string(); + ObGeoType type = ObGeoType::GEOTYPEMAX; + uint32_t srid = -1; + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, + *gis_datum, + gis_arg->datum_meta_, + gis_arg->obj_meta_.has_lob_header(), + wkb))) { + LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(temp_allocator.add_baseline_size(wkb.length()))) { + } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb, type, srid))) { + if (ret == OB_ERR_GIS_INVALID_DATA) { + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_TOUCHES); } + LOG_WARN("get type and srid from wkb failed", K(wkb), K(ret)); + } else if (OB_FAIL(ObGeoExprUtils::get_srs_item( + ctx, srs_guard, wkb, srs, true, N_PRIV_ST_TOUCHES))) { + LOG_WARN("fail to get srs item", K(ret), K(wkb)); + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, + wkb, + geo, + srs, + N_PRIV_ST_TOUCHES, + GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { + LOG_WARN("get first geo by wkb failed", K(ret)); + } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo, is_geo_empty))) { + LOG_WARN("check geo empty failed", K(ret)); } return ret; } @@ -128,7 +121,8 @@ int ObExprPrivSTTouches::eval_priv_st_touches(const ObExpr &expr, ObEvalCtx &ctx const ObSrsItem *srs1 = nullptr; const ObSrsItem *srs2 = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_TOUCHES); ObDatum *gis_datum1 = nullptr; ObDatum *gis_datum2 = nullptr; if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { @@ -136,25 +130,34 @@ int ObExprPrivSTTouches::eval_priv_st_touches(const ObExpr &expr, ObEvalCtx &ctx } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); } else if (OB_FAIL(get_input_geometry( - srs_guard, gis_datum1, ctx, gis_arg1, is_geo1_null, srs1, geo1, is_geo1_empty))) { + srs_guard, temp_allocator, ctx, gis_arg1, gis_datum1, srs1, geo1, is_geo1_empty))) { LOG_WARN("fail to get input geometry", K(ret)); - } else if (OB_FAIL(get_input_geometry( - srs_guard, gis_datum2, ctx, gis_arg2, is_geo2_null, srs2, geo2, is_geo2_empty))) { + } else if (!is_geo1_null && OB_FAIL(get_input_geometry( + srs_guard, temp_allocator, ctx, gis_arg2, gis_datum2, srs2, geo2, is_geo2_empty))) { LOG_WARN("fail to get input geometry", K(ret)); + } else if (is_geo1_null || is_geo2_null) { + res.set_null(); } else { uint32_t srid1 = srs1 == nullptr ? 0 : srs1->get_srid(); uint32_t srid2 = srs2 == nullptr ? 0 : srs2->get_srid(); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (srid1 != srid2) { ret = OB_ERR_GIS_DIFFERENT_SRIDS; LOG_WARN("srid not the same", K(ret), K(srid1), K(srid2)); LOG_USER_ERROR(OB_ERR_GIS_DIFFERENT_SRIDS, N_PRIV_ST_TOUCHES, srid1, srid2); } else if (is_geo1_empty || is_geo2_empty) { res.set_bool(false); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs1, *geo1, *geo2))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { bool result = false; - ObGeoEvalCtx gis_context(&temp_allocator, srs1); + ObGeoEvalCtx gis_context(*mem_ctx, srs1); if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, result))) { @@ -164,6 +167,9 @@ int ObExprPrivSTTouches::eval_priv_st_touches(const ObExpr &expr, ObEvalCtx &ctx res.set_bool(result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_priv_st_touches.h b/src/sql/engine/expr/ob_expr_priv_st_touches.h index 55e494525..3180f5574 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_touches.h +++ b/src/sql/engine/expr/ob_expr_priv_st_touches.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "observer/omt/ob_tenant_srs.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -33,8 +34,8 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int get_input_geometry(omt::ObSrsCacheGuard &srs_guard, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, - bool &is_null_geo, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty); + static int get_input_geometry(omt::ObSrsCacheGuard &srs_guard, MultimodeAlloctor &temp_allocator, ObEvalCtx &ctx, ObExpr *gis_arg, + ObDatum *gis_datum, const ObSrsItem *&srs, ObGeometry *&geo, bool &is_geo_empty); DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTTouches); }; } // namespace sql diff --git a/src/sql/engine/expr/ob_expr_priv_st_transform.cpp b/src/sql/engine/expr/ob_expr_priv_st_transform.cpp index 656662f17..5f26281a1 100644 --- a/src/sql/engine/expr/ob_expr_priv_st_transform.cpp +++ b/src/sql/engine/expr/ob_expr_priv_st_transform.cpp @@ -86,7 +86,8 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); const ObSrsItem *src_srs_item = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_TRANSFORM); int64_t param_num = expr.arg_cnt_; ObString src_proj4_param; ObString dest_proj4_param; @@ -95,9 +96,9 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx if (expr.args_[1]->is_boolean_ || (param_num > 2 && expr.args_[2]->is_boolean_)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("invalid type", K(ret)); - } else if (OB_FAIL(expr.args_[0]->eval(ctx, gis_datum))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, gis_datum))) { LOG_WARN("eval geo arg failed", K(ret)); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, datum2))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, datum2))) { LOG_WARN("eval sird arg failed", K(ret)); } else if (gis_datum->is_null() || datum2->is_null()) { res.set_null(); @@ -106,9 +107,10 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx uint32_t dest_srid = 0; ObString wkb = gis_datum->get_string(); const ObSrsItem *dest_srs_item = NULL; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real data.", K(ret), K(wkb)); + } else if (FALSE_IT(temp_allocator.add_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(wkb, src_srid))) { ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_TRANSFORM); @@ -118,7 +120,7 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx } else if (src_srid != 0 && OB_FAIL(srs_guard.get_srs_item(src_srid, src_srs_item))) { LOG_WARN("failed to get srs item", K(ret), K(src_srid)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, src_geo, src_srs_item, N_PRIV_ST_TRANSFORM, - ObGeoBuildFlag::GEO_ALLOW_3D))) { + GEO_ALLOW_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get geo by wkb failed", K(ret), K(wkb)); if (ret != OB_ERR_SRS_NOT_FOUND) { ret = OB_ERR_GIS_INVALID_DATA; @@ -159,9 +161,10 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx LOG_USER_ERROR(OB_ERR_TRANSFORM_SOURCE_SRS_NOT_SUPPORTED, src_srid); } else { dest_proj4_param = datum2->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *datum2, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *datum2, expr.args_[1]->datum_meta_, expr.args_[1]->obj_meta_.has_lob_header(), dest_proj4_param))) { LOG_WARN("fail to get real data.", K(ret), K(dest_proj4_param)); + } else if (FALSE_IT(temp_allocator.add_baseline_size(dest_proj4_param.length()))) { } } } @@ -177,10 +180,11 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx ObDatum *datum3 = NULL; src_proj4_param = datum2->get_string(); src_srs_item = NULL; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *datum2, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *datum2, expr.args_[1]->datum_meta_, expr.args_[1]->obj_meta_.has_lob_header(), src_proj4_param))) { LOG_WARN("fail to get real data.", K(ret), K(src_proj4_param)); - } else if (OB_FAIL(expr.args_[2]->eval(ctx, datum3))) { + } else if (FALSE_IT(temp_allocator.add_baseline_size(src_proj4_param.length()))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[2], ctx, datum3))) { LOG_WARN("failed to eval datum", K(ret)); } else if (ob_is_integer_type(expr.args_[2]->datum_meta_.type_)) { dest_srid = datum3->get_int(); @@ -201,18 +205,27 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx } } else { dest_proj4_param = datum3->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *datum3, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *datum3, expr.args_[2]->datum_meta_, expr.args_[2]->obj_meta_.has_lob_header(), dest_proj4_param))) { LOG_WARN("fail to get real data.", K(ret), K(dest_proj4_param)); + } else if (FALSE_IT(temp_allocator.add_baseline_size(dest_proj4_param.length()))) { } } } // eval by bg - if (OB_SUCC(ret) && need_eval) { + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || !need_eval) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else { int correct_result; - ObGeoEvalCtx correct_context(&temp_allocator, src_srs_item); - ObGeoEvalCtx transform_context(&temp_allocator, dest_srs_item); + ObGeoEvalCtx correct_context(*mem_ctx, src_srs_item); + ObGeoEvalCtx transform_context(*mem_ctx, dest_srs_item); ObString src_proj4; ObString dest_proj4; if (src_proj4_param.empty()) { @@ -254,6 +267,9 @@ int ObExprPrivSTTransform::eval_priv_st_transform(const ObExpr &expr, ObEvalCtx } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } } diff --git a/src/sql/engine/expr/ob_expr_priv_xml_binary.cpp b/src/sql/engine/expr/ob_expr_priv_xml_binary.cpp index 5dbd219d9..2ae92b83c 100644 --- a/src/sql/engine/expr/ob_expr_priv_xml_binary.cpp +++ b/src/sql/engine/expr/ob_expr_priv_xml_binary.cpp @@ -98,7 +98,8 @@ int ObExprPrivXmlBinary::eval_priv_xml_binary(const ObExpr &expr, ObEvalCtx &ctx res.set_null(); } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObString xml_plain_text = xml_datum->get_string(); ObIMulModeBase *xml_root = NULL; ObStringBuffer jbuf(&tmp_allocator); @@ -118,6 +119,7 @@ int ObExprPrivXmlBinary::eval_priv_xml_binary(const ObExpr &expr, ObEvalCtx &ctx true, xml_plain_text))) { LOG_WARN("get xml plain text failed", K(ret), K(xml_datum)); + } else if (OB_FALSE_IT(tmp_allocator.add_baseline_size(xml_plain_text.length()))) { } else if (xml_plain_text.empty()) { res.set_null(); } else if (expr.args_[1]->obj_meta_.is_character_type()) { diff --git a/src/sql/engine/expr/ob_expr_sdo_relate.cpp b/src/sql/engine/expr/ob_expr_sdo_relate.cpp index 230e88a5e..88234abda 100644 --- a/src/sql/engine/expr/ob_expr_sdo_relate.cpp +++ b/src/sql/engine/expr/ob_expr_sdo_relate.cpp @@ -179,8 +179,17 @@ int ObExprSdoRelate::eval_sdo_relate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_allocator, expr.type_, tenant_id, ret, N_SDO_RELATE); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); @@ -243,7 +252,7 @@ int ObExprSdoRelate::eval_sdo_relate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum } else if (ObGeoTypeUtil::is_3d_geo_type(geo1->type()) || ObGeoTypeUtil::is_3d_geo_type(geo2->type())) { ret = OB_NOT_SUPPORTED; LOG_WARN("only support 2D spatial relationship", K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2, is_geo1_cached, is_geo2_cached))) { LOG_WARN("zoom in geos failed", K(ret)); } else { // add cache if need @@ -260,7 +269,7 @@ int ObExprSdoRelate::eval_sdo_relate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum if (OB_FAIL(ret)) { } else if (!result && mask.anyinteract_ == 1) { bool tmp_result = false; - if (OB_FAIL(ObGeoExprUtils::get_intersects_res(*geo1, *geo2, gis_arg1, gis_arg2, const_param_cache, srs, temp_allocator, tmp_result))) { + if (OB_FAIL(ObGeoExprUtils::get_intersects_res(*geo1, *geo2, gis_arg1, gis_arg2, const_param_cache, srs, mem_ctx, tmp_result))) { LOG_WARN("fail to get interact res", K(ret)); } else { result = (result || tmp_result); diff --git a/src/sql/engine/expr/ob_expr_spatial_collection.cpp b/src/sql/engine/expr/ob_expr_spatial_collection.cpp index ed99cd9a9..7f5228d06 100644 --- a/src/sql/engine/expr/ob_expr_spatial_collection.cpp +++ b/src/sql/engine/expr/ob_expr_spatial_collection.cpp @@ -79,6 +79,8 @@ int ObExprSpatialCollection::calc_resultN(common::ObObj &result, if (ObGeoType::GEOMETRY >= geo_type || ObGeoType::GEOTYPEMAX <= geo_type) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid geo type", K(ret), K(geo_type)); + } else if (OB_FAIL(res_wkb_buf.reserve(WKB_OFFSET + WKB_COMMON_WKB_HEADER_LEN))) { + LOG_WARN("fail to reserve memory", K(ret), K(WKB_OFFSET + WKB_COMMON_WKB_HEADER_LEN)); } else if (OB_FAIL(res_wkb_buf.append(srid))) { LOG_WARN("fail to append srid to res wkb buf", K(ret), K(srid)); } else if (OB_FAIL(res_wkb_buf.append(static_cast(ENCODE_GEO_VERSION(GEO_VESION_1))))) { @@ -249,7 +251,8 @@ int ObExprSpatialCollection::eval_spatial_collection(const ObExpr &expr, { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, get_func_name()); ObWkbBuffer res_wkb_buf(tmp_allocator); uint32_t srid = 0; bool is_null_result = false; @@ -258,6 +261,8 @@ int ObExprSpatialCollection::eval_spatial_collection(const ObExpr &expr, if (ObGeoType::GEOMETRY >= geo_type || ObGeoType::GEOTYPEMAX <= geo_type) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid geo type", K(ret), K(geo_type)); + } else if (OB_FAIL(res_wkb_buf.reserve(WKB_OFFSET + WKB_COMMON_WKB_HEADER_LEN))) { + LOG_WARN("fail to reserve memory", K(ret), K(WKB_OFFSET + WKB_COMMON_WKB_HEADER_LEN)); } else if (OB_FAIL(res_wkb_buf.append(srid))) { LOG_WARN("fail to append srid to res wkb buf", K(ret), K(srid)); } else if (OB_FAIL(res_wkb_buf.append(static_cast(ENCODE_GEO_VERSION(GEO_VESION_1))))) { @@ -274,7 +279,7 @@ int ObExprSpatialCollection::eval_spatial_collection(const ObExpr &expr, ObDatum *datum = NULL; ObString wkb; for (uint32_t i = 0; OB_SUCC(ret) && i < expr.arg_cnt_ && !is_null_result; i++) { - if (OB_FAIL(expr.args_[i]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[i], ctx, datum))) { LOG_WARN("fail to eval datum", K(ret)); } else if (datum->is_null() ) { is_null_result = true; @@ -282,6 +287,7 @@ int ObExprSpatialCollection::eval_spatial_collection(const ObExpr &expr, } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, expr.args_[i]->datum_meta_, expr.args_[i]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(i), K(wkb)); + } else if (FALSE_IT(tmp_allocator.add_baseline_size(wkb.length()))) { } else if (ObGeoType::LINESTRING == geo_type) { // linestring if (OB_FAIL(calc_linestring(wkb, res_wkb_buf))) { LOG_WARN("fail to calc linestring", K(ret), K(wkb)); diff --git a/src/sql/engine/expr/ob_expr_sql_udt_construct.cpp b/src/sql/engine/expr/ob_expr_sql_udt_construct.cpp index 95040aa29..d3fd49af6 100644 --- a/src/sql/engine/expr/ob_expr_sql_udt_construct.cpp +++ b/src/sql/engine/expr/ob_expr_sql_udt_construct.cpp @@ -24,6 +24,7 @@ #include "lib/json_type/ob_json_base.h" #include "lib/geo/ob_sdo_geo_object.h" #include "lib/geo/ob_geo_utils.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" #ifdef OB_BUILD_ORACLE_PL #include "pl/sys_package/ob_sdo_geometry.h" #endif @@ -182,7 +183,8 @@ int ObExprUdtConstruct::eval_udt_construct(const ObExpr &expr, ObEvalCtx &ctx, O ObDatum *null_bit = NULL; bool is_null = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_SQL_UDT_CONSTRUCT); ObSqlUdtNullBitMap sub_nested_bitmap; const ObExprUdtConstructInfo *info = static_cast(expr.extra_info_); @@ -190,7 +192,7 @@ int ObExprUdtConstruct::eval_udt_construct(const ObExpr &expr, ObEvalCtx &ctx, O if (expr.arg_cnt_ < 1) { ret = OB_ERR_CALL_WRONG_ARG; LOG_WARN("invalid params cnt", K(ret), K(expr.arg_cnt_)); - } else if (OB_FAIL(expr.args_[0]->eval(ctx, null_bit))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, null_bit))) { LOG_WARN("eval null bitmap failed", K(ret)); } else if (null_bit->is_null()) { is_null = true; @@ -201,6 +203,7 @@ int ObExprUdtConstruct::eval_udt_construct(const ObExpr &expr, ObEvalCtx &ctx, O CS_TYPE_BINARY, true, raw_data))) { LOG_WARN("failed to get udt raw data", K(ret), K(info->udt_id_)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(raw_data.length()))) { } else if (OB_FAIL(eval_sdo_geom_udt_access(temp_allocator, expr, ctx, raw_data, info->udt_id_, res))) { LOG_WARN("failed to eval sdo_geom udt access", K(ret), K(info->udt_id_)); } @@ -297,7 +300,7 @@ int ObExprUdtConstruct::eval_sdo_geom_udt_access(ObIAllocator &allocator, const #else uint16_t subschema_id; ObSqlUDTMeta sql_udt_meta; - ObSdoGeoObject sdo_geo; + ObSdoGeoObject sdo_geo(allocator); ObString res_str; ObExprStrResAlloc expr_res_alloc(expr, ctx); // pl obj should use this allocator diff --git a/src/sql/engine/expr/ob_expr_st_area.cpp b/src/sql/engine/expr/ob_expr_st_area.cpp index ec36d7ff6..02c44df90 100644 --- a/src/sql/engine/expr/ob_expr_st_area.cpp +++ b/src/sql/engine/expr/ob_expr_st_area.cpp @@ -66,10 +66,11 @@ int ObExprSTArea::eval_st_area(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) ObDatum *gis_datum = NULL; ObExpr *gis_arg = expr.args_[0]; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_AREA); ObObjType input_type = gis_arg->datum_meta_.type_; - if (OB_FAIL(gis_arg->eval(ctx, gis_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(gis_arg, ctx, gis_datum))) { LOG_WARN("eval geo arg failed", K(ret)); } else if (gis_datum->is_null()) { res.set_null(); @@ -78,20 +79,28 @@ int ObExprSTArea::eval_st_area(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObString wkb = gis_datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum, + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum, gis_arg->datum_meta_, gis_arg->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, N_ST_AREA))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, geo, srs, N_ST_AREA, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, geo, srs, N_ST_AREA, GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("get geo by wkb failed", K(ret)); } else if (geo->type() != ObGeoType::POLYGON && geo->type() != ObGeoType::MULTIPOLYGON) { ret = OB_ERR_UNEXPECTED_GEOMETRY_TYPE; LOG_WARN("unexpected geometry type for st_area", K(ret)); LOG_USER_ERROR(OB_ERR_UNEXPECTED_GEOMETRY_TYPE, "POLYGON/MULTIPOLYGON", ObGeoTypeUtil::get_geo_name_by_type(geo->type()), N_ST_AREA); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); int correct_result; double result = 0.0; if (OB_FAIL(gis_context.append_geo_arg(geo))) { @@ -107,6 +116,9 @@ int ObExprSTArea::eval_st_area(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) res.set_double(result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_asewkt.cpp b/src/sql/engine/expr/ob_expr_st_asewkt.cpp index 364b8955f..dacafa740 100644 --- a/src/sql/engine/expr/ob_expr_st_asewkt.cpp +++ b/src/sql/engine/expr/ob_expr_st_asewkt.cpp @@ -89,7 +89,8 @@ int ObExprPrivSTAsEwkt::eval_priv_st_asewkt(const ObExpr &expr, ObEvalCtx &ctx, { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_ASEWKT); int num_args = expr.arg_cnt_; bool is_null_result = false; ObString res_wkt; @@ -97,13 +98,13 @@ int ObExprPrivSTAsEwkt::eval_priv_st_asewkt(const ObExpr &expr, ObEvalCtx &ctx, int64_t maxdecimaldigits = DEFAULT_DIGITS_IN_DOUBLE; // get geo - if (OB_FAIL(expr.args_[0]->eval(ctx, gis_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, gis_datum))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum->is_null()) { is_null_result = true; } else if (num_args > 1) { // get maxdecimaldigits ObDatum *precsion_data = NULL; - if (OB_FAIL(expr.args_[1]->eval(ctx, precsion_data))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, precsion_data))) { LOG_WARN("eval maxdecimaldigits args failed", K(ret)); } else if (precsion_data->is_null()){ is_null_result = true; @@ -126,6 +127,10 @@ int ObExprPrivSTAsEwkt::eval_priv_st_asewkt(const ObExpr &expr, ObEvalCtx &ctx, LOG_WARN("eval geo to ewkt failed", K(ret), K(wkb), K(maxdecimaldigits)); } else if (OB_FAIL(ObGeoExprUtils::pack_geo_res(expr, ctx, res, res_wkt))) { LOG_WARN("fail to pack geo res", K(ret)); + } else { + // assume that ObStringBuffer has 4 times memory enlargement + tmp_allocator.set_baseline_size(res_wkt.length() * 4 + wkb.length()); + tmp_allocator.memory_usage_check_if_need(); } } diff --git a/src/sql/engine/expr/ob_expr_st_asgeojson.cpp b/src/sql/engine/expr/ob_expr_st_asgeojson.cpp index 4bbe3754b..0657c4696 100644 --- a/src/sql/engine/expr/ob_expr_st_asgeojson.cpp +++ b/src/sql/engine/expr/ob_expr_st_asgeojson.cpp @@ -18,8 +18,7 @@ #include "observer/omt/ob_tenant_srs.h" #include "lib/utility/ob_fast_convert.h" #include "sql/engine/expr/ob_geo_expr_utils.h" -#include "lib/geo/ob_wkb_to_json_visitor.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" +#include "lib/geo/ob_wkb_to_json_bin_visitor.h" #include "sql/engine/expr/ob_expr_json_func_helper.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -74,7 +73,7 @@ int ObExprSTAsGeoJson::calc_result_typeN(ObExprResType &type, ObExprResType *typ } int ObExprSTAsGeoJson::process_input_params(const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, ObGeometry *&geo, bool &is_null_res, ObGeoSrid& srid, + MultimodeAlloctor &allocator, ObGeometry *&geo, bool &is_null_res, ObGeoSrid& srid, uint32_t &max_dec_digits, uint8_t &flag) { int ret = OB_SUCCESS; @@ -87,27 +86,26 @@ int ObExprSTAsGeoJson::process_input_params(const ObExpr &expr, ObEvalCtx &ctx, const ObSrsItem *srs = nullptr; if (ob_is_null(type1)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum))) { + } else if (OB_FAIL(allocator.eval_arg(arg1, ctx, datum))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum->is_null()) { is_null_res = true; } else { // construct geometry ObString wkb = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data( + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( allocator, *datum, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header())); } else if (OB_FAIL(ObGeoExprUtils::construct_geometry( - allocator, wkb, srs_guard, srs, geo, N_ST_ASGEOJSON))) { + allocator, wkb, srs_guard, srs, geo, N_ST_ASGEOJSON, true, false))) { LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb)); } else { srid = ObGeoWkbByteOrderUtil::read(wkb.ptr(), ObGeoWkbByteOrder::LittleEndian); } } // max_dec_digits - max_dec_digits = INT_MAX32; if (!is_null_res && OB_SUCC(ret) && expr.arg_cnt_ > 1) { - if (OB_FAIL(expr.args_[1]->eval(ctx, datum))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[1], ctx, datum))) { LOG_WARN("failed to eval second argument", K(ret)); } else if (datum->is_null()) { is_null_res = true; @@ -132,7 +130,7 @@ int ObExprSTAsGeoJson::process_input_params(const ObExpr &expr, ObEvalCtx &ctx, // flag flag = 0; if (!is_null_res && OB_SUCC(ret) && expr.arg_cnt_ > 2) { - if (OB_FAIL(expr.args_[2]->eval(ctx, datum))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[2], ctx, datum))) { LOG_WARN("failed to eval second argument", K(ret)); } else if (datum->is_null()) { is_null_res = true; @@ -162,8 +160,9 @@ int ObExprSTAsGeoJson::eval_st_asgeojson(const ObExpr &expr, ObEvalCtx &ctx, ObD int ret = OB_SUCCESS; bool is_null_res = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - uint32_t max_dec_digits = UINT_MAX32; + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_ASGEOJSON); + uint32_t max_dec_digits = INT_MAX32; uint8_t flag = 0; ObGeometry *geo = nullptr; ObString json_res; @@ -173,31 +172,23 @@ int ObExprSTAsGeoJson::eval_st_asgeojson(const ObExpr &expr, ObEvalCtx &ctx, ObD LOG_WARN("fail to process input geometry", K(ret)); } else if (!is_null_res) { // cal asgeojson - ObWkbToJsonVisitor visitor(&temp_allocator, max_dec_digits, flag, srid); - if (OB_FAIL(geo->do_visit(visitor))) { - LOG_WARN("fail to do visit", K(ret)); + ObWkbToJsonBinVisitor visitor(&temp_allocator, max_dec_digits, flag, srid); + if (OB_FAIL(visitor.to_jsonbin(geo, json_res))) { + LOG_WARN("fail to convert geo to jsonbin", K(ret)); } else { - visitor.get_geojson(json_res); + temp_allocator.set_baseline_size(geo->length() + json_res.length()); + temp_allocator.memory_usage_check_if_need(); } } - uint32_t parse_flag = ObJsonParser::JSN_RELAXED_FLAG; - ObJsonNode *j_tree = NULL; // set result if (OB_FAIL(ret)) { // do nothing } else if (is_null_res) { res.set_null(); - } else if (OB_FAIL(ObJsonParser::get_tree(&temp_allocator, json_res, j_tree, parse_flag))) { - LOG_WARN("fail to parse string as json", K(ret)); - } else { - ObIJsonBase *j_base = j_tree; - ObString raw_bin; - if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { - LOG_WARN("fail to get string json binary", K(ret)); - } else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(expr, ctx, res, raw_bin))) { - LOG_WARN("fail to pack json result", K(ret)); - } + } else if (OB_FAIL(ObJsonExprHelper::pack_json_str_res(expr, ctx, res, json_res))) { + LOG_WARN("fail to pack json result", K(ret)); } + return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_asgeojson.h b/src/sql/engine/expr/ob_expr_st_asgeojson.h index c8b395332..09ab90ac3 100644 --- a/src/sql/engine/expr/ob_expr_st_asgeojson.h +++ b/src/sql/engine/expr/ob_expr_st_asgeojson.h @@ -14,6 +14,8 @@ #define OCEANBASE_SQL_OB_EXPR_ST_ASGEOJSON_ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" + using namespace oceanbase::common; namespace oceanbase { @@ -31,7 +33,7 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_params(const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, + static int process_input_params(const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, ObGeometry *&geo, bool &is_null_res, ObGeoSrid& srid, uint32_t &max_dec_digits, uint8_t &flag); DISALLOW_COPY_AND_ASSIGN(ObExprSTAsGeoJson); diff --git a/src/sql/engine/expr/ob_expr_st_astext.cpp b/src/sql/engine/expr/ob_expr_st_astext.cpp index bccd73102..cd993a743 100755 --- a/src/sql/engine/expr/ob_expr_st_astext.cpp +++ b/src/sql/engine/expr/ob_expr_st_astext.cpp @@ -93,7 +93,8 @@ int ObExprSTAsText::eval_st_astext_common(const ObExpr &expr, { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, func_name); int num_args = expr.arg_cnt_; bool is_null_result = false; ObString res_wkt; @@ -107,16 +108,16 @@ int ObExprSTAsText::eval_st_astext_common(const ObExpr &expr, ObString wkb; bool is_3d_geo = false; // get geo - if (OB_FAIL(expr.args_[0]->eval(ctx, gis_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, gis_datum))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum->is_null()) { is_null_result = true; } else if (FALSE_IT(wkb = gis_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *gis_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *gis_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoExprUtils::construct_geometry(tmp_allocator, - wkb, srs_guard, srs, geo, func_name))) { + wkb, srs_guard, srs, geo, func_name, true, false))) { LOG_WARN("fail to create geo", K(ret), K(wkb)); } else if (OB_NOT_NULL(srs)){ is_geog = srs->is_geographical_srs(); @@ -128,7 +129,7 @@ int ObExprSTAsText::eval_st_astext_common(const ObExpr &expr, ObGeoAxisOrder axis_order = ObGeoAxisOrder::INVALID; ObDatum *datum = NULL; ObString dstr; - if (OB_FAIL(expr.args_[1]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, datum))) { LOG_WARN("eval axis_order axis_order failed", K(ret)); } else if (datum->is_null()){ is_null_result = true; @@ -137,7 +138,7 @@ int ObExprSTAsText::eval_st_astext_common(const ObExpr &expr, ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, func_name); } else if (FALSE_IT(dstr = datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[1]->datum_meta_, expr.args_[1]->obj_meta_.has_lob_header(), dstr))) { LOG_WARN("fail to get real string data", K(ret), K(dstr)); } else if (OB_FAIL(ObGeoExprUtils::parse_axis_order(dstr, func_name, axis_order))) { @@ -175,6 +176,10 @@ int ObExprSTAsText::eval_st_astext_common(const ObExpr &expr, if (OB_SUCC(ret)) { if (OB_FAIL(to_wkt(tmp_allocator, geo, res_wkt, func_name))) { LOG_WARN("failed to transform geo to wkt", K(ret)); + } else { + // assume that ObStringBuffer has 4 times memory enlargement + tmp_allocator.set_baseline_size(res_wkt.length() * 4 + wkb.length()); + tmp_allocator.memory_usage_check_if_need(); } } } diff --git a/src/sql/engine/expr/ob_expr_st_aswkb.cpp b/src/sql/engine/expr/ob_expr_st_aswkb.cpp index 30f84cc03..7d0274166 100644 --- a/src/sql/engine/expr/ob_expr_st_aswkb.cpp +++ b/src/sql/engine/expr/ob_expr_st_aswkb.cpp @@ -105,7 +105,8 @@ int ObExprGeomWkb::eval_geom_wkb(const ObExpr &expr, uint32_t arg_num = expr.arg_cnt_; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, get_func_name()); omt::ObSrsCacheGuard srs_guard; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); const ObSrsItem *srs = NULL; @@ -118,16 +119,17 @@ int ObExprGeomWkb::eval_geom_wkb(const ObExpr &expr, ObGeometry *geo = NULL; ObGeoAxisOrder axis_order = ObGeoAxisOrder::INVALID; - if (OB_FAIL(expr.args_[0]->eval(ctx, wkb_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, wkb_datum))) { LOG_WARN("fail to eval wkb datum", K(ret)); } else if (wkb_datum->is_null()) { is_null_result = true; } else if (FALSE_IT(wkb = wkb_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *wkb_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *wkb_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::construct_geometry(tmp_allocator, - wkb, srs_guard, srs, geo, get_func_name()))) { + wkb, srs_guard, srs, geo, get_func_name(), true, false))) { LOG_WARN("fail to create geo bin", K(ret), K(wkb)); } else if (OB_NOT_NULL(srs)) { is_geog = srs->is_geographical_srs(); @@ -138,12 +140,12 @@ int ObExprGeomWkb::eval_geom_wkb(const ObExpr &expr, if (OB_SUCC(ret) && !is_null_result && arg_num == 2) { ObDatum *option_datum = NULL; ObString option_str; - if (OB_FAIL(expr.args_[1]->eval(ctx, option_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, option_datum))) { LOG_WARN("fail to eval option datum", K(ret)); } else if (option_datum->is_null()){ is_null_result = true; } else if (FALSE_IT(option_str = option_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *option_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *option_datum, expr.args_[1]->datum_meta_, expr.args_[1]->obj_meta_.has_lob_header(), option_str))) { LOG_WARN("fail to get real string data", K(ret), K(option_str)); } else if (is_blank_string(expr.args_[1]->datum_meta_.cs_type_, option_str)) { diff --git a/src/sql/engine/expr/ob_expr_st_bestsrid.cpp b/src/sql/engine/expr/ob_expr_st_bestsrid.cpp index 644b5e798..565bc0974 100644 --- a/src/sql/engine/expr/ob_expr_st_bestsrid.cpp +++ b/src/sql/engine/expr/ob_expr_st_bestsrid.cpp @@ -19,7 +19,6 @@ #include "sql/engine/ob_exec_context.h" #include "observer/omt/ob_tenant_srs.h" #include "ob_expr_st_bestsrid.h" -#include "lib/geo/ob_geo_utils.h" #include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; @@ -67,8 +66,8 @@ int ObExprPrivSTBestsrid::calc_result_typeN(ObExprResType& type, return ret; } -int ObExprPrivSTBestsrid::get_geog_box(ObEvalCtx &ctx, ObArenaAllocator &temp_allocator, ObString wkb, - ObObjType input_type, bool &is_geo_empty, ObGeogBox *&geo_box) +int ObExprPrivSTBestsrid::get_geog_box(ObEvalCtx &ctx, lib::MemoryContext &mem_ctx, ObString wkb, + ObObjType input_type, bool &is_geo_empty, ObGeogBox *&geo_box) { int ret = OB_SUCCESS; ObGeometry *geo = NULL; @@ -76,8 +75,8 @@ int ObExprPrivSTBestsrid::get_geog_box(ObEvalCtx &ctx, ObArenaAllocator &temp_al const ObSrsItem *srs = NULL; if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs))) { LOG_WARN("get srs failed", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, geo, srs, N_PRIV_ST_BESTSRID, - ObGeoBuildFlag::GEO_ALLOW_3D))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(mem_ctx->get_arena_allocator(), wkb, geo, srs, N_PRIV_ST_BESTSRID, + GEO_ALLOW_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get geo failed", K(ret)); if (ret != OB_ERR_SRS_NOT_FOUND && ret != OB_ERR_INVALID_GEOMETRY_TYPE) { ret = OB_ERR_GIS_INVALID_DATA; @@ -95,7 +94,7 @@ int ObExprPrivSTBestsrid::get_geog_box(ObEvalCtx &ctx, ObArenaAllocator &temp_al LOG_USER_ERROR(OB_ERR_NOT_IMPLEMENTED_FOR_PROJECTED_SRS, N_PRIV_ST_BESTSRID, ObGeoTypeUtil::get_geo_name_by_type(geo->type())); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(mem_ctx, srs); ObGeogBox *result = NULL; if (OB_FAIL(gis_context.append_geo_arg(geo))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -115,26 +114,40 @@ int ObExprPrivSTBestsrid::eval_st_bestsrid(const ObExpr &expr, ObEvalCtx &ctx, O ObGeogBox *geo_box2 = NULL; uint32_t param_num = expr.arg_cnt_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_BESTSRID); omt::ObSrsCacheGuard srs_guard; bool is_null_res = false; bool is_geo_empty = false; + ObDatum *geo_datum[2] = { nullptr }; for (uint8_t i = 0; i < param_num && OB_SUCC(ret); i++) { - ObDatum *geo_datum = NULL; + ObExpr *geo_arg = expr.args_[i]; + if (OB_FAIL(temp_allocator.eval_arg(geo_arg, ctx, geo_datum[i]))) { + LOG_WARN("eval geo args failed", K(ret)); + } + } + + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + for (uint8_t i = 0; i < param_num && OB_SUCC(ret) && !is_null_res; i++) { ObString geo_str; ObExpr *geo_arg = expr.args_[i]; ObObjType input_type = geo_arg->datum_meta_.type_; - if (OB_FAIL(geo_arg->eval(ctx, geo_datum))) { - LOG_WARN("eval geo args failed", K(ret)); - } else if (geo_datum->is_null()) { + if (geo_datum[i]->is_null()) { res.set_null(); is_null_res = true; - } else if (FALSE_IT(geo_str = geo_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *geo_datum, + } else if (FALSE_IT(geo_str = geo_datum[i]->get_string())) { + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *(geo_datum[i]), geo_arg->datum_meta_, geo_arg->obj_meta_.has_lob_header(), geo_str))) { LOG_WARN("fail to get real string data", K(ret), K(geo_str)); - } else if (OB_FAIL(ObExprPrivSTBestsrid::get_geog_box(ctx, temp_allocator, + } else if (FALSE_IT(temp_allocator.add_baseline_size(geo_str.length()))) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else if (OB_FAIL(ObExprPrivSTBestsrid::get_geog_box(ctx, *mem_ctx, geo_str, input_type, is_geo_empty, @@ -151,6 +164,9 @@ int ObExprPrivSTBestsrid::eval_st_bestsrid(const ObExpr &expr, ObEvalCtx &ctx, O res.set_int(bestsrid); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_bestsrid.h b/src/sql/engine/expr/ob_expr_st_bestsrid.h index 3e154d427..e99c209ba 100644 --- a/src/sql/engine/expr/ob_expr_st_bestsrid.h +++ b/src/sql/engine/expr/ob_expr_st_bestsrid.h @@ -15,6 +15,7 @@ #define OCEANBASE_SQL_OB_EXPR_ST_BESTSRID_H_ #include "sql/engine/expr/ob_expr_operator.h" +#include "lib/geo/ob_geo_utils.h" namespace oceanbase { @@ -31,7 +32,7 @@ public: common::ObExprTypeCtx& type_ctx) const override; static int eval_st_bestsrid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); static int get_geog_box(ObEvalCtx &ctx, - common::ObArenaAllocator &temp_allocator, + lib::MemoryContext &mem_ctx, ObString wkb, ObObjType input_type, bool &is_geo_empty, diff --git a/src/sql/engine/expr/ob_expr_st_buffer.cpp b/src/sql/engine/expr/ob_expr_st_buffer.cpp index 11983a65c..9b07573ea 100644 --- a/src/sql/engine/expr/ob_expr_st_buffer.cpp +++ b/src/sql/engine/expr/ob_expr_st_buffer.cpp @@ -18,7 +18,6 @@ #include "lib/geo/ob_geo_func_common.h" #include "lib/geo/ob_geo_func_register.h" #include "lib/geo/ob_geo_normalize_visitor.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -91,7 +90,8 @@ int ObExprSTBufferStrategy::eval_st_buffer_strategy(const ObExpr &expr, ObEvalCt { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_BUFFER_STRATEGY); ObDatum *strategy_datum = NULL; ObString strategy_str; ObDatum *val_datum = NULL; @@ -102,12 +102,13 @@ int ObExprSTBufferStrategy::eval_st_buffer_strategy(const ObExpr &expr, ObEvalCt if (is_null_result) { // do nothing - } else if (OB_FAIL(expr.args_[0]->eval(ctx, strategy_datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, strategy_datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (FALSE_IT(strategy_str = strategy_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *strategy_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *strategy_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), strategy_str))) { LOG_WARN("fail to get real string data", K(ret), K(strategy_str)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(strategy_str.length()))) { } else { strategy = get_strategy_type_by_name(strategy_str); if (ObGeoBufferStrategyType::INVALID == strategy) { @@ -119,7 +120,7 @@ int ObExprSTBufferStrategy::eval_st_buffer_strategy(const ObExpr &expr, ObEvalCt LOG_WARN("invalid argument number", K(ret), K(num_args)); } else if (ob_is_null(expr.args_[1]->datum_meta_.type_)) { is_null_result = true; - } else if (OB_FAIL(expr.args_[1]->eval(ctx, val_datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, val_datum))) { LOG_WARN("failed to eval second parameter of st_buffer_strategy", K(ret)); } else { points_per_circle = val_datum->get_double(); @@ -308,7 +309,7 @@ int ObExprSTBuffer::init_buffer_strategy(const common::ObObj *params, int ObExprSTBuffer::init_buffer_strategy(const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, + MultimodeAlloctor &allocator, ObGeoBufferStrategy &buf_strat, double distance) { @@ -327,7 +328,7 @@ int ObExprSTBuffer::init_buffer_strategy(const ObExpr &expr, || (ob_is_string_type(strategy_data_type) && (strategy_cs_type != CS_TYPE_BINARY))); if (is_priv_strategy) { - if (OB_FAIL(first_strategy_arg->eval(ctx, strat_datum))) { + if (OB_FAIL(allocator.eval_arg(first_strategy_arg, ctx, strat_datum))) { LOG_WARN("eval pg style buffer strategy arg failed", K(ret)); } else if (ob_is_integer_type(strategy_data_type)) { if (strat_datum->get_int() <= 0) { @@ -352,7 +353,7 @@ int ObExprSTBuffer::init_buffer_strategy(const ObExpr &expr, } else { ObString pg_text_strategy = strat_datum->get_string(); ObString pg_strategy_clone; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, *strat_datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *strat_datum, first_strategy_arg->datum_meta_, first_strategy_arg->obj_meta_.has_lob_header(), pg_text_strategy))) { LOG_WARN("fail to get real string data", K(ret), K(pg_text_strategy)); } else { @@ -375,10 +376,10 @@ int ObExprSTBuffer::init_buffer_strategy(const ObExpr &expr, } else { for (int i = ST_BUFFER_STRATEG_ARG_START_IDX; i < num_args && OB_SUCC(ret); i++) { ObString strat_str; - if (OB_FAIL(expr.args_[i]->eval(ctx, strat_datum))) { + if (OB_FAIL(allocator.eval_arg(expr.args_[i], ctx, strat_datum))) { LOG_WARN("eval buffer strategy arg failed", K(ret)); } else if (FALSE_IT(strat_str = strat_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, *strat_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *strat_datum, expr.args_[i]->datum_meta_, expr.args_[i]->obj_meta_.has_lob_header(), strat_str))) { LOG_WARN("fail to get real string data", K(ret), K(strat_str)); } else if (OB_FAIL(parse_binary_strategy(strat_str, buf_strat))) { @@ -391,7 +392,7 @@ int ObExprSTBuffer::init_buffer_strategy(const ObExpr &expr, return ret; } -int ObExprSTBuffer::fill_proj4_params(ObIAllocator &allocator, +int ObExprSTBuffer::fill_proj4_params(lib::MemoryContext &mem_ctx, omt::ObSrsCacheGuard &srs_guard, uint32 srid, ObGeometry *geo, @@ -400,10 +401,11 @@ int ObExprSTBuffer::fill_proj4_params(ObIAllocator &allocator, bool &is_transform_method) { INIT_SUCC(ret); + ObArenaAllocator &allocator = mem_ctx->get_arena_allocator(); // Notice: consist with mysql, use boost::geometry directly for geography point // use transfrom method for other geography types. if ((srs != NULL) && srs->is_geographical_srs()) { - ObGeoEvalCtx box_context(&allocator, srs); + ObGeoEvalCtx box_context(mem_ctx, srs); ObGeogBox *geogbox = NULL; int32_t bestsrid; @@ -445,7 +447,8 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & double distance = 0.0; ObGeoBufferStrategy buf_strat; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_BUFFER); bool is_null_result = false; bool is_empty = false; uint32_t srid = 0; @@ -457,9 +460,9 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & for (int i = 0; i < num_args && !is_null_result; i++) { is_null_result = (expr.args_[i]->datum_meta_.type_ == ObNullType); } - if (OB_FAIL(expr.args_[0]->eval(ctx, geo_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, geo_datum))) { LOG_WARN("eval geo arg failed", K(ret)); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, dist_datum))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, dist_datum))) { LOG_WARN("eval distance arg failed", K(ret)); } else if (geo_datum->is_null() || dist_datum->is_null() || is_null_result) { is_null_result = true; @@ -470,13 +473,16 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ObString geo_str = geo_datum->get_string(); if (!is_null_result && OB_SUCC(ret)) { + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (!is_valid_distance(distance)) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, N_ST_BUFFER); LOG_WARN("nan distance argument", K(ret), K(distance)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *geo_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *geo_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), geo_str))) { LOG_WARN("fail to get real string data", K(ret), K(geo_str)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(geo_str.length()))) { } else if (std::abs(distance) < ST_BUFFER_DISTANCE_MIN && geo_str.length() < WKB_DATA_OFFSET + WKB_GEO_TYPE_SIZE) { // Consist with mysql, return original invalid wkb if distance is too small. @@ -492,7 +498,7 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & // However pg will return fixed geometry. ObString res_wkb; if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, geo_str, - geo, srs, N_ST_BUFFER, ObGeoBuildFlag::GEO_ALLOW_3D))) { + geo, srs, N_ST_BUFFER, GEO_ALLOW_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("parse wkb failed", K(ret), K(geo_str)); } else if (OB_FAIL(ObGeoExprUtils::geo_to_wkb(*geo, expr, ctx, srs, res_wkb))) { LOG_WARN("failed to write geometry to wkb", K(ret)); @@ -500,7 +506,7 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & res.set_string(res_wkb); } } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, geo_str, - geo, srs, N_ST_BUFFER, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + geo, srs, N_ST_BUFFER, GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("parse wkb failed", K(ret), K(geo_str)); } else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(geo_str, srid))) { LOG_WARN("get type and srid from wkb failed", K(ret)); @@ -523,6 +529,11 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & } else { res.set_string(res_wkb); } + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { if (distance < 0 && geo->type() != ObGeoType::GEOMETRYCOLLECTION @@ -534,7 +545,7 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & } else if (OB_FAIL(init_buffer_strategy(expr, ctx, temp_allocator, buf_strat, distance))) { LOG_WARN("failed to build st_buffer strategy", K(ret)); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); ObGeometry *res_geo = NULL; bool need_normalize = OB_NOT_NULL(srs) && srs->is_geographical_srs(); if (OB_FAIL(gis_context.append_geo_arg(geo))) { @@ -560,6 +571,9 @@ int ObExprSTBuffer::eval_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; @@ -807,7 +821,8 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, double distance = 0.0; ObGeoBufferStrategy buf_strat; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_BUFFER); bool is_null_result = false; bool is_transform_method = false; bool is_empty = false; @@ -819,20 +834,26 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, for (int i = 0; i < num_args && !is_null_result; i++) { is_null_result = (expr.args_[i]->datum_meta_.type_ == ObNullType); } - if (OB_FAIL(expr.args_[0]->eval(ctx, geo_datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, geo_datum))) { LOG_WARN("eval geo arg failed", K(ret)); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, dist_datum))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, dist_datum))) { LOG_WARN("eval distance arg failed", K(ret)); + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret)) { } else if (geo_datum->is_null() || geo_datum->is_null() || is_null_result) { res.set_null(); } else if (FALSE_IT(geo_str = geo_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *geo_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *geo_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), geo_str))) { LOG_WARN("fail to get real string data", K(ret), K(geo_str)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(geo_str.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, geo_str, srs, true))) { LOG_WARN("fail to get srs item", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, geo_str, geo, srs, N_PRIV_ST_BUFFER, - ObGeoBuildFlag::GEO_CHECK_RING | ObGeoBuildFlag::GEO_CORRECT | ObGeoBuildFlag::GEO_ALLOW_3D | ObGeoBuildFlag::GEO_CHECK_RANGE))) { + GEO_CHECK_RING | GEO_CORRECT | GEO_ALLOW_3D | GEO_CHECK_RANGE + | GEO_NOT_COPY_WKB))) { LOG_WARN("parse wkb failed", K(ret), K(geo_str)); } else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(geo_str, srid))) { LOG_WARN("get type and srid from wkb failed", K(ret)); @@ -855,6 +876,11 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, } else { res.set_string(res_wkb); } + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { distance = dist_datum->get_double(); if (!is_valid_distance(distance)) { @@ -879,7 +905,7 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, } } else if (OB_FAIL(init_buffer_strategy(expr, ctx, temp_allocator, buf_strat, distance))) { LOG_WARN("failed to build st_buffer strategy", K(ret)); - } else if (OB_FAIL(fill_proj4_params(temp_allocator, + } else if (OB_FAIL(fill_proj4_params(*mem_ctx, srs_guard, srid, geo, @@ -888,7 +914,7 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, is_transform_method))){ LOG_WARN("failed to fill proj4 params for st_buffer strategy", K(ret)); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); ObGeometry *res_geo = NULL; ObGeometry *wgs84_geo = NULL; if(OB_NOT_NULL(srs) && srs->is_geographical_srs()) { @@ -914,12 +940,13 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, } else if (OB_NOT_NULL(srs) && srs->is_geographical_srs() && geo->type() == ObGeoType::POINT) { ObString buffered_res_wkb; ObGeometry *res_bin = NULL; - ObGeoEvalCtx transform_context(&temp_allocator, buf_strat.srs_wgs84_); + ObGeoEvalCtx transform_context(*mem_ctx, buf_strat.srs_wgs84_); if (srs->get_srid() == buf_strat.srs_wgs84_->get_srid()) { // do nothing } else if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *res_geo, srs, buffered_res_wkb))) { LOG_WARN("fail to to_wkb for res_geo buffer", K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, buffered_res_wkb, res_bin, srs, N_PRIV_ST_BUFFER))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, buffered_res_wkb, res_bin, srs, N_PRIV_ST_BUFFER, + ObGeoBuildFlag::GEO_DEFAULT | ObGeoBuildFlag::GEO_NOT_COPY_WKB))) { LOG_WARN("fail to create geo bin for point buffer", K(ret)); } else if (OB_FAIL(transform_context.append_geo_arg(res_bin))) { LOG_WARN("failed to append geo arg to gis context", K(ret), K(transform_context.get_geo_count())); @@ -951,6 +978,9 @@ int ObExprPrivSTBuffer::eval_priv_st_buffer(const ObExpr &expr, ObEvalCtx &ctx, } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_buffer.h b/src/sql/engine/expr/ob_expr_st_buffer.h index 0679c353d..80a57f98c 100644 --- a/src/sql/engine/expr/ob_expr_st_buffer.h +++ b/src/sql/engine/expr/ob_expr_st_buffer.h @@ -82,7 +82,7 @@ protected: static int parse_text_strategy(common::ObString &str, common::ObGeoBufferStrategy &strategy); static int init_buffer_strategy(const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, + MultimodeAlloctor &allocator, common::ObGeoBufferStrategy &buf_strat, double distance); static int init_buffer_strategy(const common::ObObj *params, @@ -90,7 +90,7 @@ protected: common::ObExprCtx &expr_ctx, common::ObGeoBufferStrategy &buf_strat, double distance); - static int fill_proj4_params(common::ObIAllocator &allocator, + static int fill_proj4_params(lib::MemoryContext &mem_ctx, omt::ObSrsCacheGuard &srs_guard, uint32 srid, common::ObGeometry *geo, diff --git a/src/sql/engine/expr/ob_expr_st_centroid.cpp b/src/sql/engine/expr/ob_expr_st_centroid.cpp index 207916631..d0d58f7ae 100644 --- a/src/sql/engine/expr/ob_expr_st_centroid.cpp +++ b/src/sql/engine/expr/ob_expr_st_centroid.cpp @@ -57,7 +57,8 @@ int ObExprSTCentroid::eval_st_centroid(const ObExpr &expr, ObEvalCtx &ctx, ObDat { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_CENTROID); ObDatum *datum = NULL; bool is_null_result = false; omt::ObSrsCacheGuard srs_guard; @@ -65,18 +66,23 @@ int ObExprSTCentroid::eval_st_centroid(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObGeometry *geo = NULL; ObGeometry *res_geo = nullptr; - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval first argument", K(ret)); + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret)) { } else if (datum->is_null()) { is_null_result = true; } else { ObString wkb = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL( ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, N_ST_CENTROID))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); @@ -85,11 +91,17 @@ int ObExprSTCentroid::eval_st_centroid(const ObExpr &expr, ObEvalCtx &ctx, ObDat geo, srs, N_ST_CENTROID, - ObGeoBuildFlag::GEO_NORMALIZE | ObGeoBuildFlag::GEO_CHECK_RANGE))) { + GEO_NORMALIZE | GEO_CHECK_RANGE | GEO_NOT_COPY_WKB))) { LOG_WARN("failed to parse wkb", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo, is_null_result))) { LOG_WARN("fail to check is geometry empty", K(ret)); - } else if (!is_null_result) { + } else if (is_null_result) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else { bool is_valid = true; if (geo->crs() == ObGeoCRS::Cartesian && OB_FAIL((ObGeoTypeUtil::is_polygon_valid_simple(geo, is_valid)))) { @@ -102,7 +114,7 @@ int ObExprSTCentroid::eval_st_centroid(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_CENTROID); LOG_WARN("input geometry is invalid", K(ret)); } - ObGeoEvalCtx gis_context(&tmp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(ObGeoTypeUtil::correct_polygon(tmp_allocator, srs, true, *geo))) { @@ -133,6 +145,9 @@ int ObExprSTCentroid::eval_st_centroid(const ObExpr &expr, ObEvalCtx &ctx, ObDat } } } + if (mem_ctx != nullptr) { + tmp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_contains.cpp b/src/sql/engine/expr/ob_expr_st_contains.cpp index 448f13831..073c6f4f1 100644 --- a/src/sql/engine/expr/ob_expr_st_contains.cpp +++ b/src/sql/engine/expr/ob_expr_st_contains.cpp @@ -71,8 +71,9 @@ int ObExprSTContains::eval_st_contains(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObExpr *gis_arg2 = expr.args_[1]; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_CONTAINS); + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); @@ -90,6 +91,8 @@ int ObExprSTContains::eval_st_contains(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObString wkb2 = gis_datum2->get_string(); omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; bool is_geo1_cached = false; bool is_geo2_cached = false; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); @@ -120,13 +123,19 @@ int ObExprSTContains::eval_st_contains(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_WARN("get first geo by wkb failed", K(ret)); } else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_CONTAINS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) { LOG_WARN("get second geo by wkb failed", K(ret)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(geo1->length() + geo2->length()))) { } else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))) || (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { res.set_null(); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2, is_geo1_cached, is_geo2_cached))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { if (OB_NOT_NULL(const_param_cache)) { if (gis_arg1->is_static_const_ && !is_geo1_cached && @@ -138,55 +147,56 @@ int ObExprSTContains::eval_st_contains(const ObExpr &expr, ObEvalCtx &ctx, ObDat } } + ObGeoEvalCtx gis_context(*mem_ctx); + bool result = false; if (OB_FAIL(ret)) { + } else if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) { + LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else { - ObGeoEvalCtx gis_context(&temp_allocator); - bool result = false; - if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) { - LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); - } else { - ObCachedGeom *cache_geo = NULL; - ObGeometry *geo; - if (OB_NOT_NULL(const_param_cache)) { - if (gis_arg1->is_static_const_) { - cache_geo = const_param_cache->get_cached_geo(0); - if (cache_geo == NULL - && OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(), - temp_allocator, - const_param_cache->get_const_param_cache(0), - srs, - cache_geo))) { - LOG_WARN("add geo2 to const cache failed", K(ret)); - } else { - geo = geo2; - const_param_cache->add_cached_geo(0, cache_geo); - } + ObCachedGeom *cache_geo = NULL; + ObGeometry *geo; + if (OB_NOT_NULL(const_param_cache)) { + if (gis_arg1->is_static_const_) { + cache_geo = const_param_cache->get_cached_geo(0); + if (cache_geo == NULL + && OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(), + temp_allocator, + const_param_cache->get_const_param_cache(0), + srs, + cache_geo))) { + LOG_WARN("add geo2 to const cache failed", K(ret)); + } else { + geo = geo2; + const_param_cache->add_cached_geo(0, cache_geo); } } + } - if (OB_FAIL(ret)) { - } else if (OB_NOT_NULL(cache_geo)) { - if (OB_FAIL(cache_geo->contains(*geo, gis_context, result))) { - LOG_WARN("get contains result failed", K(ret)); - } else { - res.set_bool(result); - } - } else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_CONTAINS)) { - bool result = false; - if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_CONTAINS, result))) { - LOG_WARN("fail to get res.", K(ret)); - } else { - res.set_bool(result); - } - } else if (OB_FAIL(ObGeoFunc::gis_func::eval(gis_context, result))) { - LOG_WARN("eval Within functor failed", K(ret)); - ObGeoExprUtils::geo_func_error_handle(ret, N_ST_CONTAINS); + if (OB_FAIL(ret)) { + } else if (OB_NOT_NULL(cache_geo)) { + if (OB_FAIL(cache_geo->contains(*geo, gis_context, result))) { + LOG_WARN("get contains result failed", K(ret)); } else { res.set_bool(result); } + } else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_CONTAINS)) { + bool result = false; + if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_CONTAINS, result))) { + LOG_WARN("fail to get res.", K(ret)); + } else { + res.set_bool(result); + } + } else if (OB_FAIL(ObGeoFunc::gis_func::eval(gis_context, result))) { + LOG_WARN("eval Within functor failed", K(ret)); + ObGeoExprUtils::geo_func_error_handle(ret, N_ST_CONTAINS); + } else { + res.set_bool(result); } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_covers.cpp b/src/sql/engine/expr/ob_expr_st_covers.cpp index 8096e390e..2bac1de5f 100644 --- a/src/sql/engine/expr/ob_expr_st_covers.cpp +++ b/src/sql/engine/expr/ob_expr_st_covers.cpp @@ -21,6 +21,7 @@ #include "ob_expr_st_covers.h" #include "lib/geo/ob_geo_cache.h" #include "sql/engine/expr/ob_geo_expr_utils.h" +#include "lib/geo/ob_geo_utils.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -65,7 +66,7 @@ int ObExprPrivSTCovers::calc_result_type2(ObExprResType &type, template int ObExprPrivSTCovers::eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx, - ObArenaAllocator &temp_allocator, + MultimodeAlloctor &temp_allocator, ObString wkb1, ObString wkb2, ResType &res) @@ -87,6 +88,9 @@ int ObExprPrivSTCovers::eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx ObExpr *gis_arg2 = expr.args_[1]; ObGeoConstParamCache* const_param_cache = ObGeoExprUtils::get_geo_constParam_cache(expr.expr_ctx_id_, &ctx.exec_ctx_); ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (OB_NOT_NULL(const_param_cache) && gis_arg1->is_static_const_) { geo1 = const_param_cache->get_const_param_cache(0); if (geo1 != NULL) { @@ -123,13 +127,19 @@ int ObExprPrivSTCovers::eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx } else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_PRIV_ST_COVERS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_CHECK_RING))) { LOG_WARN("get second geo by wkb failed", K(ret)); + } else if (OB_FALSE_IT(temp_allocator.set_baseline_size(geo1->length() + geo2->length()))) { } else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))) || (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { res.set_null(); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2, is_geo1_cached, is_geo2_cached))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { if (OB_NOT_NULL(const_param_cache)) { if (gis_arg1->is_static_const_ && !is_geo1_cached && @@ -141,9 +151,16 @@ int ObExprPrivSTCovers::eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx } } + ObGeoEvalCtx gis_context(*mem_ctx, srs); + bool result = false; if (OB_FAIL(ret)) { + } else if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) { + LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, result))) { + LOG_WARN("eval st coveredBy failed", K(ret)); + ObGeoExprUtils::geo_func_error_handle(ret, N_PRIV_ST_COVERS); } else { - ObGeoEvalCtx gis_context(&temp_allocator); + ObGeoEvalCtx gis_context(*mem_ctx); bool result = false; if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -190,6 +207,9 @@ int ObExprPrivSTCovers::eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } @@ -205,17 +225,18 @@ int ObExprPrivSTCovers::eval_st_covers(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_COVERS); + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); } else if (FALSE_IT(wkb1 = gis_datum1->get_string())) { } else if (FALSE_IT(wkb2 = gis_datum2->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum1, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); } else if (OB_FAIL(ObExprPrivSTCovers::eval_st_covers_common(expr, ctx, diff --git a/src/sql/engine/expr/ob_expr_st_covers.h b/src/sql/engine/expr/ob_expr_st_covers.h index b299773a1..0d0320fca 100644 --- a/src/sql/engine/expr/ob_expr_st_covers.h +++ b/src/sql/engine/expr/ob_expr_st_covers.h @@ -15,6 +15,7 @@ #define OCEANBASE_SQL_OB_EXPR_ST_COVERS_H_ #include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -31,8 +32,9 @@ public: common::ObExprTypeCtx &type_ctx) const override; static int eval_st_covers(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); template - static int eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx, - ObArenaAllocator &temp_allocator, + static int eval_st_covers_common(const ObExpr &expr, + ObEvalCtx &ctx, + MultimodeAlloctor &temp_allocator, ObString wkb1, ObString wkb2, ResType &res); diff --git a/src/sql/engine/expr/ob_expr_st_crosses.cpp b/src/sql/engine/expr/ob_expr_st_crosses.cpp index a377f0d83..f74d8ad7e 100644 --- a/src/sql/engine/expr/ob_expr_st_crosses.cpp +++ b/src/sql/engine/expr/ob_expr_st_crosses.cpp @@ -17,7 +17,6 @@ #include "lib/geo/ob_geo_ibin.h" #include "sql/engine/ob_exec_context.h" #include "ob_expr_st_crosses.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -57,7 +56,7 @@ int ObExprSTCrosses::calc_result_type2(ObExprResType &type, ObExprResType &type1 } int ObExprSTCrosses::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, + MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs) { int ret = OB_SUCCESS; @@ -68,7 +67,7 @@ int ObExprSTCrosses::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, con ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; is_null_res = false; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { is_null_res = true; @@ -86,18 +85,19 @@ int ObExprSTCrosses::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, con ObString wkb2 = gis_datum2->get_string(); bool is_geo1_valid = false; bool is_geo2_valid = false; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) { if (ret == OB_ERR_GIS_INVALID_DATA) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_CROSSES); @@ -116,10 +116,10 @@ int ObExprSTCrosses::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, con ctx, srs_guard, wkb1, srs, true, N_ST_CROSSES))) { LOG_WARN("fail to get srs item", K(ret), K(wkb1)); } else if (OB_FAIL( - ObGeoExprUtils::build_geometry(allocator, wkb1, geo1, srs, N_ST_CROSSES, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + ObGeoExprUtils::build_geometry(allocator, wkb1, geo1, srs, N_ST_CROSSES, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); } else if (OB_FAIL( - ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_CROSSES, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_CROSSES, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } } @@ -138,21 +138,30 @@ int ObExprSTCrosses::eval_st_crosses(const ObExpr &expr, ObEvalCtx &ctx, ObDatum omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_CROSSES); if (OB_FAIL(process_input_geometry(srs_guard, expr, ctx, temp_allocator, geo1, geo2, is_null_res, srs))) { LOG_WARN("fail to process input geometry", K(ret)); - } else if (is_null_res) { + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || is_null_res) { // do nothing } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)) || OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { is_null_res = true; - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { ObGeoFuncResWithNull crosses_result; - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval( @@ -173,6 +182,9 @@ int ObExprSTCrosses::eval_st_crosses(const ObExpr &expr, ObEvalCtx &ctx, ObDatum res.set_bool(result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_crosses.h b/src/sql/engine/expr/ob_expr_st_crosses.h index c7db2d881..4fd7ae1f4 100644 --- a/src/sql/engine/expr/ob_expr_st_crosses.h +++ b/src/sql/engine/expr/ob_expr_st_crosses.h @@ -17,6 +17,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" #include "observer/omt/ob_tenant_srs.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -34,7 +35,7 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, ObGeometry *&geo1, + static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs); DISALLOW_COPY_AND_ASSIGN(ObExprSTCrosses); }; diff --git a/src/sql/engine/expr/ob_expr_st_difference.cpp b/src/sql/engine/expr/ob_expr_st_difference.cpp index 197f98e5a..867bdef18 100644 --- a/src/sql/engine/expr/ob_expr_st_difference.cpp +++ b/src/sql/engine/expr/ob_expr_st_difference.cpp @@ -18,7 +18,6 @@ #include "sql/engine/ob_exec_context.h" #include "observer/omt/ob_tenant_srs.h" #include "ob_expr_st_difference.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" #include "lib/geo/ob_geo_to_tree_visitor.h" #include "lib/geo/ob_geo_elevation_visitor.h" #include "lib/geo/ob_geo_func_utils.h" @@ -60,7 +59,7 @@ int ObExprSTDifference::calc_result_type2(ObExprResType &type, ObExprResType &ty } int ObExprSTDifference::process_input_geometry(const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, + MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs) { int ret = OB_SUCCESS; @@ -71,7 +70,7 @@ int ObExprSTDifference::process_input_geometry(const ObExpr &expr, ObEvalCtx &ct ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; is_null_res = false; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { is_null_res = true; @@ -85,18 +84,19 @@ int ObExprSTDifference::process_input_geometry(const ObExpr &expr, ObEvalCtx &ct omt::ObSrsCacheGuard srs_guard; bool is_geo1_valid = false; bool is_geo2_valid = false; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) { if (ret == OB_ERR_GIS_INVALID_DATA) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_DIFFERENCE); @@ -119,14 +119,14 @@ int ObExprSTDifference::process_input_geometry(const ObExpr &expr, ObEvalCtx &ct geo1, srs, N_ST_DIFFERENCE, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D))) { + GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_DIFFERENCE, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D))) { + GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } } @@ -143,13 +143,17 @@ int ObExprSTDifference::eval_st_difference(const ObExpr &expr, ObEvalCtx &ctx, O bool is_null_res = false; const ObSrsItem *srs = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_DIFFERENCE); ObGeometry *diff_res = nullptr; bool is_empty_res = false; if (OB_FAIL( process_input_geometry(expr, ctx, temp_allocator, geo1_3d, geo2_3d, is_null_res, srs))) { LOG_WARN("fail to process input geometry", K(ret)); - } else if (!is_null_res) { + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (!is_null_res && OB_SUCC(ret)) { ObGeometry *geo1 = nullptr; ObGeometry *geo2 = nullptr; bool is_3d_geo1 = ObGeoTypeUtil::is_3d_geo_type(geo1_3d->type()); @@ -175,6 +179,11 @@ int ObExprSTDifference::eval_st_difference(const ObExpr &expr, ObEvalCtx &ctx, O geo2 = geo2_3d; } if (OB_FAIL(ret)) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)) || OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) { LOG_WARN("check geo empty failed", K(ret)); @@ -188,7 +197,7 @@ int ObExprSTDifference::eval_st_difference(const ObExpr &expr, ObEvalCtx &ctx, O diff_res = to_tree.get_geometry(); } } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL( @@ -207,19 +216,13 @@ int ObExprSTDifference::eval_st_difference(const ObExpr &expr, ObEvalCtx &ctx, O LOG_WARN("fail to create 3D empty collection", K(ret)); } } else { - if (geo1->crs() == ObGeoCRS::Cartesian - && OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo(diff_res, temp_allocator, srs))) { - // should not do simplify in symdifference functor, it may affect - // ObGeoFuncUtils::ob_geo_gc_union - LOG_WARN("fail to simplify result", K(ret)); - } else if (geo1->crs() == ObGeoCRS::Geographic - && OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo(diff_res, temp_allocator, srs))) { + if (OB_FAIL(ObGeoTypeUtil::remove_duplicate_geo(diff_res, *mem_ctx, srs))) { // should not do simplify in symdifference functor, it may affect // ObGeoFuncUtils::ob_geo_gc_union LOG_WARN("fail to simplify result", K(ret)); } else if (is_3d_geo1 && is_3d_geo2) { // populate Z coordinates - ObGeoElevationVisitor visitor(temp_allocator, srs); + ObGeoElevationVisitor visitor(*mem_ctx, srs); ObGeometry *diff_res_bin = nullptr; if (OB_FAIL(visitor.init(*geo1_3d, *geo2_3d))) { LOG_WARN("fail to init elevation visitor", K(ret)); @@ -245,6 +248,9 @@ int ObExprSTDifference::eval_st_difference(const ObExpr &expr, ObEvalCtx &ctx, O res.set_string(res_wkb); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_difference.h b/src/sql/engine/expr/ob_expr_st_difference.h index ccd8d57fd..f9d6ab89d 100644 --- a/src/sql/engine/expr/ob_expr_st_difference.h +++ b/src/sql/engine/expr/ob_expr_st_difference.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -33,7 +34,7 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_geometry(const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, + static int process_input_geometry(const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs); DISALLOW_COPY_AND_ASSIGN(ObExprSTDifference); }; diff --git a/src/sql/engine/expr/ob_expr_st_distance.cpp b/src/sql/engine/expr/ob_expr_st_distance.cpp index 3d5da9956..c4ea00430 100644 --- a/src/sql/engine/expr/ob_expr_st_distance.cpp +++ b/src/sql/engine/expr/ob_expr_st_distance.cpp @@ -83,8 +83,12 @@ int ObExprSTDistance::eval_st_distance(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObObjType input_type2 = gis_arg2->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_DISTANCE); + const int max_arg_num = 3; + ObDatum *gis_unit = NULL; + double factor = 0.0; + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); @@ -93,7 +97,11 @@ int ObExprSTDistance::eval_st_distance(const ObExpr &expr, ObEvalCtx &ctx, ObDat ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_DISTANCE); LOG_WARN("invalid type", K(ret), K(input_type1), K(input_type2)); - } else { + } else if (expr.arg_cnt_ == max_arg_num && OB_FAIL(temp_allocator.eval_arg(expr.args_[max_arg_num - 1], ctx, gis_unit))) { + LOG_WARN("eval geo unit arg failed", K(ret)); + } else if (OB_NOT_NULL(gis_unit) && gis_unit->is_null()) { + res.set_null(); + } else { bool is_geo1_empty = false; bool is_geo2_empty = false; ObGeometry *geo1 = NULL; @@ -106,18 +114,21 @@ int ObExprSTDistance::eval_st_distance(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObString wkb2 = gis_datum2->get_string(); omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum1, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs, true, N_ST_DISTANCE))) { LOG_WARN("fail to get srs item", K(ret), K(wkb1)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_ST_DISTANCE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_ST_DISTANCE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_ST_DISTANCE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_ST_DISTANCE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) { LOG_WARN("get type and srid from wkb failed", K(wkb1), K(ret)); @@ -131,8 +142,13 @@ int ObExprSTDistance::eval_st_distance(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { res.set_null(); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); double result = 0.0; if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -143,31 +159,25 @@ int ObExprSTDistance::eval_st_distance(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else { ObGeoExprUtils::geo_func_error_handle(ret, N_ST_DISTANCE); } - } else { - const int max_arg_num = 3; - if (expr.arg_cnt_ == max_arg_num) { - ObDatum *gis_unit = NULL; - double factor = 0.0; - if (OB_FAIL(expr.args_[max_arg_num - 1]->eval(ctx, gis_unit))) { - LOG_WARN("eval geo unit arg failed", K(ret)); - } else if (gis_unit->is_null()) { - res.set_null(); - } else if (OB_FAIL(ObGeoExprUtils::length_unit_conversion(gis_unit->get_string(), srs, result, result))) { - LOG_WARN("fail to do unit conversion", K(ret), K(result)); - } else if (std::isinf(result)) { - ret = OB_ERR_GIS_INVALID_DATA; - LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_DISTANCE); - } else { - res.set_double(result); - } + } else if (expr.arg_cnt_ == max_arg_num) { + if (OB_FAIL(ObGeoExprUtils::length_unit_conversion(gis_unit->get_string(), srs, result, result))) { + LOG_WARN("fail to do unit conversion", K(ret), K(result)); } else if (std::isinf(result)) { ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_DISTANCE); } else { res.set_double(result); } + } else if (std::isinf(result)) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_DISTANCE); + } else { + res.set_double(result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_distance_sphere.cpp b/src/sql/engine/expr/ob_expr_st_distance_sphere.cpp index 7e9fdfaf2..921bf8ed1 100644 --- a/src/sql/engine/expr/ob_expr_st_distance_sphere.cpp +++ b/src/sql/engine/expr/ob_expr_st_distance_sphere.cpp @@ -85,7 +85,8 @@ int ObExprSTDistanceSphere::eval_st_distance_sphere(const ObExpr &expr, uint32_t arg_num = expr.arg_cnt_; bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_DISTANCE_SPHERE); omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs1 = NULL; const ObSrsItem *srs2 = NULL; @@ -102,29 +103,30 @@ int ObExprSTDistanceSphere::eval_st_distance_sphere(const ObExpr &expr, double sphere_radius = DEFAULT_SRID0_SPHERE_RADIUS; double result = 0.0; - if (OB_FAIL(expr.args_[0]->eval(ctx, wkb1_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, wkb1_datum))) { LOG_WARN("fail to eval wkb1 datum", K(ret)); } else if (wkb1_datum->is_null()) { is_null_result = true; - } else if (OB_FAIL(expr.args_[1]->eval(ctx, wkb2_datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, wkb2_datum))) { LOG_WARN("fail to eval wkb2 datum", K(ret)); } else if (wkb2_datum->is_null()) { is_null_result = true; } else if (FALSE_IT(wkb1 = wkb1_datum->get_string())) { } else if (FALSE_IT(wkb2 = wkb2_datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *wkb1_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *wkb1_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *wkb2_datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *wkb2_datum, expr.args_[1]->datum_meta_, expr.args_[1]->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ob_write_string(tmp_allocator, wkb1, wkb1_copy))) { LOG_WARN("fail to copy wkb1", K(ret), K(wkb1)); } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1_copy, srs1, true, N_ST_DISTANCE_SPHERE))) { LOG_WARN("fail to get srs1 item", K(ret), K(wkb1_copy)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb1_copy, - g1, srs1, N_ST_DISTANCE_SPHERE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + g1, srs1, N_ST_DISTANCE_SPHERE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("fail to create geo1", K(ret), K(wkb1_copy)); } else if (OB_FAIL(ob_write_string(tmp_allocator, wkb2, wkb2_copy))) { LOG_WARN("fail to copy wkb2", K(ret), K(wkb2)); @@ -132,7 +134,7 @@ int ObExprSTDistanceSphere::eval_st_distance_sphere(const ObExpr &expr, true, N_ST_DISTANCE_SPHERE))) { LOG_WARN("fail to get srs2 item", K(ret), K(wkb2_copy)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb2_copy, - g2, srs2, N_ST_DISTANCE_SPHERE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + g2, srs2, N_ST_DISTANCE_SPHERE, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("fail to create geo2", K(ret), K(wkb2_copy)); } else { srid1 = OB_ISNULL(srs1) ? 0:srs1->get_srid(); @@ -161,7 +163,7 @@ int ObExprSTDistanceSphere::eval_st_distance_sphere(const ObExpr &expr, if (OB_SUCC(ret) && !is_null_result && arg_num == 3) { ObDatum *radius_datum = NULL; - if (OB_FAIL(expr.args_[2]->eval(ctx, radius_datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[2], ctx, radius_datum))) { LOG_WARN("fail to eval radius datum", K(ret)); } else if (radius_datum->is_null()) { is_null_result = true; @@ -174,8 +176,16 @@ int ObExprSTDistanceSphere::eval_st_distance_sphere(const ObExpr &expr, } } - if (OB_SUCC(ret) && !is_null_result) { - ObGeoEvalCtx gis_context(&tmp_allocator, srs1); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || is_null_result) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else { + ObGeoEvalCtx gis_context(*mem_ctx, srs1); if (OB_FAIL(gis_context.append_val_arg(sphere_radius))) { LOG_WARN("fail to append sphere_radius to gis_context", K(ret), K(sphere_radius)); } else if (OB_FAIL(gis_context.append_geo_arg(g1)) || OB_FAIL(gis_context.append_geo_arg(g2))) { @@ -202,7 +212,9 @@ int ObExprSTDistanceSphere::eval_st_distance_sphere(const ObExpr &expr, res.set_double(result); } } - + if (mem_ctx != nullptr) { + tmp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_dwithin.cpp b/src/sql/engine/expr/ob_expr_st_dwithin.cpp index 8d569a84b..69cf9b190 100644 --- a/src/sql/engine/expr/ob_expr_st_dwithin.cpp +++ b/src/sql/engine/expr/ob_expr_st_dwithin.cpp @@ -18,7 +18,6 @@ #include "observer/omt/ob_tenant_srs.h" #include "sql/engine/expr/ob_expr_st_dwithin.h" #include "lib/geo/ob_geo_utils.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; @@ -68,7 +67,7 @@ int ObExprPrivSTDWithin::calc_result_type3(ObExprResType &type, template int ObExprPrivSTDWithin::eval_st_dwithin_common(ObEvalCtx &ctx, - ObArenaAllocator &temp_allocator, + MultimodeAlloctor &temp_allocator, ObString wkb1, ObString wkb2, double distance_tolerance, @@ -87,6 +86,10 @@ int ObExprPrivSTDWithin::eval_st_dwithin_common(ObEvalCtx &ctx, uint32_t srid2; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; + temp_allocator.set_baseline_size(wkb1.length() + wkb2.length()); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (distance_tolerance < 0.0) { ret = OB_ERR_GIS_INVALID_DATA; @@ -108,14 +111,14 @@ int ObExprPrivSTDWithin::eval_st_dwithin_common(ObEvalCtx &ctx, } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs))) { LOG_WARN("fail to get srs item", K(ret), K(wkb1)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_PRIV_ST_TRANSFORM, - ObGeoBuildFlag::GEO_ALLOW_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); if (ret != OB_ERR_SRS_NOT_FOUND && ret != OB_ERR_INVALID_GEOMETRY_TYPE) { ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_DWITHIN); } } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_PRIV_ST_TRANSFORM, - ObGeoBuildFlag::GEO_ALLOW_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); if (ret != OB_ERR_SRS_NOT_FOUND && ret != OB_ERR_INVALID_GEOMETRY_TYPE) { ret = OB_ERR_GIS_INVALID_DATA; @@ -132,8 +135,13 @@ int ObExprPrivSTDWithin::eval_st_dwithin_common(ObEvalCtx &ctx, } else if (ob_is_string_type(input_type2) && OB_FAIL(ObGeoExprUtils::check_coordinate_range(srs, geo2, N_PRIV_ST_DWITHIN, true))) { LOG_WARN("invalid coordinate range", K(input_type2), K(geo2)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); double result = 0.0; if (OB_FAIL(ObGeoExprUtils::normalize_wkb(srs, wkb1, temp_allocator, geo1))) { LOG_WARN("normalize wkb1 failed", K(srid1), K(ret)); @@ -148,6 +156,9 @@ int ObExprPrivSTDWithin::eval_st_dwithin_common(ObEvalCtx &ctx, res.set_bool(result <= distance_tolerance); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } @@ -167,18 +178,19 @@ int ObExprPrivSTDWithin::eval_st_dwithin(const ObExpr &expr, ObEvalCtx &ctx, ObD bool is_null_res = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2)) - || OB_FAIL(gis_arg3->eval(ctx, gis_datum3))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_DWITHIN); + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2)) + || OB_FAIL(temp_allocator.eval_arg(gis_arg3, ctx, gis_datum3))) { LOG_WARN("eval geo args failed", K(ret), KP(gis_datum1),KP(gis_datum2),KP(gis_datum3)); } else if (gis_datum1->is_null() || gis_datum2->is_null() || gis_datum3->is_null()) { res.set_null(); } else if (FALSE_IT(wkb1 = gis_datum1->get_string())) { } else if (FALSE_IT(wkb2 = gis_datum2->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum1, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); } else if (OB_FAIL(ObExprPrivSTDWithin::eval_st_dwithin_common(ctx, diff --git a/src/sql/engine/expr/ob_expr_st_dwithin.h b/src/sql/engine/expr/ob_expr_st_dwithin.h index 0c9906456..72be20225 100644 --- a/src/sql/engine/expr/ob_expr_st_dwithin.h +++ b/src/sql/engine/expr/ob_expr_st_dwithin.h @@ -15,6 +15,7 @@ #define OCEANBASE_SQL_OB_EXPR_ST_DWITHIN #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase @@ -34,7 +35,7 @@ public: common::ObExprTypeCtx &type_ctx)const; template static int eval_st_dwithin_common(ObEvalCtx &ctx, - ObArenaAllocator &temp_allocator, + MultimodeAlloctor &temp_allocator, ObString wkb1, ObString wkb2, double distance_tolerance, diff --git a/src/sql/engine/expr/ob_expr_st_geomfromewkb.cpp b/src/sql/engine/expr/ob_expr_st_geomfromewkb.cpp index 0954d6c76..8397384fa 100644 --- a/src/sql/engine/expr/ob_expr_st_geomfromewkb.cpp +++ b/src/sql/engine/expr/ob_expr_st_geomfromewkb.cpp @@ -71,13 +71,13 @@ int ObExprPrivSTGeomFromEWKB::eval_st_geomfromewkb(const ObExpr &expr, ObEvalCtx { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_GEOMFROMEWKB); ObDatum *datum = NULL; int num_args = expr.arg_cnt_; bool is_null_result = false; ObGeoAxisOrder axis_order = ObGeoAxisOrder::INVALID; ObString ewkb; - ObString ewkb_copy; omt::ObSrsCacheGuard srs_guard; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); const ObSrsItem *srs = NULL; @@ -87,20 +87,19 @@ int ObExprPrivSTGeomFromEWKB::eval_st_geomfromewkb(const ObExpr &expr, ObEvalCtx bool is_geographical = false; bool is_3d_geo = false; // get ewkb - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; } else { ewkb = datum->get_string(); ObGeoWkbHeader header; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), ewkb))) { LOG_WARN("fail to get real string data", K(ret), K(ewkb)); - } else if (OB_FAIL(ob_write_string(tmp_allocator, ewkb, ewkb_copy, false))) { - LOG_WARN("fail to deep copy ewkb", K(ret)); - } else if (OB_FAIL(get_header_info_from_ewkb(ewkb_copy, header))) { - LOG_WARN("fail to get ewkb header info from ewkb", K(ret), K(ewkb_copy)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(ewkb.length()))) { + } else if (OB_FAIL(get_header_info_from_ewkb(ewkb, header))) { + LOG_WARN("fail to get ewkb header info from ewkb", K(ret), K(ewkb)); ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_PRIV_ST_GEOMFROMEWKB); } else if (header.bo_ != ObGeoWkbByteOrder::LittleEndian) { @@ -109,7 +108,7 @@ int ObExprPrivSTGeomFromEWKB::eval_st_geomfromewkb(const ObExpr &expr, ObEvalCtx LOG_WARN("invalid byte order", K(ret), K(header.bo_)); } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(session->get_effective_tenant_id(), srs_guard, header.srid_, srs))) { LOG_WARN("fail to get srs item", K(ret), K(header.srid_)); - } else if (OB_FAIL(create_geo_by_ewkb(tmp_allocator, ewkb_copy, header, srs, geo))) { + } else if (OB_FAIL(create_geo_by_ewkb(tmp_allocator, ewkb, header, srs, geo))) { LOG_WARN("fail to create geometry object with raw ewkb", K(ret)); if (ret == OB_ERR_SRS_NOT_FOUND) { // do nothing @@ -126,11 +125,12 @@ int ObExprPrivSTGeomFromEWKB::eval_st_geomfromewkb(const ObExpr &expr, ObEvalCtx // get axis_order if (OB_SUCC(ret) && num_args > 1) { ObString axis_str; - expr.args_[1]->eval(ctx, datum); - if (datum->is_null()){ + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, datum))) { + LOG_WARN("failed to eval second argument", K(ret)); + } else if (datum->is_null()){ // do nothing } else if (FALSE_IT(axis_str = datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[1]->datum_meta_, expr.args_[1]->obj_meta_.has_lob_header(), axis_str))) { LOG_WARN("fail to get real string data", K(ret), K(axis_str)); } else if (OB_FAIL(ObGeoExprUtils::parse_axis_order(axis_str, N_PRIV_ST_GEOMFROMEWKB, axis_order))) { diff --git a/src/sql/engine/expr/ob_expr_st_geomfromewkt.cpp b/src/sql/engine/expr/ob_expr_st_geomfromewkt.cpp index 0fff7efeb..b94353b77 100644 --- a/src/sql/engine/expr/ob_expr_st_geomfromewkt.cpp +++ b/src/sql/engine/expr/ob_expr_st_geomfromewkt.cpp @@ -60,7 +60,8 @@ int ObExprPrivSTGeomFromEwkt::eval_st_geomfromewkt(const ObExpr &expr, ObEvalCtx { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_PRIV_ST_GEOMFROMEWKT); ObDatum *datum = NULL; bool is_null_result = false; uint32_t srid = 0; @@ -73,15 +74,16 @@ int ObExprPrivSTGeomFromEwkt::eval_st_geomfromewkt(const ObExpr &expr, ObEvalCtx bool is_3d_geo = false; // get wkt - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("eval wkt arg failed", K(ret)); } else if(datum->is_null()){ is_null_result = true; } else { wkt = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkt))) { LOG_WARN("fail to get real string data", K(ret), K(wkt)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkt.length()))) { } } // get srid diff --git a/src/sql/engine/expr/ob_expr_st_geomfromtext.cpp b/src/sql/engine/expr/ob_expr_st_geomfromtext.cpp index 4653cf976..a0e4c3c83 100644 --- a/src/sql/engine/expr/ob_expr_st_geomfromtext.cpp +++ b/src/sql/engine/expr/ob_expr_st_geomfromtext.cpp @@ -95,7 +95,8 @@ int ObExprSTGeomFromText::eval_st_geomfromtext_common(const ObExpr &expr, { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, func_name); ObDatum *datum = NULL; int num_args = expr.arg_cnt_; bool is_null_result = false; @@ -112,20 +113,21 @@ int ObExprSTGeomFromText::eval_st_geomfromtext_common(const ObExpr &expr, bool is_3d_geo = false; // get wkt - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; } else { wkt = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkt))) { LOG_WARN("fail to get real string data", K(ret), K(wkt)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkt.length()))) { } } // get srid if (!is_null_result && OB_SUCC(ret) && num_args > 1) { - if (OB_FAIL(expr.args_[1]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, datum))) { LOG_WARN("failed to eval second argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; @@ -151,12 +153,12 @@ int ObExprSTGeomFromText::eval_st_geomfromtext_common(const ObExpr &expr, // get axis_order if (!is_null_result && OB_SUCC(ret) && num_args > 2 ) { ObString axis_str; - if (OB_FAIL(expr.args_[2]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[2], ctx, datum))) { LOG_WARN("failed to eval third argument", K(ret)); } else if (datum->is_null()){ is_null_result = true; } else if (FALSE_IT(axis_str = datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[2]->datum_meta_, expr.args_[2]->obj_meta_.has_lob_header(), axis_str))) { LOG_WARN("fail to get real string data", K(ret), K(axis_str)); } else if (OB_FAIL(ObGeoExprUtils::parse_axis_order(axis_str, func_name, axis_order))) { diff --git a/src/sql/engine/expr/ob_expr_st_geomfromwkb.cpp b/src/sql/engine/expr/ob_expr_st_geomfromwkb.cpp index c3f13d846..23b7c9aa1 100644 --- a/src/sql/engine/expr/ob_expr_st_geomfromwkb.cpp +++ b/src/sql/engine/expr/ob_expr_st_geomfromwkb.cpp @@ -96,13 +96,13 @@ int ObIExprSTGeomFromWKB::eval_geom_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDa { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, get_func_name()); ObDatum *datum = NULL; int num_args = expr.arg_cnt_; bool is_null_result = false; ObGeoAxisOrder axis_order = ObGeoAxisOrder::INVALID; ObString wkb; - ObString wkb_copy; const ObSrsItem *srs_item = NULL; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); omt::ObSrsCacheGuard srs_guard; @@ -116,8 +116,9 @@ int ObIExprSTGeomFromWKB::eval_geom_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDa bool is_3d_geo = false; // get srid if (num_args > 1) { - expr.args_[1]->eval(ctx, datum); - if (datum->is_null()) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, datum))) { + LOG_WARN("fail to eval argument", K(ret)); + } else if (datum->is_null()) { is_null_result = true; } else if (datum->get_int() < 0 || datum->get_int() > UINT_MAX32) { ret = OB_OPERATE_OVERFLOW; @@ -141,13 +142,15 @@ int ObIExprSTGeomFromWKB::eval_geom_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDa // get axis_order if (!is_null_result && OB_SUCC(ret) && num_args > 2) { ObString axis_str; - expr.args_[2]->eval(ctx, datum); - if (datum->is_null()){ + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[2], ctx, datum))) { + LOG_WARN("fail to eval argument", K(ret)); + } else if (datum->is_null()){ is_null_result = true; } else if (FALSE_IT(axis_str = datum->get_string())) { - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[2]->datum_meta_, expr.args_[2]->obj_meta_.has_lob_header(), axis_str))) { LOG_WARN("fail to get real string data", K(ret), K(axis_str)); + } else if (FALSE_IT(tmp_allocator.add_baseline_size(axis_str.length()))) { } else if (OB_FAIL(ObGeoExprUtils::parse_axis_order(axis_str, get_func_name(), axis_order))) { LOG_WARN("failed to parse axis order option string", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::check_need_reverse(axis_order, need_reverse))) { @@ -157,18 +160,17 @@ int ObIExprSTGeomFromWKB::eval_geom_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDa // get wkb if (!is_null_result && OB_SUCC(ret)) { - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval wkb", K(ret)); } else if (datum->is_null()){ is_null_result = true; } else { wkb = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); - } else if (OB_FAIL(ob_write_string(tmp_allocator, wkb, wkb_copy, false))) { - LOG_WARN("fail to deep copy wkb", K(ret)); - } else if (OB_FAIL(create_by_wkb_without_srid(tmp_allocator, wkb_copy, srs_item, geo, bo))) { + } else if (FALSE_IT(tmp_allocator.add_baseline_size(wkb.length()))) { + } else if (OB_FAIL(create_by_wkb_without_srid(tmp_allocator, wkb, srs_item, geo, bo))) { LOG_WARN("failed to create geometry object with raw wkb", K(ret)); ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, get_func_name()); @@ -188,11 +190,12 @@ int ObIExprSTGeomFromWKB::eval_geom_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDa } if (OB_SUCC(ret) && !is_3d_geo && bo == ObGeoWkbByteOrder::BigEndian) { - ObGeoToTreeVisitor tree_visitor(&tmp_allocator); - if (OB_FAIL(geo->do_visit(tree_visitor))) { - LOG_WARN("fail to do visit", K(ret), K(geo->type())); + // transform to LittleEndian + ObWkbByteOrderVisitor bo_visitor(&tmp_allocator, ObGeoWkbByteOrder::LittleEndian); + if (OB_FAIL(geo->do_visit(bo_visitor))) { + LOG_WARN("fail to transform big endian to little endian", K(ret)); } else { - geo = tree_visitor.get_geometry(); + geo->set_data(bo_visitor.get_wkb()); } } diff --git a/src/sql/engine/expr/ob_expr_st_intersects.cpp b/src/sql/engine/expr/ob_expr_st_intersects.cpp index d519ffbfc..10d789a97 100644 --- a/src/sql/engine/expr/ob_expr_st_intersects.cpp +++ b/src/sql/engine/expr/ob_expr_st_intersects.cpp @@ -71,9 +71,10 @@ int ObExprSTIntersects::eval_st_intersects(const ObExpr &expr, ObEvalCtx &ctx, O ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_INTERSECTS); bool inter_result = false; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); @@ -95,6 +96,8 @@ int ObExprSTIntersects::eval_st_intersects(const ObExpr &expr, ObEvalCtx &ctx, O bool is_geo2_cached = false; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); bool box_intersects = true; + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (gis_arg1->is_static_const_) { ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo1, srid1, is_geo1_cached, 0); @@ -123,13 +126,19 @@ int ObExprSTIntersects::eval_st_intersects(const ObExpr &expr, ObEvalCtx &ctx, O LOG_WARN("get first geo by wkb failed", K(ret)); } else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) { LOG_WARN("get second geo by wkb failed", K(ret)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(geo1->length() + geo2->length()))) { } else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))) || (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { res.set_null(); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2, is_geo1_cached, is_geo2_cached))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { if (OB_NOT_NULL(const_param_cache)) { if (gis_arg1->is_static_const_ && !is_geo1_cached && @@ -140,16 +149,35 @@ int ObExprSTIntersects::eval_st_intersects(const ObExpr &expr, ObEvalCtx &ctx, O LOG_WARN("add geo2 to const cache failed", K(ret)); } } + ObGeoEvalCtx gis_context(*mem_ctx); + bool result = false; + if (OB_FAIL(ret)) { + } else if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { + LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, result))) { + LOG_WARN("eval st intersection failed", K(ret)); + ObGeoExprUtils::geo_func_error_handle(ret, N_ST_INTERSECTS); + } else { + if (geo1->type() == ObGeoType::POINT + && geo2->type() == ObGeoType::POINT + && result == true + && OB_FAIL(ObGeoTypeUtil::eval_point_box_intersects(srs, geo1, geo2, result))) { + LOG_WARN("eval box intersection failed", K(ret)); + } + } if (OB_FAIL(ret)) { } else if (OB_FAIL(ObGeoExprUtils::get_intersects_res(*geo1, *geo2, gis_arg1, gis_arg2, const_param_cache, srs, - temp_allocator, inter_result))) { + mem_ctx, inter_result))) { LOG_WARN("fail to get intersects res", K(ret)); } else { res.set_bool(inter_result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_isvalid.cpp b/src/sql/engine/expr/ob_expr_st_isvalid.cpp index 0a34ee49c..a25a5a6c8 100644 --- a/src/sql/engine/expr/ob_expr_st_isvalid.cpp +++ b/src/sql/engine/expr/ob_expr_st_isvalid.cpp @@ -57,7 +57,8 @@ int ObExprSTIsValid::eval_st_isvalid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_ISVALID); ObDatum *datum = NULL; int num_args = expr.arg_cnt_; bool is_null_result = false; @@ -69,27 +70,35 @@ int ObExprSTIsValid::eval_st_isvalid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum bool is_geog = false; bool isvalid_res = false; - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; } else { wkb = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, N_ST_ISVALID))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb, geo, srs, N_ST_ISVALID, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb, geo, srs, N_ST_ISVALID, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("failed to parse wkb", K(ret)); } } if (OB_SUCC(ret)) { + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (is_null_result) { res.set_null(); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoEvalCtx gis_context(&tmp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo))) { LOG_WARN("build geo gis context failed", K(ret)); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, isvalid_res))) { @@ -99,6 +108,9 @@ int ObExprSTIsValid::eval_st_isvalid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum res.set_bool(isvalid_res); } } + if (mem_ctx != nullptr) { + tmp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; diff --git a/src/sql/engine/expr/ob_expr_st_length.cpp b/src/sql/engine/expr/ob_expr_st_length.cpp index c9e83d31e..03ada1434 100644 --- a/src/sql/engine/expr/ob_expr_st_length.cpp +++ b/src/sql/engine/expr/ob_expr_st_length.cpp @@ -63,11 +63,13 @@ int ObExprSTLength::eval_st_length(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ObExpr *arg1 = expr.args_[0]; ObObjType type1 = arg1->datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_LENGTH); double res_num = 0; + ObDatum *gis_unit = NULL; if (ob_is_null(type1)) { is_null_res = true; - } else if (OB_FAIL(arg1->eval(ctx, datum1))) { + } else if (OB_FAIL(temp_allocator.eval_arg(arg1, ctx, datum1))) { LOG_WARN("fail to eval args", K(ret)); } else if (datum1->is_null()) { is_null_res = true; @@ -76,6 +78,10 @@ int ObExprSTLength::eval_st_length(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ret = OB_ERR_GIS_INVALID_DATA; LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_CROSSES); LOG_WARN("invalid type", K(ret), K(type1)); + } else if (expr.arg_cnt_ == 2 && OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, gis_unit))) { + LOG_WARN("eval geo unit arg failed", K(ret)); + } else if (expr.arg_cnt_ == 2 && gis_unit->is_null()) { + is_null_res = true; } else { // construct geometry ObString wkb = datum1->get_string(); @@ -83,19 +89,27 @@ int ObExprSTLength::eval_st_length(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ObGeometry *geo = nullptr; const ObSrsItem *srs = NULL; omt::ObSrsCacheGuard srs_guard; - if (OB_FAIL(ObTextStringHelper::read_real_string_data( + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy( temp_allocator, *datum1, arg1->datum_meta_, arg1->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to read real string data", K(ret), K(arg1->obj_meta_.has_lob_header())); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, N_ST_LENGTH))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry( - temp_allocator, wkb, geo, srs, N_ST_LENGTH, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { // ObIWkbGeom + temp_allocator, wkb, geo, srs, N_ST_LENGTH, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { // ObIWkbGeom LOG_WARN("fail to build geometry from wkb", K(ret), K(wkb)); } else if (geo->type() != ObGeoType::LINESTRING && geo->type() != ObGeoType::MULTILINESTRING) { is_null_res = true; + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { // cal length - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo))) { LOG_WARN("build gis context failed", K(ret)); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, res_num))) { @@ -111,12 +125,7 @@ int ObExprSTLength::eval_st_length(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "Length", N_ST_LENGTH); } else if (expr.arg_cnt_ == 2) { // transfer to unit - ObDatum *gis_unit = NULL; - if (OB_FAIL(expr.args_[1]->eval(ctx, gis_unit))) { - LOG_WARN("eval geo unit arg failed", K(ret)); - } else if (gis_unit->is_null()) { - is_null_res = true; - } else if (OB_FAIL(ObGeoExprUtils::length_unit_conversion( + if (OB_FAIL(ObGeoExprUtils::length_unit_conversion( gis_unit->get_string(), srs, res_num, res_num))) { LOG_WARN("fail to do unit conversion", K(ret), K(res_num)); } else if (std::isinf(res_num)) { @@ -126,6 +135,9 @@ int ObExprSTLength::eval_st_length(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } // set result if (OB_SUCC(ret)) { diff --git a/src/sql/engine/expr/ob_expr_st_overlaps.cpp b/src/sql/engine/expr/ob_expr_st_overlaps.cpp index f8cc79b37..9f91d9945 100644 --- a/src/sql/engine/expr/ob_expr_st_overlaps.cpp +++ b/src/sql/engine/expr/ob_expr_st_overlaps.cpp @@ -17,7 +17,6 @@ #include "lib/geo/ob_geo_ibin.h" #include "sql/engine/ob_exec_context.h" #include "ob_expr_st_overlaps.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -57,7 +56,7 @@ int ObExprSTOverlaps::calc_result_type2(ObExprResType &type, ObExprResType &type } int ObExprSTOverlaps::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, + MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs) { int ret = OB_SUCCESS; @@ -68,7 +67,7 @@ int ObExprSTOverlaps::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, co ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; is_null_res = false; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { is_null_res = true; @@ -86,18 +85,19 @@ int ObExprSTOverlaps::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, co ObString wkb2 = gis_datum2->get_string(); bool is_geo1_valid = false; bool is_geo2_valid = false; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) { if (ret == OB_ERR_GIS_INVALID_DATA) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_OVERLAPS); @@ -116,10 +116,10 @@ int ObExprSTOverlaps::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, co ctx, srs_guard, wkb1, srs, true, N_ST_OVERLAPS))) { LOG_WARN("fail to get srs item", K(ret), K(wkb1)); } else if (OB_FAIL( - ObGeoExprUtils::build_geometry(allocator, wkb1, geo1, srs, N_ST_OVERLAPS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + ObGeoExprUtils::build_geometry(allocator, wkb1, geo1, srs, N_ST_OVERLAPS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); } else if (OB_FAIL( - ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_OVERLAPS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_OVERLAPS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } } @@ -138,21 +138,30 @@ int ObExprSTOverlaps::eval_st_overlaps(const ObExpr &expr, ObEvalCtx &ctx, ObDat omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_OVERLAPS); if (OB_FAIL(process_input_geometry(srs_guard, expr, ctx, temp_allocator, geo1, geo2, is_null_res, srs))) { LOG_WARN("fail to process input geometry", K(ret)); - } else if (is_null_res) { + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || is_null_res) { // do nothing } else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)) || OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { is_null_res = true; - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { ObGeoFuncResWithNull overlaps_result; - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval( @@ -173,6 +182,9 @@ int ObExprSTOverlaps::eval_st_overlaps(const ObExpr &expr, ObEvalCtx &ctx, ObDat res.set_bool(result); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_overlaps.h b/src/sql/engine/expr/ob_expr_st_overlaps.h index b1a47f40d..1fccaa42f 100644 --- a/src/sql/engine/expr/ob_expr_st_overlaps.h +++ b/src/sql/engine/expr/ob_expr_st_overlaps.h @@ -17,6 +17,7 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" #include "observer/omt/ob_tenant_srs.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { @@ -34,7 +35,7 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, ObGeometry *&geo1, + static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs); // static int is_geometry_valid( // ObGeometry *geo, ObIAllocator &allocator, const common::ObSrsItem *srs_item, bool &is_valid); diff --git a/src/sql/engine/expr/ob_expr_st_srid.cpp b/src/sql/engine/expr/ob_expr_st_srid.cpp index e4e073421..4b34133c1 100644 --- a/src/sql/engine/expr/ob_expr_st_srid.cpp +++ b/src/sql/engine/expr/ob_expr_st_srid.cpp @@ -88,7 +88,8 @@ int ObExprSTSRID::eval_st_srid_common(const ObExpr &expr, ObEvalCtx &ctx, ObDatu { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, func_name); ObDatum *datum = NULL; int num_args = expr.arg_cnt_; bool is_null_result = false; @@ -106,7 +107,7 @@ int ObExprSTSRID::eval_st_srid_common(const ObExpr &expr, ObEvalCtx &ctx, ObDatu if (expr.args_[1]->is_boolean_ && T_FUN_SYS_PRIV_ST_SETSRID == expr.type_) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("invalid type", K(ret)); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, datum))) { LOG_WARN("failed to eval second argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; @@ -128,15 +129,16 @@ int ObExprSTSRID::eval_st_srid_common(const ObExpr &expr, ObEvalCtx &ctx, ObDatu // get geometry if (OB_SUCC(ret)) { - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; } else if (!is_null_result) { // srid might be null, fix 42538503 wkb = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(tmp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(tmp_allocator.set_baseline_size(wkb.length()))) { } else if (num_args == 1) { if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, func_name))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); @@ -146,7 +148,7 @@ int ObExprSTSRID::eval_st_srid_common(const ObExpr &expr, ObEvalCtx &ctx, ObDatu } if (OB_FAIL(ret)) { // do nothing - } else if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb, geo, srs, func_name, ObGeoBuildFlag::GEO_CHECK_RANGE))) { + } else if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb, geo, srs, func_name, ObGeoBuildFlag::GEO_CHECK_RANGE | GEO_NOT_COPY_WKB))) { LOG_WARN("failed to parse geometry from wkb", K(ret)); } else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(wkb, srid))) { LOG_WARN("failed to get srid from wkb", K(ret)); @@ -155,7 +157,7 @@ int ObExprSTSRID::eval_st_srid_common(const ObExpr &expr, ObEvalCtx &ctx, ObDatu LOG_WARN("srs not found"); } } else { - if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb, geo, srs, func_name, ObGeoBuildFlag::GEO_CHECK_RANGE))) { + if (OB_FAIL(ObGeoExprUtils::build_geometry(tmp_allocator, wkb, geo, srs, func_name, ObGeoBuildFlag::GEO_CHECK_RANGE | GEO_NOT_COPY_WKB))) { LOG_WARN("fail to create geo", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoExprUtils::geo_to_wkb(*geo, expr, ctx, srs, res_wkb))) { LOG_WARN("failed to write geometry to wkb", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_st_symdifference.cpp b/src/sql/engine/expr/ob_expr_st_symdifference.cpp index 1159fba0c..c9bd499db 100644 --- a/src/sql/engine/expr/ob_expr_st_symdifference.cpp +++ b/src/sql/engine/expr/ob_expr_st_symdifference.cpp @@ -15,7 +15,6 @@ #include "lib/geo/ob_geo_ibin.h" #include "sql/engine/ob_exec_context.h" #include "ob_expr_st_symdifference.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" #include "sql/engine/expr/ob_expr_lob_utils.h" #include "lib/geo/ob_geo_to_tree_visitor.h" #include "lib/geo/ob_geo_elevation_visitor.h" @@ -53,7 +52,7 @@ int ObExprSTSymDifference::calc_result_type2(ObExprResType &type, ObExprResType return ret; } int ObExprSTSymDifference::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, + MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs) { int ret = OB_SUCCESS; @@ -64,7 +63,7 @@ int ObExprSTSymDifference::process_input_geometry(omt::ObSrsCacheGuard &srs_guar ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; is_null_res = false; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { is_null_res = true; @@ -77,18 +76,19 @@ int ObExprSTSymDifference::process_input_geometry(omt::ObSrsCacheGuard &srs_guar ObString wkb2 = gis_datum2->get_string(); bool is_geo1_valid = false; bool is_geo2_valid = false; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) { if (ret == OB_ERR_GIS_INVALID_DATA) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_SYMDIFFERENCE); @@ -111,14 +111,14 @@ int ObExprSTSymDifference::process_input_geometry(omt::ObSrsCacheGuard &srs_guar geo1, srs, N_ST_SYMDIFFERENCE, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_SYMDIFFERENCE, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } } @@ -136,12 +136,16 @@ int ObExprSTSymDifference::eval_st_symdifference(const ObExpr &expr, ObEvalCtx & omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_SYMDIFFERENCE); ObGeometry *diff_res = nullptr; if (OB_FAIL( process_input_geometry(srs_guard, expr, ctx, temp_allocator, geo1_3d, geo2_3d, is_null_res, srs))) { LOG_WARN("fail to process input geometry", K(ret)); - } else if (!is_null_res) { + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_SUCC(ret) && !is_null_res) { ObGeometry *geo1 = nullptr; ObGeometry *geo2 = nullptr; bool is_3d_geo1 = ObGeoTypeUtil::is_3d_geo_type(geo1_3d->type()); @@ -166,8 +170,15 @@ int ObExprSTSymDifference::eval_st_symdifference(const ObExpr &expr, ObEvalCtx & } else { geo2 = geo2_3d; } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } if (OB_SUCC(ret)) { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); bool is_empty_res = false; if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -183,19 +194,13 @@ int ObExprSTSymDifference::eval_st_symdifference(const ObExpr &expr, ObEvalCtx & geo1->crs() == ObGeoCRS::Geographic, diff_res))) { LOG_WARN("fail to create 3D empty collection", K(ret)); } - } else if (geo1->crs() == ObGeoCRS::Cartesian - && OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo(diff_res, temp_allocator, srs))) { - // should not do simplify in symdifference functor, it may affect - // ObGeoFuncUtils::ob_geo_gc_union - LOG_WARN("fail to simplify result", K(ret)); - } else if (geo1->crs() == ObGeoCRS::Geographic - && OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo(diff_res, temp_allocator, srs))) { + } else if (OB_FAIL(ObGeoTypeUtil::remove_duplicate_geo(diff_res, *mem_ctx, srs))) { // should not do simplify in symdifference functor, it may affect // ObGeoFuncUtils::ob_geo_gc_union LOG_WARN("fail to simplify result", K(ret)); } else if (is_3d_geo1 && is_3d_geo2) { // populate Z coordinates - ObGeoElevationVisitor visitor(temp_allocator, srs); + ObGeoElevationVisitor visitor(*mem_ctx, srs); ObGeometry *diff_res_bin = nullptr; if (OB_FAIL(visitor.init(*geo1_3d, *geo2_3d))) { LOG_WARN("fail to init elevation visitor", K(ret)); @@ -221,6 +226,9 @@ int ObExprSTSymDifference::eval_st_symdifference(const ObExpr &expr, ObEvalCtx & res.set_string(res_wkb); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } int ObExprSTSymDifference::cg_expr( diff --git a/src/sql/engine/expr/ob_expr_st_symdifference.h b/src/sql/engine/expr/ob_expr_st_symdifference.h index 86c6f7cf6..525e75962 100644 --- a/src/sql/engine/expr/ob_expr_st_symdifference.h +++ b/src/sql/engine/expr/ob_expr_st_symdifference.h @@ -15,6 +15,8 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" #include "observer/omt/ob_tenant_srs.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" + namespace oceanbase { namespace sql @@ -30,7 +32,7 @@ public: virtual int cg_expr( ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, + static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs); DISALLOW_COPY_AND_ASSIGN(ObExprSTSymDifference); }; diff --git a/src/sql/engine/expr/ob_expr_st_transform.cpp b/src/sql/engine/expr/ob_expr_st_transform.cpp index 3f9357e58..b835b6f8f 100644 --- a/src/sql/engine/expr/ob_expr_st_transform.cpp +++ b/src/sql/engine/expr/ob_expr_st_transform.cpp @@ -77,7 +77,8 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD omt::ObSrsCacheGuard srs_guard; const ObSrsItem *src_srs_item = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_TRANSFORM); ObString src_proj4_param; ObString dest_proj4_param; bool need_eval = true; @@ -88,9 +89,9 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD if (is_null_result) { res.set_null(); - } else if (OB_FAIL(expr.args_[0]->eval(ctx, gis_datum))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, gis_datum))) { LOG_WARN("eval geo arg failed", K(ret)); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, datum2))) { + } else if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, datum2))) { LOG_WARN("eval sird arg failed", K(ret)); } else if (gis_datum->is_null() || datum2->is_null()) { res.set_null(); @@ -99,9 +100,10 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD uint32_t dest_srid = 0; ObString wkb = gis_datum->get_string(); const ObSrsItem *dest_srs_item = NULL; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *gis_datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, src_srs_item, true, N_ST_TRANSFORM))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(wkb, src_srid))) { @@ -119,7 +121,7 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD if (dest_srid == src_srid) { // return src geo directly ObString res_wkb; if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, src_geo, src_srs_item, N_ST_TRANSFORM, - ObGeoBuildFlag::GEO_ALLOW_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("fail to create geo", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoExprUtils::geo_to_wkb(*src_geo, expr, ctx, src_srs_item, res_wkb))) { LOG_WARN("failed to write geometry to wkb", K(ret)); @@ -144,8 +146,7 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD ret = OB_ERR_TRANSFORM_SOURCE_SRS_MISSING_TOWGS84; LOG_USER_ERROR(OB_ERR_TRANSFORM_SOURCE_SRS_MISSING_TOWGS84, src_srid); LOG_WARN("source srs is not WGS 84 and has no TOWGS84 clause", K(ret), K(src_srid)); - } - if (OB_ISNULL(dest_srs_item)) { + } else if (OB_ISNULL(dest_srs_item)) { ret = OB_ERR_TRANSFORM_TARGET_SRS_NOT_SUPPORTED; LOG_USER_ERROR(OB_ERR_TRANSFORM_TARGET_SRS_NOT_SUPPORTED, dest_srid); LOG_WARN("dest srs is null", K(ret), K(dest_srid)); @@ -171,10 +172,18 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD } // eval by bg - if (OB_SUCC(ret) && need_eval) { + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_FAIL(ret) || !need_eval) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); + } else { int correct_result; - ObGeoEvalCtx correct_context(&temp_allocator, src_srs_item); - ObGeoEvalCtx transform_context(&temp_allocator, dest_srs_item); + ObGeoEvalCtx correct_context(*mem_ctx, src_srs_item); + ObGeoEvalCtx transform_context(*mem_ctx, dest_srs_item); if (src_proj4_param.empty()) { ret = OB_ERR_TRANSFORM_SOURCE_SRS_NOT_SUPPORTED; LOG_USER_ERROR(OB_ERR_TRANSFORM_SOURCE_SRS_NOT_SUPPORTED, src_srid); @@ -211,6 +220,9 @@ int ObExprSTTransform::eval_st_transform(const ObExpr &expr, ObEvalCtx &ctx, ObD } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } } diff --git a/src/sql/engine/expr/ob_expr_st_union.cpp b/src/sql/engine/expr/ob_expr_st_union.cpp index 4a07bf580..8699a6d8a 100644 --- a/src/sql/engine/expr/ob_expr_st_union.cpp +++ b/src/sql/engine/expr/ob_expr_st_union.cpp @@ -17,7 +17,6 @@ #include "lib/geo/ob_geo_ibin.h" #include "sql/engine/ob_exec_context.h" #include "ob_expr_st_union.h" -#include "sql/engine/expr/ob_geo_expr_utils.h" #include "lib/geo/ob_geo_to_tree_visitor.h" #include "lib/geo/ob_geo_elevation_visitor.h" #include "lib/geo/ob_geo_func_utils.h" @@ -59,7 +58,7 @@ int ObExprSTUnion::calc_result_type2(ObExprResType &type, ObExprResType &type1, } int ObExprSTUnion::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, - ObIAllocator &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, + MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs) { int ret = OB_SUCCESS; @@ -70,7 +69,7 @@ int ObExprSTUnion::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObObjType input_type1 = gis_arg1->datum_meta_.type_; ObObjType input_type2 = gis_arg2->datum_meta_.type_; is_null_res = false; - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + if (OB_FAIL(allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { is_null_res = true; @@ -83,18 +82,19 @@ int ObExprSTUnion::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObString wkb2 = gis_datum2->get_string(); bool is_geo1_valid = false; bool is_geo2_valid = false; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum1, gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) { LOG_WARN("fail to get real string data", K(ret), K(wkb1)); - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum2, gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) { LOG_WARN("fail to get real string data", K(ret), K(wkb2)); + } else if (FALSE_IT(allocator.set_baseline_size(wkb1.length() + wkb2.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) { if (ret == OB_ERR_GIS_INVALID_DATA) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_UNION); @@ -117,14 +117,14 @@ int ObExprSTUnion::process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const geo1, srs, N_ST_UNION, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(allocator, wkb2, geo2, srs, N_ST_UNION, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D))) { + ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_RESERVE_3D | GEO_NOT_COPY_WKB))) { LOG_WARN("get second geo by wkb failed", K(ret)); } } @@ -142,13 +142,17 @@ int ObExprSTUnion::eval_st_union(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = nullptr; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_UNION); ObGeometry *union_res = nullptr; bool is_empty_res = false; if (OB_FAIL( process_input_geometry(srs_guard, expr, ctx, temp_allocator, geo1_3d, geo2_3d, is_null_res, srs))) { LOG_WARN("fail to process input geometry", K(ret)); - } else if (!is_null_res) { + } + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; + if (OB_SUCC(ret) && !is_null_res) { ObGeometry *geo1 = nullptr; ObGeometry *geo2 = nullptr; bool is_3d_geo1 = ObGeoTypeUtil::is_3d_geo_type(geo1_3d->type()); @@ -174,8 +178,13 @@ int ObExprSTUnion::eval_st_union(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re geo2 = geo2_3d; } if (OB_FAIL(ret)) { + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { - ObGeoEvalCtx gis_context(&temp_allocator, srs); + ObGeoEvalCtx gis_context(*mem_ctx, srs); if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL( @@ -194,55 +203,22 @@ int ObExprSTUnion::eval_st_union(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re LOG_WARN("fail to create 3D empty collection", K(ret)); } } else { - if ((!is_3d_geo1)) { - if (geo1->crs() == ObGeoCRS::Cartesian) { - if (OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo( - union_res, temp_allocator, srs))) { - // should not do simplify in symdifference functor, it may affect - // ObGeoFuncUtils::ob_geo_gc_union - LOG_WARN("fail to remove_duplicate_multi_geo", K(ret)); - } else if (OB_FAIL(ObGeoFuncUtils::simplify_geo_collection( - union_res, temp_allocator, srs))) { - LOG_WARN("fail to simplify_geo_collection", K(ret)); - } - } else if (geo1->crs() == ObGeoCRS::Geographic) { - if (OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo( - union_res, temp_allocator, srs))) { - // should not do simplify in symdifference functor, it may affect - // ObGeoFuncUtils::ob_geo_gc_union - LOG_WARN("fail to remove_duplicate_multi_geo", K(ret)); - } else if (OB_FAIL(ObGeoFuncUtils::simplify_geo_collection( - union_res, temp_allocator, srs))) { - LOG_WARN("fail to simplify_geo_collection", K(ret)); - } - } - } else { - // 3D - if (geo1->crs() == ObGeoCRS::Cartesian - && OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo( - union_res, temp_allocator, srs))) { - // should not do simplify in symdifference functor, it may affect - // ObGeoFuncUtils::ob_geo_gc_union - LOG_WARN("fail to simplify result", K(ret)); - } else if (geo1->crs() == ObGeoCRS::Geographic - && OB_FAIL(ObGeoFuncUtils::remove_duplicate_multi_geo( - union_res, temp_allocator, srs))) { - // should not do simplify in symdifference functor, it may affect - // ObGeoFuncUtils::ob_geo_gc_union - LOG_WARN("fail to simplify result", K(ret)); - } else { - // populate Z coordinates - ObGeoElevationVisitor visitor(temp_allocator, srs); - ObGeometry *union_res_bin = nullptr; - if (OB_FAIL(visitor.init(*geo1_3d, *geo2_3d))) { - LOG_WARN("fail to init elevation visitor", K(ret)); - } else if (OB_FAIL(ObGeoTypeUtil::tree_to_bin(temp_allocator, union_res, union_res_bin, srs))) { - LOG_WARN("fail to do tree to bin", K(ret)); - } else if (OB_FAIL(union_res_bin->do_visit(visitor))) { - LOG_WARN("fail to do elevation visitor", K(ret)); - } else if (OB_FAIL(visitor.get_geometry_3D(union_res))) { - LOG_WARN("failed get geometry 3D", K(ret)); - } + if (OB_FAIL(ObGeoTypeUtil::remove_duplicate_geo(union_res, *mem_ctx, srs))) { + // should not do simplify in symdifference functor, it may affect + // ObGeoFuncUtils::ob_geo_gc_union + LOG_WARN("fail to simplify result", K(ret)); + } else if (is_3d_geo1) { + // populate Z coordinates + ObGeoElevationVisitor visitor(*mem_ctx, srs); + ObGeometry *union_res_bin = nullptr; + if (OB_FAIL(visitor.init(*geo1_3d, *geo2_3d))) { + LOG_WARN("fail to init elevation visitor", K(ret)); + } else if (OB_FAIL(ObGeoTypeUtil::tree_to_bin(temp_allocator, union_res, union_res_bin, srs))) { + LOG_WARN("fail to do tree to bin", K(ret)); + } else if (OB_FAIL(union_res_bin->do_visit(visitor))) { + LOG_WARN("fail to do elevation visitor", K(ret)); + } else if (OB_FAIL(visitor.get_geometry_3D(union_res))) { + LOG_WARN("failed get geometry 3D", K(ret)); } } } @@ -259,6 +235,9 @@ int ObExprSTUnion::eval_st_union(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &re res.set_string(res_wkb); } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_union.h b/src/sql/engine/expr/ob_expr_st_union.h index eca5e069a..d2342cbcb 100644 --- a/src/sql/engine/expr/ob_expr_st_union.h +++ b/src/sql/engine/expr/ob_expr_st_union.h @@ -17,6 +17,8 @@ #include "sql/engine/expr/ob_expr_operator.h" #include "lib/geo/ob_geo_utils.h" #include "observer/omt/ob_tenant_srs.h" +#include "sql/engine/expr/ob_geo_expr_utils.h" + namespace oceanbase { @@ -34,7 +36,7 @@ public: ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator &allocator, + static int process_input_geometry(omt::ObSrsCacheGuard &srs_guard, const ObExpr &expr, ObEvalCtx &ctx, MultimodeAlloctor &allocator, ObGeometry *&geo1, ObGeometry *&geo2, bool &is_null_res, const ObSrsItem *&srs); DISALLOW_COPY_AND_ASSIGN(ObExprSTUnion); }; diff --git a/src/sql/engine/expr/ob_expr_st_within.cpp b/src/sql/engine/expr/ob_expr_st_within.cpp index dcdd1e085..def2216b1 100644 --- a/src/sql/engine/expr/ob_expr_st_within.cpp +++ b/src/sql/engine/expr/ob_expr_st_within.cpp @@ -70,8 +70,9 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & ObExpr *gis_arg1 = expr.args_[0]; ObExpr *gis_arg2 = expr.args_[1]; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); - if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) { + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, N_ST_WITHIN); + if (OB_FAIL(temp_allocator.eval_arg(gis_arg1, ctx, gis_datum1)) || OB_FAIL(temp_allocator.eval_arg(gis_arg2, ctx, gis_datum2))) { LOG_WARN("eval geo args failed", K(ret)); } else if (gis_datum1->is_null() || gis_datum2->is_null()) { res.set_null(); @@ -92,6 +93,8 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & bool is_geo1_cached = false; bool is_geo2_cached = false; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); + ObGeoBoostAllocGuard guard(tenant_id); + lib::MemoryContext *mem_ctx = nullptr; if (gis_arg1->is_static_const_) { ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo1, srid1, is_geo1_cached, 0); @@ -119,13 +122,19 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & LOG_WARN("get first geo by wkb failed", K(ret)); } else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_WITHIN, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) { LOG_WARN("get second geo by wkb failed", K(ret)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(geo1->length() + geo2->length()))) { } else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))) || (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) { LOG_WARN("check geo empty failed", K(ret)); } else if (is_geo1_empty || is_geo2_empty) { res.set_null(); - } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) { + } else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(srs, *geo1, *geo2, is_geo1_cached, is_geo2_cached))) { LOG_WARN("zoom in geos failed", K(ret)); + } else if (OB_FAIL(guard.init())) { + LOG_WARN("fail to init geo allocator guard", K(ret)); + } else if (OB_ISNULL(mem_ctx = guard.get_memory_ctx())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("fail to get mem ctx", K(ret)); } else { if (OB_NOT_NULL(const_param_cache)) { if (gis_arg1->is_static_const_ && !is_geo1_cached && @@ -137,55 +146,56 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum & } } + ObGeoEvalCtx gis_context(*mem_ctx); + bool result = false; if (OB_FAIL(ret)) { + } else if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { + LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); } else { - ObGeoEvalCtx gis_context(&temp_allocator); - bool result = false; - if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) { - LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); - } else { - ObCachedGeom *cache_geo = NULL; - ObGeometry *geo; - if (OB_NOT_NULL(const_param_cache)) { - if (gis_arg2->is_static_const_) { - cache_geo = const_param_cache->get_cached_geo(1); - if (cache_geo == NULL - && OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(), - temp_allocator, - const_param_cache->get_const_param_cache(1), - srs, - cache_geo))) { - LOG_WARN("add geo2 to const cache failed", K(ret)); - } else { - geo = geo1; - const_param_cache->add_cached_geo(1, cache_geo); - } + ObCachedGeom *cache_geo = NULL; + ObGeometry *geo; + if (OB_NOT_NULL(const_param_cache)) { + if (gis_arg2->is_static_const_) { + cache_geo = const_param_cache->get_cached_geo(1); + if (cache_geo == NULL + && OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(), + temp_allocator, + const_param_cache->get_const_param_cache(1), + srs, + cache_geo))) { + LOG_WARN("add geo2 to const cache failed", K(ret)); + } else { + geo = geo1; + const_param_cache->add_cached_geo(1, cache_geo); } } + } - if (OB_FAIL(ret)) { - } else if (OB_NOT_NULL(cache_geo)) { - if (OB_FAIL(cache_geo->contains(*geo, gis_context, result))) { - LOG_WARN("get contains result failed", K(ret)); - } else { - res.set_bool(result); - } - } else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_WITHIN)) { - bool result = false; - if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_WITHIN, result))) { - LOG_WARN("fail to get res.", K(ret)); - } else { - res.set_bool(result); - } - } else if (OB_FAIL(ObGeoFunc::gis_func::eval(gis_context, result))) { - LOG_WARN("eval st intersection failed", K(ret)); - ObGeoExprUtils::geo_func_error_handle(ret, N_ST_WITHIN); + if (OB_FAIL(ret)) { + } else if (OB_NOT_NULL(cache_geo)) { + if (OB_FAIL(cache_geo->contains(*geo, gis_context, result))) { + LOG_WARN("get contains result failed", K(ret)); } else { res.set_bool(result); } + } else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_WITHIN)) { + bool result = false; + if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_WITHIN, result))) { + LOG_WARN("fail to get res.", K(ret)); + } else { + res.set_bool(result); + } + } else if (OB_FAIL(ObGeoFunc::gis_func::eval(gis_context, result))) { + LOG_WARN("eval st intersection failed", K(ret)); + ObGeoExprUtils::geo_func_error_handle(ret, N_ST_WITHIN); + } else { + res.set_bool(result); } } } + if (mem_ctx != nullptr) { + temp_allocator.add_ext_used((*mem_ctx)->arena_used()); + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_st_x.cpp b/src/sql/engine/expr/ob_expr_st_x.cpp index 1018fa482..7f44f7335 100644 --- a/src/sql/engine/expr/ob_expr_st_x.cpp +++ b/src/sql/engine/expr/ob_expr_st_x.cpp @@ -77,7 +77,8 @@ int ObExprSTCoordinate::eval_common(const ObExpr &expr, int num_args = expr.arg_cnt_; ObDatum *datum = NULL; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret, func_name); ObIWkbPoint *point = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; @@ -90,19 +91,20 @@ int ObExprSTCoordinate::eval_common(const ObExpr &expr, ObObjType datum_type = ObMaxType; // get wkb - if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[0], ctx, datum))) { LOG_WARN("failed to eval first argument", K(ret)); } else if (datum->is_null()) { is_null_result = true; } else { ObString wkb = datum->get_string(); - if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *datum, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(temp_allocator, *datum, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(temp_allocator.set_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, func_name))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb, - geo, srs, func_name, ObGeoBuildFlag::GEO_CORRECT | ObGeoBuildFlag::GEO_CHECK_RANGE))) { + geo, srs, func_name, ObGeoBuildFlag::GEO_CORRECT | ObGeoBuildFlag::GEO_CHECK_RANGE | GEO_NOT_COPY_WKB))) { LOG_WARN("failed to create geometry object with raw wkb", K(ret)); } else if (ObGeoType::POINT != geo->type()) { ret = OB_ERR_UNEXPECTED_GEOMETRY_TYPE; @@ -135,7 +137,7 @@ int ObExprSTCoordinate::eval_common(const ObExpr &expr, double d = is_long_res ? point->x() : point->y(); res.set_double(d); } else if (num_args == 2) { - if (OB_FAIL(expr.args_[1]->eval(ctx, datum))) { + if (OB_FAIL(temp_allocator.eval_arg(expr.args_[1], ctx, datum))) { LOG_WARN("failed to eval", K(ret)); } else if (datum->is_null()) { res.set_null(); diff --git a/src/sql/engine/expr/ob_expr_sys_makexml.cpp b/src/sql/engine/expr/ob_expr_sys_makexml.cpp index 9ae323e23..1e24e546c 100644 --- a/src/sql/engine/expr/ob_expr_sys_makexml.cpp +++ b/src/sql/engine/expr/ob_expr_sys_makexml.cpp @@ -93,7 +93,8 @@ int ObExprSysMakeXML::eval_sys_makexml(const ObExpr &expr, ObEvalCtx &ctx, ObDat bool is_null_result = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObString full_xml_data; ObMulModeMemCtx* mem_ctx = nullptr; lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), "XMLModule")); @@ -106,7 +107,7 @@ int ObExprSysMakeXML::eval_sys_makexml(const ObExpr &expr, ObEvalCtx &ctx, ObDat && xml_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("input type error", K(xml_arg->datum_meta_)); - } else if (OB_FAIL(xml_arg->eval(ctx, xml_datum))) { + } else if (OB_FAIL(allocator.eval_arg(xml_arg, ctx, xml_datum))) { LOG_WARN("eval xml arg failed", K(ret)); } else if (xml_datum->is_null()) { res.set_null(); @@ -119,6 +120,7 @@ int ObExprSysMakeXML::eval_sys_makexml(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_WARN("get xml plain text failed", K(ret), K(xml_datum)); } else if (xml_plain_text.empty()) { res.set_null(); + } else if (OB_FALSE_IT(allocator.add_baseline_size(xml_plain_text.length()))) { } else if (OB_FAIL(ObXmlParserUtils::parse_document_text(mem_ctx, xml_plain_text, xml_doc))) { LOG_WARN("parse xml plain text as document failed.", K(ret), K(xml_plain_text)); ret = OB_ERR_XML_PARSE; diff --git a/src/sql/engine/expr/ob_expr_tokenize.cpp b/src/sql/engine/expr/ob_expr_tokenize.cpp index ed35f1c34..a8e53a13c 100644 --- a/src/sql/engine/expr/ob_expr_tokenize.cpp +++ b/src/sql/engine/expr/ob_expr_tokenize.cpp @@ -202,6 +202,9 @@ int ObExprTokenize::parse_param(const ObExpr &expr, ObDatum *fulltext_datum; ObDatum *parser_datum; ObDatum *parser_params_datum; + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor temp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); if (OB_UNLIKELY(expr.arg_cnt_ < 1 || expr.arg_cnt_ > 3)) { ret = OB_INVALID_ARGUMENT; @@ -235,7 +238,7 @@ int ObExprTokenize::parse_param(const ObExpr &expr, if (OB_SUCC(ret) && expr.arg_cnt_ >= 3) { ObIJsonBase *base = nullptr; bool is_null = false; - if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, allocator, 2, base, is_null))) { + if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 2, base, is_null))) { LOG_WARN("Fail to get json doc", K(ret)); } else { if (ObJsonNodeType::J_ARRAY != base->json_type()) { diff --git a/src/sql/engine/expr/ob_expr_update_xml.cpp b/src/sql/engine/expr/ob_expr_update_xml.cpp index a990134da..713ac9d32 100644 --- a/src/sql/engine/expr/ob_expr_update_xml.cpp +++ b/src/sql/engine/expr/ob_expr_update_xml.cpp @@ -130,7 +130,9 @@ int ObExprUpdateXml::eval_mysql_update_xml(const ObExpr &expr, ObEvalCtx &ctx, O { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); int64_t num_child = expr.arg_cnt_; ObString xml_target; ObString xpath_expr; @@ -142,7 +144,6 @@ int ObExprUpdateXml::eval_mysql_update_xml(const ObExpr &expr, ObEvalCtx &ctx, O ObUpdateXMLRetType res_origin = ObUpdateXMLRetType::ObRetMax; ObMulModeMemCtx* xml_mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), "XMLModule")); if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&allocator, xml_mem_ctx))) { LOG_WARN("fail to create tree memory context", K(ret)); } else if (num_child != 3) { @@ -159,10 +160,12 @@ int ObExprUpdateXml::eval_mysql_update_xml(const ObExpr &expr, ObEvalCtx &ctx, O LOG_WARN("failed to get xml_target str from expr", K(ret)); } else if (xml_target.empty()) { // do nothing + } else if (OB_FALSE_IT(allocator.add_baseline_size(xml_target.length()))) { } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[1], ctx, xpath_expr, allocator))) { LOG_WARN("failed to get xpath expr.", K(ret)); } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[2], ctx, new_xml, allocator))) { LOG_WARN("failed to get new xml.", K(ret)); + } else if (OB_FALSE_IT(allocator.add_baseline_size(new_xml.length()))) { } else if (OB_FAIL(ObMulModeFactory::get_xml_base(xml_mem_ctx, xml_target, ObNodeMemType::TREE_TYPE, ObNodeMemType::TREE_TYPE, xml_base, M_DOCUMENT))) { ret = OB_SUCCESS; if (OB_FAIL(ObMulModeFactory::get_xml_base(xml_mem_ctx, xml_target, ObNodeMemType::TREE_TYPE, ObNodeMemType::TREE_TYPE, xml_base, M_CONTENT))) { @@ -213,7 +216,8 @@ int ObExprUpdateXml::eval_update_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObDatum *xml_datum = NULL; ObString namespace_str; ObIMulModeBase *xml_tree = NULL; @@ -225,7 +229,7 @@ int ObExprUpdateXml::eval_update_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum ObMulModeMemCtx* xml_mem_ctx = nullptr; bool input_is_doc = false; ObMulModeNodeType node_type = M_MAX_TYPE; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -235,7 +239,7 @@ int ObExprUpdateXml::eval_update_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum } else if (num_child < 3) { ret = OB_ERR_PARAM_SIZE; LOG_WARN("invalid param number", K(ret), K(num_child)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum, allocator))) { LOG_WARN("fail to get xmltype", K(ret)); } else if (FALSE_IT(has_namespace_str = ((num_child - 1) % 2 != 0))) { } else if (has_namespace_str) { @@ -484,6 +488,7 @@ int ObExprUpdateXml::update_xml_tree(ObMulModeMemCtx* xml_mem_ctx, int ret = OB_SUCCESS; ObPathExprIter xpath_iter((static_cast(xml_tree))->get_mem_ctx()->allocator_); ObIMulModeBase *node = NULL; + ObXmlUpdateNodeInfoArray *update_array = nullptr; if (OB_FAIL(xpath_iter.init((static_cast(xml_tree))->get_mem_ctx(), xpath_str, default_ns, xml_tree, prefix_ns))) { LOG_WARN("fail to init xpath iterator", K(xpath_str), K(default_ns), K(ret)); ObXMLExprHelper::replace_xpath_ret_code(ret); @@ -507,12 +512,22 @@ int ObExprUpdateXml::update_xml_tree(ObMulModeMemCtx* xml_mem_ctx, ret = OB_SUCCESS; } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObXMLExprHelper::mem_ctx_add_baseline(expr, ctx, xml_mem_ctx, res_array.size()))) { + LOG_WARN("failed to add baseline.", K(ret)); + } else if (OB_ISNULL(update_array = static_cast(xml_mem_ctx->allocator_->alloc(sizeof(ObXmlUpdateNodeInfoArray))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc array.", K(ret)); + } else { // todo + memset(update_array, 0, sizeof(ObXmlUpdateNodeInfoArray)); + } + for (int i = 0; i < res_array.size() && OB_SUCC(ret); ++i) { ObIMulModeBase* update_node = res_array[i]; if (OB_ISNULL(update_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("xpath result node is null", K(ret)); - } else if (OB_FAIL(update_xml_node(xml_mem_ctx, expr, ctx, update_node))) { + } else if (OB_FAIL(update_xml_node(xml_mem_ctx, expr, ctx, *update_array, update_node))) { LOG_WARN("fail to update xml node", K(ret), K(node)); } } @@ -528,6 +543,7 @@ int ObExprUpdateXml::update_xml_tree(ObMulModeMemCtx* xml_mem_ctx, int ObExprUpdateXml::update_xml_node(ObMulModeMemCtx* xml_mem_ctx, const ObExpr *expr, ObEvalCtx &ctx, + ObXmlUpdateNodeInfoArray &update_array, ObIMulModeBase *node) { int ret = OB_SUCCESS; @@ -564,38 +580,38 @@ int ObExprUpdateXml::update_xml_node(ObMulModeMemCtx* xml_mem_ctx, if (!is_empty_content) { switch (xml_node->type()) { case M_TEXT: { - if (OB_FAIL(update_text_or_attribute_node(xml_mem_ctx, xml_node, expr, ctx, true))) { + if (OB_FAIL(update_text_or_attribute_node(xml_mem_ctx, xml_node, expr, ctx, true, update_array[ObUpdateTextType]))) { LOG_WARN("fail to update text node", K(ret), K(xml_type)); } break; } case M_ATTRIBUTE: { - if (OB_FAIL(update_text_or_attribute_node(xml_mem_ctx, xml_node, expr, ctx, false))) { + if (OB_FAIL(update_text_or_attribute_node(xml_mem_ctx, xml_node, expr, ctx, false, update_array[ObUpdateAttributeType]))) { LOG_WARN("fail to update attribute node", K(ret)); } break; } case M_NAMESPACE: { - if (OB_FAIL(update_namespace_node(xml_mem_ctx, xml_node, expr, ctx))) { + if (OB_FAIL(update_namespace_node(xml_mem_ctx, xml_node, expr, ctx, update_array[ObUpdateNamespaceType]))) { LOG_WARN("fail to update namespace node", K(ret)); } break; } case M_COMMENT: case M_CDATA: { - if (OB_FAIL(update_cdata_and_comment_node(xml_mem_ctx, xml_node, expr, ctx))) { + if (OB_FAIL(update_cdata_and_comment_node(xml_mem_ctx, xml_node, expr, ctx, update_array[ObUpdateCdateCommentType]))) { LOG_WARN("fail to update cdata node", K(ret), K(xml_type)); } break; } case M_ELEMENT: { - if (OB_FAIL(update_element_node(xml_mem_ctx, xml_node, expr, ctx))) { + if (OB_FAIL(update_element_node(xml_mem_ctx, xml_node, expr, ctx, update_array[ObUpdateElementType]))) { LOG_WARN("fail to update element node", K(ret), K(xml_type)); } break; } case M_INSTRUCT: { - if (OB_FAIL(update_pi_node(xml_mem_ctx, xml_node, expr, ctx))) { + if (OB_FAIL(update_pi_node(xml_mem_ctx, xml_node, expr, ctx, update_array[ObUpdateInstructType]))) { LOG_WARN("fail to pi node", K(ret), K(xml_type)); } break; @@ -613,51 +629,53 @@ int ObExprUpdateXml::update_xml_node(ObMulModeMemCtx* xml_mem_ctx, int ObExprUpdateXml::update_pi_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, - ObEvalCtx &ctx) + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) { int ret = OB_SUCCESS; ObObjType val_type = expr->datum_meta_.type_; uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); - ObDatum *datum = NULL; - if (OB_FAIL(expr->eval(ctx, datum))) { - LOG_WARN("fail to eval datum", K(ret)); - } else { - if (val_type == ObNullType) { - ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; - LOG_WARN("XML nodes must be updated with valid nodes and of the same type", K(ret)); - } else if (ob_is_string_type(val_type)) { - ObXmlDocument *xml_doc = NULL; - ObString value_str; - if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { - LOG_WARN("fail to get value str", K(ret), K(value_str)); - } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, value_str, xml_doc))) { + ObXmlNode *clone_node = nullptr; + if (val_type == ObNullType) { + ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; + LOG_WARN("XML nodes must be updated with valid nodes and of the same type", K(ret)); + } else if (ob_is_string_type(val_type)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_parse_str_info(xml_mem_ctx, expr, ctx, update_info))) { if (ret == OB_ERR_PARSER_SYNTAX) { ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; } LOG_WARN("fail to parse xml str", K(ret)); - } else if (xml_doc->size() > 0 && xml_doc->at(0)->type() == M_INSTRUCT) { - if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, xml_doc))) { - LOG_WARN("fail to update pi node with content node", K(ret)); - } - } else { - ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; - LOG_WARN("update pi node with invalid node", K(ret), K(value_str)); } - } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { - ObIMulModeBase *update_node = NULL; - ObXmlNode *update_xml_node = NULL; - ObCollationType cs_type = CS_TYPE_INVALID; - if (OB_FAIL(ObXMLExprHelper::get_xml_base(xml_mem_ctx, datum, cs_type, ObNodeMemType::TREE_TYPE, update_node))) { - LOG_WARN("fail to get update xml node", K(ret)); - } else if (OB_ISNULL(update_xml_node = static_cast(update_node))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("update node is NULL", K(ret)); - } else if (update_xml_node->size() == 0) { - ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; - LOG_WARN("update pi node with invalid node", K(ret)); - } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, update_xml_node))) { - LOG_WARN("fail to update xml content node ", K(ret)); + } + if (OB_FAIL(ret)) { + } else if (update_info->update_node->size() > 0 && update_info->update_node->at(0)->type() == M_INSTRUCT) { + if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone node.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update pi node with content node", K(ret)); } + } else { + ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; + LOG_WARN("update pi node with invalid node", K(ret), K(update_info->update_str)); + } + } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_xml_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to update xml info.", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(update_info->update_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("update node is NULL", K(ret)); + } else if (update_info->update_node->size() == 0) { + ret = OB_ERR_UPDATE_XML_WITH_INVALID_NODE; + LOG_WARN("update pi node with invalid node", K(ret)); + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml content node ", K(ret)); } } return ret; @@ -667,57 +685,67 @@ int ObExprUpdateXml::update_text_or_attribute_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx, - bool is_text) + bool is_text, + ObXmlUpdateNodeInfo *&update_info) { int ret = OB_SUCCESS; ObObjType val_type = expr->datum_meta_.type_; ObCollationType cs_type = expr->datum_meta_.cs_type_; uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); - ObDatum *datum = NULL; - if (OB_FAIL(expr->eval(ctx, datum))) { - LOG_WARN("fail to eval datum", K(ret)); - } else { - if (val_type == ObNullType) { - xml_node->set_value(ObString::make_empty_string()); - } else if (is_text && ob_is_clob(val_type, cs_type)) { - ObXmlDocument *xml_doc = NULL; - ObString value_str; - if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { - LOG_WARN("fail to get value str", K(ret), K(value_str)); - } else if (value_str.empty()) { + ObXmlNode *clone_node = nullptr; + if (val_type == ObNullType) { + xml_node->set_value(ObString::make_empty_string()); + } else if (is_text && ob_is_clob(val_type, cs_type)) { + if (OB_ISNULL(update_info)) { + ObXmlDocument *xml_doc = nullptr; + if (OB_FAIL(get_update_str_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("fail to get str info", K(ret)); + } else if (update_info->update_str.empty()) { ret = OB_LOB_VALUE_NOT_EXIST; - LOG_WARN("LOB value is empty", K(ret), K(value_str)); - } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, value_str, xml_doc))) { + LOG_WARN("LOB value is empty", K(ret), K(update_info->update_str)); + } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, update_info->update_str, xml_doc))) { if (ret == OB_ERR_PARSER_SYNTAX) { ret = OB_ERR_XML_PARSE; } LOG_WARN("fail to parse xml str", K(ret)); - } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, xml_doc))) { - LOG_WARN("fail to update xml element node", K(ret)); - } - } else if (ob_is_string_type(val_type)) { - ObStringBuffer buff(xml_mem_ctx->allocator_); - ObString value_str; - if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { - LOG_WARN("fail to get value str", K(ret)); - } else { - xml_node->set_value(value_str); - } - } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { - ObIMulModeBase *update_node = NULL; - ObXmlNode *update_xml_node = NULL; - ObCollationType cs_type = CS_TYPE_INVALID; - if (OB_FAIL(ObXMLExprHelper::get_xml_base(xml_mem_ctx, datum, cs_type, ObNodeMemType::TREE_TYPE, update_node))) { - LOG_WARN("fail to get update xml node", K(ret)); - } else if (OB_ISNULL(update_xml_node = static_cast(update_node))) { + } else if (OB_ISNULL(update_info->update_node = static_cast(xml_doc))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("update node is NULL", K(ret)); - } else if (is_text && OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, update_xml_node))) { - LOG_WARN("fail to update xml node ", K(ret)); - } else if (!is_text && OB_FAIL(update_attribute_xml_node(xml_node, update_xml_node))) { - LOG_WARN("fail to update xml node ", K(ret)); + LOG_WARN("failed to cast to xml node.", K(ret)); } } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone node.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml element node", K(ret)); + } + } else if (ob_is_string_type(val_type)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_str_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to get update info.", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else { + xml_node->set_value(update_info->update_str); + } + } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_xml_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to update xml info.", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(update_info->update_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("update node is NULL", K(ret)); + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone.", K(ret)); + } else if (is_text && OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml node ", K(ret)); + } else if (!is_text && OB_FAIL(update_attribute_xml_node(xml_node, clone_node))) { + LOG_WARN("fail to update xml node ", K(ret)); + } } return ret; } @@ -725,39 +753,42 @@ int ObExprUpdateXml::update_text_or_attribute_node(ObMulModeMemCtx* xml_mem_ctx, int ObExprUpdateXml::update_namespace_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, - ObEvalCtx &ctx) + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) { int ret = OB_SUCCESS; ObObjType val_type = expr->datum_meta_.type_; uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); ObDatum *datum = NULL; - if (OB_FAIL(expr->eval(ctx, datum))) { - LOG_WARN("fail to eval datum", K(ret)); - } else { - if (val_type == ObNullType) { - ret = OB_ERR_XML_PARSE; - LOG_WARN("update namespace node value to be NULL is unsupported", K(ret)); - } else if (ob_is_string_type(val_type)) { - ObStringBuffer buff(xml_mem_ctx->allocator_); - ObString value_str; - if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { - LOG_WARN("fail to get value str", K(ret)); - } else if (OB_FAIL(update_namespace_value(*xml_mem_ctx->allocator_, xml_node, value_str))) { - LOG_WARN("fail to update namespace node value", K(ret), K(value_str)); + ObXmlNode *clone_node = nullptr; + if (val_type == ObNullType) { + ret = OB_ERR_XML_PARSE; + LOG_WARN("update namespace node value to be NULL is unsupported", K(ret)); + } else if (ob_is_string_type(val_type)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_str_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to get update info.", K(ret)); } - } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { - ObIMulModeBase *update_node = NULL; - ObXmlNode *update_xml_node = NULL; - ObCollationType cs_type = CS_TYPE_INVALID; - if (OB_FAIL(ObXMLExprHelper::get_xml_base(xml_mem_ctx, datum, cs_type, ObNodeMemType::TREE_TYPE, update_node))) { - LOG_WARN("fail to get update xml node", K(ret)); - } else if (OB_ISNULL(update_xml_node = static_cast(update_node))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("update node is NULL", K(ret)); - } else if (OB_FAIL(update_namespace_xml_node(*xml_mem_ctx->allocator_, xml_node, update_xml_node))) { - LOG_WARN("fail to update xml node ", K(ret)); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(update_namespace_value(*xml_mem_ctx->allocator_, xml_node, update_info->update_str))) { + LOG_WARN("fail to update namespace node value", K(ret), K(update_info->update_str)); + } + } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_xml_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to update xml info.", K(ret)); } } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(update_info->update_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("update node is NULL", K(ret)); + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone.", K(ret)); + } else if (OB_FAIL(update_namespace_xml_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml node ", K(ret)); + } } return ret; } @@ -765,55 +796,65 @@ int ObExprUpdateXml::update_namespace_node(ObMulModeMemCtx* xml_mem_ctx, int ObExprUpdateXml::update_element_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, - ObEvalCtx &ctx) + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) { int ret = OB_SUCCESS; ObObjType val_type = expr->datum_meta_.type_; uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); - ObDatum *datum = NULL; - if (OB_FAIL(expr->eval(ctx, datum))) { - LOG_WARN("fail to eval datum", K(ret)); - } else { - ObXmlElement *ele = static_cast(xml_node); - if (val_type == ObNullType) { - ObMulModeNodeType node_type = ele->type(); - if (OB_FAIL(clear_element_child_node(ele))) { - LOG_WARN("fail to clear child node", K(ret)); - } - } else if (ob_is_string_type(val_type)) { - ObXmlDocument *xml_doc = NULL; - ObString value_str; - if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { - LOG_WARN("fail to get value str", K(ret), K(value_str)); - } else if (value_str.trim().empty()) { - if (OB_FAIL(clear_element_child_node(ele))) { - LOG_WARN("fail to clear child node", K(ret)); - } - } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, value_str, xml_doc))) { + ObXmlElement *ele = static_cast(xml_node); + ObXmlNode *clone_node = nullptr; + if (val_type == ObNullType) { + ObMulModeNodeType node_type = ele->type(); + if (OB_FAIL(clear_element_child_node(ele))) { + LOG_WARN("fail to clear child node", K(ret)); + } + } else if (ob_is_string_type(val_type)) { + if (OB_ISNULL(update_info)) { + ObXmlDocument *xml_doc = nullptr; + if (OB_FAIL(get_update_str_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to get update info.", K(ret)); + } else if (update_info->update_str.trim().empty()) { + // do nothing + } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, update_info->update_str, xml_doc))) { if (ret == OB_ERR_PARSER_SYNTAX) { ret = OB_ERR_XML_PARSE; } LOG_WARN("fail to parse xml str", K(ret)); - } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, ele, xml_doc))) { - LOG_WARN("fail to update xml element node", K(ret)); - } - } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { - ObIMulModeBase *update_node = NULL; - ObXmlNode *update_xml_node = NULL; - ObCollationType cs_type = CS_TYPE_INVALID; - if (OB_FAIL(ObXMLExprHelper::get_xml_base(xml_mem_ctx, datum, cs_type, ObNodeMemType::TREE_TYPE, update_node))) { - LOG_WARN("fail to get update xml node", K(ret)); - } else if (OB_ISNULL(update_xml_node = static_cast(update_node))) { + } else if (OB_ISNULL(update_info->update_node = static_cast(xml_doc))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("update node is NULL", K(ret)); - } else if (update_xml_node->count() == 0) { - if (OB_FAIL(clear_element_child_node(ele))) { - LOG_WARN("fail to clear child node", K(ret)); - } - } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, update_xml_node))) { - LOG_WARN("fail to update xml node ", K(ret)); + LOG_WARN("failed to cast into xml node.", K(ret)); } } + if (OB_FAIL(ret)) { + } else if (update_info->update_str.trim().empty()) { + if (OB_FAIL(clear_element_child_node(ele))) { + LOG_WARN("fail to clear child node", K(ret)); + } + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone node.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, ele, clone_node))) { + LOG_WARN("fail to update xml element node", K(ret)); + } + } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_xml_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to update xml info.", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(update_info->update_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("update node is NULL", K(ret)); + } else if (update_info->update_node->count() == 0) { + if (OB_FAIL(clear_element_child_node(ele))) { + LOG_WARN("fail to clear child node", K(ret)); + } + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml node ", K(ret)); + } } return ret; } @@ -821,43 +862,125 @@ int ObExprUpdateXml::update_element_node(ObMulModeMemCtx* xml_mem_ctx, int ObExprUpdateXml::update_cdata_and_comment_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, - ObEvalCtx &ctx) + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) { int ret = OB_SUCCESS; ObObjType val_type = expr->datum_meta_.type_; uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); - ObDatum *datum = NULL; - if (OB_FAIL(expr->eval(ctx, datum))) { - LOG_WARN("fail to eval datum", K(ret)); - } else { - if (val_type == ObNullType) { - xml_node->set_value(ObString::make_empty_string()); - } else if (ob_is_string_type(val_type)) { - ObXmlDocument *xml_doc = NULL; - ObString value_str; - if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { - LOG_WARN("fail to get value str", K(ret), K(value_str)); - } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, value_str, xml_doc))) { + ObXmlNode *clone_node = nullptr; + if (val_type == ObNullType) { + xml_node->set_value(ObString::make_empty_string()); + } else if (ob_is_string_type(val_type)) { + if (OB_ISNULL(update_info)) { + ObXmlDocument *xml_doc = nullptr; + if (OB_FAIL(get_update_parse_str_info(xml_mem_ctx, expr, ctx, update_info))) { if (ret == OB_ERR_PARSER_SYNTAX) { ret = OB_ERR_XML_PARSE; } LOG_WARN("fail to parse xml str", K(ret)); - } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, xml_doc))) { - LOG_WARN("fail to update xml element node", K(ret)); } - } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { - ObIMulModeBase *update_node = NULL; - ObXmlNode *update_xml_node = NULL; - ObCollationType cs_type = CS_TYPE_INVALID; - if (OB_FAIL(ObXMLExprHelper::get_xml_base(xml_mem_ctx, datum, cs_type, ObNodeMemType::TREE_TYPE, update_node))) { - LOG_WARN("fail to get update xml node", K(ret)); - } else if (OB_ISNULL(update_xml_node = static_cast(update_node))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("update node is NULL", K(ret)); - } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, update_xml_node))) { - LOG_WARN("fail to update xml node ", K(ret)); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone node.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml element node", K(ret)); + } + } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { + if (OB_ISNULL(update_info)) { + if (OB_FAIL(get_update_xml_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to update xml info.", K(ret)); } } + if (OB_FAIL(ret)) { + LOG_WARN("fail to get update xml node", K(ret)); + } else if (OB_ISNULL(update_info->update_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("update node is NULL", K(ret)); + } else if (OB_FAIL(update_info->update_node->clone(xml_mem_ctx, clone_node))) { + LOG_WARN("failed to clone.", K(ret)); + } else if (OB_FAIL(update_xml_child_node(*xml_mem_ctx->allocator_, xml_node, clone_node))) { + LOG_WARN("fail to update xml node ", K(ret)); + } + } + return ret; +} + +int ObExprUpdateXml::get_update_str_info(ObMulModeMemCtx* xml_mem_ctx, + const ObExpr *expr, + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) +{ + INIT_SUCC(ret); + ObDatum *datum = nullptr; + ObString value_str; + ObObjType val_type = expr->datum_meta_.type_; + uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); + if (OB_ISNULL(update_info = static_cast(xml_mem_ctx->allocator_->alloc(sizeof(ObXmlUpdateNodeInfo))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc update node info failed", K(ret)); + } else if (OB_FAIL(expr->eval(ctx, datum))) { + LOG_WARN("fail to eval datum", K(ret), K(val_type)); + } else if (ob_is_string_type(val_type)) { + update_info->update_type = val_type; + if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr, ctx, value_str, *xml_mem_ctx->allocator_))) { + LOG_WARN("fail to get value str", K(ret)); + } else { + update_info->update_str = value_str; + } + } + return ret; +} + +int ObExprUpdateXml::get_update_parse_str_info(ObMulModeMemCtx* xml_mem_ctx, + const ObExpr *expr, + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) +{ + INIT_SUCC(ret); + ObXmlDocument *xml_doc = nullptr; + if (OB_FAIL(get_update_str_info(xml_mem_ctx, expr, ctx, update_info))) { + LOG_WARN("failed to get update str info.", K(ret)); + } else if (OB_FAIL(ObXmlParserUtils::parse_content_text(xml_mem_ctx, update_info->update_str, xml_doc))) { + LOG_WARN("failed to farse content text", K(ret)); + } else if (OB_ISNULL(update_info->update_node = static_cast(xml_doc))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to cast to xml node.", K(ret)); + } + + return ret; +} + +int ObExprUpdateXml::get_update_xml_info(ObMulModeMemCtx* xml_mem_ctx, + const ObExpr *expr, + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info) +{ + INIT_SUCC(ret); + ObDatum *datum = nullptr; + ObString value_str; + ObXmlDocument *xml_doc = NULL; + ObObjType val_type = expr->datum_meta_.type_; + uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); + if (OB_ISNULL(update_info = static_cast(xml_mem_ctx->allocator_->alloc(sizeof(ObXmlUpdateNodeInfo))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc update node info failed", K(ret)); + } else if (OB_FAIL(expr->eval(ctx, datum))) { + LOG_WARN("fail to eval datum", K(ret), K(val_type)); + } else if (ob_is_xml_sql_type(val_type, sub_schema_id)) { + ObIMulModeBase *update_node = NULL; + ObXmlNode *update_xml_node = NULL; + ObCollationType cs_type = CS_TYPE_INVALID; + update_info->update_type = ObUserDefinedSQLType; + if (OB_FAIL(ObXMLExprHelper::get_xml_base(xml_mem_ctx, datum, cs_type, ObNodeMemType::TREE_TYPE, update_node))) { + LOG_WARN("fail to get update xml node", K(ret)); + } else if (OB_ISNULL(update_xml_node = static_cast(update_node))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("update node is NULL", K(ret)); + } else { + update_info->update_node = update_xml_node; + } } return ret; } diff --git a/src/sql/engine/expr/ob_expr_update_xml.h b/src/sql/engine/expr/ob_expr_update_xml.h index 0ca3cadc6..c091d0c74 100644 --- a/src/sql/engine/expr/ob_expr_update_xml.h +++ b/src/sql/engine/expr/ob_expr_update_xml.h @@ -31,6 +31,26 @@ enum ObUpdateXMLRetType: uint32_t { ObRetMax }; +enum XmlUpdateNodeType +{ + ObUpdateTextType, + ObUpdateAttributeType, + ObUpdateNamespaceType, + ObUpdateCdateCommentType, + ObUpdateElementType, + ObUpdateInstructType, + ObUpdateMaxType = 8 +}; + +struct ObXmlUpdateNodeInfo +{ + ObObjType update_type; + ObString update_str; + ObXmlNode *update_node; +}; + +typedef ObXmlUpdateNodeInfo* ObXmlUpdateNodeInfoArray[ObUpdateMaxType]; + class ObExprUpdateXml : public ObFuncExprOperator { public: @@ -61,19 +81,20 @@ private: ObString &default_ns, ObPathVarObject *prefix_ns, ObIMulModeBase *xml_tree); - static int update_xml_node(ObMulModeMemCtx* xml_mem_ctx, const ObExpr *expr, ObEvalCtx &ctx, ObIMulModeBase *node); + static int update_xml_node(ObMulModeMemCtx* xml_mem_ctx, const ObExpr *expr, ObEvalCtx &ctx, ObXmlUpdateNodeInfoArray &update_info, ObIMulModeBase *node); // for text node and attribute static int update_text_or_attribute_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx, - bool is_text); + bool is_text, + ObXmlUpdateNodeInfo *&update_info); static int update_attribute_node(ObIAllocator &allocator, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx); static int update_attribute_xml_node(ObXmlNode *old_node, ObXmlNode *update_node); // for cdata and comment - static int update_cdata_and_comment_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx); + static int update_cdata_and_comment_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx, ObXmlUpdateNodeInfo *&update_info); // for namespace - static int update_namespace_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx); + static int update_namespace_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx, ObXmlUpdateNodeInfo *&update_info); static int update_namespace_xml_node(ObIAllocator &allocator, ObXmlNode *old_node, ObXmlNode *update_node); static int update_namespace_value(ObIAllocator &allocator, ObXmlNode *xml_node, const ObString &ns_value); static int get_valid_default_ns_from_parent(ObXmlNode *cur_node, ObXmlAttribute* &default_ns); @@ -81,12 +102,32 @@ private: static int update_new_nodes_ns(ObIAllocator &allocator, ObXmlNode *parent, ObXmlNode *update_node); static int update_exist_nodes_ns(ObXmlElement *parent, ObXmlAttribute *prefix_ns); // for element - static int update_element_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx); + static int update_element_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx, ObXmlUpdateNodeInfo *&update_info); static int clear_element_child_node(ObXmlElement *ele_node); static int update_xml_child_node(ObIAllocator &allocator, ObXmlNode *old_node, ObXmlNode *update_node); static int remove_and_insert_element_node(ObXmlElement *ele_node, ObXmlNode *update_node, int64_t pos, bool is_remove); // for pi node - static int update_pi_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx); + static int update_pi_node(ObMulModeMemCtx* xml_mem_ctx, ObXmlNode *xml_node, const ObExpr *expr, ObEvalCtx &ctx, ObXmlUpdateNodeInfo *&update_info); + static int pack_long_text_res(const ObExpr &expr, + ObEvalCtx &ctx, + ObDatum &res, + ObIAllocator &allocator, + ObString input_res); + + static int get_update_str_info(ObMulModeMemCtx* xml_mem_ctx, + const ObExpr *expr, + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info); + + static int get_update_xml_info(ObMulModeMemCtx* xml_mem_ctx, + const ObExpr *expr, + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info); + + static int get_update_parse_str_info(ObMulModeMemCtx* xml_mem_ctx, + const ObExpr *expr, + ObEvalCtx &ctx, + ObXmlUpdateNodeInfo *&update_info); private: DISALLOW_COPY_AND_ASSIGN(ObExprUpdateXml); }; diff --git a/src/sql/engine/expr/ob_expr_xml_attributes.cpp b/src/sql/engine/expr/ob_expr_xml_attributes.cpp index 4a7f8bc02..6d40e74b5 100644 --- a/src/sql/engine/expr/ob_expr_xml_attributes.cpp +++ b/src/sql/engine/expr/ob_expr_xml_attributes.cpp @@ -85,7 +85,9 @@ int ObExprXmlAttributes::eval_xml_attributes(const ObExpr &expr, ObEvalCtx &ctx, { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); int attributes_escape = 1; int has_schema_check = 0; ObDatum *datum = NULL; @@ -136,6 +138,7 @@ int ObExprXmlAttributes::eval_xml_attributes(const ObExpr &expr, ObEvalCtx &ctx, } else { uint64_t length = raw_bin.length(); char *buf = expr.get_str_res_mem(ctx, length); + OB_FALSE_IT(tmp_allocator.set_baseline_size(length)); if (OB_ISNULL(buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed: alloc memory for json array result", K(ret), K(length)); diff --git a/src/sql/engine/expr/ob_expr_xml_concat.cpp b/src/sql/engine/expr/ob_expr_xml_concat.cpp new file mode 100644 index 000000000..d99102e16 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_xml_concat.cpp @@ -0,0 +1,127 @@ +/** +* Copyright (c) 2021 OceanBase +* OceanBase CE is licensed under Mulan PubL v2. +* You can use this software according to the terms and conditions of the Mulan PubL v2. +* You may obtain a copy of Mulan PubL v2 at: +* http://license.coscl.org.cn/MulanPubL-2.0 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PubL v2 for more details. +* This file is for func xmlconcat. +*/ + +#define USING_LOG_PREFIX SQL_ENG +#include "ob_expr_xml_concat.h" +#include "sql/engine/ob_exec_context.h" +#include "lib/xml/ob_xml_util.h" +#include "sql/engine/expr/ob_expr_xml_func_helper.h" + +using namespace oceanbase::common; +using namespace oceanbase::sql; + +namespace oceanbase +{ +namespace sql +{ +ObExprXmlConcat::ObExprXmlConcat(ObIAllocator &alloc) + : ObFuncExprOperator( + alloc, + T_FUN_SYS_XML_CONCAT, + N_XML_CONCAT, + PARAM_NUM_UNKNOWN, + VALID_FOR_GENERATED_COL, + NOT_ROW_DIMENSION) +{ +} + +ObExprXmlConcat::~ObExprXmlConcat() +{ +} + +int ObExprXmlConcat::calc_result_typeN( + ObExprResType& type, + ObExprResType* types_stack, + int64_t param_num, + ObExprTypeCtx& type_ctx) const +{ + UNUSED(type_ctx); + INIT_SUCC(ret); + if (!is_called_in_sql()) { + ret = OB_ERR_SP_LILABEL_MISMATCH; + LOG_WARN("expr call in pl semantics disallowed", K(ret), K(N_XML_CONCAT)); + LOG_USER_ERROR(OB_ERR_SP_LILABEL_MISMATCH, static_cast(strlen(N_XML_CONCAT)), N_XML_CONCAT); + } else { + // The input paras should be n (n >= 0) XMLType obj. + for (int i = 0; OB_SUCC(ret) && i < param_num; i++) { + ObObjType in_type = types_stack[i].get_type(); + if (in_type != ObNullType) { + if (ob_is_xml_pl_type(types_stack[i].get_type(), types_stack[i].get_udt_id())) { + types_stack[i].get_calc_meta().set_sql_udt(ObXMLSqlType); + } + if (!ob_is_xml_sql_type(in_type, types_stack[i].get_subschema_id())) { + ret = OB_ERR_INVALID_XML_DATATYPE; + LOG_USER_ERROR(OB_ERR_INVALID_XML_DATATYPE, "-", "-"); + LOG_WARN("inconsistent datatypes", K(ret), K(ob_obj_type_str(in_type))); + } + } + } + } + if (OB_SUCC(ret)) { + type.set_sql_udt(ObXMLSqlType); + } + return ret; + +} + +int ObExprXmlConcat::eval_xml_concat(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) +{ + INIT_SUCC(ret); + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + ObStringBuffer res_xml_buf(&allocator); + ObMulModeMemCtx* mem_ctx = nullptr; + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&allocator, mem_ctx))) { + LOG_WARN("fail to create tree memory context", K(ret)); + } + ObDatumMeta xml_meta; + xml_meta.type_ = ObLongTextType; + xml_meta.cs_type_ = CS_TYPE_UTF8MB4_BIN; + ObVector xml_bin_str_vec; + ObString res_bin_str; + ObString blob_locator; + + // pack input nodes + for (int i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; i++) { + ObDatum *xml_datum = NULL; + ObString xml_bin_str; + + if (!ob_is_xml_sql_type(expr.args_[i]->datum_meta_.type_, expr.args_[i]->obj_meta_.get_subschema_id())) { + LOG_WARN("input is not xmltype, skip"); + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[i], ctx, xml_datum))) { + LOG_WARN("faild to get_xmltype_from_expr", K(ret), K(i), K(expr.args_[i])); + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, *xml_datum, xml_meta, true, xml_bin_str))) { + LOG_WARN("faild to read_real_string_data", K(ret), K(i), K(xml_datum)); + } else if (xml_bin_str.length() == 0) { + // input is empty, skip + } else if (OB_FAIL(xml_bin_str_vec.push_back(xml_bin_str))) { + LOG_WARN("failed to push back xml bin str", K(ret), K(xml_bin_str)); + } + } + + OZ(ObXMLExprHelper::concat_xml_type_nodes(mem_ctx, xml_bin_str_vec, res_bin_str)); + OZ(ObXMLExprHelper::pack_binary_res(expr, ctx, res_bin_str, blob_locator)); + OX(res.set_string(blob_locator.ptr(), blob_locator.length())); + return ret; +} + +int ObExprXmlConcat::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const +{ + UNUSED(expr_cg_ctx); + UNUSED(raw_expr); + rt_expr.eval_func_ = eval_xml_concat; + return OB_SUCCESS; +} +} //sql +} //oceanbase diff --git a/src/sql/engine/expr/ob_expr_xml_concat.h b/src/sql/engine/expr/ob_expr_xml_concat.h new file mode 100644 index 000000000..5c702278a --- /dev/null +++ b/src/sql/engine/expr/ob_expr_xml_concat.h @@ -0,0 +1,47 @@ +/** +* Copyright (c) 2021 OceanBase +* OceanBase CE is licensed under Mulan PubL v2. +* You can use this software according to the terms and conditions of the Mulan PubL v2. +* You may obtain a copy of Mulan PubL v2 at: +* http://license.coscl.org.cn/MulanPubL-2.0 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PubL v2 for more details. +* This file contains implementation for xmlconcat. +*/ + +#ifndef OCEANBASE_SQL_OB_EXPR_XML_CONCAT_H_ +#define OCEANBASE_SQL_OB_EXPR_XML_CONCAT_H_ + +#include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_expr_lob_utils.h" +#include "lib/container/ob_vector.h" +#include "lib/xml/ob_xml_util.h" +#include "lib/xml/ob_xpath.h" + +namespace oceanbase +{ +namespace sql +{ +class ObExprXmlConcat : public ObFuncExprOperator +{ +public: + explicit ObExprXmlConcat(common::ObIAllocator &alloc); + virtual ~ObExprXmlConcat(); + virtual int calc_result_typeN( + ObExprResType& type, + ObExprResType* types, + int64_t param_num, + common::ObExprTypeCtx& type_ctx) + const override; + + static int eval_xml_concat(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); + + virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; +private: + DISALLOW_COPY_AND_ASSIGN(ObExprXmlConcat); +}; +} // sql +} // oceanbase +#endif // OCEANBASE_SQL_OB_EXPR_XML_CONCAT_H_ diff --git a/src/sql/engine/expr/ob_expr_xml_delete_xml.cpp b/src/sql/engine/expr/ob_expr_xml_delete_xml.cpp index ea1a0a377..51689e226 100644 --- a/src/sql/engine/expr/ob_expr_xml_delete_xml.cpp +++ b/src/sql/engine/expr/ob_expr_xml_delete_xml.cpp @@ -87,7 +87,9 @@ int ObExprDeleteXml::eval_delete_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); ObDatum *xml_datum = NULL; ObIMulModeBase *xml_tree = NULL; ObXmlDocument *xml_doc = NULL; @@ -100,7 +102,6 @@ int ObExprDeleteXml::eval_delete_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum bool should_reparse = false; ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), "XMLModule")); if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&allocator, mem_ctx))) { LOG_WARN("fail to create tree memory context", K(ret)); } else if (OB_UNLIKELY(expr.arg_cnt_ != 3)) { @@ -109,7 +110,7 @@ int ObExprDeleteXml::eval_delete_xml(const ObExpr &expr, ObEvalCtx &ctx, ObDatum } else if (ObNullType == expr.args_[1]->datum_meta_.type_) { ret = OB_ERR_INVALID_XPATH_EXPRESSION; LOG_WARN("invalid xpath expression", K(ret)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum, allocator))) { LOG_WARN("fail to get xmltype value", K(ret)); } else if (OB_FAIL(ObXMLExprHelper::get_str_from_expr(expr.args_[1], ctx, xpath_str, allocator))) { LOG_WARN("fail to get xpath str", K(ret)); diff --git a/src/sql/engine/expr/ob_expr_xml_element.cpp b/src/sql/engine/expr/ob_expr_xml_element.cpp index a4ab7ce89..41bf3981b 100644 --- a/src/sql/engine/expr/ob_expr_xml_element.cpp +++ b/src/sql/engine/expr/ob_expr_xml_element.cpp @@ -16,6 +16,7 @@ #include "sql/engine/ob_exec_context.h" #include "lib/xml/ob_xml_util.h" #include "sql/engine/expr/ob_expr_xml_func_helper.h" +#include "sql/engine/ob_exec_context.h" using namespace oceanbase::common; using namespace oceanbase::sql; @@ -101,7 +102,9 @@ int ObExprXmlElement::eval_xml_element(const ObExpr &expr, ObEvalCtx &ctx, ObDat { INIT_SUCC(ret); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); ObDatum *datum = NULL; int num_args = expr.arg_cnt_; ObString name_tag; @@ -113,10 +116,8 @@ int ObExprXmlElement::eval_xml_element(const ObExpr &expr, ObEvalCtx &ctx, ObDat ObString binary_str; ObString blob_locator; bool has_attribute = false; - ObXmlElement *element = NULL; ObXmlDocument *res_doc = NULL; ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -137,7 +138,7 @@ int ObExprXmlElement::eval_xml_element(const ObExpr &expr, ObEvalCtx &ctx, ObDat } else if (need_escape == 0 && is_name == 0) { ret = OB_ERR_XML_MISSING_COMMA; LOG_WARN("xml element param invalid", K(ret)); - } else if (OB_FAIL(expr.args_[2]->eval(ctx, datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[2], ctx, datum))) { LOG_WARN("expr args 1 failed", K(ret), K(expr.args_[2])); } else if(expr.args_[2]->datum_meta_.type_ == ObNumberType) { ret = OB_ERR_INVALID_XML_DATATYPE; @@ -145,13 +146,17 @@ int ObExprXmlElement::eval_xml_element(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_WARN("Unsupport for string typee with binary charset input.", K(ret), K(expr.args_[2]->datum_meta_.type_)); } else if (OB_FAIL(ObTextStringHelper::get_string(expr, tmp_allocator, 2, datum, name_tag))) { LOG_WARN("get xml plain text failed", K(ret)); + } else if (OB_FALSE_IT(tmp_allocator.add_baseline_size(name_tag.length()))) { + LOG_WARN("failed to add base line size.", K(ret), K(name_tag)); } } for (int i = 3; OB_SUCC(ret) && i < num_args && OB_SUCC(ret); i++) { ObObjType val_type = expr.args_[i]->datum_meta_.type_; ObItemType item_type = expr.args_[i]->type_; - if (OB_FAIL(expr.args_[i]->eval(ctx, datum))) { + if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[i], ctx, datum))) { LOG_WARN("expr args failed", K(ret), K(i)); + } else if (OB_FAIL(tmp_allocator.add_baseline_size(datum, val_type == ObUserDefinedSQLType || expr.args_[i]->obj_meta_.has_lob_header()))) { + LOG_WARN("failed to add base line size.", K(ret)); } else if (ob_is_json(val_type) && i == 3) { // result from attribute has_attribute = true; void *buf = NULL; @@ -168,121 +173,20 @@ int ObExprXmlElement::eval_xml_element(const ObExpr &expr, ObEvalCtx &ctx, ObDat LOG_WARN("invalid json type", K(ret), K(attr_json->json_type())); } } - } else { // element value - ObString xml_value_data = datum->get_string(); - ObExpr *xml_arg = expr.args_[i]; - bool validity = false; - if (val_type == ObUserDefinedSQLType) { // xmltype - if (OB_FAIL(ObTextStringHelper::read_real_string_data(&tmp_allocator, - ObObjType::ObLongTextType, - ObCollationType::CS_TYPE_BINARY, - true, xml_value_data))) { - LOG_WARN("fail to get real data.", K(ret), K(xml_value_data)); - // } else if (OB_FAIL(ObXMLExprHelper::check_xml_document_unparsed(mem_ctx, xml_value_data, validity))) { - // LOG_WARN("check document unparsed failed", K(ret), K(xml_value_data)); - // } else if (!validity) { - // ret = OB_ERR_XML_PARSE; - // LOG_WARN("input a unparsed document and parsing failed", K(ret), K(i), K(xml_value_data)); - } else { - ObObj temp_value; - temp_value.set_string(ObUserDefinedSQLType, xml_value_data); - if (OB_FAIL(value_vec.push_back(temp_value))) { - LOG_WARN("failed to push back temp value.", K(ret), K(temp_value)); - } - } - } else if (OB_FAIL(ObTextStringHelper::read_real_string_data(tmp_allocator, *datum, - xml_arg->datum_meta_, - xml_arg->obj_meta_.has_lob_header(), - xml_value_data))) { - LOG_WARN("fail to get real data.", K(ret), K(xml_value_data)); - } else if (expr.args_[i]->datum_meta_.cs_type_ == CS_TYPE_BINARY) { // binary - const ObObjMeta obj_meta = expr.args_[i]->obj_meta_; - ObObj obj; - ObObj tmp_result; - ObCastCtx cast_ctx(&tmp_allocator, NULL, CM_NONE, CS_TYPE_INVALID); - obj.set_string(ObVarcharType, xml_value_data); - if (OB_FAIL(ObHexUtils::rawtohex(obj, cast_ctx, tmp_result))) { - LOG_WARN("fail to check xml binary syntax", K(ret)); - } else if (OB_FAIL(construct_value_array(tmp_allocator, - tmp_result.get_string(), - value_vec))) { - LOG_WARN("construct value array failed", K(ret)); - } - } else { // varchar - if (need_escape) { - ObStringBuffer *escape_value = nullptr; - if (OB_ISNULL(escape_value = OB_NEWx(ObStringBuffer, &tmp_allocator, (&tmp_allocator)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("fail to allocate buffer", K(ret)); - } else if (OB_FAIL(ObXmlParserUtils::escape_xml_text(xml_value_data, *escape_value))) { - LOG_WARN("escape xml value failed", K(ret), K(need_escape)); - } else if (OB_FAIL(construct_value_array(tmp_allocator, - ObString(escape_value->length(), escape_value->ptr()), - value_vec))) { - LOG_WARN("construct value array failed", K(ret)); - } - } else if (OB_FAIL(construct_value_array(tmp_allocator, - xml_value_data, - value_vec))) { - LOG_WARN("construct value array failed", K(ret)); - } - } - } - } - - ObStringBuffer tmp_buff(&tmp_allocator); - ObString text_xml; - ObXmlDocument *xml_doc = nullptr; - - bool tag_validity = false; - bool doc_validity = true; - ObXmlText *tag_name_start; - ObXmlText *tag_name_end; - ObString start_tag("<>"); - ObString end_tag(""); - if (OB_FAIL(ret)) { - } else if (!has_attribute && name_tag.empty()) { - if (OB_ISNULL(tag_name_start = OB_NEWx(ObXmlText, mem_ctx->allocator_, ObMulModeNodeType::M_TEXT, mem_ctx))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("new xml text failed", K(ret)); - } else if (OB_FALSE_IT(tag_name_start->set_text(start_tag))) { - } else if (OB_ISNULL(tag_name_end = OB_NEWx(ObXmlText, mem_ctx->allocator_, ObMulModeNodeType::M_TEXT, mem_ctx))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("new xml text failed", K(ret)); - } else if (OB_FALSE_IT(tag_name_end->set_text(end_tag))) { + } else if (OB_FAIL(ObXMLExprHelper::construct_element_value(tmp_allocator, expr.args_[i], datum, need_escape, value_vec))) { // element value + LOG_WARN("construct_element_valuev failed", K(ret)); } } if (OB_FAIL(ret)) { - LOG_WARN("ret failed", K(ret)); - } else if (OB_ISNULL(element = OB_NEWx(ObXmlElement, (mem_ctx->allocator_), ObMulModeNodeType::M_ELEMENT, mem_ctx))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("allocate mem failed", K(ret)); - } else if (!has_attribute && name_tag.empty() && OB_FAIL(element->add_element(tag_name_start))) { - LOG_WARN("element add start element failed", K(ret)); - } else if (OB_FAIL(construct_element(mem_ctx, name_tag, value_vec, attr_json, element, tag_validity))) { - LOG_WARN("construct_element failed", K(ret)); - } else if (!has_attribute && name_tag.empty() && OB_FAIL(element->add_element(tag_name_end))) { - LOG_WARN("element add end element failed", K(ret)); - } else if (OB_ISNULL(res_doc = OB_NEWx(ObXmlDocument, (mem_ctx->allocator_), ObMulModeNodeType::M_UNPARSED, mem_ctx))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("allocate mem failed", K(ret)); - } else if (OB_FAIL(res_doc->add_element(element))) { - LOG_WARN("res doc add element failed", K(ret)); - } else if (tag_validity && element->get_unparse() && OB_FAIL(ObXMLExprHelper::check_doc_validity(mem_ctx, res_doc, doc_validity))) { // && element.get_unparse() - LOG_WARN("check doc validity failed", K(ret), K(tag_validity)); - } else if ((!tag_validity || !doc_validity)) { - res_doc->set_xml_type(ObMulModeNodeType::M_UNPARSED); - } else if (tag_validity && doc_validity) { - static_cast(res_doc->at(0))->set_unparse(0); - res_doc->set_xml_type(ObMulModeNodeType::M_DOCUMENT); - } - if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObXMLExprHelper::construct_doc(mem_ctx, name_tag, value_vec, attr_json, has_attribute, res_doc))) { + LOG_WARN("construct_doc failed", K(ret)); } else if (OB_ISNULL(res_doc)) { ret = OB_ERR_UNEXPECTED; LOG_WARN(" failed to pack result, as res_doc is nullptr", K(ret)); } else if (OB_FAIL(res_doc->get_raw_binary(binary_str, &tmp_allocator))) { LOG_WARN("get raw binary failed", K(ret)); + } else if (OB_FALSE_IT(tmp_allocator.set_baseline_size(binary_str.length()))) { } else if (OB_FAIL(ObXMLExprHelper::pack_binary_res(expr, ctx, binary_str, blob_locator))) { LOG_WARN("pack binary res failed", K(ret), K(binary_str)); } else { @@ -291,166 +195,6 @@ int ObExprXmlElement::eval_xml_element(const ObExpr &expr, ObEvalCtx &ctx, ObDat return ret; } -int ObExprXmlElement::construct_value_array(ObIAllocator &allocator, const ObString &value, ObVector &res_value) -{ - INIT_SUCC(ret); - if (value.empty()) { - // donothing - } else { - ObObj temp_value; - uint32_t vec_size = res_value.size(); - if (res_value.size() == 0) { - temp_value.set_string(ObVarcharType, value); - } else { - if (res_value[vec_size - 1].get_type() == ObUserDefinedSQLType) { - temp_value.set_string(ObVarcharType, value); - } else { - char *new_value = NULL; - ObString temp_from = res_value[vec_size - 1].get_string(); - if (OB_ISNULL(new_value = static_cast(allocator.alloc(temp_from.length() + value.length())))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("new value allocator failed", K(ret)); - } else if (OB_FAIL(res_value.remove(res_value.last()))) { - LOG_WARN("res value remove failed", K(ret)); - } else { - MEMCPY(new_value, temp_from.ptr(), temp_from.length()); - MEMCPY(new_value + temp_from.length(), value.ptr(), value.length()); - temp_value.set_string(ObVarcharType, new_value, temp_from.length() + value.length()); - } - } - } - if (OB_SUCC(ret) && OB_FAIL(res_value.push_back(temp_value))) { - LOG_WARN("failed to push back value.", K(ret), K(temp_value)); - } - } - return ret; -} -int ObExprXmlElement::construct_attribute(ObMulModeMemCtx* mem_ctx, const ObIJsonBase *attr, ObXmlElement *&element) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(attr)) { // do nothing - } else if (attr->json_type() != ObJsonNodeType::J_ARRAY) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid json type", K(ret), K(attr->json_type())); - } else if (attr->element_count() % 2 != 0) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("attribute element count invalid", K(ret), K(attr->element_count())); - } else { - for (uint64_t i = 0; OB_SUCC(ret) && i < attr->element_count(); i += 2) { - ObIJsonBase *jb_name = NULL; - ObIJsonBase *jb_value = NULL; - ObString value_str = NULL; - ObString key_str = NULL; - ObXmlAttribute *attribute = NULL; - if (OB_FAIL(attr->get_array_element(i, jb_value))) { - LOG_WARN("get attribute value failed", K(ret), K(i)); - } else if (OB_FAIL(attr->get_array_element(i + 1, jb_name))) { - LOG_WARN("get attribute name failed", K(ret), K(i)); - } else if (OB_ISNULL(jb_name) || OB_ISNULL(jb_value)) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("attribute name or value is null", K(ret), K(i), K(jb_name), K(jb_value)); - } else if (jb_name->json_type() == ObJsonNodeType::J_NULL || - jb_value->json_type() == ObJsonNodeType::J_NULL) { - LOG_DEBUG("name or content is null", K(jb_name->json_type()), K(jb_value->json_type())); - } else if (OB_FAIL(ob_write_string(*mem_ctx->allocator_, ObString(jb_value->get_data_length(), jb_value->get_data()), value_str, false))) { - LOG_WARN("write string value to string failed", K(ret), K(i), K(jb_name), K(jb_value)); - } else if (OB_FAIL(ob_write_string(*mem_ctx->allocator_, ObString(jb_name->get_data_length(), jb_name->get_data()), key_str, false))) { - LOG_WARN("write string key to string failed", K(ret), K(i), K(jb_name), K(jb_value)); - } else if (OB_FAIL(element->add_attr_by_str(key_str, value_str, ObMulModeNodeType::M_ATTRIBUTE))) { - LOG_WARN("add element failed", K(ret)); - } - } - } - return ret; -} - -int ObExprXmlElement::construct_element_children(ObMulModeMemCtx* mem_ctx, - ObVector &value_vec, - ObXmlElement *&element, - ObXmlElement *valid_ele) -{ - int ret = OB_SUCCESS; - ObXmlText *tag_value = NULL; - if (OB_ISNULL(element)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("element node is NULL", K(ret)); - } - // build xml text - for (int i = 0; OB_SUCC(ret) && i < value_vec.size(); i++) { - ObObj value = value_vec[i]; - ObIMulModeBase *node = NULL; - ObXmlDocument *doc_node = NULL; - if (value.get_type() == ObUserDefinedSQLType) { - if (OB_FAIL(ObXMLExprHelper::add_binary_to_element(mem_ctx, value.get_string(), *element))) { - LOG_WARN("add binary to element failed", K(ret), K(i)); - } - } else { - if (OB_ISNULL(tag_value = OB_NEWx(ObXmlText, mem_ctx->allocator_, ObMulModeNodeType::M_TEXT, mem_ctx))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("new xml text failed", K(ret)); - } else if (OB_FALSE_IT(tag_value->set_text(value.get_string()))) { - } else if (OB_FAIL(element->add_element(tag_value))) { - LOG_WARN("element add element failed", K(ret)); - } else { - element->set_unparse(1); - } - } - } - - // if the constructed element is not unparsed, use valid_ele to replace the element - if (!element->get_unparse()) { - if (OB_ISNULL(valid_ele)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("valid element is NULL, but validity is true", K(ret)); - } - ObXmlNode *xml_node = NULL; - for (int64_t i = 0; OB_SUCC(ret) && i < element->size(); i++) { - if (OB_ISNULL(xml_node = element->at(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("xml node is NULL", K(ret)); - } else if (OB_FAIL(valid_ele->add_element(xml_node))) { - LOG_WARN("fail to add element", K(ret)); - } - } // end for - - if (OB_SUCC(ret)) { - element = valid_ele; - } - } - return ret; -} - -int ObExprXmlElement::construct_element(ObMulModeMemCtx* mem_ctx, - const ObString &name, - ObVector &value_vec, - const ObIJsonBase *attr, - ObXmlElement *&element, - bool &validity) -{ - INIT_SUCC(ret); - ObXmlElement *valid_ele = NULL; - if (OB_ISNULL(element)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("element node is NULL", K(ret)); - } else if (OB_FAIL(element->init())) { - LOG_WARN("element init failed", K(ret)); - } else if (FALSE_IT(element->set_xml_key(name))) { - } else if (OB_FAIL(element->alter_member_sort_policy(false))) { - LOG_WARN("fail to sort child element", K(ret)); - } else if (OB_FAIL(construct_attribute(mem_ctx, attr, element))) { - LOG_WARN("fail to construct attribute", K(ret)); - } else if (OB_FAIL(ObXMLExprHelper::check_element_validity(mem_ctx, element, valid_ele, validity))) { - LOG_WARN("check element validity failed", K(ret)); - } else if (OB_FAIL(construct_element_children(mem_ctx, value_vec, element, valid_ele))) { - LOG_WARN("fail to construct element chidren", K(ret)); - } - // set sort flag - if (OB_SUCC(ret) && OB_FAIL(element->alter_member_sort_policy(true))) { - LOG_WARN("fail to sort child element", K(ret)); - } - return ret; -} - int ObExprXmlElement::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const diff --git a/src/sql/engine/expr/ob_expr_xml_element.h b/src/sql/engine/expr/ob_expr_xml_element.h index aeba3399c..e0227094d 100644 --- a/src/sql/engine/expr/ob_expr_xml_element.h +++ b/src/sql/engine/expr/ob_expr_xml_element.h @@ -27,7 +27,6 @@ namespace oceanbase { namespace sql { -typedef PageArena ElementObjCacheStatArena; class ObExprXmlElement : public ObFuncExprOperator { @@ -44,25 +43,6 @@ public: const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; private: - static int get_keys_from_wrapper(ObIJsonBase *json_doc, - ObIAllocator *allocator, - ObString &str); - static int construct_element(ObMulModeMemCtx* mem_ctx, - const ObString &name, - ObVector &value_vec, - const ObIJsonBase *attr, - ObXmlElement *&element, - bool &validity); - static int construct_attribute(ObMulModeMemCtx* mem_ctx, - const ObIJsonBase *attr, - ObXmlElement *&element); - static int construct_element_children(ObMulModeMemCtx* mem_ctx, - ObVector &value_vec, - ObXmlElement *&element, - ObXmlElement *valid_ele); - static int construct_value_array(ObIAllocator &allocator, - const ObString &value, - ObVector &res_value); DISALLOW_COPY_AND_ASSIGN(ObExprXmlElement); }; diff --git a/src/sql/engine/expr/ob_expr_xml_forest.cpp b/src/sql/engine/expr/ob_expr_xml_forest.cpp new file mode 100644 index 000000000..e4e789ba6 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_xml_forest.cpp @@ -0,0 +1,181 @@ +/** +* Copyright (c) 2021 OceanBase +* OceanBase CE is licensed under Mulan PubL v2. +* You can use this software according to the terms and conditions of the Mulan PubL v2. +* You may obtain a copy of Mulan PubL v2 at: +* http://license.coscl.org.cn/MulanPubL-2.0 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PubL v2 for more details. +* This file is for func xmlforest. +*/ + +#define USING_LOG_PREFIX SQL_ENG +#include "ob_expr_xml_forest.h" +#include "sql/engine/ob_exec_context.h" +#include "lib/xml/ob_xml_util.h" +#include "sql/engine/expr/ob_expr_xml_func_helper.h" + +using namespace oceanbase::common; +using namespace oceanbase::sql; + +namespace oceanbase +{ +namespace sql +{ +ObExprXmlForest::ObExprXmlForest(ObIAllocator &alloc) + : ObFuncExprOperator( + alloc, + T_FUN_SYS_XML_FOREST, + N_XML_FOREST, + PARAM_NUM_UNKNOWN, + VALID_FOR_GENERATED_COL, + NOT_ROW_DIMENSION) +{ +} + +ObExprXmlForest::~ObExprXmlForest() +{ +} + +int ObExprXmlForest::calc_result_typeN( + ObExprResType& type, + ObExprResType* types_stack, + int64_t param_num, + ObExprTypeCtx& type_ctx) const +{ + UNUSED(type_ctx); + INIT_SUCC(ret); + if (OB_UNLIKELY(param_num % 3 != 0)) { + ret = OB_ERR_PARAM_SIZE; + LOG_WARN("invalid param number", K(ret), K(param_num)); + } else if (!is_called_in_sql()) { + ret = OB_ERR_SP_LILABEL_MISMATCH; + LOG_WARN("expr call in pl semantics disallowed", K(ret), K(N_XML_FOREST)); + LOG_USER_ERROR(OB_ERR_SP_LILABEL_MISMATCH, static_cast(strlen(N_XML_FOREST)), N_XML_FOREST); + } else { + // check + for (int i = 0; i < param_num && OB_SUCC(ret); i++) { + const ObObjType obj_type = types_stack[i].get_type(); + if (i % 3 == 0) { + // value param + if (ob_is_string_type(obj_type)) { + if (types_stack[i].get_collation_type() == CS_TYPE_BINARY) { + types_stack[i].set_calc_collation_type(CS_TYPE_BINARY); + } else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) { + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + } else if (obj_type == ObUserDefinedSQLType) { + // xmltype, do nothing + } else if (obj_type == ObExtendType) { + types_stack[i].set_calc_type(ObUserDefinedSQLType); + } else { + types_stack[i].set_calc_type(ObVarcharType); + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); + } + } else if (i % 3 == 1) { + // tag param + if (ob_is_null(obj_type)) { + // do nothing + } else if (obj_type == ObNumberType) { + // do nothing + } else if (types_stack[i].get_collation_type() == CS_TYPE_BINARY) { + ret = OB_ERR_INVALID_XML_DATATYPE; + LOG_USER_ERROR(OB_ERR_INVALID_XML_DATATYPE, "Character", "-"); + LOG_WARN("Unsupport for string type with binary charset input.", K(ret), K(obj_type)); + } else if (ob_is_string_tc(obj_type)) { + types_stack[i].set_calc_type(ObVarcharType); + types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI); + } else { + ret = OB_ERR_INVALID_XML_DATATYPE; + LOG_USER_ERROR(OB_ERR_INVALID_XML_DATATYPE, "Character", "-"); + LOG_WARN("Unsupport for string typee with binary charset input.", K(ret), K(obj_type)); + } + } else { + // lable param do nothing + } + } + } + if (OB_SUCC(ret)) { + type.set_sql_udt(ObXMLSqlType); + } + return ret; +} + +int ObExprXmlForest::eval_xml_forest(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) +{ + INIT_SUCC(ret); + ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); + common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); + ObVector xml_bin_str_vec; + ObBinAggSerializer bin_agg(&allocator, ObBinAggType::AGG_XML, static_cast(M_CONTENT)); + ObString res_bin_str; + ObString blob_locator; + ObMulModeMemCtx* mem_ctx = nullptr; + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + + CK(OB_NOT_NULL(ctx.exec_ctx_.get_my_session())); + OZ(ObXmlUtil::create_mulmode_tree_context(&allocator, mem_ctx)); + CK(expr.arg_cnt_ % 3 == 0); + + for (int i = 0; OB_SUCC(ret) && i < expr.arg_cnt_ / 3; i++) { + ObDatum *value_datum = NULL; + ObDatum *tag_datum = NULL; + ObVector value_vec; + ObString name_tag; + ObXmlDocument *xml_doc = NULL; + ObString xml_bin_str; + + // value + if (OB_FAIL(expr.args_[i * 3]->eval(ctx, value_datum))) { + LOG_WARN("value expr args failed", K(ret), K(expr.args_[i * 3])); + } else if (OB_FAIL(ObXMLExprHelper::construct_element_value( + allocator, + expr.args_[i * 3], + value_datum, + true, + value_vec))) { + LOG_WARN("construct_element_valuev failed", K(ret)); + } + // tag + if (OB_FAIL(ret)) { + } else if (OB_FAIL(expr.args_[i * 3 + 1]->eval(ctx, tag_datum))) { + LOG_WARN("tag expr args failed", K(ret), K(expr.args_[i * 3 + 1])); + } else if(expr.args_[i * 3 + 1]->datum_meta_.type_ == ObNumberType) { + ret = OB_ERR_INVALID_XML_DATATYPE; + LOG_USER_ERROR(OB_ERR_INVALID_XML_DATATYPE, "Character", "-"); + LOG_WARN("Unsupport for string type with binary charset input.", K(ret), K(expr.args_[i * 3 + 1]->datum_meta_.type_)); + } else if (OB_FAIL(ObTextStringHelper::get_string(expr, allocator, i * 3 + 1, tag_datum, name_tag))) { + LOG_WARN("get xml plain text failed", K(ret)); + } + // construct xmltype + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObXMLExprHelper::construct_doc(mem_ctx, name_tag, value_vec, nullptr, false, xml_doc))) { + LOG_WARN("construct_doc failed", K(ret)); + } else if (OB_ISNULL(xml_doc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to pack result, as xml_doc is nullptr", K(ret)); + } else if (OB_FAIL(xml_doc->get_raw_binary(xml_bin_str, &allocator))) { + LOG_WARN("get raw binary failed", K(ret)); + } else if (OB_FAIL(xml_bin_str_vec.push_back(xml_bin_str))) { + LOG_WARN("failed to push back.", K(ret), K(xml_bin_str)); + } + } + + OZ(ObXMLExprHelper::concat_xml_type_nodes(mem_ctx, xml_bin_str_vec, res_bin_str)); + OZ(ObXMLExprHelper::pack_binary_res(expr, ctx, res_bin_str, blob_locator)); + OX(res.set_string(blob_locator.ptr(), blob_locator.length())); + + return ret; +} + +int ObExprXmlForest::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const +{ + UNUSED(expr_cg_ctx); + UNUSED(raw_expr); + rt_expr.eval_func_ = eval_xml_forest; + return OB_SUCCESS; +} +} //sql +} //oceanbase diff --git a/src/sql/engine/expr/ob_expr_xml_forest.h b/src/sql/engine/expr/ob_expr_xml_forest.h new file mode 100644 index 000000000..ec4ee0171 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_xml_forest.h @@ -0,0 +1,50 @@ +/** +* Copyright (c) 2021 OceanBase +* OceanBase CE is licensed under Mulan PubL v2. +* You can use this software according to the terms and conditions of the Mulan PubL v2. +* You may obtain a copy of Mulan PubL v2 at: +* http://license.coscl.org.cn/MulanPubL-2.0 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PubL v2 for more details. +* This file contains implementation for xmlforest. +*/ + +#ifndef OCEANBASE_SQL_OB_EXPR_XML_FOREST_H_ +#define OCEANBASE_SQL_OB_EXPR_XML_FOREST_H_ + +#include "sql/engine/expr/ob_expr_operator.h" +#include "sql/engine/expr/ob_expr_lob_utils.h" +#include "lib/container/ob_vector.h" +#include "lib/xml/ob_xml_util.h" + +namespace oceanbase +{ +namespace sql +{ +class ObExprXmlForest : public ObFuncExprOperator +{ +public: + explicit ObExprXmlForest(common::ObIAllocator &alloc); + virtual ~ObExprXmlForest(); + virtual int calc_result_typeN( + ObExprResType& type, + ObExprResType* types, + int64_t param_num, + common::ObExprTypeCtx& type_ctx) + const override; + + static int eval_xml_forest(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); + + virtual int cg_expr( + ObExprCGCtx &expr_cg_ctx, + const ObRawExpr &raw_expr, + ObExpr &rt_expr) + const override; +private: + DISALLOW_COPY_AND_ASSIGN(ObExprXmlForest); +}; +} // sql +} // oceanbase +#endif // OCEANBASE_SQL_OB_EXPR_XML_FOREST_H_ diff --git a/src/sql/engine/expr/ob_expr_xml_func_helper.cpp b/src/sql/engine/expr/ob_expr_xml_func_helper.cpp index 8de3364de..6a99805c8 100644 --- a/src/sql/engine/expr/ob_expr_xml_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_xml_func_helper.cpp @@ -170,7 +170,7 @@ int ObXMLExprHelper::get_xml_base(ObMulModeMemCtx *ctx, ObString xml_text; ObDatumMeta xml_meta; xml_meta.type_ = ObLongTextType; - xml_meta.cs_type_ = CS_TYPE_UTF8MB4_BIN; + xml_meta.cs_type_ = CS_TYPE_BINARY; ObXmlDocument *xml_doc = NULL; if (OB_ISNULL(xml_datum)) { ret = OB_ERR_UNEXPECTED; @@ -536,7 +536,8 @@ int ObXMLExprHelper::get_str_from_expr(const ObExpr *expr, ObDatum *datum = NULL; ObObjType val_type = expr->datum_meta_.type_; uint16_t sub_schema_id = expr->obj_meta_.get_subschema_id(); - if (OB_FAIL(expr->eval(ctx, datum))) { + MultimodeAlloctor &alloc = static_cast(allocator); + if (OB_FAIL(alloc.eval_arg(expr, ctx, datum))) { LOG_WARN("eval xml arg failed", K(ret)); } else if (!ob_is_string_type(val_type)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; @@ -587,6 +588,42 @@ int ObXMLExprHelper::get_xmltype_from_expr(const ObExpr *expr, return ret; } +int ObXMLExprHelper::get_xmltype_from_expr(const ObExpr *expr, + ObEvalCtx &ctx, + ObDatum *&xml_datum, + MultimodeAlloctor &allocator) +{ + INIT_SUCC(ret); + if (OB_FAIL(get_xmltype_from_expr(expr, ctx, xml_datum))) { + LOG_WARN("get xmltype failed.", K(ret)); + } else { + ObLobLocatorV2 locator(xml_datum->get_string()); + int64_t byte_len = static_cast(xml_datum->len_); + if (OB_FAIL(locator.get_lob_data_byte_len(byte_len))) { + LOG_WARN("get lob data byte length failed", K(ret)); + } else { + allocator.add_baseline_size(byte_len); + } + } + return ret; +} + +int ObXMLExprHelper::mem_ctx_add_baseline(const ObExpr *expr, + ObEvalCtx &ctx, + ObMulModeMemCtx *&mem_ctx, + uint32_t multiple) +{ + INIT_SUCC(ret); + MultimodeAlloctor *mul_alloc = static_cast(mem_ctx->allocator_); + if (OB_ISNULL(mul_alloc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get mul alloc null", K(ret)); + } else if (OB_FAIL(mul_alloc->add_baseline_size(expr, ctx, multiple))) { + LOG_WARN("failed to add baseline size.", K(ret)); + } + return ret; +} + int ObXMLExprHelper::get_xml_base_from_expr(const ObExpr *expr, ObMulModeMemCtx *mem_ctx, ObEvalCtx &ctx, @@ -606,7 +643,16 @@ int ObXMLExprHelper::get_xml_base_from_expr(const ObExpr *expr, } else if (xml_text.empty()) { ret = OB_ERR_XQUERY_TYPE_MISMATCH; LOG_WARN("node is NULL", K(ret)); - } else if (OB_FAIL(ObMulModeFactory::get_xml_base(mem_ctx, xml_text, + } else { + MultimodeAlloctor *mul_alloc = static_cast(mem_ctx->allocator_); + if (OB_ISNULL(mul_alloc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get mul alloc null", K(ret)); + } else { + mul_alloc->add_baseline_size(xml_text.length()); + } + } + if (OB_SUCC(ret) && OB_FAIL(ObMulModeFactory::get_xml_base(mem_ctx, xml_text, ObNodeMemType::TREE_TYPE, ObNodeMemType::BINARY_TYPE, node, M_DOCUMENT, false, true))) { @@ -1149,7 +1195,6 @@ int ObXMLExprHelper::process_sql_udt_results(ObObj& value, sql::ObResultSet &res { int ret = OB_SUCCESS; ObArenaAllocator *allocator = NULL; - sql::ObSQLSessionInfo *session_info = &result.get_session(); if (OB_FAIL(result.get_exec_context().get_convert_charset_allocator(allocator))) { LOG_WARN("fail to get convert charset allocator", K(ret)); } else if (OB_ISNULL(allocator)) { @@ -1174,7 +1219,10 @@ int ObXMLExprHelper::process_sql_udt_results(common::ObObj& value, ObSchemaGetterGuard *schema_guard) // need fields and schema guard { int ret = OB_SUCCESS; - if (!value.is_user_defined_sql_type() && !value.is_collection_sql_type() && !value.is_geometry()) { + if (OB_ISNULL(session_info) || OB_ISNULL(allocator)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get session info null", K(ret)); + } else if (!value.is_user_defined_sql_type() && !value.is_collection_sql_type() && !value.is_geometry()) { ret = OB_NOT_SUPPORTED; OB_LOG(WARN, "not supported udt type", K(ret), K(value.get_type()), K(value.get_udt_subschema_id())); @@ -1185,12 +1233,13 @@ int ObXMLExprHelper::process_sql_udt_results(common::ObObj& value, } else if (is_client_support_binary_xml) { // convert to udt client format } else { + ObArenaAllocator tmp_alloc("ObXmlRes", OB_MALLOC_NORMAL_BLOCK_SIZE, session_info->get_effective_tenant_id()); ObString data; ObLobLocatorV2 loc(value.get_string(), true); ObString converted_str; if (!loc.is_null()) { ObTextStringIter instr_iter(ObLongTextType, CS_TYPE_BINARY, value.get_string(), true); - if (OB_FAIL(instr_iter.init(0, session_info, allocator))) { + if (OB_FAIL(instr_iter.init(0, session_info, &tmp_alloc))) { LOG_WARN("init lob str inter failed", K(ret), K(value)); } else if (OB_FAIL(instr_iter.get_full_data(data))) { LOG_WARN("get xml full data failed", K(value)); @@ -1204,11 +1253,8 @@ int ObXMLExprHelper::process_sql_udt_results(common::ObObj& value, ObNsSortedVector* ns_vec_point = nullptr; ObNsSortedVector ns_vec; - if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(allocator, ctx))) { + if (OB_FAIL(ObXmlUtil::create_mulmode_tree_context(&tmp_alloc, ctx))) { LOG_WARN("fail to create tree memory context", K(ret)); - } else if (OB_ISNULL(allocator)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid input args", K(ret), KP(allocator)); } else if (data.length() == 0) { } else if (OB_FAIL(ObXmlUtil::xml_bin_type(data, node_type))) { LOG_WARN("xml bin type failed", K(ret)); @@ -1217,7 +1263,7 @@ int ObXMLExprHelper::process_sql_udt_results(common::ObObj& value, ObNodeMemType::BINARY_TYPE, node))) { LOG_WARN("fail to get xml base", K(ret), K(data.length())); - } else if (OB_FAIL(ObXmlUtil::init_print_ns(allocator, node, ns_vec, ns_vec_point))) { + } else if (OB_FAIL(ObXmlUtil::init_print_ns(&tmp_alloc, node, ns_vec, ns_vec_point))) { LOG_WARN("fail to init ns vector by extend area", K(ret)); } @@ -1532,5 +1578,539 @@ void ObXMLExprHelper::get_accuracy_from_expr(const ObExpr &expr, ObAccuracy &acc } } +int ObXMLExprHelper::construct_value_array( + ObIAllocator &allocator, + const ObString &value, + ObVector &res_value) +{ + INIT_SUCC(ret); + if (value.empty()) { + // donothing + } else { + ObObj temp_value; + uint32_t vec_size = res_value.size(); + if (res_value.size() == 0) { + temp_value.set_string(ObVarcharType, value); + } else { + if (res_value[vec_size - 1].get_type() == ObUserDefinedSQLType) { + temp_value.set_string(ObVarcharType, value); + } else { + char *new_value = NULL; + ObString temp_from = res_value[vec_size - 1].get_string(); + if (OB_ISNULL(new_value = static_cast(allocator.alloc(temp_from.length() + value.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("new value allocator failed", K(ret)); + } else if (OB_FAIL(res_value.remove(res_value.last()))) { + LOG_WARN("res value remove failed", K(ret)); + } else { + MEMCPY(new_value, temp_from.ptr(), temp_from.length()); + MEMCPY(new_value + temp_from.length(), value.ptr(), value.length()); + temp_value.set_string(ObVarcharType, new_value, temp_from.length() + value.length()); + } + } + } + if (OB_SUCC(ret) && OB_FAIL(res_value.push_back(temp_value))) { + LOG_WARN("failed to push back value.", K(ret), K(temp_value)); + } + } + return ret; +} + +int ObXMLExprHelper::construct_element_value( + ObIAllocator &allocator, + ObExpr *xml_arg, + ObDatum *datum, + bool need_escape, + ObVector &value_vec) +{ + INIT_SUCC(ret); + ObString xml_value_data = datum->get_string(); + if (xml_arg->datum_meta_.type_ == ObUserDefinedSQLType) { // xmltype + if (OB_FAIL(ObTextStringHelper::read_real_string_data( + &allocator, + ObObjType::ObLongTextType, + ObCollationType::CS_TYPE_BINARY, + true, xml_value_data))) { + LOG_WARN("fail to get real data.", K(ret), K(xml_value_data)); + } else { + ObObj temp_value; + temp_value.set_string(ObUserDefinedSQLType, xml_value_data); + if (OB_FAIL(value_vec.push_back(temp_value))) { + LOG_WARN("failed to push back temp value.", K(ret), K(temp_value)); + } + } + } else if (OB_FAIL(ObTextStringHelper::read_real_string_data( + allocator, *datum, + xml_arg->datum_meta_, + xml_arg->obj_meta_.has_lob_header(), + xml_value_data))) { + LOG_WARN("fail to get real data.", K(ret), K(xml_value_data)); + } else if (xml_arg->datum_meta_.cs_type_ == CS_TYPE_BINARY) { // binary + const ObObjMeta obj_meta = xml_arg->obj_meta_; + ObObj obj; + ObObj tmp_result; + ObCastCtx cast_ctx(&allocator, NULL, CM_NONE, CS_TYPE_INVALID); + obj.set_string(ObVarcharType, xml_value_data); + if (OB_FAIL(ObHexUtils::rawtohex(obj, cast_ctx, tmp_result))) { + LOG_WARN("fail to check xml binary syntax", K(ret)); + } else if (OB_FAIL(construct_value_array( + allocator, + tmp_result.get_string(), + value_vec))) { + LOG_WARN("construct value array failed", K(ret)); + } + } else { // varchar + if (need_escape) { + ObStringBuffer *escape_value = nullptr; + if (OB_ISNULL(escape_value = OB_NEWx(ObStringBuffer, &allocator, (&allocator)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate buffer", K(ret)); + } else if (OB_FAIL(ObXmlParserUtils::escape_xml_text(xml_value_data, *escape_value))) { + LOG_WARN("escape xml value failed", K(ret), K(need_escape)); + } else if (OB_FAIL(construct_value_array( + allocator, + ObString(escape_value->length(), escape_value->ptr()), + value_vec))) { + LOG_WARN("construct value array failed", K(ret)); + } + } else if (OB_FAIL(construct_value_array( + allocator, + xml_value_data, + value_vec))) { + LOG_WARN("construct value array failed", K(ret)); + } + } + return ret; +} + +int ObXMLExprHelper::construct_attribute( + ObMulModeMemCtx* mem_ctx, + const ObIJsonBase *attr, + ObXmlElement *&element) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(attr)) { // do nothing + } else if (attr->json_type() != ObJsonNodeType::J_ARRAY) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid json type", K(ret), K(attr->json_type())); + } else if (attr->element_count() % 2 != 0) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("attribute element count invalid", K(ret), K(attr->element_count())); + } else { + for (uint64_t i = 0; OB_SUCC(ret) && i < attr->element_count(); i += 2) { + ObIJsonBase *jb_name = NULL; + ObIJsonBase *jb_value = NULL; + ObString value_str = NULL; + ObString key_str = NULL; + ObXmlAttribute *attribute = NULL; + if (OB_FAIL(attr->get_array_element(i, jb_value))) { + LOG_WARN("get attribute value failed", K(ret), K(i)); + } else if (OB_FAIL(attr->get_array_element(i + 1, jb_name))) { + LOG_WARN("get attribute name failed", K(ret), K(i)); + } else if (OB_ISNULL(jb_name) || OB_ISNULL(jb_value)) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("attribute name or value is null", K(ret), K(i), K(jb_name), K(jb_value)); + } else if (jb_name->json_type() == ObJsonNodeType::J_NULL || + jb_value->json_type() == ObJsonNodeType::J_NULL) { + LOG_DEBUG("name or content is null", K(jb_name->json_type()), K(jb_value->json_type())); + } else if (OB_FAIL(ob_write_string( + *mem_ctx->allocator_, + ObString(jb_value->get_data_length(), + jb_value->get_data()), + value_str, false))) { + LOG_WARN("write string value to string failed", K(ret), K(i), K(jb_name), K(jb_value)); + } else if (OB_FAIL(ob_write_string( + *mem_ctx->allocator_, + ObString(jb_name->get_data_length(), + jb_name->get_data()), + key_str, + false))) { + LOG_WARN("write string key to string failed", K(ret), K(i), K(jb_name), K(jb_value)); + } else if (OB_FAIL(element->add_attr_by_str(key_str, value_str, ObMulModeNodeType::M_ATTRIBUTE))) { + LOG_WARN("add element failed", K(ret)); + } + } + } + return ret; +} + +int ObXMLExprHelper::construct_element_children( + ObMulModeMemCtx* mem_ctx, + ObVector &value_vec, + ObXmlElement *&element, + ObXmlElement *valid_ele) +{ + int ret = OB_SUCCESS; + ObXmlText *tag_value = NULL; + if (OB_ISNULL(element)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("element node is NULL", K(ret)); + } + // build xml text + for (int i = 0; OB_SUCC(ret) && i < value_vec.size(); i++) { + ObObj value = value_vec[i]; + ObIMulModeBase *node = NULL; + ObXmlDocument *doc_node = NULL; + if (value.get_type() == ObUserDefinedSQLType) { + if (OB_FAIL(add_binary_to_element(mem_ctx, value.get_string(), *element))) { + LOG_WARN("add binary to element failed", K(ret), K(i)); + } + } else { + if (OB_ISNULL(tag_value = OB_NEWx(ObXmlText, mem_ctx->allocator_, ObMulModeNodeType::M_TEXT, mem_ctx))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("new xml text failed", K(ret)); + } else if (OB_FALSE_IT(tag_value->set_text(value.get_string()))) { + } else if (OB_FAIL(element->add_element(tag_value))) { + LOG_WARN("element add element failed", K(ret)); + } else { + element->set_unparse(1); + } + } + } + + // if the constructed element is not unparsed, use valid_ele to replace the element + if (!element->get_unparse()) { + if (OB_ISNULL(valid_ele)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("valid element is NULL, but validity is true", K(ret)); + } + ObXmlNode *xml_node = NULL; + for (int64_t i = 0; OB_SUCC(ret) && i < element->size(); i++) { + if (OB_ISNULL(xml_node = element->at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("xml node is NULL", K(ret)); + } else if (OB_FAIL(valid_ele->add_element(xml_node))) { + LOG_WARN("fail to add element", K(ret)); + } + } // end for + + if (OB_SUCC(ret)) { + element = valid_ele; + } + } + return ret; +} + +int ObXMLExprHelper::construct_element( + ObMulModeMemCtx* mem_ctx, + const ObString &name, + ObVector &value_vec, + const ObIJsonBase *attr, + ObXmlElement *&element, + bool &validity) +{ + INIT_SUCC(ret); + ObXmlElement *valid_ele = NULL; + if (OB_ISNULL(element)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("element node is NULL", K(ret)); + } else if (OB_FAIL(element->init())) { + LOG_WARN("element init failed", K(ret)); + } else if (FALSE_IT(element->set_xml_key(name))) { + } else if (OB_FAIL(element->alter_member_sort_policy(false))) { + LOG_WARN("fail to sort child element", K(ret)); + } else if (OB_FAIL(construct_attribute(mem_ctx, attr, element))) { + LOG_WARN("fail to construct attribute", K(ret)); + } else if (OB_FAIL(check_element_validity(mem_ctx, element, valid_ele, validity))) { + LOG_WARN("check element validity failed", K(ret)); + } else if (OB_FAIL(construct_element_children(mem_ctx, value_vec, element, valid_ele))) { + LOG_WARN("fail to construct element chidren", K(ret)); + } + // set sort flag + if (OB_SUCC(ret) && OB_FAIL(element->alter_member_sort_policy(true))) { + LOG_WARN("fail to sort child element", K(ret)); + } + return ret; +} + +int ObXMLExprHelper::construct_doc( + ObMulModeMemCtx* mem_ctx, + const ObString &name_tag, + ObVector &value_vec, + const ObIJsonBase *attr_json, + bool has_attribute, + ObXmlDocument *&res_doc) +{ + int ret = OB_SUCCESS; + ObXmlElement *element = NULL; + bool tag_validity = false; + bool doc_validity = true; + ObXmlText *tag_name_start; + ObXmlText *tag_name_end; + ObString start_tag("<>"); + ObString end_tag(""); + if (!has_attribute && name_tag.empty()) { + if (OB_ISNULL(tag_name_start = OB_NEWx( + ObXmlText, + mem_ctx->allocator_, + ObMulModeNodeType::M_TEXT, mem_ctx))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("new xml text failed", K(ret)); + } else if (OB_FALSE_IT(tag_name_start->set_text(start_tag))) { + } else if (OB_ISNULL(tag_name_end = OB_NEWx( + ObXmlText, + mem_ctx->allocator_, + ObMulModeNodeType::M_TEXT, + mem_ctx))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("new xml text failed", K(ret)); + } else if (OB_FALSE_IT(tag_name_end->set_text(end_tag))) { + } + } + + if (OB_FAIL(ret)) { + LOG_WARN("ret failed", K(ret)); + } else if (OB_ISNULL(element = OB_NEWx( + ObXmlElement, + (mem_ctx->allocator_), + ObMulModeNodeType::M_ELEMENT, + mem_ctx))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate mem failed", K(ret)); + } else if (!has_attribute && name_tag.empty() && OB_FAIL(element->add_element(tag_name_start))) { + LOG_WARN("element add start element failed", K(ret)); + } else if (OB_FAIL(construct_element(mem_ctx, name_tag, value_vec, attr_json, element, tag_validity))) { + LOG_WARN("construct_element failed", K(ret)); + } else if (!has_attribute && name_tag.empty() && OB_FAIL(element->add_element(tag_name_end))) { + LOG_WARN("element add end element failed", K(ret)); + } else if (OB_ISNULL(res_doc = OB_NEWx( + ObXmlDocument, + (mem_ctx->allocator_), + ObMulModeNodeType::M_UNPARSED, + mem_ctx))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate mem failed", K(ret)); + } else if (OB_FAIL(res_doc->add_element(element))) { + LOG_WARN("res doc add element failed", K(ret)); + } else if (tag_validity + && element->get_unparse() + && OB_FAIL(check_doc_validity(mem_ctx, res_doc, doc_validity))) { // && element.get_unparse() + LOG_WARN("check doc validity failed", K(ret), K(tag_validity)); + } else if ((!tag_validity || !doc_validity)) { + res_doc->set_xml_type(ObMulModeNodeType::M_UNPARSED); + } else if (tag_validity && doc_validity) { + static_cast(res_doc->at(0))->set_unparse(0); + res_doc->set_xml_type(ObMulModeNodeType::M_DOCUMENT); + } + return ret; + } + +int ObXMLExprHelper::concat_xml_type_nodes( + ObMulModeMemCtx* mem_ctx, + ObVector &xml_bin_str_vec, + ObString &res_bin_str) +{ + INIT_SUCC(ret); + bool first_is_doc = false; + ObString version; + ObString encoding; + uint16_t standalone; + ObMulModeNodeType res_node_type = M_NULL; + ObBinAggSerializer bin_agg(mem_ctx->allocator_, ObBinAggType::AGG_XML, static_cast(M_CONTENT)); + int num = xml_bin_str_vec.size(); + + if (num == 0) { + // do noting + } else if (num == 1) { + res_bin_str = xml_bin_str_vec[0]; + } else if (num > 1) { + for (int i = 0; OB_SUCC(ret) && i < num; i++) { + ObMulModeNodeType node_type = M_NULL; + ObIMulModeBase *xml_doc = NULL; + ObXmlBin *xml_bin = NULL; + if (OB_FAIL(ObXmlUtil::xml_bin_type(xml_bin_str_vec[i], node_type))) { + LOG_WARN("faild to xml_bin_type", K(ret), K(i), K(xml_bin_str_vec[i])); + } else if (OB_FAIL(common::ObMulModeFactory::get_xml_base( + mem_ctx, xml_bin_str_vec[i], + ObNodeMemType::BINARY_TYPE, + ObNodeMemType::BINARY_TYPE, + xml_doc))) { + if (node_type == M_DOCUMENT || node_type == M_CONTENT) { + LOG_WARN("fail to parse to xml binary", K(ret), K(i), K(xml_bin_str_vec[i])); + } else { + LOG_WARN("try to add by text"); + ret = OB_SUCCESS; + ObString xml_text; + ObStringBuffer xml_buf(mem_ctx->allocator_); + ObXmlBin xml_text_bin(mem_ctx); + if (OB_FAIL(xml_text_bin.parse(xml_bin_str_vec[i].ptr(), xml_bin_str_vec[i].length()))) { + LOG_WARN("fail to parse bin text to bin"); + } else { + xml_bin = &xml_text_bin; + res_node_type = M_UNPARSED; + } + } + } else { + xml_bin = static_cast(xml_doc); + ObMulModeNodeType node_type = xml_doc->type(); + if (res_node_type == M_NULL) { + // this is the first node + if (node_type == M_DOCUMENT || node_type == M_UNPARESED_DOC) { + res_node_type = M_DOCUMENT; + version = xml_doc->get_version(); + encoding = xml_doc->get_encoding(); + standalone = xml_doc->get_standalone(); + first_is_doc = version.empty() ? false : true; + } else { + res_node_type = node_type; + } + } else { + if (res_node_type != M_UNPARSED && node_type != M_UNPARSED) { + res_node_type = M_CONTENT; + } else { + res_node_type = M_UNPARSED; + } + } + } + if (OB_FAIL(ret) || OB_ISNULL(xml_bin)) { + // skip + } else if (xml_bin->meta_.len_ == 0) { + // do noting + } else if (OB_FAIL(bin_agg.append_key_and_value(xml_bin))) { + LOG_WARN("failed to append binary", K(ret)); + } + } + OX(bin_agg.set_header_type(res_node_type)); + if (first_is_doc && res_node_type == M_DOCUMENT) { + OX(bin_agg.set_xml_decl(version, encoding, standalone)); + } + OZ(bin_agg.serialize()); + OX(res_bin_str = bin_agg.get_buffer()->string()); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid xml_bin_str_vec.size()", K(num)); + } + return ret; +} + +int ObXMLExprHelper::concat_xpath_result( + ObMulModeMemCtx* mem_ctx, + ObPathExprIter &xpath_iter, + ObString &bin_str, + bool &is_null_res) +{ + int ret = OB_SUCCESS; + ObCollationType cs_type = CS_TYPE_INVALID; + ObMulModeNodeType node_type = M_MAX_TYPE; + ObIMulModeBase *node = NULL; + int64_t append_node_num = 0; + int element_count = 0; + int text_count = 0; + ObString version; + ObString encoding; + uint16_t standalone; + bool first_is_doc = false; + ObIMulModeBase* last_parent = nullptr; + common::hash::ObHashMap ns_map; + ObBinAggSerializer bin_agg(mem_ctx->allocator_, ObBinAggType::AGG_XML, static_cast(M_CONTENT)); + + if (OB_FAIL(xpath_iter.open())) { + LOG_WARN("fail to open xpath iterator", K(ret)); + ObXMLExprHelper::replace_xpath_ret_code(ret); + } else if (OB_FAIL(ns_map.create(10, lib::ObMemAttr(MTL_ID(), "XMLModule")))) { + LOG_WARN("ns map create failed", K(ret)); + } + + while (OB_SUCC(ret)) { + ObIMulModeBase* tmp = nullptr; + ObXmlBin extend; + if (OB_FAIL(xpath_iter.get_next_node(node))) { + if (ret != OB_ITER_END) { + LOG_WARN("fail to get next xml node", K(ret)); + } + } else if (OB_ISNULL(node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("xpath result node is null", K(ret)); + } else if (node->is_tree() && OB_FAIL(ObMulModeFactory::transform(mem_ctx, node, BINARY_TYPE, node))) { + LOG_WARN("fail to transform to tree", K(ret)); + } else { + ObXmlBin *bin = nullptr; + if (OB_ISNULL(bin = static_cast(node))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get bin failed", K(ret)); + } else if (bin->meta_.len_ == 0) { + // do nothing + } else if (bin->check_extend()) { + bool conflict = false; + // check key conflict + if (OB_FAIL(bin->get_extend(extend))) { + LOG_WARN("fail to get extend", K(ret)); + } else if (OB_FAIL(ObXmlUtil::check_ns_conflict( + xpath_iter.get_cur_res_parent(), + last_parent, + &extend, + ns_map, + conflict))) { + LOG_WARN("fail to check conflict", K(ret)); + } else if (conflict) { + // if conflict, merge bin + if (OB_FAIL(bin->merge_extend(extend))) { + LOG_WARN("fail to merge extend", K(ret)); + } else { + bin = &extend; + } + } else if (OB_FAIL(bin->remove_extend())) { // if not conflict, erase extend + LOG_WARN("fail to remove extend", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(bin_agg.append_key_and_value(bin))) { + LOG_WARN("failed to append binary", K(ret)); + } else { + ObMulModeNodeType type = node->type(); + if (append_node_num == 0 && type == ObMulModeNodeType::M_DOCUMENT) { + version = node->get_version(); + encoding = node->get_encoding(); + standalone = node->get_standalone(); + first_is_doc = version.empty() ? false : true; + } + + if (type == ObMulModeNodeType::M_ELEMENT || type == ObMulModeNodeType::M_DOCUMENT) { + element_count++; + } else if (type == ObMulModeNodeType::M_TEXT || type == ObMulModeNodeType::M_CDATA) { + text_count++; + } else if (type == ObMulModeNodeType::M_CONTENT) { + append_node_num += bin->count() - 1; + } + append_node_num++; + } + } + } + + if (ret == OB_ITER_END) { + ret = OB_SUCCESS; + if (element_count > 1 || element_count == 0) { + node_type = ObMulModeNodeType::M_CONTENT; + } else if (element_count == 1 && text_count > 0) { + node_type = ObMulModeNodeType::M_CONTENT; + } else if (append_node_num == 0) { + // do nothing + } else { + node_type = ObMulModeNodeType::M_DOCUMENT; + } + + bin_agg.set_header_type(node_type); + if (first_is_doc && append_node_num == 1) { + bin_agg.set_xml_decl(version, encoding, standalone); + } + } + + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = xpath_iter.close())) { + LOG_WARN("fail to close xpath iter", K(tmp_ret)); + ret = COVER_SUCC(tmp_ret); + } else if (append_node_num == 0) { + is_null_res = true; + } else if (OB_FAIL(bin_agg.serialize())) { + LOG_WARN("failed to serialize binary.", K(ret)); + } else if (ns_map.size() > 0 && OB_FAIL(ObXmlUtil::ns_to_extend(mem_ctx, ns_map, bin_agg.get_buffer()))) { + LOG_WARN("failed to serialize extend.", K(ret)); + } else { + bin_str = bin_agg.get_buffer()->string(); + } + ns_map.clear(); + return ret; +} + } // sql } // oceanbase diff --git a/src/sql/engine/expr/ob_expr_xml_func_helper.h b/src/sql/engine/expr/ob_expr_xml_func_helper.h index 1c734ce9b..f3d4f6620 100644 --- a/src/sql/engine/expr/ob_expr_xml_func_helper.h +++ b/src/sql/engine/expr/ob_expr_xml_func_helper.h @@ -21,6 +21,8 @@ #include "lib/xml/ob_xpath.h" #include "lib/xml/ob_xml_tree.h" #include "lib/xml/ob_xml_util.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" +#include "lib/xml/ob_binary_aggregate.h" using namespace oceanbase::common; @@ -36,6 +38,7 @@ class ObSchemaGetterGuard; namespace sql { +typedef PageArena ElementObjCacheStatArena; class ObExpr; class ObEvalCtx; @@ -88,6 +91,14 @@ public: static int get_xmltype_from_expr(const ObExpr *expr, ObEvalCtx &ctx, ObDatum *&xml_datum); + static int get_xmltype_from_expr(const ObExpr *expr, + ObEvalCtx &ctx, + ObDatum *&xml_datum, + MultimodeAlloctor &allocator); + static int mem_ctx_add_baseline(const ObExpr *expr, + ObEvalCtx &ctx, + ObMulModeMemCtx *&mem_ctx, + uint32_t multiple = 1); static int get_str_from_expr(const ObExpr *expr, ObEvalCtx &ctx, ObString &res, @@ -136,6 +147,51 @@ public: static int get_valid_default_ns_from_parent(ObXmlNode *cur_node, ObXmlAttribute* &default_ns); static int set_ns_recrusively(ObXmlNode *update_node, ObXmlAttribute *ns); + static int construct_doc( + ObMulModeMemCtx* mem_ctx, + const ObString &name_tag, + ObVector &value_vec, + const ObIJsonBase *attr_json, + bool has_attribute, + ObXmlDocument *&res_doc); + static int construct_element( + ObMulModeMemCtx* mem_ctx, + const ObString &name, + ObVector &value_vec, + const ObIJsonBase *attr, + ObXmlElement *&element, + bool &validity); + static int construct_attribute( + ObMulModeMemCtx* mem_ctx, + const ObIJsonBase *attr, + ObXmlElement *&element); + static int construct_element_children( + ObMulModeMemCtx* mem_ctx, + ObVector &value_vec, + ObXmlElement *&element, + ObXmlElement *valid_ele); + static int construct_element_value( + ObIAllocator &allocator, + ObExpr *xml_arg, + ObDatum *datum, + bool need_escape, + ObVector &value_vec); + static int construct_value_array( + ObIAllocator &allocator, + const ObString &value, + ObVector &res_value); + + static int concat_xml_type_nodes( + ObMulModeMemCtx* mem_ctx, + ObVector &xml_bin_str_vec, + ObString &res_bin_str); + + static int concat_xpath_result( + ObMulModeMemCtx* mem_ctx, + ObPathExprIter &xpath_iter, + ObString &bin_str, + bool &is_null_res); + private: static int add_ns_to_container_node(ObPathVarObject &container, ObString &prefix, diff --git a/src/sql/engine/expr/ob_expr_xml_sequence.cpp b/src/sql/engine/expr/ob_expr_xml_sequence.cpp index 2f6e848d7..9bc2e5cbf 100644 --- a/src/sql/engine/expr/ob_expr_xml_sequence.cpp +++ b/src/sql/engine/expr/ob_expr_xml_sequence.cpp @@ -17,6 +17,7 @@ #include "pl/ob_pl_resolver.h" #include "pl/ob_pl_package.h" #include "lib/utility/utility.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" #define USING_LOG_PREFIX SQL_ENG using namespace oceanbase::common; diff --git a/src/sql/engine/expr/ob_expr_xml_serialize.cpp b/src/sql/engine/expr/ob_expr_xml_serialize.cpp index 315e84a0a..1cae256bf 100644 --- a/src/sql/engine/expr/ob_expr_xml_serialize.cpp +++ b/src/sql/engine/expr/ob_expr_xml_serialize.cpp @@ -118,7 +118,6 @@ int ObExprXmlSerialize::eval_xml_serialize(const ObExpr &expr, ObEvalCtx &ctx, O { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); int64_t xml_doc_type = OB_XML_DOC_TYPE_IMPLICIT; int64_t opt_encoding_type = OB_XML_NONE_ENCODING; int64_t opt_version_type = OB_XML_NONE_VERSION; @@ -132,7 +131,9 @@ int ObExprXmlSerialize::eval_xml_serialize(const ObExpr &expr, ObEvalCtx &ctx, O ObDatum *xml_datum = NULL; ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -164,7 +165,7 @@ int ObExprXmlSerialize::eval_xml_serialize(const ObExpr &expr, ObEvalCtx &ctx, O LOG_WARN("fail to get indent size", K(ret)); } else if (OB_FAIL(get_and_check_int_from_expr(expr.args_[9], ctx, OB_XML_DEFAULTS_IMPLICIT, OB_XML_SHOW_DEFAULTS, opt_defaults))) { LOG_WARN("fail to get defaults option", K(ret)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[1], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[1], ctx, xml_datum, allocator))) { // according to xmlserialize behavior in oracle: it will check the xmltype data type after the checks IMPLICIT done LOG_WARN("fail to get xmltype data", K(ret)); } else if (xml_datum->is_null()) { diff --git a/src/sql/engine/expr/ob_expr_xmlcast.cpp b/src/sql/engine/expr/ob_expr_xmlcast.cpp index 171345dd9..b78b0d3e2 100644 --- a/src/sql/engine/expr/ob_expr_xmlcast.cpp +++ b/src/sql/engine/expr/ob_expr_xmlcast.cpp @@ -153,11 +153,12 @@ int ObExprXmlcast::eval_xmlcast(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res ObIMulModeBase *xml_doc = NULL; ObString xml_res_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &allocator = tmp_alloc_g.get_allocator(); ObCollationType cs_type = CS_TYPE_INVALID; + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -167,7 +168,7 @@ int ObExprXmlcast::eval_xmlcast(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res } else if (OB_UNLIKELY(expr.arg_cnt_ != 2)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid arg_cnt_", K(ret), K(expr.arg_cnt_)); - } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum))) { + } else if (OB_FAIL(ObXMLExprHelper::get_xmltype_from_expr(expr.args_[0], ctx, xml_datum, allocator))) { // temporally use LOG_WARN("fail to get xml str", K(ret)); } else if (OB_FAIL(ObXMLExprHelper::get_xml_base(mem_ctx, xml_datum, cs_type, ObNodeMemType::BINARY_TYPE, xml_doc))) { diff --git a/src/sql/engine/expr/ob_expr_xmlparse.cpp b/src/sql/engine/expr/ob_expr_xmlparse.cpp index 0b6588c3a..be885db9a 100644 --- a/src/sql/engine/expr/ob_expr_xmlparse.cpp +++ b/src/sql/engine/expr/ob_expr_xmlparse.cpp @@ -96,9 +96,10 @@ int ObExprXmlparse::eval_xmlparse(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &r bool need_format = false; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); - common::ObArenaAllocator &tmp_allocator = tmp_alloc_g.get_allocator(); + uint64_t tenant_id = ObMultiModeExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()); + MultimodeAlloctor tmp_allocator(tmp_alloc_g.get_allocator(), expr.type_, tenant_id, ret); + lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(tenant_id, "XMLModule")); ObMulModeMemCtx* mem_ctx = nullptr; - lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "XMLModule")); if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) { ret = OB_ERR_UNEXPECTED; @@ -108,14 +109,14 @@ int ObExprXmlparse::eval_xmlparse(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &r } else if (OB_UNLIKELY(expr.arg_cnt_ != 4)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid arg_cnt_", K(expr.arg_cnt_)); - } else if (OB_FAIL(expr.args_[3]->eval(ctx, xml_datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[3], ctx, xml_datum))) { LOG_WARN("get extra para failed", K(ret)); } else if (FALSE_IT(need_format = (xml_datum->get_int() & 0x08) != 0)) { } else if (OB_FAIL(get_clause_opt(expr, ctx, 0, xml_type, OB_XML_DOC_TYPE_COUNT))) { LOG_WARN("get document/context error", K(ret), K(xml_type)); } else if (OB_FAIL(get_clause_opt(expr, ctx, 2, is_wellformed, OB_WELLFORMED_COUNT))) { LOG_WARN("get wellformed error", K(ret), K(is_wellformed)); - } else if (OB_FAIL(expr.args_[1]->eval(ctx, xml_datum))) { + } else if (OB_FAIL(tmp_allocator.eval_arg(expr.args_[1], ctx, xml_datum))) { LOG_WARN("get extra para failed", K(ret)); } else if (expr.args_[1]->datum_meta_.type_ == ObNullType || xml_datum->is_null()) { is_xml_text_null = true; @@ -123,6 +124,7 @@ int ObExprXmlparse::eval_xmlparse(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &r LOG_WARN("get xml plain text failed", K(ret), K(is_xml_text_null)); } + tmp_allocator.set_baseline_size(xml_plain_text.length()); bool is_unparsed_res = false; if(OB_FAIL(ret)) { } else if (is_xml_text_null) { diff --git a/src/sql/engine/expr/ob_geo_expr_utils.cpp b/src/sql/engine/expr/ob_geo_expr_utils.cpp index 7307036df..24638c584 100644 --- a/src/sql/engine/expr/ob_geo_expr_utils.cpp +++ b/src/sql/engine/expr/ob_geo_expr_utils.cpp @@ -30,7 +30,7 @@ #include "lib/geo/ob_geo_3d.h" #include "lib/geo/ob_geo_reverse_coordinate_visitor.h" #include "lib/geo/ob_geo_cache_polygon.h" - +#include "share/object/ob_obj_cast_util.h" using namespace oceanbase::common; namespace oceanbase { @@ -128,7 +128,8 @@ int ObGeoExprUtils::construct_geometry(ObIAllocator &allocator, const ObSrsItem *&srs, ObGeometry *&geo, const char *func_name, - bool has_srid /* = true */) + bool has_srid /* = true */, + bool with_copy /* = true */) { int ret = OB_SUCCESS; const int64_t len = wkb.length(); @@ -155,8 +156,8 @@ int ObGeoExprUtils::construct_geometry(ObIAllocator &allocator, if (OB_FAIL(ret)) { // do nothing - } else if (OB_FAIL(ObGeoTypeUtil::construct_geometry(allocator, wkb, srs, geo, has_srid))) { - if ((OB_ERR_GIS_INVALID_DATA == ret && OB_NOT_NULL(func_name))) { + } else if (OB_FAIL(ObGeoTypeUtil::construct_geometry(allocator, wkb, srs, geo, has_srid, with_copy))) { + if (OB_ERR_GIS_INVALID_DATA == ret && OB_NOT_NULL(func_name)) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, func_name); } else if (OB_ERR_INVALID_GEOMETRY_TYPE == ret && OB_NOT_NULL(func_name)) { ret = OB_ERR_GIS_INVALID_DATA; @@ -556,7 +557,7 @@ int ObGeoExprUtils::get_box_bestsrid(ObGeogBox *geo_box1, int ObGeoExprUtils::normalize_wkb(const ObSrsItem *srs, ObString &wkb, - ObArenaAllocator &allocator, + ObIAllocator &allocator, ObGeometry *&geo) { int ret = OB_SUCCESS; @@ -750,18 +751,42 @@ void ObGeoExprUtils::geo_func_error_handle(int error_ret, const char* func_name) } } -int ObGeoExprUtils::zoom_in_geos_for_relation(ObGeometry &geo1, ObGeometry &geo2, - bool is_geo1_cached, bool is_geo2_cached) +int ObGeoExprUtils::zoom_in_geos_for_relation(const ObSrsItem *srs, ObGeometry &geo1, ObGeometry &geo2, bool is_geo1_cached, bool is_geo2_cached) { int ret = OB_SUCCESS; - if (geo1.get_zoom_in_value() > 0 || geo2.get_zoom_in_value() > 0) { - uint32_t zoom_in = geo1.get_zoom_in_value(); - zoom_in = zoom_in > geo2.get_zoom_in_value() ? zoom_in : geo2.get_zoom_in_value(); - ObGeoZoomInVisitor zoom_in_visitor(zoom_in); - if (!is_geo1_cached && OB_FAIL(geo1.do_visit(zoom_in_visitor))) { - LOG_WARN("failed to zoom in visit", K(ret), K(zoom_in)); - } else if (!is_geo2_cached && OB_FAIL(geo2.do_visit(zoom_in_visitor))) { - LOG_WARN("failed to zoom in visit", K(ret), K(zoom_in)); + uint32_t zoom_in_value1 = 0; + uint32_t zoom_in_value2 = 0; + if (geo1.get_srid() != geo2.get_srid()) { + ret = OB_ERR_GIS_INVALID_DATA; + LOG_WARN("geo1 and geo2 have different srids", K(ret), K(geo1.get_srid()), K(geo2.get_srid())); + } else if (OB_ISNULL(srs) || !srs->is_geographical_srs()) { + // do not zoom cartesian geometry + } else { + ObGeoZoomInVisitor zoom_in_visitor(0, true); + if (is_geo1_cached) { + } else if (OB_FAIL(geo1.do_visit(zoom_in_visitor))) { + LOG_WARN("failed to zoom in visit", K(ret)); + } else { + zoom_in_value1 = zoom_in_visitor.get_zoom_in_value(); + zoom_in_visitor.set_zoom_in_value(0); + } + + if (OB_FAIL(ret) || is_geo2_cached) { // do nothing + } else if (OB_FAIL(geo2.do_visit(zoom_in_visitor))) { + LOG_WARN("failed to zoom in visit", K(ret)); + } else { + zoom_in_value2 = zoom_in_visitor.get_zoom_in_value(); + } + + if (OB_SUCC(ret) && (zoom_in_value1 > 0 || zoom_in_value2 > 0)) { + uint32_t zoom_in = zoom_in_value1 > zoom_in_value2 ? zoom_in_value1 : zoom_in_value2; + zoom_in_visitor.set_is_calc_zoom(false); + zoom_in_visitor.set_zoom_in_value(zoom_in); + if (OB_FAIL(geo1.do_visit(zoom_in_visitor))) { + LOG_WARN("failed to zoom in visit", K(ret), K(zoom_in)); + } else if (OB_FAIL(geo2.do_visit(zoom_in_visitor))) { + LOG_WARN("failed to zoom in visit", K(ret), K(zoom_in)); + } } } return ret; @@ -863,20 +888,20 @@ int ObGeoExprUtils::length_unit_conversion(const ObString &unit_str, const ObSrs return ret; } -int ObGeoExprUtils::get_input_geometry(ObIAllocator &allocator, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, - omt::ObSrsCacheGuard &srs_guard, const char *func_name, - const ObSrsItem *&srs, ObGeometry *&geo) +int ObGeoExprUtils::get_input_geometry(const char* func_name, MultimodeAlloctor &allocator, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, + omt::ObSrsCacheGuard &srs_guard, const ObSrsItem *&srs, ObGeometry *&geo) { int ret = OB_SUCCESS; ObString wkb = gis_datum->get_string(); ObGeoType type = ObGeoType::GEOTYPEMAX; uint32_t srid = -1; - if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, + if (OB_FAIL(ObTextStringHelper::read_real_string_data_with_copy(allocator, *gis_datum, gis_arg->datum_meta_, gis_arg->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real string data", K(ret), K(wkb)); + } else if (FALSE_IT(allocator.add_baseline_size(wkb.length()))) { } else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb, type, srid))) { if (ret == OB_ERR_GIS_INVALID_DATA) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, func_name); @@ -890,18 +915,18 @@ int ObGeoExprUtils::get_input_geometry(ObIAllocator &allocator, ObDatum *gis_dat geo, srs, func_name, - ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) { + ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | GEO_NOT_COPY_WKB))) { LOG_WARN("get first geo by wkb failed", K(ret)); } return ret; } int ObGeoExprUtils::union_polygons( - ObIAllocator &allocator, const ObGeometry &poly, ObGeometry *&polygons_union) + lib::MemoryContext &mem_ctx, const ObGeometry &poly, ObGeometry *&polygons_union) { int ret = OB_SUCCESS; ObGeometry *union_res = nullptr; - ObGeoEvalCtx union_ctx(&allocator); + ObGeoEvalCtx union_ctx(mem_ctx); if (OB_FAIL(union_ctx.append_geo_arg(&poly))) { LOG_WARN("failed to append geo arg to gis context", K(ret), K(union_ctx.get_geo_count())); } else if (OB_FAIL(union_ctx.append_geo_arg(polygons_union))) { @@ -909,16 +934,16 @@ int ObGeoExprUtils::union_polygons( } else if (OB_FAIL(ObGeoFunc::geo_func::eval(union_ctx, union_res))) { LOG_WARN("eval boost union failed", K(ret)); } else { - allocator.free(polygons_union); polygons_union = union_res; } return ret; } -int ObGeoExprUtils::make_valid_polygon(ObGeometry *poly, ObIAllocator &allocator, ObGeometry *&valid_poly) +int ObGeoExprUtils::make_valid_polygon(ObGeometry *poly, lib::MemoryContext &mem_ctx, ObGeometry *&valid_poly) { int ret = OB_SUCCESS; - ObGeoEvalCtx gis_context(&allocator); + ObGeoEvalCtx gis_context(mem_ctx); + ObIAllocator &allocator = mem_ctx->get_arena_allocator(); int res_unused = 0; if (OB_ISNULL(poly) || (poly->type() != ObGeoType::POLYGON && poly->type() != ObGeoType::MULTIPOLYGON)) { @@ -931,23 +956,21 @@ int ObGeoExprUtils::make_valid_polygon(ObGeometry *poly, ObIAllocator &allocator LOG_WARN("eval boost dissolve polygon failed", K(ret)); } else if (poly->type() == ObGeoType::POLYGON) { if (OB_FAIL(make_valid_polygon_inner(static_cast(*poly), - allocator, valid_poly))) { + mem_ctx, valid_poly))) { LOG_WARN("make polygon valid failed", K(ret)); } } else { ObCartesianMultipolygon &mpy = *reinterpret_cast(poly); for (uint32_t i = 0; OB_SUCC(ret) && i < mpy.size(); ++i) { ObGeometry *valid_inner_poly = nullptr; - if (OB_FAIL(make_valid_polygon_inner(mpy[i], allocator, valid_inner_poly))) { + if (OB_FAIL(make_valid_polygon_inner(mpy[i], mem_ctx, valid_inner_poly))) { LOG_WARN("fail to make polygon valid", K(ret)); } else if (OB_NOT_NULL(valid_inner_poly)) { if (OB_ISNULL(valid_poly)) { valid_poly = valid_inner_poly; } else if (!valid_inner_poly->is_empty() - && OB_FAIL(union_polygons(allocator, *valid_inner_poly, valid_poly))) { + && OB_FAIL(union_polygons(mem_ctx, *valid_inner_poly, valid_poly))) { LOG_WARN("fail to union holes", K(ret)); - } else { - allocator.free(valid_inner_poly); } } } @@ -956,9 +979,10 @@ int ObGeoExprUtils::make_valid_polygon(ObGeometry *poly, ObIAllocator &allocator } int ObGeoExprUtils::make_valid_polygon_inner( - ObCartesianPolygon &poly, ObIAllocator &allocator, ObGeometry *&valid_poly) + ObCartesianPolygon &poly, lib::MemoryContext &mem_ctx, ObGeometry *&valid_poly) { int ret = OB_SUCCESS; + ObArenaAllocator &allocator = mem_ctx->get_arena_allocator(); if (!poly.empty() && poly.inner_ring_size() != 0) { ObCartesianPolygon tmp_ext_poly; tmp_ext_poly.exterior_ring() = poly.exterior_ring(); @@ -968,21 +992,16 @@ int ObGeoExprUtils::make_valid_polygon_inner( ObCartesianPolygon tmp_poly; tmp_poly.exterior_ring() = poly.inner_ring(i); bool is_intersects = false; - ObGeoEvalCtx correct_context(&allocator); - ObGeoEvalCtx intersects_ctx(&allocator); + ObGeoEvalCtx intersects_ctx(mem_ctx); int res_unused; - if (OB_FAIL(correct_context.append_geo_arg(&tmp_poly))) { + if (OB_FAIL(intersects_ctx.append_geo_arg(&tmp_poly))) { LOG_WARN("build geo gis context failed", K(ret)); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(correct_context, res_unused))) { + } else if (OB_FAIL(ObGeoFunc::geo_func::eval(intersects_ctx, res_unused))) { LOG_WARN("eval geo correct failed", K(ret)); } else if (OB_FAIL(intersects_ctx.append_geo_arg(&tmp_ext_poly))) { LOG_WARN("failed to append geo arg to gis context", K(ret), K(intersects_ctx.get_geo_count())); - } else if (OB_FAIL(intersects_ctx.append_geo_arg(&tmp_poly))) { - LOG_WARN("failed to append geo arg to gis context", - K(ret), - K(intersects_ctx.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval( intersects_ctx, is_intersects))) { LOG_WARN("eval boost intersects failed", K(ret)); @@ -996,7 +1015,7 @@ int ObGeoExprUtils::make_valid_polygon_inner( } else { holes_union = holes; } - } else if (OB_FAIL(union_polygons(allocator, *&tmp_poly, holes_union))) { + } else if (OB_FAIL(union_polygons(mem_ctx, *&tmp_poly, holes_union))) { LOG_WARN("fail to union holes", K(ret)); } } else { @@ -1009,7 +1028,7 @@ int ObGeoExprUtils::make_valid_polygon_inner( } else { shells_union = shells; } - } else if (OB_FAIL(union_polygons(allocator, *&tmp_poly, shells_union))) { + } else if (OB_FAIL(union_polygons(mem_ctx, *&tmp_poly, shells_union))) { LOG_WARN("fail to union shells", K(ret)); } } @@ -1018,7 +1037,7 @@ int ObGeoExprUtils::make_valid_polygon_inner( } else if (OB_ISNULL(holes_union)) { holes_union = &tmp_ext_poly; } else { - ObGeoEvalCtx diff_ctx(&allocator); + ObGeoEvalCtx diff_ctx(mem_ctx); ObGeometry *diff_holes = nullptr; if (OB_FAIL(diff_ctx.append_geo_arg(&tmp_ext_poly))) { LOG_WARN("failed to append geo arg to gis context", K(ret), K(diff_ctx.get_geo_count())); @@ -1032,7 +1051,7 @@ int ObGeoExprUtils::make_valid_polygon_inner( } if (OB_FAIL(ret)) { } else if (OB_NOT_NULL(shells_union) - && OB_FAIL(union_polygons(allocator, *shells_union, holes_union))) { + && OB_FAIL(union_polygons(mem_ctx, *shells_union, holes_union))) { LOG_WARN("fail to union shells", K(ret)); } else { if (holes_union->type() == ObGeoType::MULTIPOLYGON @@ -1043,28 +1062,20 @@ int ObGeoExprUtils::make_valid_polygon_inner( } } } else if (!poly.empty() && poly.inner_ring_size() == 0) { - ObGeoEvalCtx dissol_ctx(&allocator); + ObGeoEvalCtx dissol_ctx(mem_ctx); ObGeometry *diff_holes; if (OB_FAIL(dissol_ctx.append_geo_arg(&poly))) { LOG_WARN("failed to append geo arg to gis context", K(ret), K(dissol_ctx.get_geo_count())); } else if (OB_FAIL(ObGeoFunc::geo_func::eval(dissol_ctx, diff_holes))) { LOG_WARN("eval boost dissolve polygon failed", K(ret)); } else { - ObGeoEvalCtx gis_context(&allocator); - int res_unused; - if (OB_FAIL(gis_context.append_geo_arg(diff_holes))) { - LOG_WARN("failed to append geo arg to gis context", K(ret), K(gis_context.get_geo_count())); - } else if (OB_FAIL(ObGeoFunc::geo_func::eval(gis_context, res_unused))) { - LOG_WARN("eval boost correct polygon failed", K(ret)); - } else { - valid_poly = diff_holes; - } + valid_poly = diff_holes; } } else if (poly.empty()) { valid_poly = &poly; } else { int unused = 0; - ObGeoEvalCtx gis_context(&allocator); + ObGeoEvalCtx gis_context(mem_ctx); if (OB_FAIL(gis_context.append_geo_arg(&poly))) { LOG_WARN("failed to append geo arg to gis context", K(ret), K(gis_context.get_geo_count())); } else if (OB_FAIL( @@ -1114,7 +1125,7 @@ void ObGeoExprUtils::expr_get_const_param_cache(ObGeoConstParamCache* const_para } } -int ObGeoExprUtils::expr_prepare_build_geometry(ObIAllocator &allocator, const ObDatum &datum, const ObExpr &gis_arg, ObString& wkb, ObGeoType& type, uint32_t& srid) +int ObGeoExprUtils::expr_prepare_build_geometry(MultimodeAlloctor &allocator, const ObDatum &datum, const ObExpr &gis_arg, ObString& wkb, ObGeoType& type, uint32_t& srid) { INIT_SUCC(ret); if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, datum, @@ -1156,10 +1167,10 @@ void ObGeoExprUtils::init_boxes_by_cache(ObGeogBox *&box_ptr1, ObGeogBox& box1, } } -int ObGeoExprUtils::init_box_by_geo(ObGeometry &geo, ObIAllocator &allocator, ObGeogBox *&box_ptr) +int ObGeoExprUtils::init_box_by_geo(ObGeometry &geo, lib::MemoryContext& ctx, ObGeogBox *&box_ptr) { int ret = OB_SUCCESS; - ObGeoEvalCtx gis_context(&allocator); + ObGeoEvalCtx gis_context(ctx); bool result = false; if (OB_FAIL(gis_context.append_geo_arg(&geo))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -1169,7 +1180,7 @@ int ObGeoExprUtils::init_box_by_geo(ObGeometry &geo, ObIAllocator &allocator, Ob return ret; } -int ObGeoExprUtils::check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, ObIAllocator &allocator, +int ObGeoExprUtils::check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, lib::MemoryContext& ctx, ObGeoConstParamCache* const_param_cache, bool is_geo1_cached, bool is_geo2_cached, bool& box_intersects) { @@ -1181,8 +1192,8 @@ int ObGeoExprUtils::check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, ObI ObGeogBox box2; init_boxes_by_cache(box_ptr1, box1, box_ptr2, box2, const_param_cache, is_geo1_cached, is_geo2_cached); - if ((OB_ISNULL(box_ptr1) && OB_FAIL(init_box_by_geo(geo1, allocator, box_ptr1))) - || (OB_ISNULL(box_ptr2) && OB_FAIL(init_box_by_geo(geo2, allocator, box_ptr2)))) { + if ((OB_ISNULL(box_ptr1) && OB_FAIL(init_box_by_geo(geo1, ctx, box_ptr1))) + || (OB_ISNULL(box_ptr2) && OB_FAIL(init_box_by_geo(geo2, ctx, box_ptr2)))) { LOG_WARN("get failed", K(ret)); } else if (OB_ISNULL(box_ptr1) || OB_ISNULL(box_ptr2)) { ret = OB_BAD_NULL_ERROR; @@ -1240,7 +1251,6 @@ int ObGeoConstParamCache::add_const_param_cache(int arg_idx, const common::ObGeo } else { geo->set_data(data); geo->set_srid(cache.get_srid()); - geo->set_zoom_in_value(cache.get_zoom_in_value()); if (arg_idx == 0) { param1_ = geo; } else if (arg_idx == 1) { @@ -1262,6 +1272,34 @@ int ObGeoExprUtils::create_3D_empty_collection(ObIAllocator &allocator, uint32_t return ret; } +// ob_obj_cast.cpp string_double does not return error +// when empty string is converted to double in mysql mode +int ObGeoExprUtils::string_to_double(const common::ObString &in_str, ObCollationType cs_type, + double &res) +{ + int ret = OB_SUCCESS; + if (in_str.empty()) { + ret = OB_ERR_DOUBLE_TRUNCATED; + LOG_WARN("input string is empty", K(ret), K(in_str)); + } else { + int err = 0; + char *endptr = NULL; + double out_val = ObCharset::strntodv2(in_str.ptr(), in_str.length(), &endptr, &err); + if (EOVERFLOW == err && (-DBL_MAX == out_val || DBL_MAX == out_val)) { + ret = OB_DATA_OUT_OF_RANGE; + LOG_WARN("value is out of range", K(ret), K(out_val)); + } else { + if (OB_FAIL(check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err, cs_type))) { + LOG_WARN("fail to check convert str err", K(ret), K(in_str), K(out_val), K(err)); + ret = OB_ERR_DOUBLE_TRUNCATED; + } else { + res = out_val; + } + } + } + return ret; +} + void ObGeoConstParamCache::add_cached_geo(int arg_idx, common::ObCachedGeom *cache) { if (arg_idx == 0) { @@ -1275,10 +1313,11 @@ int ObGeoExprUtils::get_intersects_res(ObGeometry &geo1, ObGeometry &geo2, ObExpr *gis_arg1, ObExpr *gis_arg2, ObGeoConstParamCache* const_param_cache, const ObSrsItem *srs, - ObArenaAllocator& temp_allocator, bool& res) + lib::MemoryContext *mem_ctx, bool& res) { INIT_SUCC(ret); - ObGeoEvalCtx gis_context(&temp_allocator); + ObGeoEvalCtx gis_context(*mem_ctx); + ObArenaAllocator &temp_allocator = (*mem_ctx)->get_arena_allocator(); bool result = false; if (OB_FAIL(gis_context.append_geo_arg(&geo1)) || OB_FAIL(gis_context.append_geo_arg(&geo2))) { LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count())); @@ -1344,5 +1383,6 @@ int ObGeoExprUtils::get_intersects_res(ObGeometry &geo1, ObGeometry &geo2, return ret; } + } // sql } // oceanbase diff --git a/src/sql/engine/expr/ob_geo_expr_utils.h b/src/sql/engine/expr/ob_geo_expr_utils.h index 967f63c27..4f38cde41 100644 --- a/src/sql/engine/expr/ob_geo_expr_utils.h +++ b/src/sql/engine/expr/ob_geo_expr_utils.h @@ -25,6 +25,8 @@ #include "share/ob_i_sql_expression.h" // for ObExprCtx #include "observer/omt/ob_tenant_srs.h" #include "sql/engine/expr/ob_expr_lob_utils.h" +#include "sql/engine/expr/ob_expr_multi_mode_func_helper.h" +//#include "lib/rc/context.h" namespace oceanbase { @@ -130,7 +132,8 @@ public: const common::ObSrsItem *&srs, common::ObGeometry *&geo, const char *func_name, - bool has_srid = true); + bool has_srid = true, + bool with_copy = true); static int check_coordinate_range(const common::ObSrsItem *srs, common::ObGeometry *geo, const char *func_name, @@ -153,7 +156,7 @@ public: int32 &bestsrid); static int normalize_wkb(const common::ObSrsItem *srs, common::ObString &wkb, - common::ObArenaAllocator &allocator, + common::ObIAllocator &allocator, common::ObGeometry *&geo); static int normalize_wkb(common::ObString &proj4text, common::ObGeometry *geo); // for st_transform @@ -183,35 +186,35 @@ public: common::ObString &res_wkb, uint32_t srs_id = 0); static void geo_func_error_handle(int ret, const char* func_name); - static int zoom_in_geos_for_relation(common::ObGeometry &geo1, common::ObGeometry &geo2, + static int zoom_in_geos_for_relation(const ObSrsItem *srs, common::ObGeometry &geo1, common::ObGeometry &geo2, bool is_geo1_cached = false, bool is_geo2_cached = false); static int pack_geo_res(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res, const ObString &str); static int reverse_coordinate(ObGeometry *geo, const char *func_name); static int length_unit_conversion(const ObString &unit_str, const ObSrsItem *srs, double in_num, double &out_num); - static int get_input_geometry(ObIAllocator &allocator, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, - omt::ObSrsCacheGuard &srs_guard, const char *func_name, - const ObSrsItem *&srs, ObGeometry *&geo); + static int get_input_geometry(const char* func_name, MultimodeAlloctor &allocator, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg, + omt::ObSrsCacheGuard &srs_guard, const ObSrsItem *&srs, ObGeometry *&geo); static int make_valid_polygon_inner( - ObCartesianPolygon &poly, ObIAllocator &allocator, ObGeometry *&valid_poly); + ObCartesianPolygon &poly, lib::MemoryContext &mem_ctx, ObGeometry *&valid_poly); static int union_polygons( - ObIAllocator &allocator, const ObGeometry &poly, ObGeometry *&polygons_union); - static int make_valid_polygon(ObGeometry *poly, ObIAllocator &allocator, ObGeometry *&valid_poly); + lib::MemoryContext &mem_ctx, const ObGeometry &poly, ObGeometry *&polygons_union); + static int make_valid_polygon(ObGeometry *poly, lib::MemoryContext &mem_ctx, ObGeometry *&valid_poly); static int create_3D_empty_collection(ObIAllocator &allocator, uint32_t srid, bool is_3d, bool is_geog, ObGeometry *&geo); static ObGeoConstParamCache* get_geo_constParam_cache(const uint64_t& id, ObExecContext *exec_ctx); static void expr_get_const_param_cache(ObGeoConstParamCache* const_param_cache, ObGeometry *&geo, uint32_t& srid, bool& is_geo_cached, int cache_idx); - static int expr_prepare_build_geometry(ObIAllocator &allocator, const ObDatum &datum, const ObExpr &gis_arg, ObString& wkb, ObGeoType& type, uint32_t& srid); - static int check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, ObIAllocator &allocator, + static int expr_prepare_build_geometry(MultimodeAlloctor &allocator, const ObDatum &datum, const ObExpr &gis_arg, ObString& wkb, ObGeoType& type, uint32_t& srid); + static int check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, lib::MemoryContext& ctx, ObGeoConstParamCache* const_param_cache, bool is_geo1_cached, bool is_geo2_cached, bool& box_intersects); + static int string_to_double(const common::ObString &in_str, ObCollationType cs_type, double &res); static int get_intersects_res(ObGeometry &geo1, ObGeometry &geo2, ObExpr *gis_arg1, ObExpr *gis_arg2, ObGeoConstParamCache* const_param_cache, const ObSrsItem *srs, - ObArenaAllocator& temp_allocator, bool& res); + lib::MemoryContext *mem_ctx, bool& res); private: static int ob_geo_find_unit(const ObGeoUnit *units, const ObString &name, double &factor); - static int init_box_by_geo(ObGeometry &geo, ObIAllocator &allocator, ObGeogBox *&box_ptr); + static int init_box_by_geo(ObGeometry &geo, lib::MemoryContext& ctx, ObGeogBox *&box_ptr); static void init_boxes_by_cache(ObGeogBox *&box_ptr1, ObGeogBox& box1, ObGeogBox *&box_ptr2, ObGeogBox& box2, ObGeoConstParamCache* const_param_cache, diff --git a/src/sql/monitor/flt/ob_flt_utils.cpp b/src/sql/monitor/flt/ob_flt_utils.cpp index 833ed14d6..3cea81394 100644 --- a/src/sql/monitor/flt/ob_flt_utils.cpp +++ b/src/sql/monitor/flt/ob_flt_utils.cpp @@ -626,7 +626,7 @@ namespace sql jo_ptr->json_type() != ObJsonNodeType::J_ARRAY) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid json type", K(ret), K(jo_ptr->json_type())); - } else if (OB_FAIL(jo_ptr->print(j_buf, true, false, 0))) { + } else if (OB_FAIL(jo_ptr->print(j_buf, true, 0, false, 0))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("fail to convert json to string", K(ret)); } else { diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index 453ea1b58..09ed94612 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -7537,9 +7537,7 @@ int ObSPIService::convert_obj(ObPLExecCtx *ctx, && result_types[i].get_meta_type().is_ext() && !ob_is_xml_pl_type(result_types[i].get_obj_type(), result_types[i].get_udt_id())) { // sql udt or oracle gis can cast to pl extend, null from sql udt type can cast to pl extend(xmltype) - // but null may not cast to other pl extends (return error 4016 in store_datums) // support: select extract(xmlparse(document 'a'), '/b') into xml_data from dual; - // not support: select null into xml_data from dual; ret = OB_ERR_INTO_EXPR_ILLEGAL; LOG_WARN("PLS-00597: expression 'string' in the INTO list is of wrong type", K(ret), K(obj), K(i), K(current_type.at(i)), K(result_types[i])); } else { diff --git a/src/sql/plan_cache/ob_sql_parameterization.cpp b/src/sql/plan_cache/ob_sql_parameterization.cpp index 4688819cb..a8ed10991 100644 --- a/src/sql/plan_cache/ob_sql_parameterization.cpp +++ b/src/sql/plan_cache/ob_sql_parameterization.cpp @@ -2075,13 +2075,11 @@ int ObSqlParameterization::mark_tree(ParseNode *tree ,SqlInfo &sql_info) if (OB_FAIL(mark_args(node[1], mark_arr, ARGS_NUMBER_ONE, sql_info))) { SQL_PC_LOG(WARN, "fail to mark arg", K(ret)); } - } else if ((0 == func_name.case_compare("substr") - || 0 == func_name.case_compare("extract_xml")) - && (3 == node[1]->num_child_)) { + } else if (0 == func_name.case_compare("substr") && (3 == node[1]->num_child_)) { const int64_t ARGS_NUMBER_THREE = 3; bool mark_arr[ARGS_NUMBER_THREE] = {0, 1, 1}; //0表示参数化, 1 表示不参数化 if (OB_FAIL(mark_args(node[1], mark_arr, ARGS_NUMBER_THREE, sql_info))) { - SQL_PC_LOG(WARN, "fail to mark arg", K(ret)); + SQL_PC_LOG(WARN, "fail to mark substr arg", K(ret)); } } else if (0 == func_name.case_compare("xmlserialize") && (10 == node[1]->num_child_)) { diff --git a/src/sql/printer/ob_raw_expr_printer.cpp b/src/sql/printer/ob_raw_expr_printer.cpp index bc9555fc2..879d7fe32 100644 --- a/src/sql/printer/ob_raw_expr_printer.cpp +++ b/src/sql/printer/ob_raw_expr_printer.cpp @@ -3351,6 +3351,12 @@ int ObRawExprPrinter::print(ObSysFunRawExpr *expr) } break; } + case T_FUN_SYS_XML_FOREST : { + if (OB_FAIL(print_xml_forest_expr(expr))) { + LOG_WARN("print xml_forest expr failed", K(ret)); + } + break; + } case T_FUN_SYS_XML_ATTRIBUTES : { if (OB_FAIL(print_xml_attributes_expr(expr))) { LOG_WARN("print xml_attributes expr failed", K(ret)); @@ -4984,6 +4990,43 @@ int ObRawExprPrinter::print_xml_element_expr(ObSysFunRawExpr *expr) return ret; } +int ObRawExprPrinter::print_xml_forest_expr(ObSysFunRawExpr *expr) +{ + int ret = OB_SUCCESS; + int num = expr->get_param_count(); + int64_t format_type = 0; + if (num % 3 != 0) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected param count of expr", K(ret), KPC(expr)); + } else { + DATA_PRINTF("xmlforest("); + for (int i = 0; i < num / 3; i++) { + PRINT_EXPR(expr->get_param_expr(3 * i)); + format_type = static_cast(expr->get_param_expr(3 * i + 2))->get_value().get_int(); + if (format_type == 0) { + DATA_PRINTF(" AS "); + int64_t cur_pos = *pos_; + PRINT_EXPR(expr->get_param_expr(3 * i + 1)); + int64_t new_pos = *pos_; + if (buf_[cur_pos] == '\'') { + buf_[cur_pos] = '"'; + } + if (buf_[new_pos - 1] == '\'') { + buf_[new_pos - 1] = '"'; + } + } else if (format_type == 1) { + DATA_PRINTF(" AS EVALNAME "); + PRINT_EXPR(expr->get_param_expr(3 * i + 1)); + } + if (i != num / 3 - 1) { + DATA_PRINTF(", "); + } + } + DATA_PRINTF(")"); + } + return ret; +} + int ObRawExprPrinter::print_xml_agg_expr(ObAggFunRawExpr *expr) { INIT_SUCC(ret); diff --git a/src/sql/printer/ob_raw_expr_printer.h b/src/sql/printer/ob_raw_expr_printer.h index 68caa06ac..7434965d7 100644 --- a/src/sql/printer/ob_raw_expr_printer.h +++ b/src/sql/printer/ob_raw_expr_printer.h @@ -155,6 +155,7 @@ private: int print_window_clause(ObWinFunRawExpr *expr); int print_xml_parse_expr(ObSysFunRawExpr *expr); int print_xml_element_expr(ObSysFunRawExpr *expr); + int print_xml_forest_expr(ObSysFunRawExpr *expr); int print_xml_attributes_expr(ObSysFunRawExpr *expr); int print_xml_agg_expr(ObAggFunRawExpr *expr); int print_xml_serialize_expr(ObSysFunRawExpr *expr); diff --git a/src/sql/resolver/expr/ob_raw_expr.h b/src/sql/resolver/expr/ob_raw_expr.h index b4654fa13..a27658cf9 100644 --- a/src/sql/resolver/expr/ob_raw_expr.h +++ b/src/sql/resolver/expr/ob_raw_expr.h @@ -185,7 +185,9 @@ extern ObRawExpr *USELESS_POINTER; || ((op) == T_FUN_SYS_PRIV_ST_POINTONSURFACE) \ || ((op) == T_FUN_SYS_PRIV_ST_GEOMETRYTYPE) \ || ((op) == T_FUN_SYS_PRIV_ST_ASMVTGEOM) \ - || ((op) == T_FUN_SYS_PRIV_ST_MAKE_VALID)) \ + || ((op) == T_FUN_SYS_PRIV_ST_MAKE_VALID) \ + || ((op) == T_FUN_SYS_PRIV_ST_GEOHASH) \ + || ((op) == T_FUN_SYS_PRIV_ST_MAKEPOINT)) \ #define IS_GEO_OP(op) ((IS_MYSQL_GEO_OP(op)) || IS_PRIV_GEO_OP(op)) diff --git a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp index 49f3b4003..bf81ee4d9 100644 --- a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp @@ -1319,6 +1319,12 @@ int ObRawExprResolverImpl::do_recursive_resolve(const ParseNode *node, } break; } + case T_FUN_SYS_XML_FOREST: { + if (OB_FAIL(process_xml_forest_node(node, expr))) { + LOG_WARN("fail to process xml forest node", K(ret), K(node)); + } + break; + } case T_FUN_SYS_XML_ATTRIBUTES: { if (OB_FAIL(process_xml_attributes_node(node, expr))) { LOG_WARN("fail to process xmlattributes node", K(ret), K(node)); @@ -2549,6 +2555,8 @@ void ObRawExprResolverImpl::get_special_func_ident_name(ObString &ident_name, co // get ident name of spacial exprs not using first child as function name if (func_type == T_FUN_SYS_XML_ELEMENT) { ident_name = ObString::make_string("xmlelement"); + } else if (func_type == T_FUN_SYS_XML_FOREST) { + ident_name = ObString::make_string("xmlforest"); } else if (func_type == T_FUN_SYS_XMLPARSE) { ident_name = ObString::make_string("xmlparse"); } else if (func_type == T_FUN_ORA_XMLAGG) { @@ -2629,6 +2637,8 @@ int ObRawExprResolverImpl::resolve_func_node_of_obj_access_idents(const ParseNod OZ (process_xmlparse_node(&func_node, func_expr)); } else if (func_node.type_ == T_FUN_SYS_XML_ELEMENT) { OZ (process_xml_element_node(&func_node, func_expr)); + } else if (func_node.type_ == T_FUN_SYS_XML_FOREST) { + OZ (process_xml_forest_node(&func_node, func_expr)); } else if (func_node.type_ == T_FUN_ORA_XMLAGG) { OZ (process_agg_node(&func_node, func_expr)); }else { @@ -2744,6 +2754,7 @@ int ObRawExprResolverImpl::resolve_left_node_of_obj_access_idents(const ParseNod OZ (q_name.access_idents_.push_back(ObObjAccessIdent(ident_name, OB_INVALID_INDEX)), K(q_name)); } else if (T_FUN_SYS == left_node.type_ || T_FUN_SYS_XML_ELEMENT == left_node.type_ + || T_FUN_SYS_XML_FOREST == left_node.type_ || T_FUN_SYS_XMLPARSE == left_node.type_ || T_FUN_ORA_XMLAGG == left_node.type_) { OZ (resolve_func_node_of_obj_access_idents(left_node, q_name)); @@ -6851,6 +6862,74 @@ int ObRawExprResolverImpl::process_json_mergepatch_node(const ParseNode *node, O return ret; } +int ObRawExprResolverImpl::process_xml_forest_node(const ParseNode *node, ObRawExpr *&expr) +{ + INIT_SUCC(ret); + CK(OB_NOT_NULL(node)); + CK(node->type_ == T_FUN_SYS_XML_FOREST); + + ObSysFunRawExpr *func_expr = NULL; + OZ(ctx_.expr_factory_.create_raw_expr(T_FUN_SYS_XML_FOREST, func_expr)); + CK(OB_NOT_NULL(func_expr)); + OX(func_expr->set_func_name(ObString::make_string("xmlforest"))); + + for (int i = 0; i < node->num_child_ && OB_SUCC(ret); i++) { + ParseNode *param_node = node->children_[i]; + ParseNode *value_node = NULL; + ParseNode *tag_node = NULL; + ObRawExpr *value_expr = NULL; + ObRawExpr *tag_expr = NULL; + ObRawExpr *lable_expr = NULL; + if (param_node->type_ != T_EXPR_LIST) { + LOG_WARN("empty/invalid param_node", K(param_node->type_)); + } else { + if (param_node->num_child_ != 3) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid param_node", K(param_node->num_child_)); + } else { + value_node = param_node->children_[0]; + tag_node = param_node->children_[1]; + } + // fill tag + if (OB_FAIL(ret)) { + } else if (tag_node->type_ == T_VARCHAR && tag_node->str_value_ == NULL) { + if (value_node->type_ == T_OBJ_ACCESS_REF && OB_NOT_NULL(value_node->children_[0])) { + // fill tag with column name + if (value_node->children_[0]->str_value_ != NULL && value_node->children_[0]->str_len_ > 0) { + tag_node->str_value_ = value_node->children_[0]->str_value_; + tag_node->str_len_ = value_node->children_[0]->str_len_; + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to fill the empty tag", K(value_node->children_[0]->str_value_)); + } + } else { + // not the case that can fill the tag name with column name + ret = OB_ERR_XMLELEMENT_ALIASED; + LOG_USER_ERROR(OB_ERR_XMLELEMENT_ALIASED, i + 1); + } + } + if (OB_FAIL(ret)) { + } else if (OB_NOT_NULL(value_node->raw_text_) && STRCMP(value_node->raw_text_, "NULL") == 0) { // NULL input + LOG_WARN("NULL value, skip", K(value_node->num_child_)); + } else { + OZ(recursive_resolve(value_node, value_expr)); + CK(OB_NOT_NULL(value_expr)); + OZ(func_expr->add_param_expr(value_expr)); + OZ(recursive_resolve(tag_node, tag_expr)); + CK(OB_NOT_NULL(tag_expr)); + OZ(func_expr->add_param_expr(tag_expr)); + CK(param_node->children_[2]->type_ == T_INT); + OZ(recursive_resolve(param_node->children_[2], lable_expr)); + CK(OB_NOT_NULL(lable_expr)); + OZ(func_expr->add_param_expr(lable_expr)); + } + } + } + + OX(expr = func_expr); + return ret; +} + int ObRawExprResolverImpl::process_is_json_node(const ParseNode *node, ObRawExpr *&expr) { INIT_SUCC(ret); diff --git a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.h b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.h index 4a0e8ab58..98e4a39f0 100644 --- a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.h +++ b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.h @@ -208,6 +208,7 @@ private: int process_sql_udt_construct_node(const ParseNode *node, ObRawExpr *&expr); int process_sql_udt_attr_access_node(const ParseNode *node, ObRawExpr *&expr); int process_xml_element_node(const ParseNode *node, ObRawExpr *&expr); + int process_xml_forest_node(const ParseNode *node, ObRawExpr *&expr); int process_xml_attributes_node(const ParseNode *node, ObRawExpr *&expr); int process_xml_attributes_values_node(const ParseNode *node, ObRawExpr *&expr); int process_xmlparse_node(const ParseNode *node, ObRawExpr *&expr); diff --git a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/st_distance_mysql.result b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/st_distance_mysql.result index c87e5a997..962993eea 100644 --- a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/st_distance_mysql.result +++ b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/st_distance_mysql.result @@ -3169,6 +3169,25 @@ st_distance(ST_GEOMFROMTEXT('POINT(0 0)', 4053), ST_GEOMFROMTEXT('POINT(0 45)', select st_distance(ST_GEOMFROMTEXT('POINT(0 0)', 4053), ST_GEOMFROMTEXT('POINT(0 45)', 4053), "Indian yard (1937)"); st_distance(ST_GEOMFROMTEXT('POINT(0 0)', 4053), ST_GEOMFROMTEXT('POINT(0 45)', 4053), "Indian yard (1937)") 5472415.653115767 +SET @coll1 = ST_GEOMFROMTEXT(@star_collection_multilinestr); +SET @coll2 = ST_GEOMFROMTEXT(@star_collection_elems_3); +SELECT ST_DISTANCE( +GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(@coll1, @coll1),@coll1),@coll1),@coll1),@coll1),@coll1),@coll1),@coll1), +GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(@coll2, @coll2),@coll2),@coll2),@coll2),@coll2),@coll2),@coll2),@coll2) +); +ST_DISTANCE( +GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(@coll1, @coll1),@coll1),@coll1),@coll1),@coll1),@coll1),@coll1),@coll1), +GEOMETRYCOLLECTIO +30 +SELECT ST_DISTANCE( +GEOMETRYCOLLECTION(@coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1), +GEOMETRYCOLLECTION(@coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2) +); +ST_DISTANCE( +GEOMETRYCOLLECTION(@coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1), +GEOMETRYCOLLECTION(@coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2) +) +30 bugfix: 54168045 select ST_Distance(ST_Distance(ST_GeomFromText('POINT(-1.000009 -30)'),ST_GeomFromText('POINT(-1.000009 -30)')),ST_GeomFromText('POINT(-1.000009 -30 )')); ERROR 22023: Invalid GIS data provided to function st_distance. diff --git a/tools/deploy/mysql_test/test_suite/geometry/t/st_distance_mysql.test b/tools/deploy/mysql_test/test_suite/geometry/t/st_distance_mysql.test index 1791d85a4..de6095b12 100644 --- a/tools/deploy/mysql_test/test_suite/geometry/t/st_distance_mysql.test +++ b/tools/deploy/mysql_test/test_suite/geometry/t/st_distance_mysql.test @@ -2428,6 +2428,20 @@ select st_distance(ST_GEOMFROMTEXT('POINT(0 0)', 4053), ST_GEOMFROMTEXT('POINT(0 45)', 4053), "Indian yard"); select st_distance(ST_GEOMFROMTEXT('POINT(0 0)', 4053), ST_GEOMFROMTEXT('POINT(0 45)', 4053), "Indian yard (1937)"); + # 2 layers of GEOMETRYCOLLECTION nested + SET @coll1 = ST_GEOMFROMTEXT(@star_collection_multilinestr); + SET @coll2 = ST_GEOMFROMTEXT(@star_collection_elems_3); + # 10 layers of GEOMETRYCOLLECTION nested + SELECT ST_DISTANCE( + GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(@coll1, @coll1),@coll1),@coll1),@coll1),@coll1),@coll1),@coll1),@coll1), + GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(@coll2, @coll2),@coll2),@coll2),@coll2),@coll2),@coll2),@coll2),@coll2) + ); + # long geometrycollection + SELECT ST_DISTANCE( + GEOMETRYCOLLECTION(@coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1, @coll1), + GEOMETRYCOLLECTION(@coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2, @coll2) + ); + --echo bugfix: 54168045 # case 1 --error 3037 diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index 4ba55acd2..1d8d6e292 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -417,6 +417,7 @@ _memstore_limit_percentage _migrate_block_verify_level _minor_compaction_amplification_factor _min_malloc_sample_interval +_multimodel_memory_trace_level _mvcc_gc_using_min_txn_snapshot _nested_loop_join_enabled _object_storage_io_timeout diff --git a/unittest/share/test_geo_bin.cpp b/unittest/share/test_geo_bin.cpp index 67f5f3eb5..bae10f0a8 100644 --- a/unittest/share/test_geo_bin.cpp +++ b/unittest/share/test_geo_bin.cpp @@ -3724,7 +3724,7 @@ TEST_F(TestGeoBin, visitor_Geometrycollection) ObGeographGeometrycollection *GeographGc = static_cast(gc); // point - GeographGc->push_back(ObGeographPoint(10.0 * srs_item->angular_unit(), 0.0 * srs_item->angular_unit(), 0, &allocator)); + GeographGc->push_back(ObGeographPoint(10.0 * srs_item->angular_unit(), 0.0 * srs_item->angular_unit(), 0)); // lineString ObGeographLineString ls(0, allocator); ls.push_back(ObWkbGeogInnerPoint(180 * srs_item->angular_unit(), 90 * srs_item->angular_unit() )); @@ -3788,7 +3788,7 @@ TEST_F(TestGeoBin, visitor_Geometrycollection) ObCartesianGeometrycollection *CartesianGc = static_cast(gc); // point - CartesianGc->push_back(ObCartesianPoint(10.0, 0.0, 0, &allocator)); + CartesianGc->push_back(ObCartesianPoint(10.0, 0.0, 0)); // lineString ObCartesianLineString cart_ls(0, allocator); cart_ls.push_back(ObWkbGeomInnerPoint(180, 90 )); @@ -5258,7 +5258,7 @@ TEST_F(TestGeoBin, sdo_point) { // case 1: SDO_ELEM_INFO = NULL, SDO_POINT_TYPE = (x, y, NULL) ObSdoPoint point(x, y); - ObSdoGeoObject geo(ObGeoType::POINT, point); + ObSdoGeoObject geo(ObGeoType::POINT, point, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5275,7 +5275,7 @@ TEST_F(TestGeoBin, sdo_point) { ASSERT_EQ(OB_SUCCESS, ordinate.push_back(y)); // ObSdoGeoToWkb trans2(&allocator); - ObSdoGeoObject geo2(ObGeoType::POINT, elem_info, ordinate); + ObSdoGeoObject geo2(ObGeoType::POINT, elem_info, ordinate, allocator); ObString wkb2; trans.reset(); ASSERT_EQ(OB_SUCCESS, trans.translate(&geo2, wkb2)); @@ -5298,7 +5298,7 @@ TEST_F(TestGeoBin, sdo_point_3d) { // case 1: SDO_ELEM_INFO = NULL, SDO_POINT_TYPE = (x, y, NULL) ObSdoPoint point(x, y, z); - ObSdoGeoObject geo(ObGeoType::POINTZ, point, 0); + ObSdoGeoObject geo(ObGeoType::POINTZ, point, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5315,7 +5315,7 @@ TEST_F(TestGeoBin, sdo_point_3d) { ASSERT_EQ(OB_SUCCESS, ordinate.push_back(y)); ASSERT_EQ(OB_SUCCESS, ordinate.push_back(z)); // ObSdoGeoToWkb trans2(&allocator); - ObSdoGeoObject geo2(ObGeoType::POINTZ, elem_info, ordinate); + ObSdoGeoObject geo2(ObGeoType::POINTZ, elem_info, ordinate, allocator); ObString wkb2; trans.reset(); ASSERT_EQ(OB_SUCCESS, trans.translate(&geo2, wkb2)); @@ -5323,7 +5323,7 @@ TEST_F(TestGeoBin, sdo_point_3d) { ObGeometry3D geo_3d; geo_3d.set_data(wkb2); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5354,7 +5354,7 @@ TEST_F(TestGeoBin, sdo_linestring) { ordinate.push_back(xv[k]); ordinate.push_back(yv[k]); } - ObSdoGeoObject geo(ObGeoType::LINESTRING, elem_info, ordinate); + ObSdoGeoObject geo(ObGeoType::LINESTRING, elem_info, ordinate, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5384,14 +5384,14 @@ TEST_F(TestGeoBin, sdo_linestring_3d) { ordinate.push_back(yv[k]); ordinate.push_back(zv[k]); } - ObSdoGeoObject geo(ObGeoType::LINESTRINGZ, elem_info, ordinate, 0); + ObSdoGeoObject geo(ObGeoType::LINESTRINGZ, elem_info, ordinate, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); ASSERT_EQ(wkb == res, true); ObGeometry3D geo_3d; geo_3d.set_data(wkb); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5435,7 +5435,7 @@ TEST_F(TestGeoBin, sdo_polygon) { } } - ObSdoGeoObject geo(ObGeoType::POLYGON, elem_info, ordinate); + ObSdoGeoObject geo(ObGeoType::POLYGON, elem_info, ordinate, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5480,14 +5480,14 @@ TEST_F(TestGeoBin, sdo_polygon_3d) { } } - ObSdoGeoObject geo(ObGeoType::POLYGONZ, elem_info, ordinate, 0); + ObSdoGeoObject geo(ObGeoType::POLYGONZ, elem_info, ordinate, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); ASSERT_EQ(wkb == res, true); ObGeometry3D geo_3d; geo_3d.set_data(wkb); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5518,7 +5518,7 @@ TEST_F(TestGeoBin, sdo_multipoint) { ordinate.push_back(xv[k]); ordinate.push_back(yv[k]); } - ObSdoGeoObject geo(ObGeoType::MULTIPOINT, elem_info, ordinate); + ObSdoGeoObject geo(ObGeoType::MULTIPOINT, elem_info, ordinate, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5548,14 +5548,14 @@ TEST_F(TestGeoBin, sdo_multipoint_3d) { ordinate.push_back(yv[k]); ordinate.push_back(zv[k]); } - ObSdoGeoObject geo(ObGeoType::MULTIPOINTZ, elem_info, ordinate, 0); + ObSdoGeoObject geo(ObGeoType::MULTIPOINTZ, elem_info, ordinate, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); ASSERT_EQ(wkb == res, true); ObGeometry3D geo_3d; geo_3d.set_data(wkb); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5594,7 +5594,7 @@ TEST_F(TestGeoBin, sdo_multilinestring) { } } - ObSdoGeoObject geo(ObGeoType::MULTILINESTRING, elem_info, ordinate); + ObSdoGeoObject geo(ObGeoType::MULTILINESTRING, elem_info, ordinate, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5632,14 +5632,14 @@ TEST_F(TestGeoBin, sdo_multilinestring_3d) { } } - ObSdoGeoObject geo(ObGeoType::MULTILINESTRINGZ, elem_info, ordinate, 0); + ObSdoGeoObject geo(ObGeoType::MULTILINESTRINGZ, elem_info, ordinate, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); ASSERT_EQ(wkb == res, true); ObGeometry3D geo_3d; geo_3d.set_data(wkb); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5691,7 +5691,7 @@ TEST_F(TestGeoBin, sdo_multipolygon) { ordinate.push_back(yv[y_idx++]); } } - ObSdoGeoObject geo(ObGeoType::MULTIPOLYGON, elem_info, ordinate); + ObSdoGeoObject geo(ObGeoType::MULTIPOLYGON, elem_info, ordinate, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5738,14 +5738,14 @@ TEST_F(TestGeoBin, sdo_multipolygon_3d) { ordinate.push_back(zv[z_idx++]); } } - ObSdoGeoObject geo(ObGeoType::MULTIPOLYGONZ, elem_info, ordinate, 0); + ObSdoGeoObject geo(ObGeoType::MULTIPOLYGONZ, elem_info, ordinate, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); ASSERT_EQ(wkb == res, true); ObGeometry3D geo_3d; geo_3d.set_data(wkb); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5802,7 +5802,7 @@ TEST_F(TestGeoBin, sdo_collection) { ordinate.push_back(yv[y_idx++]); } } - ObSdoGeoObject geo(ObGeoType::GEOMETRYCOLLECTION, elem_info, ordinate); + ObSdoGeoObject geo(ObGeoType::GEOMETRYCOLLECTION, elem_info, ordinate, allocator); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5856,7 +5856,7 @@ TEST_F(TestGeoBin, sdo_collection_3d) { ordinate.push_back(zv[z_idx++]); } } - ObSdoGeoObject geo(ObGeoType::GEOMETRYCOLLECTIONZ, elem_info, ordinate, 0); + ObSdoGeoObject geo(ObGeoType::GEOMETRYCOLLECTIONZ, elem_info, ordinate, allocator, 0); ObSdoGeoToWkb trans(&allocator); ObString wkb; ASSERT_EQ(OB_SUCCESS, trans.translate(&geo, wkb)); @@ -5864,7 +5864,7 @@ TEST_F(TestGeoBin, sdo_collection_3d) { ASSERT_EQ(wkb == res, true); ObGeometry3D geo_3d; geo_3d.set_data(wkb); - ObSdoGeoObject geo3; + ObSdoGeoObject geo3(allocator); ASSERT_EQ(OB_SUCCESS, geo_3d.to_sdo_geometry(geo3)); geo3.set_srid(geo.get_srid()); ASSERT_EQ(geo == geo3, true); @@ -5993,7 +5993,10 @@ TEST_F(TestGeoBin, interior_point_vistor_point) ObGeometry *geo = NULL; ObGeometry *interior_point = NULL; ASSERT_EQ(ObWktParser::parse_wkt(allocator, "POINT(10 0)", geo, true, false), OB_SUCCESS); - ObGeoInteriorPointVisitor visitor(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_mem_attr(MTL_ID(), "GIS_UT", ObCtxIds::DEFAULT_CTX_ID)), OB_SUCCESS); + ObGeoInteriorPointVisitor visitor(mem_context); ASSERT_EQ(geo->do_visit(visitor), OB_SUCCESS); ASSERT_EQ(visitor.get_interior_point(interior_point) , OB_SUCCESS); ASSERT_EQ(interior_point->type(), ObGeoType::POINT); @@ -6008,7 +6011,10 @@ TEST_F(TestGeoBin, interior_point_vistor_line) ObGeometry *geo = NULL; ObGeometry *interior_point = NULL; ASSERT_EQ(ObWktParser::parse_wkt(allocator, "LINESTRING(0 0, 5 0, 10 0)", geo, true, false), OB_SUCCESS); - ObGeoInteriorPointVisitor visitor(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_mem_attr(MTL_ID(), "GIS_UT", ObCtxIds::DEFAULT_CTX_ID)), OB_SUCCESS); + ObGeoInteriorPointVisitor visitor(mem_context); ASSERT_EQ(geo->do_visit(visitor), OB_SUCCESS); ASSERT_EQ(visitor.get_interior_point(interior_point) , OB_SUCCESS); ASSERT_EQ(interior_point->type(), ObGeoType::POINT); @@ -6029,7 +6035,10 @@ TEST_F(TestGeoBin, interior_point_vistor_poly) "182814.953577191 141758.480925126,182766.155358861 141721.682268681," "182742.156235092 141744.881421657,182692.558045971 141716.882443927," "182635.760119718 141846.477712277))", geo, true, false), OB_SUCCESS); - ObGeoInteriorPointVisitor visitor(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_mem_attr(MTL_ID(), "GIS_UT", ObCtxIds::DEFAULT_CTX_ID)), OB_SUCCESS); + ObGeoInteriorPointVisitor visitor(mem_context); ASSERT_EQ(geo->do_visit(visitor), OB_SUCCESS); ASSERT_EQ(visitor.get_interior_point(interior_point) , OB_SUCCESS); ASSERT_EQ(interior_point->type(), ObGeoType::POINT); @@ -6044,7 +6053,10 @@ TEST_F(TestGeoBin, interior_point_vistor_empty) ObGeometry *geo = NULL; ObGeometry *interior_point = NULL; ASSERT_EQ(ObWktParser::parse_wkt(allocator, "GEOMETRYCOLLECTION EMPTY", geo, true, false), OB_SUCCESS); - ObGeoInteriorPointVisitor visitor(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_mem_attr(MTL_ID(), "GIS_UT", ObCtxIds::DEFAULT_CTX_ID)), OB_SUCCESS); + ObGeoInteriorPointVisitor visitor(mem_context); ASSERT_EQ(geo->do_visit(visitor), OB_SUCCESS); ASSERT_EQ(visitor.get_interior_point(interior_point) , OB_SUCCESS); ASSERT_EQ(interior_point->type(), ObGeoType::GEOMETRYCOLLECTION); @@ -6064,7 +6076,10 @@ void elevation_visitor_checker(ObIAllocator &allocator, const ObString &wkt1, co ASSERT_EQ(ObWktParser::parse_wkt(allocator, cal_wkt, geo_cal, true, false), OB_SUCCESS); ASSERT_EQ(ObGeoTypeUtil::is_3d_geo_type(geo_cal->type()), false); - ObGeoElevationVisitor visitor(allocator, nullptr); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_mem_attr(MTL_ID(), "GIS_UT", ObCtxIds::DEFAULT_CTX_ID)), OB_SUCCESS); + ObGeoElevationVisitor visitor(mem_context, nullptr); ObGeometry *res_geo = nullptr; ASSERT_EQ(visitor.init(*geo1, *geo2), OB_SUCCESS); ASSERT_EQ(geo_cal->do_visit(visitor), OB_SUCCESS); diff --git a/unittest/share/test_geo_func_box.cpp b/unittest/share/test_geo_func_box.cpp index 1edbd957e..897072f4f 100644 --- a/unittest/share/test_geo_func_box.cpp +++ b/unittest/share/test_geo_func_box.cpp @@ -236,7 +236,10 @@ TEST_F(TestGeoFuncBox, geom_point) ObIWkbGeomPoint p; p.set_data(data.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &p); ObGeogBox *result = NULL; @@ -260,7 +263,10 @@ TEST_F(TestGeoFuncBox, geom_linestring) ObIWkbGeomLineString line; line.set_data(data.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &line); ObGeogBox *result = NULL; @@ -287,7 +293,10 @@ TEST_F(TestGeoFuncBox, geom_polygon) ObIWkbGeomPolygon poly; poly.set_data(data.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &poly); ObGeogBox *result = NULL; @@ -313,7 +322,10 @@ TEST_F(TestGeoFuncBox, geom_multipoint) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &multi_point); ObGeogBox *result = NULL; @@ -342,7 +354,10 @@ TEST_F(TestGeoFuncBox, geom_multilinestring) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &multi_line); ObGeogBox *result = NULL; @@ -375,7 +390,10 @@ TEST_F(TestGeoFuncBox, geom_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &multi_poly); ObGeogBox *result = NULL; @@ -442,7 +460,10 @@ TEST_F(TestGeoFuncBox, geom_collection) ObIWkbGeomCollection collection; collection.set_data(data.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(1); gis_context.ut_set_geo_arg(0, &collection); ObGeogBox *result = NULL; diff --git a/unittest/share/test_geo_func_difference.cpp b/unittest/share/test_geo_func_difference.cpp index 091fdd889..d0ee27915 100644 --- a/unittest/share/test_geo_func_difference.cpp +++ b/unittest/share/test_geo_func_difference.cpp @@ -180,7 +180,10 @@ TEST_F(TestGeoFuncDifference, point_point) ObIWkbGeomPoint q; q.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &q); @@ -216,7 +219,10 @@ TEST_F(TestGeoFuncDifference, point_line) ObIWkbGeomLineString line; line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &line); @@ -255,7 +261,10 @@ TEST_F(TestGeoFuncDifference, point_polygon) ObIWkbGeomPolygon poly; poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &poly); @@ -294,7 +303,10 @@ TEST_F(TestGeoFuncDifference, point_multipoint) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_point); @@ -334,7 +346,10 @@ TEST_F(TestGeoFuncDifference, point_multiline) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_line); @@ -379,7 +394,10 @@ TEST_F(TestGeoFuncDifference, point_multipolygon) ObIWkbGeomMultiPolygon multi_polygon; multi_polygon.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_polygon); @@ -416,7 +434,10 @@ TEST_F(TestGeoFuncDifference, line_point) ObIWkbGeomPoint q; q.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &q); @@ -457,7 +478,10 @@ TEST_F(TestGeoFuncDifference, line_line) ObIWkbGeomLineString line1; line1.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &line1); @@ -565,7 +589,10 @@ TEST_F(TestGeoFuncDifference, line_polygon) */ - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); @@ -654,7 +681,10 @@ TEST_F(TestGeoFuncDifference, line_multiline) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); @@ -730,7 +760,10 @@ TEST_F(TestGeoFuncDifference, line_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); @@ -835,7 +868,10 @@ TEST_F(TestGeoFuncDifference, polygon_polygon) } ObIWkbGeomPolygon poly2; poly2.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly1); @@ -940,7 +976,10 @@ TEST_F(TestGeoFuncDifference, polygon_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); @@ -991,7 +1030,10 @@ TEST_F(TestGeoFuncDifference, multipoint_point) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &p); @@ -1037,7 +1079,10 @@ TEST_F(TestGeoFuncDifference, multipoint_linestring) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &line); @@ -1087,7 +1132,10 @@ TEST_F(TestGeoFuncDifference, multipoint_polygon) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &pol); @@ -1136,7 +1184,10 @@ TEST_F(TestGeoFuncDifference, multipoint_multipoint) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_point1); @@ -1189,7 +1240,10 @@ TEST_F(TestGeoFuncDifference, multipoint_multilinestring) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1282,7 +1336,10 @@ TEST_F(TestGeoFuncDifference, point_point_geog) ObIWkbGeogPoint q; q.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &q); @@ -1320,7 +1377,10 @@ TEST_F(TestGeoFuncDifference, point_line_geog) ObIWkbGeogLineString line; line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &line); @@ -1357,7 +1417,10 @@ TEST_F(TestGeoFuncDifference, point_polygon_geog) ObIWkbGeogPolygon poly; poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &poly); @@ -1398,7 +1461,10 @@ TEST_F(TestGeoFuncDifference, point_multipoint_geog) ObIWkbGeogMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_point); @@ -1436,7 +1502,10 @@ TEST_F(TestGeoFuncDifference, point_multiline_geog) ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1483,7 +1552,10 @@ TEST_F(TestGeoFuncDifference, point_multipolygon_geog) ObIWkbGeogMultiPolygon multi_polygon; multi_polygon.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_polygon); @@ -1522,7 +1594,10 @@ TEST_F(TestGeoFuncDifference, line_point_geog) ObIWkbGeogPoint q; q.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &q); @@ -1587,7 +1662,10 @@ TEST_F(TestGeoFuncDifference, line_line_geog) ObIWkbGeogLineString line1; line1.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &line1); @@ -1694,7 +1772,10 @@ TEST_F(TestGeoFuncDifference, line_polygon_geog) ObIWkbGeogPolygon poly; poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); @@ -1759,7 +1840,10 @@ TEST_F(TestGeoFuncDifference, line_multiline_geog) ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); @@ -1836,7 +1920,10 @@ TEST_F(TestGeoFuncDifference, line_multipolygon_geog) ObIWkbGeogMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); @@ -1933,7 +2020,10 @@ TEST_F(TestGeoFuncDifference, polygon_polygon_geog) } ObIWkbGeogPolygon poly2; poly2.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly1); @@ -2023,7 +2113,10 @@ TEST_F(TestGeoFuncDifference, polygon_multipolygon_geog) ASSERT_EQ(multi_p->size(), 2); std::cout << "ob::mpoly1" << boost::geometry::dsv(*multi_p) << std::endl; - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_poly); diff --git a/unittest/share/test_geo_func_union.cpp b/unittest/share/test_geo_func_union.cpp index e9bca08e0..e42625c26 100644 --- a/unittest/share/test_geo_func_union.cpp +++ b/unittest/share/test_geo_func_union.cpp @@ -216,7 +216,10 @@ TEST_F(TestGeoFuncUnion, point_point) ObIWkbGeomPoint q; q.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &q); @@ -254,7 +257,10 @@ TEST_F(TestGeoFuncUnion, point_point_overlap) ObIWkbGeomPoint q; q.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &q); @@ -293,7 +299,10 @@ TEST_F(TestGeoFuncUnion, point_line) ObIWkbGeomLineString line; line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &line); @@ -338,7 +347,10 @@ TEST_F(TestGeoFuncUnion, point_line_overlap) ObIWkbGeomLineString line; line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &line); @@ -382,7 +394,10 @@ TEST_F(TestGeoFuncUnion, point_polygon) ObIWkbGeomPolygon poly; poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &poly); @@ -440,7 +455,10 @@ TEST_F(TestGeoFuncUnion, point_multipoint) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_point); @@ -498,7 +516,10 @@ TEST_F(TestGeoFuncUnion, point_multiline) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_line); @@ -579,7 +600,10 @@ TEST_F(TestGeoFuncUnion, point_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_poly); @@ -648,7 +672,10 @@ TEST_F(TestGeoFuncUnion, line_line) ObIWkbGeomLineString line1; line1.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &line1); @@ -689,7 +716,10 @@ TEST_F(TestGeoFuncUnion, line_polygon) ObIWkbGeomPolygon poly; poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &poly); @@ -736,7 +766,10 @@ TEST_F(TestGeoFuncUnion, line_multipoint) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_point); @@ -798,7 +831,10 @@ TEST_F(TestGeoFuncUnion, line_multiline) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_line); @@ -853,7 +889,10 @@ TEST_F(TestGeoFuncUnion, line_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_poly); @@ -911,7 +950,10 @@ TEST_F(TestGeoFuncUnion, polygon_multipoint) ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_point); @@ -974,7 +1016,10 @@ TEST_F(TestGeoFuncUnion, polygon_multiline) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1040,7 +1085,10 @@ TEST_F(TestGeoFuncUnion, polygon_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_poly); @@ -1067,7 +1115,7 @@ TEST_F(TestGeoFuncUnion, polygon_multipolygon) ASSERT_EQ(poly_visitor1.get_geometry()->crs(), ObGeoCRS::Cartesian); ObCartesianMultipolygon *poly_tree2 = static_cast(poly_visitor1.get_geometry()); - ObGeoEvalCtx gis_tree_context(&allocator); + ObGeoEvalCtx gis_tree_context(mem_context); gis_tree_context.ut_set_geo_count(2); gis_tree_context.ut_set_geo_arg(0, poly_tree1); gis_tree_context.ut_set_geo_arg(1, poly_tree2); @@ -1113,7 +1161,10 @@ TEST_F(TestGeoFuncUnion, multipoint_multipoint) ObIWkbGeomMultiPoint multi_point1; multi_point1.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_point1); @@ -1168,7 +1219,10 @@ TEST_F(TestGeoFuncUnion, multipoint_multiline) ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1236,7 +1290,10 @@ TEST_F(TestGeoFuncUnion, multipoint_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_poly); @@ -1312,7 +1369,10 @@ TEST_F(TestGeoFuncUnion, multiline_multiline) ObIWkbGeomMultiLineString multi_line2; multi_line2.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_line1); gis_context.ut_set_geo_arg(1, &multi_line2); @@ -1375,7 +1435,10 @@ TEST_F(TestGeoFuncUnion, multiline_multipolygon) ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_line); gis_context.ut_set_geo_arg(1, &multi_poly); @@ -1452,7 +1515,10 @@ TEST_F(TestGeoFuncUnion, multipolygon_multipolygon) ObIWkbGeomMultiPolygon multi_poly2; multi_poly2.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_poly1); gis_context.ut_set_geo_arg(1, &multi_poly2); @@ -1536,7 +1602,10 @@ TEST_F(TestGeoFuncUnion, line_line_geog) ObIWkbGeogLineString line1; line1.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &line1); @@ -1598,7 +1667,10 @@ TEST_F(TestGeoFuncUnion, polygon_multipolygon_geog) ObIWkbGeogMultiPolygon multi_poly; multi_poly.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_poly); @@ -1625,7 +1697,7 @@ TEST_F(TestGeoFuncUnion, polygon_multipolygon_geog) ASSERT_EQ(poly_visitor1.get_geometry()->crs(), ObGeoCRS::Geographic); ObGeographMultipolygon *poly_tree2 = static_cast(poly_visitor1.get_geometry()); - ObGeoEvalCtx gis_tree_context(&allocator, srs); + ObGeoEvalCtx gis_tree_context(mem_context, srs); gis_tree_context.ut_set_geo_count(2); gis_tree_context.ut_set_geo_arg(0, poly_tree1); gis_tree_context.ut_set_geo_arg(1, poly_tree2); @@ -1685,7 +1757,10 @@ TEST_F(TestGeoFuncUnion, multipoint_multiline_geog) ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1759,7 +1834,10 @@ TEST_F(TestGeoFuncUnion, polygon_multiline_geog) ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1821,7 +1899,10 @@ TEST_F(TestGeoFuncUnion, point_multiline_geog) ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator, srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_line); @@ -1877,7 +1958,10 @@ TEST_F(TestGeoFuncUnion, polygon_polygon) ObIWkbGeomPolygon poly1; poly1.set_data(data1.string()); - ObGeoEvalCtx gis_context(&allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &poly1); @@ -1903,7 +1987,7 @@ TEST_F(TestGeoFuncUnion, polygon_polygon) ASSERT_EQ(poly_visitor1.get_geometry()->crs(), ObGeoCRS::Cartesian); ObCartesianPolygon *poly_tree2 = static_cast(poly_visitor1.get_geometry()); - ObGeoEvalCtx gis_tree_context(&allocator); + ObGeoEvalCtx gis_tree_context(mem_context); gis_tree_context.ut_set_geo_count(2); gis_tree_context.ut_set_geo_arg(0, poly_tree1); gis_tree_context.ut_set_geo_arg(1, poly_tree2); @@ -2007,7 +2091,10 @@ TEST_F(TestGeoFuncUnion, gc_union) const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); - int ret = ObGeoFuncUtils::ob_geo_gc_union(allocator, *srs, multi_point_tree, multi_line_tree, multi_poly_tree); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_mem_attr(MTL_ID(), "GIS_UT", ObCtxIds::DEFAULT_CTX_ID)), OB_SUCCESS); + int ret = ObGeoFuncUtils::ob_geo_gc_union(mem_context, *srs, multi_point_tree, multi_line_tree, multi_poly_tree); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_EQ(true, is_geo_equal(mp_bg_res, *multi_point_tree)); ASSERT_EQ(true, is_geo_equal(mls_bg_res, *multi_line_tree)); diff --git a/unittest/share/test_geo_tree.cpp b/unittest/share/test_geo_tree.cpp index 52e5abc97..e8ecd0cd4 100644 --- a/unittest/share/test_geo_tree.cpp +++ b/unittest/share/test_geo_tree.cpp @@ -230,7 +230,7 @@ TEST_F(TestGeoTree, ObGeomVector) TEST_F(TestGeoTree, point) { ObArenaAllocator allocator(ObModIds::TEST); - ObCartesianPoint p(1.12, 2.32, 0, &allocator); + ObCartesianPoint p(1.12, 2.32, 0); ASSERT_EQ(1.12, p.get<0>()); ASSERT_EQ(2.32, p.get<1>()); ASSERT_EQ(ObGeoCRS::Cartesian, p.crs()); @@ -406,11 +406,11 @@ TEST_F(TestGeoTree, Geometrycollection) ASSERT_FALSE(cartesianGc->empty()); ASSERT_TRUE(cartesianGc->is_empty()); - cartesianGc->push_back(ObCartesianPoint(0.0, 0.0, 0, &allocator)); - cartesianGc->push_back(ObCartesianPoint(10.0, 0.0, 0, &allocator)); - cartesianGc->push_back(ObCartesianPoint(10.0, 10.0, 0, &allocator)); - cartesianGc->push_back(ObCartesianPoint(0.0, 10.0, 0, &allocator)); - cartesianGc->push_back(ObCartesianPoint(0.0, 0.0, 0, &allocator)); + cartesianGc->push_back(ObCartesianPoint(0.0, 0.0, 0)); + cartesianGc->push_back(ObCartesianPoint(10.0, 0.0, 0)); + cartesianGc->push_back(ObCartesianPoint(10.0, 10.0, 0)); + cartesianGc->push_back(ObCartesianPoint(0.0, 10.0, 0)); + cartesianGc->push_back(ObCartesianPoint(0.0, 0.0, 0)); ObCartesianLineString ls(0, allocator); ls.push_back(ObWkbGeomInnerPoint(0.0, 0.0)); @@ -662,7 +662,10 @@ void clip_visitor_test(const ObString &wkt, const ObString &wkt_res, ObGeogBox & wkt_to_tree_geo(wkt, allocator, geo_tree); ObGeometry *geo_res = nullptr; - ObGeoBoxClipVisitor clip_visitor(box, allocator); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoBoxClipVisitor clip_visitor(box, mem_context); ASSERT_EQ(geo_tree->do_visit(clip_visitor), OB_SUCCESS); ASSERT_EQ(clip_visitor.get_geometry(geo_res), OB_SUCCESS); ASSERT_EQ(geo_res == nullptr, false); diff --git a/unittest/share/test_wkt_parser.cpp b/unittest/share/test_wkt_parser.cpp index a6a0d4fc7..b85a68bfe 100644 --- a/unittest/share/test_wkt_parser.cpp +++ b/unittest/share/test_wkt_parser.cpp @@ -16,6 +16,7 @@ #include "lib/geo/ob_wkt_parser.h" #include "lib/utility/ob_print_utils.h" #include "lib/geo/ob_geo_ibin.h" +#include "lib/geo/ob_geo_3d.h" #undef private #undef protected @@ -56,7 +57,16 @@ public: return wkb; } - void compare_wkt_parse_result(ObGeoType geotype, const ObString &wkt, const ObString &wkb_res); + ObString mock_3d_to_wkb(ObGeometry *geo) { + ObString wkb; + if (OB_NOT_NULL(geo) && !geo->is_tree()) { + ObGeometry3D *geo_bin = reinterpret_cast(geo); + wkb = geo_bin->data_; + } + return wkb; + } + + void compare_3d_wkt_parse_result(ObGeoType geotype, const ObString &wkt, const ObString &wkb_res); void comapre_wkt_parse_wrong_result(const ObString &wkt); private: @@ -65,14 +75,14 @@ private: DISALLOW_COPY_AND_ASSIGN(TestWktParser); }; -void TestWktParser::compare_wkt_parse_result(ObGeoType geotype, const ObString &wkt, const ObString &wkb_res) +void TestWktParser::compare_3d_wkt_parse_result(ObGeoType geotype, const ObString &wkt, const ObString &wkb_res) { ObArenaAllocator allocator(ObModIds::TEST); ObGeometry *geo = NULL; ASSERT_EQ(OB_SUCCESS, ObWktParser::parse_wkt(allocator, wkt, geo, true, false)); ASSERT_TRUE(NULL != geo); ASSERT_EQ(geo->type(), geotype); - ObString wkb = to_hex(mock_to_wkb(geo)); + ObString wkb = to_hex(mock_3d_to_wkb(geo)); // std::cout<CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")); + ObGeoEvalCtx gis_context(mem_context, context.get_srs()); ObString dumy_wkb(4, 4, "dumy"); ObIWkbGeogPoint gmp1; ObIWkbGeogPoint gmp2; diff --git a/unittest/sql/engine/expr/test_gis_dispatcher.cpp b/unittest/sql/engine/expr/test_gis_dispatcher.cpp index f77b7e223..d971a6047 100644 --- a/unittest/sql/engine/expr/test_gis_dispatcher.cpp +++ b/unittest/sql/engine/expr/test_gis_dispatcher.cpp @@ -69,7 +69,10 @@ TEST_F(TestGisDispatcher, not_impl) ObIWkbGeogPoint gp; int ret = OB_SUCCESS; int result; - ObGeoEvalCtx gis_context; + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context); ret = ObGisTestFunc::geo_func::eval(gis_context, result); ASSERT_EQ(ret, OB_ERR_GIS_INVALID_DATA); @@ -99,7 +102,10 @@ TEST_F(TestGisDispatcher, dispatcher) ObArenaAllocator allocator(ObModIds::TEST); ObSrsItem srs(NULL); - ObGeoEvalCtx gis_context(&allocator, &srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, &srs); ObGeometry *gis_args[3][8] = {{0}}; gis_args[static_cast(ObGeoCRS::Cartesian)][static_cast(ObGeoType::POINT)] = &cp; @@ -170,7 +176,10 @@ TEST_F(TestGisDispatcher, specialization_and_exception_test) int ret = OB_SUCCESS; ObArenaAllocator allocator(ObModIds::TEST); ObSrsItem srs(NULL); - ObGeoEvalCtx gis_context(&allocator, &srs); + lib::MemoryContext mem_context; + ASSERT_EQ(CURRENT_CONTEXT->CREATE_CONTEXT(mem_context, + lib::ContextParam().set_label("GIS_UT")), OB_SUCCESS); + ObGeoEvalCtx gis_context(mem_context, &srs); ret = gis_context.append_geo_arg(&cp); ASSERT_EQ(ret, OB_SUCCESS);