[CP] [FEAT MERGE] JSON/XML/GIS MEM OPTIMIZATION AND NEW XML/GIS EXPR

This commit is contained in:
Carrot-77 2024-11-13 15:15:03 +00:00 committed by ob-robot
parent ba5bcd80ac
commit a8a00b05fc
251 changed files with 8396 additions and 3296 deletions

View File

@ -1784,7 +1784,7 @@ inline int obj_print_sql<ObJsonType>(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<ObJsonType>(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<ObJsonType>(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<int>(MIN(jbuf.length(), buf_len - pos)),

View File

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

View File

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

View File

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

View File

@ -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<double>(ptr + cur_pos, bo);
double y = ObGeoWkbByteOrderUtil::read<double>(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE, bo);
double z = ObGeoWkbByteOrderUtil::read<double>(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<double>(ptr + cur_pos, nx, bo);
ObGeoWkbByteOrderUtil::write<double>(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE, ny, bo);
}
}
if (OB_SUCC(ret)) {
ObGeoWkbByteOrderUtil::write<double>(ptr + cur_pos, nx, bo);
ObGeoWkbByteOrderUtil::write<double>(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE, ny, bo);
ObGeoWkbByteOrderUtil::write<double>(ptr + cur_pos + WKB_GEO_DOUBLE_STORED_SIZE * 2, nz, bo);
}
}
}
return ret;

View File

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

View File

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

View File

@ -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<ObGeoWkbByteOrder>(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<std::size_t K>
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<ObGeoWkbByteOrder>(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

View File

@ -21,7 +21,7 @@
namespace oceanbase {
namespace common {
typedef common::ObSEArray<uint64_t, 64> ObWkbIterOffsetArray;
typedef common::ObArray<uint64_t> ObWkbIterOffsetArray;
template<typename T, typename O>
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);
};

View File

@ -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<typename T, typename O>
ObWkbConstIterator<T, O>::ObWkbConstIterator()
: idx_(-1), owner_(NULL), diff_info_(),
diff_info_ptr_(&diff_info_), offsets_(), offsets_ptr_(&offsets_)
{}
offsets_ptr_(nullptr)
{
}
template<typename T, typename O>
ObWkbConstIterator<T, O>::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_t*>(owner);
}
@ -36,10 +37,20 @@ template<typename T, typename O>
ObWkbConstIterator<T, O>::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<typename T, typename O>
ObWkbConstIterator<T, O>::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<typename T, typename O>
ObWkbConstIterator<T, O>::~ObWkbConstIterator()
{
OB_DELETE(ObWkbIterOffsetArray, "GeoWkbIter", offsets_ptr_);
}
// shift iter interface
template<typename T, typename O>
typename ObWkbConstIterator<T, O>::self& ObWkbConstIterator<T, O>::operator++()
@ -93,10 +120,24 @@ const typename ObWkbConstIterator<T, O>::self& ObWkbConstIterator<T, O>::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<T, O>::reference ObWkbConstIterator<T, O>::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<typename T, typename O>
void ObWkbConstIterator<T, O>::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<T, O>::reference ObWkbIterator<T, O>::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;

View File

@ -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<ObCartesianLineString *>(&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<ObGeoFuncType::Within>::gis_func::eval(

View File

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

View File

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

View File

@ -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<typename PolyTree>
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

View File

@ -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<typename PolyTree>
int visit_poly(PolyTree *geo);
DISALLOW_COPY_AND_ASSIGN(ObGeoCloseRingVisitor);
};
} // namespace common
} // namespace oceanbase
#endif

View File

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

View File

@ -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 <typename RetType, typename Functype>
@ -207,6 +209,7 @@ int ObIGeoDispatcher<RetType, Functype>::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<RetType, Functype>::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<RetType, Functype>::eval_tree_binary(const common::ObGeomet
template <typename RetType, typename Functype>
int ObIGeoDispatcher<RetType, Functype>::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 <typename RetType, typename Functype>
int ObIGeoDispatcher<RetType, Functype>::eval_geo_func_inner(
const common::ObGeoEvalCtx &gis_context, RetType &result)
{
INIT_SUCC(ret);
try {
@ -1079,6 +1102,7 @@ int ObIGeoDispatcher<RetType, Functype>::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()) {

View File

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

View File

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

View File

@ -61,13 +61,6 @@ private:
static bool apply_bg_equal(ObGeographPolygon &geo1,
ObGeographPolygon &geo2,
const ObSrsItem *srs);
template<typename MultiPointType, typename MultiLineType, typename MultiPolygonType>
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 <typename GeoTreeType>
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<ObCartesianGeometrycollection>(context, const_cast<ObGeometry *>(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<ObGeometry *>(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<ObGeometry *>(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<ObGeometry *>(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<ObIWkbGeomCollection *>(reinterpret_cast<const ObIWkbGeomCollection *>(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<ObCartesianGeometrycollection *>(visitor.get_geometry());
mpt = reinterpret_cast<ObCartesianMultipoint *>(dedup_pt_ptr);
ml = reinterpret_cast<ObCartesianMultilinestring *>(dedup_ml_ptr);
mpo = reinterpret_cast<ObCartesianMultipolygon *>(dedup_mpo_ptr);
// param 1, 2
bg::strategy::buffer::distance_symmetric<double> 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<ObCartesianGeometrycollection *>(reinterpret_cast<const ObCartesianGeometrycollection *>(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<ObGeometry *>(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<ObGeometry *>(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<ObGeometry *>(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<ObCartesianMultipoint *>(dedup_pt_ptr);
ml = reinterpret_cast<ObCartesianMultilinestring *>(dedup_ml_ptr);
mpo = reinterpret_cast<ObCartesianMultipolygon *>(dedup_mpo_ptr);
// param 1, 2
bg::strategy::buffer::distance_symmetric<double> 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<typename MultiPointType, typename MultiLineType, typename MultiPolygonType>
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<MultiPointType *>(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<MultiLineType *>(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<MultiPolygonType *>(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<ObGeographMultipoint,
ObGeographMultilinestring, ObGeographMultipolygon>(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<ObCartesianMultipoint,
ObCartesianMultilinestring, ObCartesianMultipolygon>(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 <typename GeoTreeType>
int ObGeoFuncBufferImpl::unwrap_geo_tree_inner(ObGeometry *geo_in,
ObGeometry *&geo_out)

View File

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

View File

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

View File

@ -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<const ObWkbGeomPolygon*>(sub_ptr);
ObString tmp(polygon->length(), reinterpret_cast<const char*>(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<ObWkbGeomPolygon*>(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<const ObWkbGeomMultiPolygon*>(sub_ptr);
ObString tmp(multi_poly->length(), reinterpret_cast<const char*>(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<ObWkbGeomMultiPolygon*>(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<const ObWkbGeogPolygon*>(sub_ptr);
ObString tmp(polygon->length(), reinterpret_cast<const char*>(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<ObWkbGeogPolygon*>(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<const ObWkbGeogMultiPolygon*>(sub_ptr);
ObString tmp(multi_poly->length(), reinterpret_cast<const char*>(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<ObWkbGeogMultiPolygon*>(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<const ObCartesianPoint *>(g1);
const ObCartesianLineString *geo1 = reinterpret_cast<const ObCartesianLineString *>(g1);
const ObCartesianPolygon *geo2 = reinterpret_cast<const ObCartesianPolygon *>(g2);
result = boost::geometry::covered_by(*geo1, *geo2);
return OB_SUCCESS;

View File

@ -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<ObGeoFuncType::Difference>::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;

View File

@ -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<MptType *>(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<GcTreeType>(result, *allocator)))) {
if (OB_FAIL((ObGeoTypeUtil::simplify_multi_geo<GcTreeType>(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));

View File

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

View File

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

View File

@ -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<GcTreeType>(push_geo, allocator)))) {
if (OB_FAIL((ObGeoTypeUtil::simplify_multi_geo<GcTreeType>(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<typename PolyTreeType, typename GcTreeType>
template<typename PolyTreeType, typename GcTreeType, typename GeomType>
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<ObGeometry *>(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<const GeomType *>(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<PolyTreeType *>(g1_tree), *mpy, *mpy_res);
bg::difference(*mls, *reinterpret_cast<PolyTreeType *>(g1_tree), *mls_res);
bg::difference(*mpt, *reinterpret_cast<PolyTreeType *>(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<double> 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<PolyTreeType *>(g1_tree), *mpy, *mpy_res, line_strategy);
bg::difference(*mls, *reinterpret_cast<PolyTreeType *>(g1_tree), *mls_res, line_strategy);
bg::difference(*mpt, *reinterpret_cast<PolyTreeType *>(g1_tree), *mpt_res, point_strategy);
}
if (OB_SUCC(ret) && !mpy_res->is_empty()
&& OB_FAIL(simplify_and_push_geometry(
*allocator, reinterpret_cast<ObGeometry *>(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<ObGeometry *>(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<ObGeometry *>(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<double> 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<ObGeometry *>(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<ObGeometry *>(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<ObGeometry *>(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<GcTreeType>(mpy_res, *allocator)))) {
} else if (OB_FAIL(!mpy_res->is_empty() && (ObGeoTypeUtil::simplify_multi_geo<GcTreeType>(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<GcTreeType>(mls_res, *allocator)))) {
} else if (OB_FAIL(!mls_res->is_empty() && (ObGeoTypeUtil::simplify_multi_geo<GcTreeType>(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<GcTreeType>(result, *allocator)))) {
} else if (OB_FAIL(!result->is_empty() && (ObGeoTypeUtil::simplify_multi_geo<GcTreeType>(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<ObCartesianPolygon, ObCartesianGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObCartesianPolygon, ObCartesianGeometrycollection, ObWkbGeomPolygon>(
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<ObCartesianMultipolygon, ObCartesianGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObCartesianMultipolygon, ObCartesianGeometrycollection, ObWkbGeomMultiPolygon>(
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<ObCartesianPolygon, ObCartesianGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObCartesianPolygon, ObCartesianGeometrycollection, ObWkbGeomPolygon>(
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<ObCartesianMultipolygon, ObCartesianGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObCartesianMultipolygon, ObCartesianGeometrycollection, ObWkbGeomMultiPolygon>(
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<ObGeographPolygon, ObGeographGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObGeographPolygon, ObGeographGeometrycollection, ObWkbGeogPolygon>(
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<ObGeographMultipolygon, ObGeographGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObGeographMultipolygon, ObGeographGeometrycollection, ObWkbGeogMultiPolygon>(
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<ObGeographPolygon, ObGeographGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObGeographPolygon, ObGeographGeometrycollection, ObWkbGeogPolygon>(
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<ObGeographMultipolygon, ObGeographGeometrycollection>(
return apply_bg_symdifference_poly_coll<ObGeographMultipolygon, ObGeographGeometrycollection, ObWkbGeogMultiPolygon>(
g2, g1, context, ObBGStrategyType::LL_LA_AA_STRATEGY, result);
}
OB_GEO_FUNC_END;

View File

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

View File

@ -51,7 +51,7 @@ private:
lib::ObMallocHookAttrGuard malloc_guard(last_mem_attr);
const PtInType *src_geo = reinterpret_cast<const PtInType *>(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 {

View File

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

View File

@ -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<typename MultiPointType, typename MultiLineType, typename MultiPolygonType>
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<typename GcTreeType>
static int remove_duplicate_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs);
template<typename GcTreeType>
static int simplify_geo_collection(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs);
template<typename GcType>
static int simplify_multi_geo(ObGeometry *&geo, common::ObIAllocator &allocator);
private:
template<typename GcTreeType>
@ -70,12 +65,10 @@ private:
typename GcTreeType::sub_mpt_type &mpt,
typename GcTreeType::sub_ml_type &ml,
typename GcTreeType::sub_mp_type &mpo);
template<typename MpType>
static int is_in_geometry(const ObGeometry &geo, const MpType &multi_geo, const ObSrsItem *srs, bool &res);
};
template<typename MultiPointType, typename MultiLineType, typename MultiPolygonType>
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<const GcTreeType *>(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<const GcTreeType *>(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<typename MpType>
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<ObGeoFuncType::Equals>::geo_func::eval(gis_context, res))) {
OB_LOG(WARN, "eval st intersection failed", K(ret));
}
}
return ret;
}
template<typename GcType>
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<typename GcType::sub_ml_type *>(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<typename GcType::sub_mpt_type *>(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<typename GcType::sub_mp_type *>(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<GcType *>(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<GcType>(geo, allocator)))) {
OB_LOG(WARN, "fail to simplify geometry", K(ret));
}
}
break;
}
default: {
break; // do nothing
}
}
return ret;
}
// for geo tree
template<typename GcTreeType>
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<GcTreeType *&>(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<typename GcTreeType::sub_pt_type &>((*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<typename GcTreeType>
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<typename GcTreeType::sub_mpt_type &>(*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<typename GcTreeType::sub_ml_type &>(*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<typename GcTreeType::sub_mp_type &>(*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<GcTreeType *&>(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<GcTreeType>(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<GcTreeType>(geo, allocator)))) {
OB_LOG(WARN, "fail to simplify result", K(ret));
}
return ret;
}
} // sql
} // oceanbase
#endif // OCEANBASE_LIB_OB_GEO_FUNC_UTILS_H_

View File

@ -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<ObGeometry *>(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<ObGeometry *>(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<ObGeometry *>(multi_line),
reinterpret_cast<ObGeometry *>(multi_poly),
@ -324,7 +324,7 @@ static int ob_caculate_ml_within_gc_geog(const ObGeometry *g1, const ObGeometry
ObGeometry *i_geo1 = const_cast<ObGeometry *>(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<ObGeometry *>(multi_line),
reinterpret_cast<ObGeometry *>(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<ObGeometry *>(g1_multi_point),
if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast<ObGeometry *>(g1_multi_point),
reinterpret_cast<ObGeometry *>(g2_multi_point),
reinterpret_cast<ObGeometry *>(g2_multi_line),
reinterpret_cast<ObGeometry *>(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<ObGeometry *>(g1_multi_line),
if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast<ObGeometry *>(g1_multi_line),
NULL,
reinterpret_cast<ObGeometry *>(g2_multi_line),
reinterpret_cast<ObGeometry *>(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<ObGeometry *>(g1_multi_poly),
if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast<ObGeometry *>(g1_multi_poly),
NULL,
NULL,
reinterpret_cast<ObGeometry *>(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<ObGeometry *>(g1_multi_point),
if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast<ObGeometry *>(g1_multi_point),
reinterpret_cast<ObGeometry *>(g2_multi_point),
reinterpret_cast<ObGeometry *>(g2_multi_line),
reinterpret_cast<ObGeometry *>(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<ObGeometry *>(g1_multi_line),
if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast<ObGeometry *>(g1_multi_line),
NULL,
reinterpret_cast<ObGeometry *>(g2_multi_line),
reinterpret_cast<ObGeometry *>(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<ObGeometry *>(g1_multi_poly),
if (OB_FAIL(do_multi_difference(*srs, context, reinterpret_cast<ObGeometry *>(g1_multi_poly),
NULL,
NULL,
reinterpret_cast<ObGeometry *>(g2_multi_poly),

View File

@ -94,11 +94,11 @@ bool ObIWkbGeomPolygon::is_empty_inner() const
return (poly->exterior_ring().size(static_cast<ObGeoWkbByteOrder>(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<ObWkbGeomCollection*>(const_cast<char*>(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<ObWkbGeogCollection*>(const_cast<char*>(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: {

View File

@ -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<const ObWkbGeomCollection*>(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<const ObWkbGeogCollection*>(val())->size(); }

View File

@ -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<const ObWkbGeomPolygon *>(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));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<typename T>
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<ObGeometrycollection *, ModulePageAllocator> ObCGeoModuleArena;
ObIAllocator *allocator_;
ObGeometry *root_;
ModulePageAllocator page_allocator_;
ObCGeoModuleArena mode_arena_;
ObVector<ObGeometrycollection *, ObCGeoModuleArena> parent_;
ObArray<ObGeometrycollection *> parent_;
DISALLOW_COPY_AND_ASSIGN(ObGeoToTreeVisitor);
};

View File

@ -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<int16_t>(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<typename T_IBIN>
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<typename T_IBIN, typename T_BIN,
typename T_BIN_RING, typename T_BIN_INNER_RING>
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<typename T_IBIN, typename T_BIN,
typename T_BIN_RING, typename T_BIN_INNER_RING>
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<T_IBIN, T_BIN, T_BIN_RING, T_BIN_INNER_RING>(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_));

View File

@ -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<typename T_IBIN>
int appendTypeNameWithMode(T_IBIN *geo);
template<typename T_IBIN, typename T_BIN,
typename T_BIN_RING, typename T_BIN_INNER_RING>
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);

View File

@ -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 <typename GeometryT,
typename CartesianT,
typename GeographT>
@ -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>();

View File

@ -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 <typename T>
class ObGeomConstIterator : public array::Iterator<common::ObArray<T, ModulePageAllocator, true>, T>
class ObGeomConstIterator : public array::Iterator<common::ObArray<T, ModulePageAllocator, false>, T>
{
typedef array::Iterator<common::ObArray<T, ModulePageAllocator, true>, T> base_t;
typedef array::Iterator<common::ObArray<T, ModulePageAllocator, false>, T> base_t;
typedef ObGeomConstIterator<T> 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<T> const_iterator;
typedef typename ObArray<T, ModulePageAllocator, true>::iterator iterator;
typedef typename ObArray<T, ModulePageAllocator, false>::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<T> &v) = default;
ObGeomVector<T> &operator=(const ObGeomVector<T> &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<common::ObArray<T, ModulePageAllocator, true> *>(&vec_))->begin()); }
const_iterator begin() const { return const_iterator(&*(const_cast<common::ObArray<T, ModulePageAllocator, false> *>(&vec_))->begin()); }
iterator end() { return vec_.end(); }
const_iterator end() const { return const_iterator(&*(const_cast<common::ObArray<T, ModulePageAllocator, true> *>(&vec_))->end()); }
// ObArray<T, ModulePageAllocator, true>& get_vec_() const { return vec_; }
const_iterator end() const { return const_iterator(&*(const_cast<common::ObArray<T, ModulePageAllocator, false> *>(&vec_))->end()); }
// ObArray<T, ModulePageAllocator, false>& get_vec_() const { return vec_; }
int remove(int64_t idx) { return vec_.remove(idx); }
private:
common::ObArray<T, ModulePageAllocator, true> vec_;
common::ObArray<T, ModulePageAllocator, false> 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<ObWkbGeomInnerPoint>::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<ObWkbGeomInnerPoint> &get_points() const {return points_;}
ObGeomVector<ObWkbGeomInnerPoint> &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<ObWkbGeomInnerPoint> points_;
};
@ -373,14 +378,12 @@ public:
typedef ObGeomVector<ObWkbGeogInnerPoint>::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<ObWkbGeogInnerPoint> &get_points() const {return points_;}
ObGeomVector<ObWkbGeogInnerPoint> &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<ObWkbGeogInnerPoint> 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<ObCartesianLinearring &>(exterior_); }
ObGeomVector<ObCartesianLinearring> &interior_rings() { return inner_rings_; }
ObGeomVector<ObCartesianLinearring> 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<ObCartesianLinearring> 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<ObGeographLinearring &>(exterior_); }
ObGeomVector<ObGeographLinearring> &interior_rings() { return inner_rings_; }
ObGeomVector<ObGeographLinearring> 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<ObGeographLinearring> 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<ObGeometry &>(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<ObGeometry *, ObCGeoModuleArena> geoms_;
ObArray<ObGeometry *> 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<ObGeometry &>(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<ObGeometry *, ObCGeoModuleArena> geoms_;
ObArray<ObGeometry *> geoms_;
};
} // namespace common

View File

@ -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<ObGeometry3D *>(&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 *&copy_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<ObGeoFuncType::Correct>::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<ObGeoFuncType::Correct>::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<ObGeoFuncType::Correct>::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<ObGeoFuncType::Buffer>::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<ObGeoFuncType::Correct>::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<ObGeoFuncType::Buffer>::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<typename MpType>
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<ObGeoFuncType::Equals>::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<ObGeographGeometrycollection>(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<ObGeographGeometrycollection>(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<ObGeographGeometrycollection>(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<ObGeographGeometrycollection>(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<ObCartesianGeometrycollection>(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<ObCartesianGeometrycollection>(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<ObCartesianGeometrycollection>(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<ObCartesianGeometrycollection>(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

View File

@ -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 *&copy_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<typename CachedGeoType>
@ -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<typename GcTreeType>
static int remove_duplicate_multi_geo(ObGeometry *&geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs);
template<typename GcTreeType>
static int simplify_geo_collection(ObGeometry *&geo, common::ObIAllocator &allocator, const ObSrsItem *srs);
template<typename GcType>
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<typename GcTreeType>
static int check_if_geo_duplicate(ObGeometry *geo, lib::MemoryContext &mem_ctx, const ObSrsItem *srs, bool &is_duplicate);
private:
template<typename PT, typename LN, typename PY, typename MPT, typename MLN, typename MPY, typename GC>
static int create_geo_bin_by_type(ObIAllocator &allocator,
@ -295,9 +306,12 @@ private:
template<typename T_IBIN, typename T_BIN>
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<typename MpType>
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<typename GeometryType>
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<typename GeometryType>
@ -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<typename GcType>
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<typename GcType::sub_ml_type *>(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<typename GcType::sub_mpt_type *>(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<typename GcType::sub_mp_type *>(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<GcType *>(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<GcType>(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<typename GcTreeType>
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<GcTreeType *&>(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<typename GcTreeType::sub_pt_type &>((*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<typename GcTreeType>
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<typename GcTreeType::sub_mpt_type &>(*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<typename GcTreeType::sub_ml_type &>(*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<typename GcTreeType::sub_mp_type &>(*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<GcTreeType *&>(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<GcTreeType>(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<typename GcTreeType>
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<typename GcTreeType::sub_mpt_type &>(*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<typename GcTreeType::sub_ml_type &>(*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<typename GcTreeType::sub_mp_type &>(*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<GcTreeType *&>(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<GcTreeType>(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<typename GeometryType>
int ObGeoBoxUtil::fast_box(const GeometryType *g, ObGeogBox &box, bool &has_fast_box)

View File

@ -19,14 +19,31 @@ namespace common {
template<typename T_Point>
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;
}

View File

@ -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<typename T_Point>
int zoom_in_point(T_Point *geo);
uint32_t zoom_in_value_;
bool is_calc_zoom_;
DISALLOW_COPY_AND_ASSIGN(ObGeoZoomInVisitor);
};

View File

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

View File

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

View File

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

View File

@ -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<uint64_t> elem_info,
ObArray<double> ordinates, uint32_t srid = UINT32_MAX)
: gtype_(gtype), elem_info_(elem_info), ordinates_(ordinates), srid_(srid)
ObArray<double> 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<uint64_t> elem_info_;
ObArray<double> ordinates_;
uint32_t srid_;
DISALLOW_COPY_AND_ASSIGN(ObSdoGeoObject);
};
} // namespace common

File diff suppressed because it is too large Load Diff

View File

@ -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<typename T_IBIN>
int appendPointObj(T_IBIN *geo, const ObString &type_name);
// for LineString
template<typename T_BIN>
int appendLine(const T_BIN *line, ObJsonBin &bin, uint64_t &start_pos, uint64_t &val_idx);
template<typename T_IBIN, typename T_BIN>
int appendLineObj(T_IBIN *geo, const ObString &type_name);
template<typename T_IBIN, typename T_BIN, typename T_BIN_LINE>
int appendMultiLineObj(T_IBIN *geo, const ObString &type_name);
// for Polygon
template<typename T_BIN, typename T_BIN_RING, typename T_BIN_INNER_RING>
int appendPolygon(const T_BIN *poly, ObJsonBin &bin, uint64_t &start_pos, uint64_t &val_idx);
template<typename T_IBIN, typename T_BIN, typename T_BIN_RING, typename T_BIN_INNER_RING>
int appendPolygonObj(T_IBIN *geo, const ObString &type_name);
template<typename T_IBIN, typename T_BIN, typename T_BIN_POLY, typename T_BIN_RING, typename T_BIN_INNER_RING>
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<typename T_IBIN, typename T_BIN>
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

View File

@ -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<ObGeoFuncType::Box>::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<ObGeoFuncType::Box>::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;

View File

@ -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<ObJsonString*> (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:<binary data>
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<ObJsonNode *>(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));
}
}

View File

@ -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.
//

View File

@ -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<const char*>(&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<const char*>(&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<const ObJsonDouble*>(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<const char*>(&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<const ObJsonString*>(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<const char*>(&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<const char*>(&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<uint8_t>(var);
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint8_t));
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint8_t), 0);
break;
}
case JBLS_UINT16: {
uint16_t var_trans = static_cast<uint16_t>(var);
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint16_t));
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint16_t), 0);
break;
}
case JBLS_UINT32: {
uint32_t var_trans = static_cast<uint32_t>(var);
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint32_t));
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint32_t), 0);
break;
}
case JBLS_UINT64: {
uint64_t var_trans = static_cast<uint64_t>(var);
ret = result.append(reinterpret_cast<const char*>(&var_trans), sizeof(uint64_t));
ret = result.append(reinterpret_cast<const char*>(&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<char*>(&header), sizeof(header)))) {
} else if (OB_FAIL(buffer.append(reinterpret_cast<char*>(&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));

View File

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

View File

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

View File

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

View File

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

View File

@ -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<ObMulModeNodeType>(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<uint8_t*>(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));
}

View File

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

View File

@ -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<ObXmlBin*>(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("<?"))) {
LOG_WARN("fail to print <? in pi", K(ret));
} else if (OB_FAIL(x_buf.append(key))) {
} else if (OB_FAIL(x_buf.append(key, 0))) {
LOG_WARN("fail to print target in attr", K(ret), K(key));
} else if (value.empty()) { // if value is empty then do nothing
} else if (OB_FAIL(x_buf.append(" "))) {
LOG_WARN("fail to print space in attr", K(ret));
} 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));
}
@ -394,13 +411,18 @@ int ObIMulModeBase::print_unparsed(ObStringBuffer& x_buf, ObCollationType charse
ObString version = get_version();
ObString encoding = get_encoding();
uint16_t standalone = get_standalone();
if (!(format_flag & ObXmlFormatType::HIDE_PROLOG) && has_flags(XML_DECL_FLAG)) {
uint64_t reserve_size = 0;
if (OB_FAIL(get_bin_size(reserve_size))) {
LOG_WARN("failed to get binary size.", K(ret));
} else if (reserve_size > 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("<?xml"))) {
LOG_WARN("fail to print <?xml in document", K(ret));
} else if (!version.empty()) {
if (OB_FAIL(x_buf.append(" version=\""))) {
LOG_WARN("fail to print version=\" in document", K(ret));
} else if (OB_FAIL(x_buf.append(version))) {
} else if (OB_FAIL(x_buf.append(version, 0))) {
LOG_WARN("fail to print version value in document", K(ret), K(version));
} else if (OB_FAIL(x_buf.append("\""))) {
LOG_WARN("fail to print \" in document", K(ret));
@ -412,7 +434,7 @@ int ObIMulModeBase::print_unparsed(ObStringBuffer& x_buf, ObCollationType charse
}
if (OB_FAIL(x_buf.append(" encoding=\""))) {
LOG_WARN("fail to print encoding=\" in document", K(ret));
} else if (OB_FAIL(x_buf.append(encoding))) {
} else if (OB_FAIL(x_buf.append(encoding, 0))) {
LOG_WARN("fail to print encoding value in document", K(ret), K(encoding), K(charset));
} else if (OB_FAIL(x_buf.append("\""))) {
LOG_WARN("fail to print \" in document", K(ret));
@ -461,14 +483,18 @@ int ObIMulModeBase::print_document(ObStringBuffer& x_buf, ObCollationType charse
ObString encoding = get_encoding();
uint16_t standalone = get_standalone();
bool need_newline_end = true;
if (!(format_flag & ObXmlFormatType::HIDE_PROLOG) && has_flags(XML_DECL_FLAG)) {
uint64_t reserve_size = 0;
if (OB_FAIL(get_bin_size(reserve_size))) {
LOG_WARN("failed to get binary size.", K(ret));
} else if (reserve_size > 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("<?xml"))) {
LOG_WARN("fail to print <?xml in document", K(ret));
} else if (!version.empty()) {
if (OB_FAIL(x_buf.append(" version=\""))) {
LOG_WARN("fail to print version=\" in document", K(ret));
} else if (OB_FAIL(x_buf.append(version))) {
} else if (OB_FAIL(x_buf.append(version, 0))) {
LOG_WARN("fail to print version value in document", K(ret), K(version));
} else if (OB_FAIL(x_buf.append("\""))) {
LOG_WARN("fail to print \" in document", K(ret));
@ -480,7 +506,7 @@ int ObIMulModeBase::print_document(ObStringBuffer& x_buf, ObCollationType charse
}
if (OB_FAIL(x_buf.append(" encoding=\""))) {
LOG_WARN("fail to print encoding=\" in document", K(ret));
} else if (OB_FAIL(x_buf.append(encoding))) {
} else if (OB_FAIL(x_buf.append(encoding, 0))) {
LOG_WARN("fail to print encoding value in document", K(ret), K(encoding), K(charset));
} else if (OB_FAIL(x_buf.append("\""))) {
LOG_WARN("fail to print \" in document", K(ret));
@ -551,14 +577,19 @@ int ObIMulModeBase::print_content(ObStringBuffer& x_buf, bool with_encoding, boo
{
INIT_SUCC(ret);
bool need_newline_end = true;
uint64_t reserve_size = 0;
if (with_encoding || with_version) {
if (OB_FAIL(get_bin_size(reserve_size))) {
LOG_WARN("failed to get binary size.", K(ret));
} else if (reserve_size > 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("<?xml"))) {
LOG_WARN("fail to print <?xml in document", K(ret));
} else if (with_version) {
if (OB_FAIL(x_buf.append(" version=\""))) {
LOG_WARN("fail to print version=\" in document", K(ret));
} else if (OB_FAIL(x_buf.append(param_list.version))) {
} else if (OB_FAIL(x_buf.append(param_list.version, 0))) {
LOG_WARN("fail to print version value in document", K(ret), K(param_list.version));
} else if (OB_FAIL(x_buf.append("\""))) {
LOG_WARN("fail to print \" in document", K(ret));
@ -567,7 +598,7 @@ int ObIMulModeBase::print_content(ObStringBuffer& x_buf, bool with_encoding, boo
if (OB_SUCC(ret) && with_encoding) {
if (OB_FAIL(x_buf.append(" encoding=\""))) {
LOG_WARN("fail to print encoding=\" in document", K(ret));
} else if (OB_FAIL(x_buf.append(param_list.encode))) {
} else if (OB_FAIL(x_buf.append(param_list.encode, 0))) {
LOG_WARN("fail to print encoding value in document", K(ret), K(param_list.encode));
} else if (OB_FAIL(x_buf.append("\""))) {
LOG_WARN("fail to print \" in document", K(ret));
@ -650,7 +681,7 @@ int ObIMulModeBase::print_cdata(ObStringBuffer& x_buf, uint32_t format_flag)
}
} else if (OB_FAIL(x_buf.append("<![CDATA["))) {
LOG_WARN("fail to print <![CDATA[ in pi", K(ret));
} else if (OB_FAIL(x_buf.append(value))) {
} else if (OB_FAIL(x_buf.append(value, 0))) {
LOG_WARN("fail to print text in attr", K(ret), K(value));
} else 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 pi", K(ret));
} else if (OB_FAIL(x_buf.append(value))) {
} else if (OB_FAIL(x_buf.append(value, 0))) {
LOG_WARN("fail to print text in attr", K(ret), K(value));
} 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;

View File

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

View File

@ -49,10 +49,12 @@ int ObXmlElementBinHeader::serialize(ObStringBuffer& buffer)
*reinterpret_cast<uint8_t*>(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<uint8_t*>(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;

View File

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

View File

@ -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<ObXmlElement>(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<ObXmlElement*>(node)) ||
OB_ISNULL(origin_node = static_cast<ObXmlNode*>(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<ObXmlDocument>(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<ObXmlDocument*>(node)) ||
OB_ISNULL(origin_node = static_cast<ObXmlNode*>(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<ObXmlText>(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<ObXmlAttribute>(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<ObXmlAttribute*>(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;

View File

@ -177,6 +177,7 @@ public:
virtual int get_value(ObIArray<ObXmlNode*> &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<ObIMulModeBase*>& 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_;

View File

@ -1544,5 +1544,21 @@ int ObXmlUtil::restore_ns_vec(ObNsSortedVector* element_ns_vec, ObVector<ObNsPai
return ret;
}
template <typename T, typename... Args>
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>(args)...);
}
return static_cast<ObXmlNode *>(new_node);
}
} // namespace common
} // namespace oceanbase

View File

@ -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 <typename T, typename... Args>
static ObXmlNode* clone_new_node(ObIAllocator* allocator, Args &&... args);
};
class ObMulModeFactory

View File

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

View File

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

View File

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

View File

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

View File

@ -8586,7 +8586,7 @@ static int json_raw(const ObObjType expect_type, ObObjCastParams &params,
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 &params,
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);

View File

@ -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",

View File

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

View File

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

View File

@ -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<MultimodeAlloctor*>(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<const ObJsonTableSpec*>(&spec_);
jt_ctx_.spec_ptr_ = const_cast<ObJsonTableSpec*>(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<MultimodeAlloctor*>(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<char*>(ctx.row_alloc_.alloc(buf_len)))) {
if (OB_ISNULL(buf = static_cast<char*>(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;

View File

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

View File

@ -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 */

View File

@ -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<int>(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

View File

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

View File

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

View File

@ -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<ObString, ObString> 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<uint8_t>(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<ObXmlBin*>(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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More