[FEAT MERGE]Patch Spatial Relationship Computation Performance Optimization & Implement of oracle spatial index

This commit is contained in:
wu-xingying 2024-06-18 01:31:46 +00:00 committed by ob-robot
parent d5629a2b36
commit 0cd742f372
107 changed files with 7016 additions and 1261 deletions

View File

@ -103,6 +103,16 @@ 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_cache.cpp
geo/ob_geo_vertex_collect_visitor.cpp
geo/ob_geo_segment_collect_visitor.cpp
geo/ob_geo_cache_polygon.cpp
geo/ob_geo_cache_point.cpp
geo/ob_geo_cache_linestring.cpp
geo/ob_geo_segment_intersect_analyzer.cpp
geo/ob_geo_topology_calculate.cpp
geo/ob_point_location_analyzer.cpp
geo/ob_geo_point_location_visitor.cpp
)
ob_set_subtarget(oblib_lib encode

View File

@ -25,6 +25,7 @@ public:
// constructor
ObGeometry(uint32_t srid = 0, ObIAllocator *allocator = NULL)
: srid_(srid),
zoom_in_value_(0),
allocator_(allocator),
version_(ENCODE_GEO_VERSION(GEO_VESION_1)) {}
virtual ~ObGeometry() = default;
@ -46,7 +47,7 @@ public:
// srid
uint32_t get_srid() const { return srid_; }
void set_srid(uint32_t srid) { srid_ = srid; }
uint32_t get_zoom_in_value() { return zoom_in_value_; }
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_; }

View File

@ -119,6 +119,32 @@ double ObWkbGeomInnerPoint::get<1>(ObGeoWkbByteOrder bo/* = ObGeoWkbByteOrder::L
return ObGeoWkbByteOrderUtil::read<double>(ptr, bo);
}
double ObWkbGeomInnerPoint::get_x(ObGeoWkbByteOrder bo/* = ObGeoWkbByteOrder::LittleEndian */) const
{
char* ptr = reinterpret_cast<char*>(const_cast<ObWkbGeomInnerPoint*>(this));
return ObGeoWkbByteOrderUtil::read_double(ptr, bo);
}
double ObWkbGeomInnerPoint::get_y(ObGeoWkbByteOrder bo/* = ObGeoWkbByteOrder::LittleEndian */) const
{
char* ptr = reinterpret_cast<char*>(const_cast<ObWkbGeomInnerPoint*>(this));
ptr = ptr + sizeof(double);
return ObGeoWkbByteOrderUtil::read_double(ptr, bo);
}
double ObWkbGeogInnerPoint::get_x(ObGeoWkbByteOrder bo/* = ObGeoWkbByteOrder::LittleEndian */) const
{
char* ptr = reinterpret_cast<char*>(const_cast<ObWkbGeogInnerPoint*>(this));
return ObGeoWkbByteOrderUtil::read_double(ptr, bo);
}
double ObWkbGeogInnerPoint::get_y(ObGeoWkbByteOrder bo/* = ObGeoWkbByteOrder::LittleEndian */) const
{
char* ptr = reinterpret_cast<char*>(const_cast<ObWkbGeogInnerPoint*>(this));
ptr = ptr + sizeof(double);
return ObGeoWkbByteOrderUtil::read_double(ptr, bo);
}
template<>
void ObWkbGeomInnerPoint::set<0>(double d)
{

View File

@ -87,6 +87,8 @@ public:
uint64_t length() const;
template<std::size_t K>
double get(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const;
double get_x(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const;
double get_y(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const;
template<std::size_t K>
void set(double d);
// candidate function not viable: 'this' argument has type 'point_type' (aka 'const oceanbase::common::ObWkbGeomInnerPoint'), but method is not marked const
@ -457,6 +459,8 @@ public:
uint64_t length() const;
template<std::size_t K>
double get(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const;
double get_x(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const;
double get_y(ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) const;
template<std::size_t K>
void set(double d, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian);
ObWkbGeogInnerPoint& operator=(const ObWkbGeogInnerPoint& p);

105
deps/oblib/src/lib/geo/ob_geo_cache.cpp vendored Normal file
View File

@ -0,0 +1,105 @@
/**
* 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 "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_vertex_collect_visitor.h"
#include "lib/geo/ob_geo_func_register.h"
#include "lib/geo/ob_geo_point_location_visitor.h"
namespace oceanbase
{
namespace common
{
int ObCachedGeomBase::init()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(origin_geo_) || OB_ISNULL(allocator_)) {
ret = OB_BAD_NULL_ERROR;
LOG_WARN("should not be null.", KP(origin_geo_), KP(allocator_), K(ret));
} else if (!is_inited_) {
ObGeoVertexCollectVisitor vertex_visitor(vertexes_);
if (OB_FAIL(origin_geo_->do_visit(vertex_visitor))) {
LOG_WARN("failed to collect geo vertexes", K(ret));
} else {
x_min_ = vertex_visitor.get_x_min();
x_max_ = vertex_visitor.get_x_max();
is_inited_ = true;
}
}
return ret;
}
int ObCachedGeomBase::intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Intersects>::geo_func::eval(gis_context, res))) {
LOG_WARN("eval st intersection failed", K(ret));
} else if (geo.type() == ObGeoType::POINT
&& origin_geo_->type() == ObGeoType::POINT
&& res == true
&& OB_FAIL(ObGeoTypeUtil::eval_point_box_intersects(gis_context.get_srs(), &geo, origin_geo_, res))) {
LOG_WARN("eval box intersection failed", K(ret));
}
return ret;
}
int ObCachedGeomBase::contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Within>::gis_func::eval(gis_context, res))) {
LOG_WARN("eval Within functor failed", K(ret));
}
return ret;
}
int ObCachedGeomBase::cover(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObGeoFunc<ObGeoFuncType::CoveredBy>::geo_func::eval(gis_context, res))) {
LOG_WARN("eval st coveredBy failed", K(ret));
}
return ret;
}
int ObCachedGeomBase::within(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Within>::gis_func::eval(gis_context, res))) {
LOG_WARN("eval st withIn failed", K(ret));
}
return ret;
}
// check whether is there any point from cached poly in geo
int ObCachedGeomBase::check_any_vertexes_in_geo(ObGeometry& geo, bool &res)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else {
int size = get_vertexes().size();
for (uint32_t i = 0; i < size && OB_SUCC(ret) && !res; i++) {
ObGeoPointLocationVisitor point_loc_visitor(get_vertexes()[i]);
if (OB_FAIL(geo.do_visit(point_loc_visitor))) {
LOG_WARN("failed to do point location visitor", K(ret));
} else if (point_loc_visitor.get_point_location() == ObPointLocation::INTERIOR
|| point_loc_visitor.get_point_location() == ObPointLocation::BOUNDARY) {
res = true;
}
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

96
deps/oblib/src/lib/geo/ob_geo_cache.h vendored Normal file
View File

@ -0,0 +1,96 @@
/**
* 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_CACHE_
#define OCEANBASE_LIB_GEO_OB_CACHE_
#include "lib/string/ob_string.h"
#include "lib/geo/ob_geo_common.h"
#include "lib/geo/ob_geo_utils.h"
namespace oceanbase {
namespace common {
class ObGeoEvalCtx;
enum ObGeoCacheType
{
GEO_BASE_CACHE = 0,
GEO_POINT_CACHE = 1,
GEO_LINESTRING_CACHE = 2,
GEO_POLYGON_CACHE = 3,
};
// only 2d geometry is supported
// interface
class ObCachedGeom {
public:
// constructor
virtual ~ObCachedGeom() {};
virtual int intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) = 0;
virtual int contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) = 0;
virtual int cover(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) = 0;
virtual int within(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) = 0;
virtual bool is_inited() = 0;
virtual double get_x_min() = 0;
virtual double get_x_max() = 0;
virtual ObGeoCacheType get_cache_type() = 0;
virtual ObGeometry* get_cached_geom() = 0;
virtual void set_cached_geom(ObGeometry* geo) = 0;
virtual ObVertexes& get_vertexes() = 0;
virtual ObLineSegments* get_line_segments() = 0;
virtual ObSegments* get_segments() = 0;
};
class ObCachedGeomBase : public ObCachedGeom {
public:
ObCachedGeomBase(ObGeometry *geom, ObIAllocator &allocator, const ObSrsItem *srs)
: origin_geo_(geom),
allocator_(&allocator),
page_allocator_(allocator, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
point_mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_),
vertexes_(&point_mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
srs_(srs),
x_min_(NAN), x_max_(NAN), is_inited_(false) {}
virtual ~ObCachedGeomBase() {};
// get vertex from origin_geo_
virtual int init();
// use boost::geometry functor
virtual int intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual int contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual int cover(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual int within(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual ObGeometry* get_cached_geom() { return origin_geo_;}
virtual ObGeoCacheType get_cache_type() { return ObGeoCacheType::GEO_BASE_CACHE;}
virtual void set_cached_geom(ObGeometry* geo) { origin_geo_ = geo; }
virtual ObVertexes& get_vertexes() { return vertexes_; }
virtual ObLineSegments* get_line_segments() { return nullptr;}
virtual ObSegments* get_segments() { return nullptr; }
virtual inline double get_x_min() { return x_min_; }
virtual inline double get_x_max() { return x_max_; }
virtual inline ObIAllocator *get_allocator() { return allocator_; }
virtual inline bool is_inited() { return is_inited_; }
int check_any_vertexes_in_geo(ObGeometry& geo, bool &res);
protected:
ObGeometry *origin_geo_;
ObIAllocator *allocator_;
ModulePageAllocator page_allocator_;
ObCachePointModuleArena point_mode_arena_;
ObVertexes vertexes_;
const ObSrsItem *srs_;
double x_min_;
double x_max_;
bool is_inited_;
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_OB_CACHE_

View File

@ -0,0 +1,96 @@
/**
* 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 "lib/geo/ob_geo_cache_linestring.h"
#include "lib/geo/ob_point_location_analyzer.h"
#include "lib/geo/ob_geo_point_location_visitor.h"
#include "lib/geo/ob_geo_segment_collect_visitor.h"
#include "lib/geo/ob_geo_vertex_collect_visitor.h"
namespace oceanbase
{
namespace common
{
int ObCachedGeoLinestring::init()
{
int ret = OB_SUCCESS;
if (!is_inited()) {
ObGeoSegmentCollectVisitor seg_visitor(&line_segments_);
if (OB_FAIL(ObCachedGeomBase::init())) {
LOG_WARN("cache geom base init failed", K(ret));
} else if (OB_FAIL(get_cached_geom()->do_visit(seg_visitor))) {
LOG_WARN("do segment visit failed", K(ret));
} else if (OB_ISNULL(lAnalyzer_)) {
ObLineIntersectionAnalyzer *buf = static_cast<ObLineIntersectionAnalyzer *>(allocator_->alloc(sizeof(ObLineIntersectionAnalyzer)));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc point location analyzer failed", K(ret));
} else {
lAnalyzer_ = new(buf) ObLineIntersectionAnalyzer(this, &rtree_);
}
}
}
return ret;
}
int ObCachedGeoLinestring::intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
res = false;
ObGeoDimension dim = ObGeoDimension::MAX_DIMENSION;
bool has_dimension = false;
if (!is_inited() && OB_FAIL(init())) {
LOG_WARN("cached polygon init failed", K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_geo_dimension(&geo, dim))) {
LOG_WARN("fail to get geo dimension.", K(ret));
} else if (OB_FAIL(lAnalyzer_->segment_intersection_query(&geo))) { // check if lines intersect
LOG_WARN("calculate segment intersection failed", K(ret));
} else if (lAnalyzer_->is_intersects()) {
res = lAnalyzer_->is_intersects();
} else if (dim == ObGeoDimension::TWO_DIMENSION) {
// check if cached line in geo polygon
for (uint32_t i = 0; i < get_vertexes().size() && OB_SUCC(ret) && !res; i++) {
ObGeoPointLocationVisitor point_loc_visitor(get_vertexes()[i]);
if (OB_FAIL(geo.do_visit(point_loc_visitor))) {
LOG_WARN("failed to do point location visitor", K(ret));
} else if (point_loc_visitor.get_point_location() == ObPointLocation::INTERIOR
|| point_loc_visitor.get_point_location() == ObPointLocation::BOUNDARY) {
res = true;
}
}
}
if (OB_FAIL(ret) || res) {
} else if (OB_SUCC(ObGeoTypeUtil::has_dimension(geo, ObGeoDimension::ZERO_DIMENSION, has_dimension)) && has_dimension) {
// check if geo point on cached line
input_vertexes_.reset();
ObGeoVertexCollectVisitor vertex_visitor(input_vertexes_);
if (OB_FAIL(geo.do_visit(vertex_visitor))) {
LOG_WARN("failed to collect geo vertexes", K(ret));
} else {
for (uint32_t i = 0; i < input_vertexes_.size() && OB_SUCC(ret) && !res; i++) {
ObGeoPointLocationVisitor point_loc_visitor(input_vertexes_[i]);
if (OB_FAIL(get_cached_geom()->do_visit(point_loc_visitor))) {
LOG_WARN("failed to do point location visitor", K(ret));
} else if (point_loc_visitor.get_point_location() == ObPointLocation::INTERIOR
|| point_loc_visitor.get_point_location() == ObPointLocation::BOUNDARY) {
res = true;
}
}
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,48 @@
/**
* 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_CACHE_LINESTRING_
#define OCEANBASE_LIB_GEO_OB_CACHE_LINESTRING_
#include "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_rstar_tree.h"
#include "lib/geo/ob_geo_segment_intersect_analyzer.h"
namespace oceanbase {
namespace common {
class ObLineSegments;
class ObCachedGeoLinestring : public ObCachedGeomBase {
public:
ObCachedGeoLinestring(ObGeometry *geom, ObIAllocator &allocator, const ObSrsItem *srs)
: ObCachedGeomBase(geom, allocator, srs),
rtree_(this),
lAnalyzer_(nullptr),
line_segments_(page_allocator_, point_mode_arena_),
input_vertexes_(&point_mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {}
virtual ~ObCachedGeoLinestring() {};
// get segments from origin_geo_
virtual int init();
virtual ObGeoCacheType get_cache_type() { return ObGeoCacheType::GEO_LINESTRING_CACHE;}
virtual int intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual ObLineSegments* get_line_segments() { return &line_segments_; }
private:
ObRstarTree<ObLineSegment> rtree_;
ObLineIntersectionAnalyzer *lAnalyzer_;
ObLineSegments line_segments_;
ObVertexes input_vertexes_;
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_OB_CACHE_LINESTRING_

View File

@ -0,0 +1,37 @@
/**
* 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 "lib/geo/ob_geo_cache_point.h"
#include "lib/geo/ob_geo_point_location_visitor.h"
#include "ob_point_location_analyzer.h"
namespace oceanbase
{
namespace common
{
int ObCachedGeoPoint::intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
bool is_intersects = false;
if (!is_inited() && OB_FAIL(init())) {
LOG_WARN("cached polygon init failed", K(ret));
} else if (OB_FAIL(ObCachedGeomBase::check_any_vertexes_in_geo(geo, res))) {
LOG_WARN("fail to check whether is there any point from cached poly in geo.", K(ret));
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,34 @@
/**
* 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_CACHE_POINT_
#define OCEANBASE_LIB_GEO_OB_CACHE_POINT_
#include "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_rstar_tree.h"
namespace oceanbase {
namespace common {
class ObCachedGeoPoint : public ObCachedGeomBase {
public:
ObCachedGeoPoint(ObGeometry *geom, ObIAllocator &allocator, const ObSrsItem *srs)
: ObCachedGeomBase(geom, allocator, srs) {}
virtual ~ObCachedGeoPoint() {};
virtual ObGeoCacheType get_cache_type() { return ObGeoCacheType::GEO_POINT_CACHE;}
virtual int intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_OB_CACHE_Point_

View File

@ -0,0 +1,593 @@
/**
* 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 "lib/geo/ob_geo_cache_polygon.h"
#include "lib/geo/ob_point_location_analyzer.h"
#include "lib/geo/ob_geo_segment_intersect_analyzer.h"
#include "lib/geo/ob_geo_point_location_visitor.h"
#include "lib/geo/ob_geo_segment_collect_visitor.h"
#include "lib/geo/ob_geo_vertex_collect_visitor.h"
namespace oceanbase
{
namespace common
{
// find rings_rtree in range [start, end)
int ObRingsRtree::get_ring_strat_idx(int p_idx, int &start, int& end)
{
int ret = OB_SUCCESS;
if (!inited_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("should be inited", K(ret));
} else if (poly_count_ != ring_count_.size() || p_idx > poly_count_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("wrong ring count", K(ret), K(poly_count_), K(ring_count_.size()), K(p_idx));
} else {
start = 0;
end = 0;
int last_size = 0;
for (int i = 0; i < p_idx && OB_SUCC(ret); ++i) {
start += last_size;
end += ring_count_[i];
last_size = ring_count_[i];
}
if (OB_FAIL(ret)) {
} else if (start >= end || end > rtrees_.size()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("wrong range", K(ret), K(start), K(end), K(rtrees_.size()));
}
}
return ret;
}
int ObCachedGeoPolygon::init()
{
int ret = OB_SUCCESS;
if (!is_inited()) {
if (OB_FAIL(ObCachedGeomBase::init())) {
LOG_WARN("cache geom base init failed", K(ret));
}
}
return ret;
}
int ObCachedGeoPolygon::init_point_analyzer()
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else if (OB_ISNULL(pAnalyzer_)) {
segments_.reset();
ObGeoSegmentCollectVisitor seg_visitor(&segments_);
if (OB_FAIL(get_cached_geom()->do_visit(seg_visitor))) {
LOG_WARN("do segment visit failed", K(ret));
} else {
ObPointLocationAnalyzer *buf = static_cast<ObPointLocationAnalyzer *>(get_allocator()->alloc(sizeof(ObPointLocationAnalyzer)));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc point location analyzer failed", K(ret));
} else {
pAnalyzer_ = new(buf) ObPointLocationAnalyzer(this, &seg_rtree_);
}
}
}
return ret;
}
int ObCachedGeoPolygon::alloc_rtree(ObSegRtree*& rtree_ptr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(allocator_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("should not be null", K(ret));
} else {
ObSegRtree *buf = static_cast<ObSegRtree *>(get_allocator()->alloc(sizeof(ObSegRtree)));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc segment rtree failed", K(ret));
} else {
rtree_ptr = new(buf) ObSegRtree(this);
}
}
return ret;
}
template<typename T_IBIN, typename T_BIN, typename T_IRING, typename T_RING, typename T_INNER_RING>
int ObCachedGeoPolygon::polygon_init_rings_rtree(T_IBIN *geo)
{
int ret = OB_SUCCESS;
int ring_size = geo->size();
if (ring_size == 0) {
// do nothing
} else if (OB_FAIL(rings_rtree_.ring_count_.push_back(ring_size))) {
LOG_WARN("fail to record polygon ring count", K(geo->size()), K(ret));
} else {
const T_BIN *polygon = reinterpret_cast<const T_BIN*>(geo->val());
T_IRING ring;
ObString data(sizeof(T_RING), reinterpret_cast<const char *>(&polygon->exterior_ring()));
ring.set_data(data);
int seg_start_idx = rings_rtree_.ring_segments_.size();
ObGeoSegmentCollectVisitor tmp_seg_visitor(&rings_rtree_.ring_segments_);
ObSegRtree* tmp_rtree = nullptr;
int rtree_size_old = rings_rtree_.rtrees_.size();
// record exterior_ring first
if (OB_FAIL(ring.do_visit(tmp_seg_visitor))) {
OB_LOG(WARN,"failed to do geog polygon exterior ring visit", K(ret));
} else if (OB_FAIL(alloc_rtree(tmp_rtree))) {
LOG_WARN("alloc segment rtree failed", K(ret));
} else if (OB_FAIL(tmp_rtree->construct_rtree_index(rings_rtree_.ring_segments_, seg_start_idx))) {
LOG_WARN("construct rtree index failed", K(ret));
} else if (OB_FAIL(rings_rtree_.rtrees_.push_back(tmp_rtree))) {
LOG_WARN("push back rtree index failed", K(ret));
} else {
const T_INNER_RING &rings = polygon->inner_rings();
typename T_INNER_RING::iterator iter = rings.begin();
for ( ; iter != rings.end() && OB_SUCC(ret); ++iter) {
data.assign_ptr(reinterpret_cast<const char *>(iter.operator->()), sizeof(T_RING));
ring.set_data(data);
tmp_rtree = nullptr;
seg_start_idx = rings_rtree_.ring_segments_.size();
if (OB_FAIL(ring.do_visit(tmp_seg_visitor))) {
OB_LOG(WARN,"failed to do geog polygon inner ring visit", K(ret));
} else if (OB_FAIL(alloc_rtree(tmp_rtree))) {
LOG_WARN("alloc segment rtree failed", K(ret));
} else if (OB_FAIL(tmp_rtree->construct_rtree_index(rings_rtree_.ring_segments_, seg_start_idx))) {
LOG_WARN("construct rtree index failed", K(ret));
} else if (OB_FAIL(rings_rtree_.rtrees_.push_back(tmp_rtree))) {
LOG_WARN("push back rtree index failed", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (rings_rtree_.rtrees_.size() - rtree_size_old != ring_size) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("check rtree size failed", K(rings_rtree_.rtrees_.size()), K(rtree_size_old), K(ring_size), K(ret));
}
}
}
return ret;
}
template<typename T_IBIN, typename T_BIN, typename T_IITEM, typename T_ITEM, typename T_IRING, typename T_RING, typename T_INNER_RING>
int ObCachedGeoPolygon::multipolygon_init_rings_rtree()
{
int ret = OB_SUCCESS;
bool ret_bool = true;
const T_IBIN *multi_poly = reinterpret_cast<const T_IBIN*>(origin_geo_);
uint32_t size = multi_poly->size();
if (size == 0) {
// do nothing
} else {
const T_BIN *items = reinterpret_cast<const T_BIN*>(origin_geo_->val());
typename T_BIN::iterator iter = items->begin();
T_IITEM item;
for ( ; iter != items->end() && OB_SUCC(ret); ++iter) {
rings_rtree_.poly_count_++;
ObString data(sizeof(T_ITEM), reinterpret_cast<char *>(iter.operator->()));
item.set_data(data);
ret = polygon_init_rings_rtree<T_IITEM, T_ITEM, T_IRING, T_RING, T_INNER_RING>(&item);
}
}
return ret;
}
int ObCachedGeoPolygon::init_rings_rtree()
{
int ret = OB_SUCCESS;
if (rings_rtree_.inited_) {
} else if (OB_ISNULL(origin_geo_) || OB_ISNULL(allocator_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else if (origin_geo_->type() == ObGeoType::POLYGON) {
rings_rtree_.poly_count_ = 1;
if (origin_geo_->crs() == ObGeoCRS::Cartesian) {
ret = polygon_init_rings_rtree<ObIWkbGeomPolygon, ObWkbGeomPolygon,
ObIWkbGeomLinearRing, ObWkbGeomLinearRing, ObWkbGeomPolygonInnerRings>(static_cast<ObIWkbGeomPolygon*>(origin_geo_));
} else {
ret = polygon_init_rings_rtree<ObIWkbGeogPolygon, ObWkbGeogPolygon,
ObIWkbGeogLinearRing, ObWkbGeogLinearRing, ObWkbGeogPolygonInnerRings>(static_cast<ObIWkbGeogPolygon*>(origin_geo_));
}
} else {
if (origin_geo_->crs() == ObGeoCRS::Cartesian) {
ret = multipolygon_init_rings_rtree<ObIWkbGeomMultiPolygon, ObWkbGeomMultiPolygon, ObIWkbGeomPolygon, ObWkbGeomPolygon,
ObIWkbGeomLinearRing, ObWkbGeomLinearRing, ObWkbGeomPolygonInnerRings>();
} else {
ret = multipolygon_init_rings_rtree<ObIWkbGeogMultiPolygon, ObWkbGeogMultiPolygon, ObIWkbGeogPolygon, ObWkbGeogPolygon,
ObIWkbGeogLinearRing, ObWkbGeogLinearRing, ObWkbGeogPolygonInnerRings>();
}
}
if (OB_FAIL(ret)) {
LOG_WARN("rings rtree fail to init", K(ret));
} else if (!rings_rtree_.inited_) {
rings_rtree_.inited_ = true;
}
return ret;
}
int ObCachedGeoPolygon::init_line_analyzer()
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else if (OB_ISNULL(lAnalyzer_)) {
ObLineIntersectionAnalyzer *buf = static_cast<ObLineIntersectionAnalyzer *>(get_allocator()->alloc(sizeof(ObLineIntersectionAnalyzer)));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc line segment intersection analyzer failed", K(ret));
} else {
lAnalyzer_ = new(buf) ObLineIntersectionAnalyzer(this, &rtree_);
// collect line segments
ObGeoSegmentCollectVisitor seg_visitor(&line_segments_);
if (OB_FAIL(get_cached_geom()->do_visit(seg_visitor))) {
LOG_WARN("do segment visit failed", K(ret));
}
}
} else {
lAnalyzer_->reset_flag();
}
return ret;
}
int ObCachedGeoPolygon::eval_point_intersects(ObGeometry& geo, bool &res)
{
int ret = OB_SUCCESS;
input_vertexes_.reset();
ObGeoVertexCollectVisitor vertex_coll(input_vertexes_);
bool is_intersects = false;
if (OB_FAIL(geo.do_visit(vertex_coll))) {
LOG_WARN("collect points failed", K(ret));
} else {
for (uint32_t i = 0; i < input_vertexes_.size() && OB_SUCC(ret) && !is_intersects; ++i) {
// check each point position to polygon, i is point idx, p_idx is polygon idx
for (int p_idx = 1; p_idx <= rings_rtree_.poly_count_ && OB_SUCC(ret) && !is_intersects; ++p_idx) {
ObPointLocation poly_pos = ObPointLocation::INVALID;
if (OB_FAIL(get_point_position_in_polygon(p_idx, input_vertexes_[i], poly_pos))) {
LOG_WARN("calculate point position to polygon failed", K(ret), K(i), K(p_idx));
} else if (poly_pos == ObPointLocation::INTERIOR || poly_pos == ObPointLocation::BOUNDARY) {
is_intersects = true;
}
}
}
if (OB_SUCC(ret)) {
res = is_intersects;
}
}
return ret;
}
int ObCachedGeoPolygon::eval_point_contains(ObGeometry& geo, bool &res, bool is_cover)
{
int ret = OB_SUCCESS;
input_vertexes_.reset();
ObGeoVertexCollectVisitor vertex_coll(input_vertexes_);
res = false;
bool res_for_each_point = false;
bool end_check = false;
if (OB_FAIL(geo.do_visit(vertex_coll))) {
LOG_WARN("collect points failed", K(ret));
} else {
for (uint32_t i = 0; i < input_vertexes_.size() && OB_SUCC(ret) && !end_check; ++i) {
// check each point position to polygon, i is point idx, p_idx is polygon idx, make sure every point is is within at least one of the polygon
res_for_each_point = false;
int p_idx = 1;
for (; p_idx <= rings_rtree_.poly_count_ && OB_SUCC(ret) && !res_for_each_point; ++p_idx) {
ObPointLocation poly_pos = ObPointLocation::INVALID;
if (OB_FAIL(get_point_position_in_polygon(p_idx, input_vertexes_[i], poly_pos))) {
LOG_WARN("calculate point position to polygon failed", K(ret), K(i), K(p_idx));
} else if (poly_pos == ObPointLocation::INTERIOR) {
res_for_each_point = true;
is_cover = true;
} else if (poly_pos == ObPointLocation::BOUNDARY) {
res_for_each_point = true;
}
}
if (p_idx > rings_rtree_.poly_count_ && !res_for_each_point) {
end_check = true;
res = false;
}
}
if (OB_SUCC(ret) && !end_check) {
res = is_cover;
}
}
return ret;
}
int ObCachedGeoPolygon::get_point_position_in_polygon(int p_idx, const ObPoint2d &test_point, ObPointLocation &pos)
{
int ret = OB_SUCCESS;
int start = 0;
int end = 0;
if (OB_FAIL(rings_rtree_.get_ring_strat_idx(p_idx, start, end))) {
LOG_WARN("fail to get range", K(ret));
} else {
pos = ObPointLocation::INVALID;
for (int i = start; i < end && OB_SUCC(ret) && pos == ObPointLocation::INVALID; ++i) {
ObPointLocationAnalyzer tmp_pAnalyzer(this, rings_rtree_.rtrees_[i]);
if (i == start) {
// exterior ring
if (OB_FAIL(tmp_pAnalyzer.calculate_point_position(test_point))) {
LOG_WARN("calculate point position failed", K(ret), K(input_vertexes_[i]));
} else if (tmp_pAnalyzer.get_position() == ObPointLocation::EXTERIOR) {
// outside the exterior ring
pos = ObPointLocation::EXTERIOR;
} else if (tmp_pAnalyzer.get_position() == ObPointLocation::BOUNDARY) {
pos = ObPointLocation::BOUNDARY;
} // if is ObPointLocation::INTERIOR, need to check inner rings
} else if (OB_FAIL(tmp_pAnalyzer.calculate_point_position(test_point))) {
LOG_WARN("calculate point position failed", K(ret), K(input_vertexes_[i]));
} else if (tmp_pAnalyzer.get_position() == ObPointLocation::INTERIOR) {
// inside a hole => outside the polygon
pos = ObPointLocation::EXTERIOR;
} else if (tmp_pAnalyzer.get_position() == ObPointLocation::BOUNDARY) {
pos = ObPointLocation::BOUNDARY;
}
}
if (OB_SUCC(ret) && pos == ObPointLocation::INVALID) {
pos = ObPointLocation::INTERIOR;
}
}
return ret;
}
int ObCachedGeoPolygon::inner_eval_intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
ObGeoDimension dim = ObGeoDimension::MAX_DIMENSION;
// 1. check points(geo) location
input_vertexes_.reset();
ObGeoVertexCollectVisitor vertex_coll(input_vertexes_);
bool is_intersects = false;
if (OB_FAIL(geo.do_visit(vertex_coll))) {
LOG_WARN("collect points failed", K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_geo_dimension(&geo, dim))) {
LOG_WARN("fail to get geo dimension.", K(ret));
} else if (OB_ISNULL(pAnalyzer_) && OB_FAIL(init_point_analyzer())) {
LOG_WARN("fail to init_point_Analyzer", K(ret));
} else {
for (uint32_t i = 0; i < input_vertexes_.size() && OB_SUCC(ret) && !is_intersects; ++i) {
if (OB_FAIL(pAnalyzer_->calculate_point_position(input_vertexes_[i]))) {
LOG_WARN("calculate point position failed", K(ret), K(input_vertexes_[i]));
} else {
is_intersects = pAnalyzer_->get_position() == ObPointLocation::BOUNDARY
|| pAnalyzer_->get_position() == ObPointLocation::INTERIOR;
}
}
}
if (OB_FAIL(ret)) {
} else if (dim == ObGeoDimension::ZERO_DIMENSION || is_intersects) {
res = is_intersects;
} else if (OB_ISNULL(lAnalyzer_) && OB_FAIL(init_line_analyzer())) { // dim of geo is 1 or 2
LOG_WARN("fail to init_line_Analyzer", K(ret));
} else if (OB_FAIL(lAnalyzer_->segment_intersection_query(&geo))) { // 2. check ling segment intersection
LOG_WARN("calculate segment intersection failed", K(ret));
} else if (lAnalyzer_->is_intersects()) {
res = lAnalyzer_->is_intersects();
} else if (dim == ObGeoDimension::TWO_DIMENSION) {
if (OB_FAIL(ObCachedGeomBase::check_any_vertexes_in_geo(geo, res))) {
LOG_WARN("fail to check whether is there any point from cached poly in geo.", K(ret));
}
}
return ret;
}
int ObCachedGeoPolygon::get_farthest_point_position(ObVertexes& vertexes, ObPointLocation& farthest_position, bool& has_point_internal)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(pAnalyzer_) && OB_FAIL(init_point_analyzer())) {
LOG_WARN("fail to init_point_Analyzer", K(ret));
} else {
for (uint32_t i = 0; i < vertexes.size() && OB_SUCC(ret) && (farthest_position != ObPointLocation::EXTERIOR); ++i) {
if (OB_FAIL(pAnalyzer_->calculate_point_position(vertexes[i]))) {
LOG_WARN("calculate point position failed", K(ret), K(vertexes[i]));
} else if (pAnalyzer_->get_position() == ObPointLocation::INVALID) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("wrong position.", K(i), K(ret));
} else if (farthest_position == ObPointLocation::INVALID || farthest_position < pAnalyzer_->get_position()) {
farthest_position = pAnalyzer_->get_position();
}
if (!has_point_internal && OB_SUCC(ret) && pAnalyzer_->get_position() == ObPointLocation::INTERIOR) {
has_point_internal = true;
}
}
}
return ret;
}
template<typename T_IBIN, typename T_BIN, typename T_IITEM, typename T_ITEM>
bool ObCachedGeoPolygon::multi_polygons_has_inner_rings()
{
bool ret_bool = true;
const T_IBIN *multi_poly = reinterpret_cast<const T_IBIN*>(origin_geo_);
uint32_t size = multi_poly->size();
if (size == 0) {
ret_bool = false;
} else if (size == 1) {
const T_BIN *items = reinterpret_cast<const T_BIN*>(origin_geo_->val());
typename T_BIN::iterator iter = items->begin();
T_IITEM item;
ObString data(sizeof(T_ITEM), reinterpret_cast<char *>(iter.operator->()));
item.set_data(data);
ret_bool = (item.size() > 1);
}
return ret_bool;
}
bool ObCachedGeoPolygon::has_inner_rings()
{
bool ret_bool = true;
if (origin_geo_->crs() == ObGeoCRS::Cartesian) {
if (origin_geo_->type() == ObGeoType::POLYGON) {
ret_bool = ((static_cast<ObIWkbGeomPolygon*>(origin_geo_))->size() <= 1);
} else {
ret_bool = multi_polygons_has_inner_rings<ObIWkbGeomMultiPolygon, ObWkbGeomMultiPolygon, ObIWkbGeomPolygon, ObWkbGeomPolygon>();
}
} else {
if (origin_geo_->type() == ObGeoType::POLYGON) {
ret_bool = ((static_cast<ObIWkbGeogPolygon*>(origin_geo_))->size() <= 1);
} else {
ret_bool = multi_polygons_has_inner_rings<ObIWkbGeogMultiPolygon, ObWkbGeogMultiPolygon, ObIWkbGeogPolygon, ObWkbGeogPolygon>();
}
}
return ret_bool;
}
// check contains or cover
int ObCachedGeoPolygon::inner_eval_contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res, bool eval_contains)
{
int ret = OB_SUCCESS;
// 1. check points(geo) location
input_vertexes_.reset();
ObGeoVertexCollectVisitor vertex_coll(input_vertexes_);
ObPointLocation farthest_position = ObPointLocation::INVALID;
bool has_point_internal = false;
ObGeoDimension dim = ObGeoDimension::MAX_DIMENSION;
if (OB_FAIL(ObGeoTypeUtil::get_geo_dimension(&geo, dim))) {
LOG_WARN("fail to get geo dimension.", K(ret));
} else if (OB_FAIL(geo.do_visit(vertex_coll))) {
LOG_WARN("collect points failed", K(ret));
} else if (OB_FAIL(get_farthest_point_position(input_vertexes_, farthest_position, has_point_internal))) {
LOG_WARN("fail to get farthest point position.", K(ret));
} else if (farthest_position == ObPointLocation::EXTERIOR) {
res = false;
} else if (dim == ObGeoDimension::ZERO_DIMENSION) {
// 2. if points, make sure at least one point is interior
res = eval_contains ? has_point_internal : true;
} else if (OB_FAIL(init_line_analyzer())) { // dim of geo is 1 or 2
LOG_WARN("fail to init_line_Analyzer", K(ret));
} else if (OB_FALSE_IT(lAnalyzer_->set_intersects_analyzer_type(true))) {
} else if (OB_FAIL(lAnalyzer_->segment_intersection_query(&geo))) { // 2. check ling segment intersection
LOG_WARN("calculate segment intersection failed", K(ret));
} else if ((dim == ObGeoDimension::TWO_DIMENSION || !has_inner_rings())
&& lAnalyzer_->has_external_intersects()) {
res = false;
} else if (lAnalyzer_->is_intersects() && !lAnalyzer_->has_internal_intersects()) {
res = false;
} else if (lAnalyzer_->is_intersects()) {
if (eval_contains && OB_FAIL(ObCachedGeomBase::contains(geo, gis_context, res))) {
LOG_WARN("fail to check contains by base", K(ret));
} else if (!eval_contains && OB_FAIL(ObCachedGeomBase::cover(geo, gis_context, res))) {
LOG_WARN("fail to check contains by base", K(ret));
}
} else if (dim == ObGeoDimension::TWO_DIMENSION) {
bool any_point_in = false;
if (OB_FAIL(ObCachedGeomBase::check_any_vertexes_in_geo(geo, any_point_in))) {
LOG_WARN("fail to check whether is there any point from cached poly in geo.", K(ret));
} else {
res = !any_point_in;
}
} else {
res = true;
}
return ret;
}
// check if CachedPolygon catains geo
int ObCachedGeoPolygon::contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (!is_inited_ && OB_FAIL(init())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else if (ObGeoTypeUtil::is_point(geo)) {
if (!rings_rtree_.inited_ && OB_FAIL(init_rings_rtree())) {
LOG_WARN("fail to init rings rtree", K(ret));
} else if (OB_FAIL(eval_point_contains(geo, res, false))) {
LOG_WARN("fail to get point position", K(ret));
}
} else if (!check_valid_ && OB_FAIL(check_valid(gis_context))) {
LOG_WARN("cached polygon fail to check valid", K(ret));
} else if (is_valid_) {
if (OB_FAIL(inner_eval_contains(geo, gis_context, res, true))) {
LOG_WARN("fail to check contains.", K(ret));
}
} else if (OB_FAIL(ObCachedGeomBase::contains(geo, gis_context, res))) {
LOG_WARN("cache geom base check contains", K(ret));
}
return ret;
}
// check if CachedPolygon catains geo
int ObCachedGeoPolygon::cover(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (!is_inited_ && OB_FAIL(init())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else if (ObGeoTypeUtil::is_point(geo)) {
if (!rings_rtree_.inited_ && OB_FAIL(init_rings_rtree())) {
LOG_WARN("fail to init rings rtree", K(ret));
} else if (OB_FAIL(eval_point_contains(geo, res, true))) {
LOG_WARN("fail to get point position", K(ret));
}
} else if (!check_valid_ && OB_FAIL(check_valid(gis_context))) {
LOG_WARN("cached polygon fail to check valid", K(ret));
} else if (is_valid_) {
if (OB_FAIL(inner_eval_contains(geo, gis_context, res, false))) {
LOG_WARN("fail to check contains.", K(ret));
}
} else if (OB_FAIL(ObCachedGeomBase::cover(geo, gis_context, res))) {
LOG_WARN("cache geom base check cover", K(ret));
}
return ret;
}
int ObCachedGeoPolygon::intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res)
{
int ret = OB_SUCCESS;
if (ObGeoTypeUtil::is_point(geo)) {
if (!rings_rtree_.inited_ && OB_FAIL(init_rings_rtree())) {
LOG_WARN("fail to init rings rtree", K(ret));
} else if (OB_FAIL(eval_point_intersects(geo, res))) {
LOG_WARN("fail to get point position", K(ret));
}
} else if (!is_inited_ && OB_FAIL(init())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cached polygon must be inited", K(ret));
} else if (!check_valid_ && OB_FAIL(check_valid(gis_context))) {
LOG_WARN("cached polygon fail to check valid", K(ret));
} else if (is_valid_) {
if (OB_FAIL(inner_eval_intersects(geo, gis_context, res))) {
LOG_WARN("fail to check contains.", K(ret));
}
} else if (OB_FAIL(ObCachedGeomBase::intersects(geo, gis_context, res))) {
LOG_WARN("cache geom base check contains", K(ret));
}
return ret;
}
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))) {
LOG_WARN("cached polygon fail to check valid", K(ret));
} else {
check_valid_ = true;
is_valid_ = !invalid_for_cache;
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,110 @@
/**
* 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_CACHE_POLYGON_
#define OCEANBASE_LIB_GEO_OB_CACHE_POLYGON_
#include "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_rstar_tree.h"
namespace oceanbase {
namespace common {
class ObLineIntersectionAnalyzer;
class ObPointLocationAnalyzer;
typedef ObRstarTree<ObSegment> ObSegRtree;
typedef PageArena<ObSegRtree*, ModulePageAllocator> ObRtreeVecArena;
typedef PageArena<int, ModulePageAllocator> ObIntArena;
static const int64_t COUNT_DEFAULT_PAGE_SIZE = (1LL << 10); // 1k
class ObRingsRtree {
public:
ObRingsRtree() {}
ObRingsRtree(ModulePageAllocator& page_allocator, ObCacheSegModuleArena& seg_mode_arena) :
rtrees_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator),
int_arena_(COUNT_DEFAULT_PAGE_SIZE, page_allocator),
rtrees_(&rtrees_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
ring_count_(&int_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
ring_segments_(&seg_mode_arena, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
poly_count_(0),
inited_(false) {}
~ObRingsRtree() {}
int get_ring_strat_idx(int p_idx, int &start, int& end);
ObRtreeVecArena rtrees_arena_;
ObIntArena int_arena_;
ObVector<ObSegRtree*, ObRtreeVecArena> rtrees_;
ObVector<int, ObIntArena> ring_count_;
ObSegments ring_segments_;
int poly_count_;
bool inited_;
};
class ObCachedGeoPolygon : public ObCachedGeomBase {
public:
ObCachedGeoPolygon(ObGeometry *geom, ObIAllocator& allocator, const ObSrsItem *srs)
: ObCachedGeomBase(geom, allocator, srs),
rtree_(this),
seg_rtree_(this),
lAnalyzer_(nullptr),
pAnalyzer_(nullptr),
seg_mode_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator_),
segments_(&seg_mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
line_segments_(page_allocator_, point_mode_arena_),
input_vertexes_(&point_mode_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
rings_rtree_(page_allocator_, seg_mode_arena_),
check_valid_(false),
is_valid_(false) {}
virtual ~ObCachedGeoPolygon() {};
// get segments from origin_geo_
virtual int init();
virtual ObGeoCacheType get_cache_type() { return ObGeoCacheType::GEO_POLYGON_CACHE;}
virtual int intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual int contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual int cover(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) override;
virtual ObLineSegments* get_line_segments() { return &line_segments_; }
virtual ObSegments* get_segments() { return &segments_; }
private:
int get_farthest_point_position(ObVertexes& vertexes, ObPointLocation& farthest_position, bool& has_point_internal);
int init_line_analyzer();
int init_point_analyzer();
int init_rings_rtree();
int inner_eval_contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res, bool eval_contains = true);
int inner_eval_intersects(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res);
int eval_point_intersects(ObGeometry& geo, bool &res);
int eval_point_contains(ObGeometry& geo, bool &res, bool is_cover = false);
int get_point_position_in_polygon(int p_idx, const ObPoint2d &test_point, ObPointLocation &pos);
bool has_inner_rings();
template<typename T_IBIN, typename T_BIN, typename T_IITEM, typename T_ITEM>
bool multi_polygons_has_inner_rings();
template<typename T_IBIN, typename T_BIN, typename T_IRING, typename T_RING, typename T_INNER_RING>
int polygon_init_rings_rtree(T_IBIN *geo);
template<typename T_IBIN, typename T_BIN, typename T_IITEM, typename T_ITEM, typename T_IRING, typename T_RING, typename T_INNER_RING>
int multipolygon_init_rings_rtree();
int alloc_rtree(ObSegRtree*& rtree_ptr);
int check_valid(ObGeoEvalCtx& gis_context);
private:
ObRstarTree<ObLineSegment> rtree_;
ObRstarTree<ObSegment> seg_rtree_;
ObLineIntersectionAnalyzer *lAnalyzer_;
ObPointLocationAnalyzer *pAnalyzer_;
ObCacheSegModuleArena seg_mode_arena_;
ObSegments segments_;
ObLineSegments line_segments_;
ObVertexes input_vertexes_;
ObRingsRtree rings_rtree_;
bool check_valid_;
bool is_valid_;
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_OB_CACHE_POLYGON_

View File

@ -31,6 +31,7 @@ public:
// stop when found first non-empty point
bool is_end(ObGeometry *geo) { UNUSED(geo); return (is_empty_ == false); }
bool get_result() { return is_empty_; };
bool set_after_visitor() { return false; }
private:
int check_empty(ObIWkbPoint *geo) { is_empty_ = geo->is_empty(); return OB_SUCCESS; }

View File

@ -34,6 +34,19 @@ double ObGeoWkbByteOrderUtil::read<double>(const char* data, ObGeoWkbByteOrder b
return res;
}
double ObGeoWkbByteOrderUtil::read_double(const char* data, ObGeoWkbByteOrder bo)
{
double res = 0.0;
if (bo == ObGeoWkbByteOrder::LittleEndian) {
res = *reinterpret_cast<const double*>(data);
} else {
for(int i = 0; i < 8; i++) {
reinterpret_cast<char *>(&res)[i] = data[7 - i];
}
}
return res;
}
template<>
uint32_t ObGeoWkbByteOrderUtil::read<uint32_t>(const char* data, ObGeoWkbByteOrder bo)
{

View File

@ -80,8 +80,16 @@ enum class ObDomainOpType
T_GEO_DWITHIN,
T_GEO_DFULLYWITHIN,
T_GEO_COVEREDBY,
T_GEO_RELATE,
T_DOMAIN_OP_END,
};
// sort from inside to outside, the order cannot be changed
enum class ObPointLocation {
INTERIOR = 0,
BOUNDARY = 1,
EXTERIOR = 2,
INVALID = 3,
};
class ObGeoWkbByteOrderUtil
{
@ -90,6 +98,7 @@ public:
// NOTE: ensure data is readble/writable before use
template<typename T>
static T read(const char* data, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian);
static double read_double(const char* data, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian);
template<typename T>
static void write(char* data, T val, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian);

View File

@ -49,6 +49,7 @@ public:
double lati,
bool is_normalized,
ObGeoCoordRangeResult &result);
bool set_after_visitor() { return false; }
private:
const ObSrsItem *srs_;

View File

@ -41,7 +41,11 @@ static bool ob_apply_bg_covered_by_with_pl_strategy(const ObGeometry *g1, const
const ObSrsItem *srs = context.get_srs();
boost::geometry::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
ObPlPaStrategy point_strategy(geog_sphere);
#ifdef USE_SPHERE_GEO
return boost::geometry::covered_by(*geo1, *geo2, point_strategy);
#else
return boost::geometry::covered_by(*geo1, *geo2);
#endif
}
template<typename GeoType1, typename GeoType2>
@ -53,7 +57,11 @@ static bool ob_apply_bg_covered_by_with_ll_strategy(const ObGeometry *g1, const
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);
#ifdef USE_SPHERE_GEO
return boost::geometry::covered_by(*geo1, *geo2, line_strategy);
#else
return boost::geometry::covered_by(*geo1, *geo2);
#endif
}
// ----- ObGeoFuncCoveredByImpl -----
@ -655,8 +663,13 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogPoint, ObWkbGeogC
} else {
ObWkbGeogPolygon *poly_copy = reinterpret_cast<ObWkbGeogPolygon*>(pol_data.ptr());
boost::geometry::strategy::area::geographic<> area_strategy(geog_sphere);
#ifdef USE_SPHERE_GEO
boost::geometry::correct(*poly_copy, area_strategy);
result = boost::geometry::covered_by(*geo1, *poly_copy, point_strategy);
#else
boost::geometry::correct(*poly_copy);
result = boost::geometry::covered_by(*geo1, *poly_copy);
#endif
}
break;
}
@ -669,8 +682,13 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogPoint, ObWkbGeogC
} else {
ObWkbGeogMultiPolygon *multipoly_copy = reinterpret_cast<ObWkbGeogMultiPolygon*>(multipol_data.ptr());
boost::geometry::strategy::area::geographic<> area_strategy(geog_sphere);
#ifdef USE_SPHERE_GEO
boost::geometry::correct(*multipoly_copy, area_strategy);
result = boost::geometry::covered_by(*geo1, *multipoly_copy, point_strategy);
#else
boost::geometry::correct(*multipoly_copy);
result = boost::geometry::covered_by(*geo1, *multipoly_copy);
#endif
}
break;
}
@ -741,7 +759,11 @@ OB_GEO_GEOG_BINARY_FUNC_GEO1_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogMultiPoint,
boost::geometry::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
ObPlPaStrategy point_strategy(geog_sphere);
FOREACH_X(item, *geo1, (result == true)) {
result = boost::geometry::covered_by(*item, *geo2, point_strategy);
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*item, *geo2, point_strategy);
#else
result = boost::geometry::covered_by(*item, *geo2);
#endif
}
return OB_SUCCESS;
} OB_GEO_FUNC_END;
@ -791,9 +813,14 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogLineString, ObWkb
ObLlLaAaStrategy line_strategy(geog_sphere);
const ObWkbGeogLineString *geo1 = reinterpret_cast<const ObWkbGeogLineString *>(g1->val());
ObGeographMultilinestring res_geo1(srid, *allocator);
boost::geometry::difference(*geo1, *multi_line, res_geo1, line_strategy);
ObGeographMultilinestring res_geo2(srid, *allocator);
#ifdef USE_SPHERE_GEO
boost::geometry::difference(*geo1, *multi_line, res_geo1, line_strategy);
boost::geometry::difference(res_geo1, *multi_poly, res_geo2, line_strategy);
#else
boost::geometry::difference(*geo1, *multi_line, res_geo1);
boost::geometry::difference(res_geo1, *multi_poly, res_geo2);
#endif
result = res_geo2.is_empty();
}
return ret;
@ -888,9 +915,14 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogMultiLineString,
ObLlLaAaStrategy line_strategy(geog_sphere);
const ObWkbGeogMultiLineString *geo1 = reinterpret_cast<const ObWkbGeogMultiLineString *>(g1->val());
ObGeographMultilinestring res_geo1(srid, *allocator);
boost::geometry::difference(*geo1, *multi_line, res_geo1, line_strategy);
ObGeographMultilinestring res_geo2(srid, *allocator);
#ifdef USE_SPHERE_GEO
boost::geometry::difference(*geo1, *multi_line, res_geo1, line_strategy);
boost::geometry::difference(res_geo1, *multi_poly, res_geo2, line_strategy);
#else
boost::geometry::difference(*geo1, *multi_line, res_geo1);
boost::geometry::difference(res_geo1, *multi_poly, res_geo2);
#endif
result = res_geo2.is_empty();
}
return ret;
@ -987,11 +1019,19 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogCollection, ObWkb
boost::geometry::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
ObLlLaAaStrategy line_strategy(geog_sphere);
if (!multi_line->empty()) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*multi_line, *geo2, line_strategy);
#else
result = boost::geometry::covered_by(*multi_line, *geo2);
#endif
}
ObPlPaStrategy point_strategy(geog_sphere);
FOREACH_X(item, *multi_point, (result == true)) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*item, *geo2, point_strategy);
#else
result = boost::geometry::covered_by(*item, *geo2);
#endif
}
}
return ret;
@ -1017,14 +1057,26 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogCollection, ObWkb
ObLlLaAaStrategy line_strategy(geog_sphere);
const ObWkbGeogPolygon *geo2 = reinterpret_cast<const ObWkbGeogPolygon *>(g2->val());
if (!multi_poly->empty()) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*multi_poly, *geo2, line_strategy);
#else
result = boost::geometry::covered_by(*multi_poly, *geo2);
#endif
}
if (result == true && !multi_line->empty()) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*multi_line, *geo2, line_strategy);
#else
result = boost::geometry::covered_by(*multi_line, *geo2);
#endif
}
ObPlPaStrategy point_strategy(geog_sphere);
FOREACH_X(item, *multi_point, (result == true)) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*item, *geo2, point_strategy);
#else
result = boost::geometry::covered_by(*item, *geo2);
#endif
}
}
return ret;
@ -1086,11 +1138,19 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogCollection, ObWkb
boost::geometry::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
ObLlLaAaStrategy line_strategy(geog_sphere);
if (!multi_line->empty()) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*multi_line, *geo2, line_strategy);
#else
result = boost::geometry::covered_by(*multi_line, *geo2);
#endif
}
ObPlPaStrategy point_strategy(geog_sphere);
FOREACH_X(item, *multi_point, (result == true)) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*item, *geo2, point_strategy);
#else
result = boost::geometry::covered_by(*item, *geo2);
#endif
}
}
return ret;
@ -1116,14 +1176,26 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogCollection, ObWkb
ObLlLaAaStrategy line_strategy(geog_sphere);
const ObWkbGeogMultiPolygon *geo2 = reinterpret_cast<const ObWkbGeogMultiPolygon *>(g2->val());
if (!multi_poly->empty()) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*multi_poly, *geo2, line_strategy);
#else
result = boost::geometry::covered_by(*multi_poly, *geo2);
#endif
}
if (result == true && !multi_line->empty()) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*multi_line, *geo2, line_strategy);
#else
result = boost::geometry::covered_by(*multi_line, *geo2);
#endif
}
ObPlPaStrategy point_strategy(geog_sphere);
FOREACH_X(item, *multi_point, (result == true)) {
#ifdef USE_SPHERE_GEO
result = boost::geometry::covered_by(*item, *geo2, point_strategy);
#else
result = boost::geometry::covered_by(*item, *geo2);
#endif
}
}
return ret;
@ -1159,22 +1231,36 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncCoveredByImpl, ObWkbGeogCollection, ObWkb
ObGeographMultipoint diff_geo1(srid, *allocator);
boost::geometry::difference(*multi_point1, *multi_point2, diff_geo1);
ObGeographMultipoint diff_geo2(srid, *allocator);
boost::geometry::difference(diff_geo1, *multi_line2, diff_geo2, point_strategy);
ObGeographMultipoint diff_geo3(srid, *allocator);
#ifdef USE_SPHERE_GEO
boost::geometry::difference(diff_geo1, *multi_line2, diff_geo2, point_strategy);
boost::geometry::difference(diff_geo2, *multi_poly2, diff_geo3, point_strategy);
#else
boost::geometry::difference(diff_geo1, *multi_line2, diff_geo2);
boost::geometry::difference(diff_geo2, *multi_poly2, diff_geo3);
#endif
if (!diff_geo3.empty()) {
result = false;
} else {
ObLlLaAaStrategy line_strategy(geog_sphere);
ObGeographMultilinestring diff_line1(srid, *allocator);
boost::geometry::difference(*multi_line1, *multi_line2, diff_line1, line_strategy);
ObGeographMultilinestring diff_line2(srid, *allocator);
#ifdef USE_SPHERE_GEO
boost::geometry::difference(*multi_line1, *multi_line2, diff_line1, line_strategy);
boost::geometry::difference(diff_line1, *multi_poly2, diff_line2, line_strategy);
#else
boost::geometry::difference(*multi_line1, *multi_line2, diff_line1);
boost::geometry::difference(diff_line1, *multi_poly2, diff_line2);
#endif
if (!diff_line2.empty()) {
result = false;
} else {
ObGeographMultipolygon diff_poly(srid, *allocator);
#ifdef USE_SPHERE_GEO
boost::geometry::difference(*multi_poly1, *multi_poly2, diff_poly, line_strategy);
#else
boost::geometry::difference(*multi_poly1, *multi_poly2, diff_poly);
#endif
if (!diff_poly.empty()) {
result = false;
}

View File

@ -46,12 +46,16 @@ int eval_distance_with_point_strategy(const ObGeometry *g1,
ret = OB_ERR_NULL_VALUE;
LOG_WARN("srs is null", K(ret), K(g1->get_srid()), K(g1), K(g2));
} else {
bg::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
bg::strategy::distance::andoyer<bg::srs::spheroid<double>> point_strategy(geog_sphere);
const GeoType1 *geo1 = reinterpret_cast<const GeoType1 *>(g1->val());
const GeoType2 *geo2 = reinterpret_cast<const GeoType2 *>(g2->val());
result = bg::distance(*geo1, *geo2, point_strategy);
if (lib::is_mysql_mode()) {
bg::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
bg::strategy::distance::andoyer<bg::srs::spheroid<double>> point_strategy(geog_sphere);
result = bg::distance(*geo1, *geo2, point_strategy);
} else {
bg::strategy::distance::geographic<bg::strategy::vincenty> vincenty_strategy;
result = bg::distance(*geo1, *geo2, vincenty_strategy);
}
}
return ret;
}

View File

@ -73,7 +73,11 @@ int eval_intersects_with_point_strategy(const ObGeometry *g1,
bg::strategy::within::geographic_winding<ObWkbGeogPoint> point_strategy(geog_sphere);
const GeoType1 *geo1 = reinterpret_cast<const GeoType1 *>(g1->val());
const GeoType2 *geo2 = reinterpret_cast<const GeoType2 *>(g2->val());
#ifdef USE_SPHERE_GEO
result = bg::intersects(*geo1, *geo2, point_strategy);
#else
result = bg::intersects(*geo1, *geo2);
#endif
}
return ret;
}
@ -94,7 +98,11 @@ int eval_intersects_with_nonpoint_strategy(const ObGeometry *g1,
bg::strategy::intersection::geographic_segments<> nonpoint_strategy(geog_sphere);
const GeoType1 *geo1 = reinterpret_cast<const GeoType1 *>(g1->val());
const GeoType2 *geo2 = reinterpret_cast<const GeoType2 *>(g2->val());
#ifdef USE_SPHERE_GEO
result = bg::intersects(*geo1, *geo2, nonpoint_strategy);
#else
result = bg::intersects(*geo1, *geo2);
#endif
}
return ret;
}

View File

@ -120,7 +120,11 @@ static int apply_bg_within_pl_pa_strategy(const ObGeometry *g1,
ObPlPaStrategy geog_pl_pa_strategy(geog_sphere);
const GeoType1 *geo1 = reinterpret_cast<const GeoType1 *>(g1->val());
const GeoType2 *geo2 = reinterpret_cast<const GeoType2 *>(g2->val());
#ifdef USE_SPHERE_GEO
result = bg::within(*geo1, *geo2, geog_pl_pa_strategy);
#else
result = bg::within(*geo1, *geo2);
#endif
}
return ret;
}
@ -141,7 +145,11 @@ static int apply_bg_within_ll_la_aa_strategy(const ObGeometry *g1,
ObLlLaAaStrategy geog_ll_la_aa_strategy(geog_sphere);
const GeoType1 *geo1 = reinterpret_cast<const GeoType1 *>(g1->val());
const GeoType2 *geo2 = reinterpret_cast<const GeoType2 *>(g2->val());
#ifdef USE_SPHERE_GEO
result = bg::within(*geo1, *geo2, geog_ll_la_aa_strategy);
#else
result = bg::within(*geo1, *geo2);
#endif
}
return ret;
}
@ -220,6 +228,7 @@ static int ob_caculate_mp_within_l_a_geog(const ObGeometry *g1, const ObGeometry
for (; iter != geo1->end(); ++iter) {
typename MpType::value_type& point = *iter;
if (!within) {
#ifdef USE_SPHERE_GEO
within = bg::within(point, *geo2, geog_pl_pa_strategy);
if (!within) {
intersects = bg::intersects(point, *geo2, geog_pl_pa_strategy);
@ -229,6 +238,17 @@ static int ob_caculate_mp_within_l_a_geog(const ObGeometry *g1, const ObGeometry
} else {
intersects = bg::intersects(point, *geo2, geog_pl_pa_strategy);
}
#else
within = bg::within(point, *geo2);
if (!within) {
intersects = bg::intersects(point, *geo2);
} else {
intersects = true;
}
} else {
intersects = bg::intersects(point, *geo2);
}
#endif
if (!intersects) break;
}
result = (within && intersects);
@ -316,8 +336,13 @@ static int ob_caculate_ml_within_gc_geog(const ObGeometry *g1, const ObGeometry
// Checks relation between a pair of geometries defined by a mask.
bg::de9im::mask mask("T********");
result = res_geo2->is_empty() &&
#ifdef USE_SPHERE_GEO
(bg::relate(*geo1, *multi_line, mask, geog_ll_la_aa_strategy) ||
bg::relate(*geo1, *multi_poly, mask, geog_ll_la_aa_strategy));
#else
(bg::relate(*geo1, *multi_line, mask) ||
bg::relate(*geo1, *multi_poly, mask));
#endif
}
}
return ret;
@ -368,7 +393,11 @@ static int ob_caculate_mpl_within_gc_geog(const ObGeometry *g1, const ObGeometry
} else {
bg::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
ObLlLaAaStrategy geog_ll_la_aa_strategy(geog_sphere);
#ifdef USE_SPHERE_GEO
result = bg::within(*geo1, *multi_poly, geog_ll_la_aa_strategy);
#else
result = bg::within(*geo1, *multi_poly);
#endif
}
return ret;
}
@ -1305,13 +1334,22 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo
LOG_WARN("failed to do within by functor between GeogMultiPoint and GeogLineString", K(ret));
} else if (mp_within_l) {
result = multi_line->empty() ||
#ifdef USE_SPHERE_GEO
bg::covered_by(*multi_line, *geo2, geog_ll_la_aa_strategy);
} else if (bg::within(*multi_line, *geo2, geog_ll_la_aa_strategy)){
#else
bg::covered_by(*multi_line, *geo2);
} else if (bg::within(*multi_line, *geo2)){
#endif
bool covered = true;
ObGeographMultipoint::iterator iter = multi_point->begin();
for (; iter != multi_point->end() && covered; ++iter) {
ObGeographMultipoint::value_type& point = *iter;
#ifdef USE_SPHERE_GEO
covered = bg::covered_by(point, *geo2, geog_pl_pa_strategy);
#else
covered = bg::covered_by(point, *geo2);
#endif
}
result = covered;
} else {
@ -1354,29 +1392,53 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo
LOG_WARN("failed to do within by functor between multipoint and polygon", K(ret));
} else if (mp_within_l) {
result = (multi_line->empty() ||
#ifdef USE_SPHERE_GEO
bg::covered_by(*multi_line, *geo2, geog_ll_la_aa_strategy)) &&
(multi_poly->empty() ||
bg::covered_by(*multi_poly, *geo2, geog_ll_la_aa_strategy));
} else if (bg::within(*multi_line, *geo2, geog_ll_la_aa_strategy)) {
#else
bg::covered_by(*multi_line, *geo2)) &&
(multi_poly->empty() ||
bg::covered_by(*multi_poly, *geo2));
} else if (bg::within(*multi_line, *geo2)) {
#endif
bool covered = true;
ObGeographMultipoint::iterator iter = multi_point->begin();
for (; iter != multi_point->end() && covered; ++iter) {
ObGeographMultipoint::value_type& point = *iter;
#ifdef USE_SPHERE_GEO
covered = bg::covered_by(point, *geo2, geog_pl_pa_strategy);
#else
covered = bg::covered_by(point, *geo2);
#endif
}
result = !covered ? false :
(multi_poly->empty() ||
#ifdef USE_SPHERE_GEO
bg::covered_by(*multi_poly, *geo2, geog_ll_la_aa_strategy));
} else if (bg::within(*multi_poly, *geo2, geog_ll_la_aa_strategy)) {
#else
bg::covered_by(*multi_poly, *geo2));
} else if (bg::within(*multi_poly, *geo2)) {
#endif
bool covered = true;
ObGeographMultipoint::iterator iter = multi_point->begin();
for (; iter != multi_point->end() && covered; ++iter) {
ObGeographMultipoint::value_type& point = *iter;
#ifdef USE_SPHERE_GEO
covered = bg::covered_by(point, *geo2, geog_pl_pa_strategy);
#else
covered = bg::covered_by(point, *geo2);
#endif
}
result = !covered ? false :
(multi_line->empty() ||
#ifdef USE_SPHERE_GEO
bg::covered_by(*multi_line, *geo2, geog_ll_la_aa_strategy));
#else
bg::covered_by(*multi_line, *geo2));
#endif
} else {
result = false;
}
@ -1423,14 +1485,24 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo
if (OB_FAIL(ret)) {
LOG_WARN("failed to do within by functor between GeogMultiPoint and GeogMultiLineString", K(ret));
} else if (mp_within_l) {
#ifdef USE_SPHERE_GEO
result = multi_line->empty() ||
bg::covered_by(*multi_line, *geo2, geog_ll_la_aa_strategy);
} else if (bg::within(*multi_line, *geo2, geog_ll_la_aa_strategy)){
#else
result = multi_line->empty() ||
bg::covered_by(*multi_line, *geo2);
} else if (bg::within(*multi_line, *geo2)){
#endif
bool covered = true;
ObGeographMultipoint::iterator iter = multi_point->begin();
for (; iter != multi_point->end() && covered; ++iter) {
typename ObGeographMultipoint::value_type& point = *iter;
#ifdef USE_SPHERE_GEO
covered = bg::covered_by(point, *geo2, geog_pl_pa_strategy);
#else
covered = bg::covered_by(point, *geo2);
#endif
}
result = covered;
} else {
@ -1472,30 +1544,55 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo
if (OB_FAIL(ret)) {
LOG_WARN("failed to do within by functor between multipoint and polygon", K(ret));
} else if (mp_within_poly) {
#ifdef USE_SPHERE_GEO
result = (multi_line->empty() ||
bg::covered_by(*multi_line, *geo2, geog_ll_la_aa_strategy)) &&
(multi_poly->empty() ||
bg::covered_by(*multi_poly, *geo2, geog_ll_la_aa_strategy));
} else if (bg::within(*multi_line, *geo2, geog_ll_la_aa_strategy)){
#else
result = (multi_line->empty() ||
bg::covered_by(*multi_line, *geo2)) &&
(multi_poly->empty() ||
bg::covered_by(*multi_poly, *geo2));
} else if (bg::within(*multi_line, *geo2)){
#endif
bool covered = true;
ObGeographMultipoint::iterator iter = multi_point->begin();
for (; iter != multi_point->end() && covered; ++iter) {
ObGeographMultipoint::value_type& point = *iter;
#ifdef USE_SPHERE_GEO
covered = bg::covered_by(point, *geo2, geog_pl_pa_strategy);
#else
covered = bg::covered_by(point, *geo2);
#endif
}
result = !covered ? false :
(multi_poly->empty() ||
#ifdef USE_SPHERE_GEO
bg::covered_by(*multi_poly, *geo2, geog_ll_la_aa_strategy));
} else if (bg::within(*multi_poly, *geo2, geog_ll_la_aa_strategy)){
} else if (bg::within(*multi_poly, *geo2, geog_ll_la_aa_strategy)) {
#else
bg::covered_by(*multi_poly, *geo2));
} else if (bg::within(*multi_poly, *geo2)) {
#endif
bool covered = true;
ObGeographMultipoint::iterator iter = multi_point->begin();
for (; iter != multi_point->end() && covered; ++iter) {
ObGeographMultipoint::value_type& point = *iter;
#ifdef USE_SPHERE_GEO
covered = bg::covered_by(point, *geo2, geog_pl_pa_strategy);
#else
covered = bg::covered_by(point, *geo2);
#endif
}
result = !covered ? false :
(multi_line->empty() ||
#ifdef USE_SPHERE_GEO
bg::covered_by(*multi_line, *geo2, geog_ll_la_aa_strategy));
#else
bg::covered_by(*multi_line, *geo2));
#endif
} else {
result = false;
}
@ -1578,10 +1675,17 @@ OB_GEO_GEOG_BINARY_FUNC_BEGIN(ObGeoFuncWithinImpl, ObWkbGeogCollection, ObWkbGeo
} else {
// Checks relation between a pair of geometries defined by a mask.
bg::de9im::mask mask("T********");
#ifdef USE_SPHERE_GEO
result = mp_within_gc ||
bg::relate(*g1_multi_line, *g2_multi_line, mask, geog_ll_la_aa_strategy) ||
bg::relate(*g1_multi_line, *g2_multi_poly, mask, geog_ll_la_aa_strategy) ||
bg::relate(*g1_multi_poly, *g2_multi_poly, mask, geog_ll_la_aa_strategy);
#else
result = mp_within_gc ||
bg::relate(*g1_multi_line, *g2_multi_line, mask) ||
bg::relate(*g1_multi_line, *g2_multi_poly, mask) ||
bg::relate(*g1_multi_poly, *g2_multi_poly, mask);
#endif
}
}
}

View File

@ -290,7 +290,7 @@ int ObIWkbGeogCollection::do_visit(ObIGeoVisitor &visitor)
ObWkbGeogCollection::iterator iter = collection->begin();
uint64_t total_len = data_.length();
uint64_t pos = WKB_COMMON_WKB_HEADER_LEN;
for ( ; iter != collection->end() && OB_SUCC(ret) && !visitor.is_end(this); iter++) {
for ( ; iter != collection->end() && OB_SUCC(ret) && !visitor.is_end(this); ++iter) {
typename ObWkbGeogCollection::const_pointer sub_ptr = iter.operator->();
if (pos + WKB_GEO_TYPE_SIZE + WKB_GEO_BO_SIZE > total_len) {
ret = OB_INVALID_ARGUMENT;
@ -455,7 +455,7 @@ int ObIWkbGeomCollection::do_visit(ObIGeoVisitor &visitor)
ObWkbGeomCollection::iterator iter = collection->begin();
uint64_t total_len = data_.length();
uint64_t pos = WKB_COMMON_WKB_HEADER_LEN;
for ( ; iter != collection->end() && OB_SUCC(ret) && !visitor.is_end(this); iter++) {
for ( ; iter != collection->end() && OB_SUCC(ret) && !visitor.is_end(this); ++iter) {
typename ObWkbGeomCollection::const_pointer sub_ptr = iter.operator->();
if (pos + WKB_GEO_TYPE_SIZE + WKB_GEO_BO_SIZE > total_len) {
ret = OB_INVALID_ARGUMENT;

View File

@ -183,6 +183,9 @@ private:
};
class ObIWkbGeomLinearRing : public ObIWkbGeometry {
public:
typedef ObWkbGeomLinearRing value_type;
public:
// constructor
ObIWkbGeomLinearRing(uint32_t srid = 0, ObIAllocator *allocator = NULL)
@ -303,6 +306,9 @@ private:
};
class ObIWkbGeogLinearRing : public ObIWkbGeometry {
public:
typedef ObWkbGeogLinearRing value_type;
public:
// constructor
ObIWkbGeogLinearRing(uint32_t srid = 0, ObIAllocator *allocator = NULL)

View File

@ -0,0 +1,197 @@
/**
* 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_point_location_visitor.h"
#include "ob_geo_topology_calculate.h"
#include "ob_point_location_analyzer.h"
namespace oceanbase {
namespace common {
bool ObGeoPointLocationVisitor::prepare(ObGeometry *geo)
{
bool bret = true;
if (OB_ISNULL(geo)) {
bret = false;
}
return bret;
}
template<typename T>
int ObGeoPointLocationVisitor::calculate_ring_intersects_cnt(T &ext, uint32_t &intersects_cnt, bool &is_on_boundary)
{
int ret = OB_SUCCESS;
if (ext.size() <= 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid exterior ring", K(ret), K(ext.size()));
} else {
typename T::const_iterator iter_befor = ext.begin();
typename T::const_iterator iter_cur = ext.begin() + 1;
typename T::const_iterator iter_end = ext.end();
ObPoint2d begin;
ObPoint2d end;
for ( ; iter_cur != iter_end && OB_SUCC(ret) && !is_on_boundary; ++iter_befor, ++iter_cur) {
begin.x = (iter_befor)->get_x();
begin.y = (iter_befor)->get_y();
end.x = (iter_cur)->get_x();
end.y = (iter_cur)->get_y();
if (LineIntersect::POINT_INTERSECT == ObGeoTopology::calculate_point_inersect_horizontally(begin, end,
test_point_, is_on_boundary)) {
++intersects_cnt;
}
}
}
return ret;
}
template <typename T_BIN, typename T_RINGS>
int ObGeoPointLocationVisitor::calculate_point_location_in_polygon(T_BIN *poly)
{
int ret = OB_SUCCESS;
ObPointLocation pos = ObPointLocation::INVALID;
typename T_RINGS::value_type &ext = poly->exterior_ring();
bool is_on_boundary = false;
uint32_t intersects_cnt = 0;
if (OB_FAIL(calculate_ring_intersects_cnt(ext, intersects_cnt, is_on_boundary))) {
LOG_WARN("failed to get intersects cnt", K(ret), K(ext.size()));
} else {
if (is_on_boundary) {
pos = ObPointLocation::BOUNDARY;
} else if (intersects_cnt % 2 == 0) {
pos = ObPointLocation::EXTERIOR;
} else {
intersects_cnt = 0;
T_RINGS &inner_rings = poly->inner_rings();
typename T_RINGS::iterator iterInnerRing = inner_rings.begin();
typename T_RINGS::iterator iter_end = inner_rings.end();
for (; iterInnerRing != iter_end && OB_SUCC(ret) && pos == ObPointLocation::INVALID; ++iterInnerRing) {
if (OB_FAIL(calculate_ring_intersects_cnt(*iterInnerRing, intersects_cnt, is_on_boundary))) {
LOG_WARN("failed to get intersects cnt", K(ret), K(iterInnerRing->size()));
} else if (is_on_boundary) {
pos = ObPointLocation::BOUNDARY;
} else if (intersects_cnt % 2 == 1) {
pos = ObPointLocation::EXTERIOR;
}
}
}
if (OB_SUCC(ret)) {
if (pos == ObPointLocation::INVALID) {
// test point is in exterior ring and outside inner rings
point_location_ = ObPointLocation::INTERIOR;
} else {
point_location_ = pos;
}
}
}
return ret;
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeomPolygon *geo)
{
return calculate_point_location_in_polygon<ObWkbGeomPolygon, ObWkbGeomPolygonInnerRings>(reinterpret_cast<ObWkbGeomPolygon *>(geo->val()));
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeogPolygon *geo)
{
return calculate_point_location_in_polygon<ObWkbGeogPolygon, ObWkbGeogPolygonInnerRings>(reinterpret_cast<ObWkbGeogPolygon *>(geo->val()));
}
int ObGeoPointLocationVisitor::visit(ObIWkbPoint *geo)
{
int ret = OB_SUCCESS;
ObPointLocation pos = ObPointLocation::INVALID;
if (geo->x() == test_point_.x && geo->y() == test_point_.y) {
point_location_ = ObPointLocation::BOUNDARY;
} else {
point_location_ = ObPointLocation::EXTERIOR;
}
return ret;
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeogMultiPoint *geo)
{
if (point_location_ == ObPointLocation::INVALID) {
point_location_ = ObPointLocation::EXTERIOR;
}
return OB_SUCCESS;
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeomMultiPoint *geo)
{
if (point_location_ == ObPointLocation::INVALID) {
point_location_ = ObPointLocation::EXTERIOR;
}
return OB_SUCCESS;
}
template<typename T_IBIN>
int ObGeoPointLocationVisitor::calculate_point_location_in_linestring(T_IBIN *geo)
{
int ret = OB_SUCCESS;
const typename T_IBIN::value_type *line = reinterpret_cast<const typename T_IBIN::value_type*>(geo->val());
int geo_size = geo->size();
if (geo_size > 1) {
typename T_IBIN::value_type::iterator iter = line->begin();
typename T_IBIN::value_type::iterator iter_after = line->begin() + 1;
ObSegment seg;
for (uint32_t i = 0; i < geo_size - 1 && OB_SUCC(ret); ++i, ++iter, ++iter_after) {
seg.begin.x = iter->template get<0>();
seg.begin.y = iter->template get<1>();
seg.end.x = (iter_after)->template get<0>();
seg.end.y = (iter_after)->template get<1>();
if (test_point_.x > std::max(seg.begin.x, seg.end.x) || test_point_.y > std::max(seg.begin.y, seg.end.y)
||test_point_.x < std::min(seg.begin.x, seg.end.x) || test_point_.y < std::min(seg.begin.y, seg.end.y)) {
point_location_ = ObPointLocation::EXTERIOR;
} else if ((seg.begin.x == test_point_.x && seg.begin.y == test_point_.y)
||(seg.end.x == test_point_.x && seg.end.y == test_point_.y)) {
point_location_ = ObPointLocation::BOUNDARY;
} else if (PointPosition::ON == ObGeoTopology::calculate_point_position(seg.begin, seg.end, test_point_)) {
point_location_ = ObPointLocation::INTERIOR;
} else {
point_location_ = ObPointLocation::EXTERIOR;
}
}
}
return ret;
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeomLineString *geo)
{
return calculate_point_location_in_linestring<ObIWkbGeomLineString>(geo);
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeogLineString *geo)
{
return calculate_point_location_in_linestring<ObIWkbGeogLineString>(geo);
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeomMultiLineString *geo)
{
if (point_location_ == ObPointLocation::INVALID) {
point_location_ = ObPointLocation::EXTERIOR;
}
return OB_SUCCESS;
}
int ObGeoPointLocationVisitor::visit(ObIWkbGeogMultiLineString *geo)
{
if (point_location_ == ObPointLocation::INVALID) {
point_location_ = ObPointLocation::EXTERIOR;
}
return OB_SUCCESS;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,64 @@
/**
* 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_POINT_LOCATION_VISITOR_
#define OCEANBASE_LIB_GEO_OB_GEO_POINT_LOCATION_VISITOR_
#include "lib/geo/ob_geo_visitor.h"
#include "lib/geo/ob_geo_cache.h"
namespace oceanbase
{
namespace common
{
class ObGeoPointLocationVisitor : public ObEmptyGeoVisitor
{
public:
ObGeoPointLocationVisitor(ObPoint2d &test_point)
: test_point_(test_point),
point_location_(ObPointLocation::INVALID) {}
virtual ~ObGeoPointLocationVisitor() {}
bool prepare(ObGeometry *geo);
int visit(ObIWkbGeomPolygon *geo);
int visit(ObIWkbGeogPolygon *geo);
int visit(ObIWkbPoint *geo);
int visit(ObIWkbGeogMultiPoint *geo);
int visit(ObIWkbGeomMultiPoint *geo);
int visit(ObIWkbGeomLineString *geo);
int visit(ObIWkbGeogLineString *geo);
int visit(ObIWkbGeomMultiLineString *geo);
int visit(ObIWkbGeogMultiLineString *geo);
int visit(ObIWkbGeometry *geo) { UNUSED(geo); return OB_SUCCESS; }
bool is_end(ObIWkbGeogLinearRing *geo) { UNUSED(geo); return true; }
bool is_end(ObIWkbGeomLinearRing *geo) { UNUSED(geo); return true; }
bool is_end(ObGeometry *geo) { UNUSED(geo); return (point_location_ == ObPointLocation::INTERIOR
|| point_location_ == ObPointLocation::BOUNDARY); }
inline ObPointLocation get_point_location() { return point_location_; }
bool set_after_visitor() { return false; }
private:
template<typename T>
int calculate_ring_intersects_cnt(T &ext, uint32_t &intersects_cnt, bool &is_on_boundary);
template <typename T_BIN, typename T_RINGS>
int calculate_point_location_in_polygon(T_BIN *poly);
template<typename T_IBIN>
int calculate_point_location_in_linestring(T_IBIN *line);
ObPoint2d &test_point_;
ObPointLocation point_location_;
DISALLOW_COPY_AND_ASSIGN(ObGeoPointLocationVisitor);
};
} // namespace common
} // namespace oceanbase
#endif

View File

@ -0,0 +1,99 @@
/**
* 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_RSTAR_TREE_
#define OCEANBASE_LIB_GEO_RSTAR_TREE_
#include "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_dispatcher.h"
#include <boost/geometry.hpp>
namespace oceanbase {
namespace common {
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
enum QueryRelation {
INTERSECTS = 0,
};
template <typename T>
class ObRstarTree {
public:
typedef T value_type;
typedef PageArena<value_type, ModulePageAllocator> ObModuleArenaType;
typedef std::pair<ObCartesianBox, value_type *> RtreeNodeValue;
// create the rtree using default constructor
typedef bgi::rtree<RtreeNodeValue, bgi::rstar<16, 8>, bgi::indexable<RtreeNodeValue>,
bgi::equal_to<RtreeNodeValue>> RStarTree;
public:
ObRstarTree(ObCachedGeomBase *cache_geo)
: cache_geo_(cache_geo),
rtree_index_(),
is_built_(false) {}
virtual ~ObRstarTree() {}
int construct_rtree_index(ObVector<T, ObModuleArenaType> &elements, int start = 0)
{
int ret = OB_SUCCESS;
ObVector<RtreeNodeValue> rtree_nodes;
for (uint32_t i = start; i < elements.size() && OB_SUCC(ret); i++) {
ObCartesianBox box;
if (OB_FAIL(elements[i].get_box(box))) {
LOG_WARN("failed to get segment box", K(ret));
} else if (OB_FAIL(rtree_nodes.push_back(std::make_pair(box, &elements[i])))) {
LOG_WARN("failed to record rtree node", K(ret));
}
}
if (OB_FAIL(ret)) {
} else {
try {
new (&rtree_index_) RStarTree(rtree_nodes.begin(), rtree_nodes.end());
is_built_ = true;
} catch (...) {
ret = ob_boost_geometry_exception_handle();
}
}
return ret;
}
int query(QueryRelation relation, const ObCartesianBox &box, std::vector<RtreeNodeValue> &res)
{
int ret = OB_SUCCESS;
if (!is_built_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("rtree isn't built", K(ret));
} else if (relation == QueryRelation::INTERSECTS) {
try {
rtree_index_.query(bgi::intersects(box), std::back_inserter(res));
} catch (...) {
ret = ob_boost_geometry_exception_handle();
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("query type isn't supported", K(ret), K(relation));
}
return ret;
}
inline bool is_built() { return is_built_; }
private:
ObVector<RtreeNodeValue> rtree_nodes_;
ObCachedGeomBase *cache_geo_;
RStarTree rtree_index_;
bool is_built_;
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_RSTAR_TREE_

View File

@ -0,0 +1,198 @@
/**
* 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_segment_collect_visitor.h"
namespace oceanbase {
namespace common {
bool ObGeoSegmentCollectVisitor::prepare(ObGeometry *geo)
{
bool bret = true;
if (OB_ISNULL(geo)) {
bret = false;
}
return bret;
}
template<typename T_IBIN>
int ObGeoSegmentCollectVisitor::collect_line_segment(T_IBIN *geo)
{
int ret = OB_SUCCESS;
bool is_new_start = true;
uint32_t start_idx = 0;
uint32_t end_idx = 0;
ObPoint2d start;
ObPoint2d end;
QuadDirection last_dir = QuadDirection::INVALID_QUAD;
const typename T_IBIN::value_type *line = reinterpret_cast<const typename T_IBIN::value_type*>(geo->val());
int64_t node_num = geo->size();
typename T_IBIN::value_type::iterator iter = line->begin();
typename T_IBIN::value_type::iterator iter_after = line->begin() + 1;
for (int64_t i = 0; i < node_num - 1 && OB_SUCC(ret); ++i, ++iter, ++iter_after) {
QuadDirection curr_dir = QuadDirection::INVALID_QUAD;
start.x = iter->template get<0>();
start.y = iter->template get<1>();
end.x = iter_after->template get<0>();
end.y = iter_after->template get<1>();
if (start.x == end.x && start.y == end.y) {
// do nothing
} else if (OB_FAIL(line_segments_->verts_.push_back(start))) {
LOG_WARN("failed to append segment", K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_quadrant_direction(start, end, curr_dir))) {
LOG_WARN("failed to get point direction", K(ret), K(start.x), K(start.y), K(end.x), K(end.y));
} else {
if (is_new_start) {
is_new_start = false;
last_dir = curr_dir;
start_idx = line_segments_->verts_.size() - 1;
} else if (curr_dir != last_dir) {
// generate new line segment
ObLineSegment seg;
seg.verts = &line_segments_->verts_;
seg.begin = start_idx;
seg.end = line_segments_->verts_.size() - 1;
// last end point is current start point
start_idx = seg.end;
last_dir = curr_dir;
if (OB_FAIL(line_segments_->segs_.push_back(seg))) {
LOG_WARN("failed to append segment", K(ret));
}
}
}
}
if (OB_SUCC(ret) && line_segments_->verts_.size() > 0) {
uint32_t last_idx = line_segments_->verts_.size() - 1;
if (line_segments_->verts_[last_idx].x == end.x && line_segments_->verts_[last_idx].y == end.y) {
// do nothing
} else if (OB_FAIL(line_segments_->verts_.push_back(end))) {
LOG_WARN("failed to append segment", K(ret));
}
if (OB_SUCC(ret) && start_idx < line_segments_->verts_.size() - 1) {
// generate last new line segment
ObLineSegment seg;
seg.verts = &line_segments_->verts_;
seg.begin = start_idx;
seg.end = line_segments_->verts_.size() - 1;
// last end point is current start point
start_idx = seg.end;
if (OB_FAIL(line_segments_->segs_.push_back(seg))) {
LOG_WARN("failed to append segment", K(ret));
}
}
}
return ret;
}
template<typename T_IBIN>
int ObGeoSegmentCollectVisitor::collect_segment(T_IBIN *geo)
{
int ret = OB_SUCCESS;
const typename T_IBIN::value_type *line = reinterpret_cast<const typename T_IBIN::value_type*>(geo->val());
uint32_t node_num = geo->size();
typename T_IBIN::value_type::iterator iter = line->begin();
typename T_IBIN::value_type::iterator iter_after = line->begin() + 1;
for (uint32_t i = 0; i < node_num - 1 && OB_SUCC(ret); ++i, ++iter, ++iter_after) {
ObSegment seg;
seg.begin.x = iter->template get<0>();
seg.begin.y = iter->template get<1>();
seg.end.x = iter_after->template get<0>();
seg.end.y = iter_after->template get<1>();
if (seg.begin.x == seg.end.x && seg.begin.y == seg.end.y) {
// do nothing
} else if (OB_FAIL(segments_->push_back(seg))) {
LOG_WARN("failed to append segment", K(ret));
}
}
return ret;
}
int ObGeoSegmentCollectVisitor::visit(ObIWkbGeomLineString *geo)
{
int ret = OB_SUCCESS;
if (is_collect_mono_) {
if (OB_ISNULL(line_segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_line_segment(geo))) {
LOG_WARN("failed to collect line segment", K(ret));
}
} else if (OB_ISNULL(segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_segment(geo))) {
LOG_WARN("failed to collect segment", K(ret));
}
return ret;
}
int ObGeoSegmentCollectVisitor::visit(ObIWkbGeogLineString *geo)
{
int ret = OB_SUCCESS;
if (is_collect_mono_) {
if (OB_ISNULL(line_segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_line_segment(geo))) {
LOG_WARN("failed to collect line segment", K(ret));
}
} else if (OB_ISNULL(segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_segment(geo))) {
LOG_WARN("failed to collect segment", K(ret));
}
return ret;
}
int ObGeoSegmentCollectVisitor::visit(ObIWkbGeomLinearRing *geo)
{
int ret = OB_SUCCESS;
if (is_collect_mono_) {
if (OB_ISNULL(line_segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_line_segment(geo))) {
LOG_WARN("failed to collect line segment", K(ret));
}
} else if (OB_ISNULL(segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_segment(geo))) {
LOG_WARN("failed to collect segment", K(ret));
}
return ret;
}
int ObGeoSegmentCollectVisitor::visit(ObIWkbGeogLinearRing *geo)
{
int ret = OB_SUCCESS;
if (is_collect_mono_) {
if (OB_ISNULL(line_segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_line_segment(geo))) {
LOG_WARN("failed to collect line segment", K(ret));
}
} else if (OB_ISNULL(segments_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("line segments is null", K(ret));
} else if (OB_FAIL(collect_segment(geo))) {
LOG_WARN("failed to collect segment", K(ret));
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,61 @@
/**
* 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_SEGMENT_COLLECT_VISITOR_
#define OCEANBASE_LIB_GEO_OB_GEO_SEGMENT_COLLECT_VISITOR_
#include "lib/geo/ob_geo_visitor.h"
#include "lib/geo/ob_geo_cache.h"
namespace oceanbase
{
namespace common
{
class ObGeoSegmentCollectVisitor : public ObEmptyGeoVisitor
{
public:
ObGeoSegmentCollectVisitor(ObLineSegments *segments)
: line_segments_(segments),
segments_(nullptr),
is_collect_mono_(true) {}
ObGeoSegmentCollectVisitor(ObSegments *segments)
: line_segments_(nullptr),
segments_(segments),
is_collect_mono_(false) {}
virtual ~ObGeoSegmentCollectVisitor() {}
bool prepare(ObGeometry *geo);
int visit(ObIWkbGeomLineString *geo);
int visit(ObIWkbGeogLineString *geo);
int visit(ObIWkbGeomLinearRing *geo);
int visit(ObIWkbGeogLinearRing *geo);
int visit(ObIWkbGeometry *geo) { UNUSED(geo); return OB_SUCCESS; }
bool is_end(ObIWkbGeomLineString *geo) override { UNUSED(geo); return true;}
bool is_end(ObIWkbGeogLineString *geo) override { UNUSED(geo); return true;}
bool is_end(ObIWkbGeomLinearRing *geo) override { UNUSED(geo); return true;}
bool is_end(ObIWkbGeogLinearRing *geo) override { UNUSED(geo); return true;}
bool set_after_visitor() { return false; }
private:
template<typename T_IBIN>
int collect_line_segment(T_IBIN *geo);
template<typename T_IBIN>
int collect_segment(T_IBIN *geo);
ObLineSegments *line_segments_;
ObSegments *segments_;
bool is_collect_mono_;
DISALLOW_COPY_AND_ASSIGN(ObGeoSegmentCollectVisitor);
};
} // namespace common
} // namespace oceanbase
#endif

View File

@ -0,0 +1,86 @@
/**
* 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_segment_intersect_analyzer.h"
#include "ob_geo_segment_collect_visitor.h"
namespace oceanbase {
namespace common {
bool ObLineIntersectionAnalyzer::is_check_done(LineIntersect inter_res)
{
bool res = false;
if (check_all_intesect_) {
res = has_internal_intersect_ && has_external_intersect_;
} else {
res = is_intersect_;
}
return res;
}
int ObLineIntersectionAnalyzer::segment_intersection_query(ObGeometry *geo)
{
int ret = OB_SUCCESS;
is_intersect_ = false;
if (OB_ISNULL(rtree_index_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("rtree index is null", K(ret));
} else if (!rtree_index_->is_built()) {
ObLineSegments* line_segs = cache_geo_->get_line_segments();
if (OB_ISNULL(line_segs)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("should not be null", K(ret));
} else if (OB_FAIL(rtree_index_->construct_rtree_index(line_segs->segs_))) {
LOG_WARN("construct rtree index failed", K(ret));
}
}
if (OB_SUCC(ret)) {
ObLineSegments input_segments;
ObGeoSegmentCollectVisitor seg_visitor(&input_segments);
if (OB_FAIL(geo->do_visit(seg_visitor))) {
LOG_WARN("failed to get input segment", K(ret));
} else {
LineIntersect inter_res = LineIntersect::NO_INTERSCT;
// query rtree to check intersesctiion
for (uint32_t i = 0; i < input_segments.segs_.size() && OB_SUCC(ret) && !is_check_done(inter_res); i++) {
ObCartesianBox box;
std::vector<RtreeNodeValue> res;
inter_res = LineIntersect::NO_INTERSCT;
if (OB_FAIL(input_segments.segs_[i].get_box(box))) {
LOG_WARN("failed to get segment box", K(ret));
} else if (OB_FAIL(rtree_index_->query(QueryRelation::INTERSECTS, box, res))) {
LOG_WARN("failed to query rtree", K(ret));
} else {
for (uint32_t j = 0; j < res.size() && OB_SUCC(ret) && !is_check_done(inter_res); j++) {
const ObLineSegment* seg1 = res[j].second;
if (OB_FAIL(ObGeoTopology::calculate_line_segments_intersect(*seg1, input_segments.segs_[i], inter_res))) {
LOG_WARN("failed to get segment box", K(ret));
} else if (inter_res != LineIntersect::NO_INTERSCT) {
is_intersect_ = true;
if (inter_res == LineIntersect::POINT_INTERSECT) {
has_external_intersect_ = 1;
} else {
has_internal_intersect_ = 1;
}
}
}
}
}
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,59 @@
/**
* 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_SEG_INTERSECTS_ANALYZER_
#define OCEANBASE_LIB_GEO_SEG_INTERSECTS_ANALYZER_
#include "lib/geo/ob_geo_cache.h"
#include "ob_geo_topology_calculate.h"
#include "ob_geo_rstar_tree.h"
namespace oceanbase {
namespace common {
class ObLineIntersectionAnalyzer {
public:
typedef std::pair<ObCartesianBox, ObLineSegment *> RtreeNodeValue;
public:
ObLineIntersectionAnalyzer(ObCachedGeomBase *cache_geo, ObRstarTree<ObLineSegment> *rtree_index)
: cache_geo_(cache_geo),
rtree_index_(rtree_index),
flags_(0) {}
virtual ~ObLineIntersectionAnalyzer() {}
int segment_intersection_query(ObGeometry *geo);
bool is_intersects() { return is_intersect_; }
void set_intersects_analyzer_type(bool check_all_intesect) { check_all_intesect_ = check_all_intesect;}
void reset_flag() { flags_ = 0; }
bool is_check_done(LineIntersect inter_res);
bool has_external_intersects() { return check_all_intesect_ && has_external_intersect_;}
bool has_internal_intersects() { return check_all_intesect_ && has_internal_intersect_;}
bool set_after_visitor() { return false; }
private:
ObCachedGeomBase *cache_geo_;
ObRstarTree<ObLineSegment> *rtree_index_;
union {
struct {
uint8_t is_intersect_ : 1;
uint8_t has_internal_intersect_ : 1; // the intersection point is a endpoints
uint8_t has_external_intersect_ : 1; // the intersection point is not endpoints
uint8_t check_all_intesect_: 1; // need to distinguish intersection types
uint8_t reserved_ : 4;
};
uint8_t flags_;
};
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_SEG_INTERSECTS_ANALYZER_

View File

@ -13,7 +13,8 @@
#define USING_LOG_PREFIX LIB
#include "ob_geo_to_s2_visitor.h"
#include "ob_srs_info.h"
#include "ob_geo_dispatcher.h"
#include "lib/hash/ob_hashset.h"
#include "lib/geo/ob_geo_dispatcher.h"
namespace oceanbase {
namespace common {
@ -220,7 +221,8 @@ int ObWkbToS2Visitor::MakeS2Polygon(T_IBIN *geo, S2Polygon *&res)
LOG_WARN("failed to alloc s2cell", K(ret));
} else {
loop->Normalize();
if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
if (OB_FAIL(ret)) {
} else if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
LOG_WARN("failed to add loop", K(ret));
}
}
@ -247,7 +249,8 @@ int ObWkbToS2Visitor::MakeS2Polygon(T_IBIN *geo, S2Polygon *&res)
LOG_WARN("failed to alloc s2cell", K(ret));
} else {
loop->Normalize();
if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
if (OB_FAIL(ret)) {
} else if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
LOG_WARN("failed to add loop", K(ret));
}
}
@ -292,7 +295,8 @@ int ObWkbToS2Visitor::MakeProjS2Polygon(T_IBIN *geo, S2Polygon *&res)
LOG_WARN("failed to alloc s2cell", K(ret));
} else {
loop->Normalize();
if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
if (OB_FAIL(ret)) {
} else if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
LOG_WARN("failed to add loop", K(ret));
}
}
@ -318,7 +322,8 @@ int ObWkbToS2Visitor::MakeProjS2Polygon(T_IBIN *geo, S2Polygon *&res)
LOG_WARN("failed to alloc s2cell", K(ret));
} else {
loop->Normalize();
if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
if (OB_FAIL(ret)) {
} else if (OB_FAIL(vector_emplace_back(s2poly, loop))) {
LOG_WARN("failed to add loop", K(ret));
}
}
@ -485,6 +490,82 @@ int64_t ObWkbToS2Visitor::get_cellids(ObS2Cellids &cells, bool is_query, bool ne
return ret;
}
int64_t ObWkbToS2Visitor::get_cellids_and_unrepeated_ancestors(ObS2Cellids &cells,
ObS2Cellids &ancestors,
bool need_buffer,
S1Angle distance)
{
INIT_SUCC(ret);
if (invalid_) {
if (OB_FAIL(cells.push_back(exceedsBoundsCellID))) {
LOG_WARN("fail to push_back cellid", K(ret));
}
} else {
S2CellUnion cellids;
S2RegionCoverer coverer(options_);
uint32_t s2v_size = s2v_.size();
hash::ObHashSet<uint64_t> cellid_set;
if (OB_FAIL(cellid_set.create(128, "CellidSet", "HashNode"))) {
LOG_WARN("failed to create cellid set", K(ret));
} else if (!cellid_set.created()) {
ret = OB_NOT_INIT;
LOG_WARN("fail to init cellid set", K(ret));
} else {
for (int i = 0; i < s2v_size && OB_SUCC(ret); i++) {
S2CellUnion tmp = coverer.GetCovering(*s2v_[i]);
cellids = cellids.Union(tmp);
}
if (need_buffer) {
const int max_level_diff = 2;
cellids.Expand(distance, max_level_diff);
}
if (s2v_size > 1) {
cellids.Normalize();
}
S2CellId prev_id = S2CellId::None();
for (int i = 0; OB_SUCC(ret) && i < cellids.size(); i++) {
int hash_ret = cellid_set.exist_refactored(cellids[i].id());
if (OB_HASH_NOT_EXIST == hash_ret) {
if (OB_FAIL(cellid_set.set_refactored(cellids[i].id()))) {
LOG_WARN("failed to add cellid into set", K(ret));
} else if (OB_FAIL(cells.push_back(cellids[i].id()))) {
LOG_WARN("fail to push_back cellid", K(ret));
}
if (OB_SUCC(ret)) {
int level = cellids[i].level();
while (OB_SUCC(ret) && (level -= options_.level_mod()) >= options_.min_level()) {
S2CellId ancestor_id = cellids[i].parent(level);
if (prev_id != S2CellId::None() && prev_id.level() > level &&
prev_id.parent(level) == ancestor_id) {
break;
}
int ancestor_hash_ret = cellid_set.exist_refactored(ancestor_id.id());
if (OB_HASH_NOT_EXIST == ancestor_hash_ret) {
if (OB_FAIL(cellid_set.set_refactored(ancestor_id.id()))) {
LOG_WARN("failed to add cellid into set", K(ret));
} else if (OB_FAIL(ancestors.push_back(ancestor_id.id()))) {
LOG_WARN("fail to push_back cellid", K(ret));
}
} else if (OB_HASH_EXIST != ancestor_hash_ret) {
ret = ancestor_hash_ret;
LOG_WARN("fail to check if key exist", K(ret), K(i));
}
}
}
} else if (OB_HASH_EXIST != hash_ret) {
ret = hash_ret;
LOG_WARN("fail to check if key exist", K(ret), K(i));
}
prev_id = cellids[i];
}
if (OB_SUCC(ret) && has_reset_ && OB_FAIL(cells.push_back(exceedsBoundsCellID))) {
LOG_WARN("fail to push_back cellid", K(ret));
}
}
}
return ret;
}
int64_t ObWkbToS2Visitor::get_inner_cover_cellids(ObS2Cellids &cells)
{
INIT_SUCC(ret);

View File

@ -92,6 +92,7 @@ public:
int finish(ObIWkbGeomCollection *geo) { UNUSED(geo); return OB_SUCCESS; }
int64_t get_cellids(ObS2Cellids &cells, bool is_query, bool need_buffer, S1Angle distance);
int64_t get_cellids_and_unrepeated_ancestors(ObS2Cellids &cells, ObS2Cellids &ancestors, bool need_buffer, S1Angle distance);
int64_t get_inner_cover_cellids(ObS2Cellids &cells);
int64_t get_mbr(S2LatLngRect &mbr, bool need_buffer, S1Angle distance);
bool is_invalid() { return invalid_; }

View File

@ -0,0 +1,221 @@
/**
* 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_topology_calculate.h"
namespace oceanbase {
namespace common {
LineIntersect ObGeoTopology::calculate_point_inersect_horizontally(const ObPoint2d &start, const ObPoint2d &end,
const ObPoint2d &target, bool &is_on_boundary)
{
LineIntersect res = LineIntersect::NO_INTERSCT;
if (start.x < target.x && end.x < target.x) {
// line is on left of point
res = LineIntersect::NO_INTERSCT;
} else if (end.x == target.x && end.y == target.y) {
res = LineIntersect::POINT_INTERSECT;
is_on_boundary = true;
} else if (start.y == end.y && start.y == target.y) {
// line is horizontal
if (target.x >= std::min(start.x, end.x) && target.x <= std::max(start.x, end.x)) {
res = LineIntersect::POINT_INTERSECT;
is_on_boundary = true;
}
} else if (((start.y > target.y) && (end.y <= target.y)) ||
((end.y > target.y) && (start.y <= target.y))) {
PointPosition pos = calculate_point_position(start, end, target);
if (pos == PointPosition::ON) {
res = LineIntersect::POINT_INTERSECT;
is_on_boundary = true;
} else if ((pos == PointPosition::LEFT && start.y < end.y)
|| (pos == PointPosition::RIGHT && start.y > end.y)) {
res = LineIntersect::POINT_INTERSECT;
}
}
return res;
}
PointPosition ObGeoTopology::calculate_point_position(const ObPoint2d &start, const ObPoint2d &end,
const ObPoint2d &target)
{
PointPosition res = PointPosition::UNKNOWN;
double constexpr DP_SAFE_EPSILON = 1e-15;
double detsum;
double const detleft = (start.x - target.x) * (end.y - target.y);
double const detright = (start.y - target.y) * (end.x - target.x);
double const det = detleft - detright;
if(detleft > 0.0) {
if(detright <= 0.0) {
if(det < 0) {
res = PointPosition::RIGHT;
} else if(det > 0) {
res = PointPosition::LEFT;
} else {
res = PointPosition::ON;
}
} else {
detsum = detleft + detright;
}
} else if (detleft < 0.0) {
if(detright >= 0.0) {
if(det < 0) {
res = PointPosition::RIGHT;
} else if(det > 0) {
res = PointPosition::LEFT;
} else {
res = PointPosition::ON;
}
} else {
detsum = -detleft - detright;
}
} else {
if(det < 0) {
res = PointPosition::RIGHT;
} else if(det > 0) {
res = PointPosition::LEFT;
} else {
res = PointPosition::ON;
}
}
if (res == PointPosition::UNKNOWN) {
double err_range = DP_SAFE_EPSILON * detsum;
if((det >= err_range) || (-det >= err_range) || det == 0) {
if(det < 0) {
res = PointPosition::RIGHT;
} else if(det > 0) {
res = PointPosition::LEFT;
} else {
res = PointPosition::ON;
}
}
}
return res;
}
// start 0 is query box, start 1 is testline
int ObGeoTopology::calculate_segment_intersect(const ObPoint2d &start0, const ObPoint2d &end0,
const ObPoint2d &start1, const ObPoint2d &end1,
LineIntersect &res)
{
int ret = OB_SUCCESS;
// check box intersects
ObCartesianBox box0(std::min(start0.x, end0.x), std::min(start0.y, end0.y),
std::max(start0.x, end0.x), std::max(start0.y, end0.y));
ObCartesianBox box1(std::min(start1.x, end1.x), std::min(start1.y, end1.y),
std::max(start1.x, end1.x), std::max(start1.y, end1.y));
if (!box0.Intersects(box1)) {
res = LineIntersect::NO_INTERSCT;
} else {
PointPosition p1_start_pos = calculate_point_position(start0, end0, start1);
PointPosition p1_end_pos = calculate_point_position(start0, end0, end1);
if (p1_start_pos == PointPosition::UNKNOWN || p1_end_pos == PointPosition::UNKNOWN) {
ret = OB_ERR_GIS_INVALID_DATA;
LOG_WARN("got a double precision problem", K(ret), K(start0), K(end0),
K(start1), K(end1), K(p1_start_pos), K(p1_end_pos));
} else if (p1_start_pos == p1_end_pos && p1_start_pos != PointPosition::ON) {
// both points of line1 are on the same side of line0
res = LineIntersect::NO_INTERSCT;
} else {
PointPosition p0_start_pos = calculate_point_position(start1, end1, start0);
PointPosition p0_end_pos = calculate_point_position(start1, end1, end0);
if (p0_start_pos == PointPosition::UNKNOWN || p0_end_pos == PointPosition::UNKNOWN) {
ret = OB_ERR_GIS_INVALID_DATA;
LOG_WARN("got a double precision problem", K(ret), K(start0), K(end0),
K(start1), K(end1), K(p0_start_pos), K(p0_end_pos));
} else if (p0_start_pos == p0_end_pos && p0_start_pos != PointPosition::ON) {
// both points of line0 are on the same side of line1
res = LineIntersect::NO_INTERSCT;
} else if (p0_start_pos == PointPosition::ON && p0_start_pos == p0_end_pos
&& p0_start_pos == p1_end_pos && p0_start_pos == p1_start_pos) {
// The two line segments coincide exactly.
res = LineIntersect::LINE_INTERSECT;
} else if (p0_start_pos == PointPosition::ON || p0_end_pos == PointPosition::ON
|| p1_end_pos == PointPosition::ON || p1_start_pos == PointPosition::ON) {
// at least exist a point on another line
// needed in contains
res = LineIntersect::END_POINT_INTERSECT;
} else {
res = LineIntersect::POINT_INTERSECT;
}
}
}
return ret;
}
int ObGeoTopology::calculate_line_segments_intersect(const ObLineSegment& seg1, const ObLineSegment& seg2,
LineIntersect &res)
{
int ret = OB_SUCCESS;
bool is_stack_overflow = false;
if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
LOG_WARN("failed to check stack overflow", K(ret));
} else if (is_stack_overflow) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow));
} else if (res == LineIntersect::LINE_INTERSECT || res == LineIntersect::POINT_INTERSECT || res == LineIntersect::END_POINT_INTERSECT) {
// return res
} else if (seg1.end - seg1.begin == 1 && seg2.end - seg2.begin == 1) {
if (OB_FAIL(calculate_segment_intersect((*seg1.verts)[seg1.begin], (*seg1.verts)[seg1.end],
(*seg2.verts)[seg2.begin], (*seg2.verts)[seg2.end],
res))) {
LOG_WARN("get segment intersect result failed", K(ret));
}
} else {
uint32_t middle1 = (seg1.begin + seg1.end) / 2;
uint32_t middle2 = (seg2.begin + seg2.end) / 2;
if (middle1 > seg1.begin) {
ObLineSegment forward_seg1 = seg1;
forward_seg1.end = middle1;
if (middle2 > seg2.begin) {
ObLineSegment forward_seg2 = seg2;
forward_seg2.end = middle2;
if (OB_FAIL(calculate_line_segments_intersect(forward_seg1, forward_seg2, res))) {
LOG_WARN("calculate_line_segments_intersect failed", K(ret));
}
}
if (OB_SUCC(ret) && middle2 < seg2.end) {
ObLineSegment back_seg2 = seg2;
back_seg2.begin = middle2;
if (OB_FAIL(calculate_line_segments_intersect(forward_seg1, back_seg2, res))) {
LOG_WARN("calculate_line_segments_intersect failed", K(ret));
}
}
}
if (OB_FAIL(ret)) {
} else if (middle1 < seg1.end) {
ObLineSegment back_seg1 = seg1;
back_seg1.begin = middle1;
if (OB_SUCC(ret) && middle2 > seg2.begin) {
ObLineSegment forward_seg2 = seg2;
forward_seg2.end = middle2;
if (OB_FAIL(calculate_line_segments_intersect(back_seg1, forward_seg2, res))) {
LOG_WARN("calculate_line_segments_intersect failed", K(ret));
}
}
if (OB_SUCC(ret) && middle2 < seg2.end) {
ObLineSegment back_seg2 = seg2;
back_seg2.begin = middle2;
if (OB_FAIL(calculate_line_segments_intersect(back_seg1, back_seg2, res))) {
LOG_WARN("calculate_line_segments_intersect failed", K(ret));
}
}
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,55 @@
/**
* 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_TOPOLOGY_
#define OCEANBASE_LIB_GEO_OB_TOPOLOGY_
#include "lib/string/ob_string.h"
#include "lib/geo/ob_geo_common.h"
#include "lib/geo/ob_geo_utils.h"
namespace oceanbase {
namespace common {
// point relative position to line
enum PointPosition {
LEFT = 0,
RIGHT = 1,
ON = 2,
UNKNOWN = 3,
};
enum LineIntersect {
NO_INTERSCT = 0,
POINT_INTERSECT = 1,
END_POINT_INTERSECT = 2, // Intersects at a endpoint.
LINE_INTERSECT = 3,
};
class ObGeoTopology {
public:
static LineIntersect calculate_point_inersect_horizontally(const ObPoint2d &start, const ObPoint2d &end,
const ObPoint2d &target, bool &is_on_boundary);
static PointPosition calculate_point_position(const ObPoint2d &start, const ObPoint2d &end,
const ObPoint2d &target);
static int calculate_segment_intersect(const ObPoint2d &start0, const ObPoint2d &end0,
const ObPoint2d &start1, const ObPoint2d &end1,
LineIntersect &res);
static int calculate_line_segments_intersect(const ObLineSegment& seg1, const ObLineSegment& seg2,
LineIntersect &res);
static bool is_same(const ObPoint2d &point, const ObPoint2d &target) {return point.x == target.x && point.y == target.y;}
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_OB_TOPOLOGY_

View File

@ -354,6 +354,22 @@ int ObCartesianGeometrycollection::do_visit(ObIGeoVisitor &visitor)
return ObGeoTreeVisitorImplement::collection_do_visit(this, visitor);
}
ObCartesianBox::ObCartesianBox(double min_x, double min_y, double max_x, double max_y)
{
min_p_.set<0>(min_x);
min_p_.set<1>(min_y);
max_p_.set<0>(max_x);
max_p_.set<1>(max_y);
}
void ObCartesianBox::set_box(double min_x, double min_y, double max_x, double max_y)
{
min_p_.set<0>(min_x);
min_p_.set<1>(min_y);
max_p_.set<0>(max_x);
max_p_.set<1>(max_y);
}
bool ObCartesianBox::Contains(ObCartesianBox &other)
{
double this_min_x = min_corner().get<0>();

View File

@ -1088,6 +1088,8 @@ public:
ObCartesianBox() = default;
ObCartesianBox(ObWkbGeomInnerPoint &min_point, ObWkbGeomInnerPoint &max_point)
: min_p_(min_point), max_p_(max_point) {}
ObCartesianBox(double min_x, double min_y, double max_x, double max_y);
void set_box(double min_x, double min_y, double max_x, double max_y);
ObGeoCRS coordinate_system() const {
return ObGeoCRS::Cartesian;
}

View File

@ -42,6 +42,13 @@
#include "lib/geo/ob_geo_affine_visitor.h"
#include "lib/geo/ob_geo_simplify_visitor.h"
#include "lib/geo/ob_geo_grid_visitor.h"
#include "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_cache_polygon.h"
#include "lib/geo/ob_geo_cache_point.h"
#include "lib/geo/ob_geo_cache_linestring.h"
#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"
namespace oceanbase
{
@ -696,6 +703,25 @@ int ObGeoTypeUtil::construct_geometry(ObIAllocator &allocator,
return ret;
}
int ObGeoTypeUtil::copy_geometry(ObIAllocator &allocator,
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))) {
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))) {
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;
}
int ObGeoTypeUtil::correct_polygon(ObIAllocator &alloc,
const ObSrsItem *srs,
bool is_ring_closed,
@ -1439,13 +1465,15 @@ int ObGeoBoxUtil::clip_by_box(ObGeometry &geo_in, ObIAllocator &allocator, const
} else {
geo_bin = &geo_in;
ObGeoToTreeVisitor tree_visitor(&allocator);
if (OB_FAIL(geo_in.do_visit(tree_visitor))) {
if (OB_FAIL(ret)) {
} else if (OB_FAIL(geo_in.do_visit(tree_visitor))) {
LOG_WARN("fail to do tree visitor", K(ret));
} else {
geo_tree = tree_visitor.get_geometry();
}
}
if (OB_ISNULL(geo_tree) || OB_ISNULL(geo_bin)) {
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(geo_tree) || OB_ISNULL(geo_bin)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc memory for geometry", K(ret));
}
@ -2594,6 +2622,12 @@ bool ObGeoTypeUtil::is_2d_geo_type(ObGeoType geo_type) {
geo_type == ObGeoType::GEOMETRYCOLLECTION;
}
bool ObGeoTypeUtil::is_multi_geo_type(ObGeoType geo_type) {
return geo_type == ObGeoType::MULTIPOINT ||
geo_type == ObGeoType::MULTILINESTRING || geo_type == ObGeoType::MULTIPOLYGON ||
geo_type == ObGeoType::GEOMETRYCOLLECTION;
}
int ObGeoTypeUtil::get_coll_dimension(ObIWkbGeomCollection *geo, int8_t &dimension)
{
int ret = OB_SUCCESS;
@ -2646,6 +2680,70 @@ int ObGeoTypeUtil::get_coll_dimension(ObIWkbGeomCollection *geo, int8_t &dimensi
}
return ret;
}
int ObLineSegment::get_box(ObCartesianBox &box)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(verts)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("vertexes is null", K(ret));
} else if (begin >= end) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("line segment don't have enough points", K(begin), K(end), K(ret));
} else {
double min_x = (*verts)[begin].x;
double min_y = (*verts)[begin].y;
double max_x = (*verts)[begin].x;
double max_y = (*verts)[begin].y;
for (uint32_t i = begin + 1; i <= end; i++) {
min_x = std::min(min_x, (*verts)[i].x);
min_y = std::min(min_y, (*verts)[i].y);
max_x = std::max(max_x, (*verts)[i].x);
max_y = std::max(max_y, (*verts)[i].y);
}
box.min_corner().set<0>(min_x);
box.min_corner().set<1>(min_y);
box.max_corner().set<0>(max_x);
box.max_corner().set<1>(max_y);
}
return ret;
}
int ObSegment::get_box(ObCartesianBox &box)
{
double min_x = std::min(begin.x, end.x);
double min_y = std::min(begin.y, end.y);
double max_x = std::max(begin.x, end.x);
double max_y = std::max(begin.y, end.y);
box.min_corner().set<0>(min_x);
box.min_corner().set<1>(min_y);
box.max_corner().set<0>(max_x);
box.max_corner().set<1>(max_y);
return OB_SUCCESS;
}
int ObGeoTypeUtil::get_quadrant_direction(const ObPoint2d &start, const ObPoint2d &end, QuadDirection &res)
{
int ret = OB_SUCCESS;
if(start.x == end.x && start.y == end.y) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("start and end is same", K(start.x), K(start.y));
} else {
if (end.x >= start.x) {
if (end.y >= start.y) {
res = QuadDirection::NORTH_EAST;
} else {
res = QuadDirection::SOUTH_EAST;
}
} else {
if (end.y >= start.y) {
res = QuadDirection::NORTH_WEST;
} else {
res = QuadDirection::SOUTH_WEST;
}
}
}
return ret;
}
double ObGeoTypeUtil::distance_point_squre(const ObWkbGeomInnerPoint& p1, const ObWkbGeomInnerPoint& p2)
{
@ -2689,6 +2787,433 @@ int ObGeoMVTUtil::affine_transformation(ObGeometry *geo, const ObAffineMatrix &a
return ret;
}
template<typename CachedGeoType>
int ObGeoTypeUtil::create_cached_geometry(ObIAllocator &allocator, ObGeometry *geo, ObCachedGeom *&cached_geo, const ObSrsItem *srs)
{
int ret = OB_SUCCESS;
CachedGeoType *tmp_cached = reinterpret_cast<CachedGeoType *>(allocator.alloc(sizeof(CachedGeoType)));
if (OB_ISNULL(tmp_cached)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc cached polygon", K(ret));
} else {
cached_geo = new(tmp_cached) CachedGeoType(geo, allocator, srs);
}
return ret;
}
int ObGeoTypeUtil::get_polygon_size(ObGeometry &geo)
{
int size = 0;
if (geo.crs() == ObGeoCRS::Cartesian) {
if (geo.type() == ObGeoType::POLYGON) {
size = (static_cast<ObIWkbGeomPolygon*>(&geo))->size();
} else {
const ObWkbGeomMultiPolygon *multi_poly = reinterpret_cast<const ObWkbGeomMultiPolygon*>(&geo);
size = multi_poly->size();
}
} else {
if (geo.type() == ObGeoType::POLYGON) {
size = (static_cast<ObIWkbGeogPolygon*>(&geo))->size();
} else {
const ObWkbGeogMultiPolygon *multi_poly = reinterpret_cast<const ObWkbGeogMultiPolygon*>(&geo);
size = multi_poly->size();
}
}
return size;
}
int ObGeoTypeUtil::magnify_and_recheck(ObIAllocator &allocator, ObGeometry &geo, ObGeoEvalCtx& gis_context, bool& invalid_for_cache)
{
int ret = OB_SUCCESS;
ObGeometry *tmp_geo = nullptr;
bool valid = false;
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)) {
// 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));
} else {
gis_context.ut_set_geo_arg(0, tmp_geo);
ret = check_valid_and_self_intersects(gis_context, invalid_for_cache, need_recheck);
}
return ret;
}
int ObGeoTypeUtil::check_valid_and_self_intersects(ObGeoEvalCtx& gis_context, bool& invalid_for_cache, bool& need_recheck)
{
int ret = OB_SUCCESS;
bool valid = false;
const ObGeoNormalVal *val_arg = nullptr;
if (OB_FAIL(ObGeoFunc<ObGeoFuncType::IsValid>::geo_func::eval(gis_context, valid))) {
LOG_WARN("eval geo func isvalid failed", K(ret));
} else if (valid) {
invalid_for_cache = false;
} else if (OB_FALSE_IT(val_arg = gis_context.get_val_arg(0))) {
} else if (OB_ISNULL(val_arg)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("should not be null", K(ret));
} else if (static_cast<int64_t>(bg::validity_failure_type::failure_self_intersections) == val_arg->int64_) {
invalid_for_cache = true;
need_recheck = true;
} else if (static_cast<int64_t>(bg::validity_failure_type::failure_wrong_topological_dimension) == val_arg->int64_) {
invalid_for_cache = true;
need_recheck = false;
} else {
invalid_for_cache = false;
}
return ret;
}
int ObGeoTypeUtil::polygon_check_self_intersections(ObIAllocator &allocator, ObGeometry &geo, const ObSrsItem *srs, bool& invalid_for_cache)
{
int ret = OB_SUCCESS;
ObGeoEvalCtx gis_context(&allocator, srs);
ObGeoNormalVal reason;
bool valid = false;
const ObGeoNormalVal *val_arg = nullptr;
bool need_recheck = false;
if (OB_FAIL(gis_context.append_geo_arg(&geo))) {
LOG_WARN("build geo gis context failed", K(ret));
} else if (OB_FAIL(gis_context.append_val_arg(reason))) {
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))) {
LOG_WARN("fail to magnify_and_recheck.", K(ret));
} else if (invalid_for_cache) {
LOG_WARN("self intersects, use geo cache base.", K(ret));
}
return ret;
}
int ObGeoTypeUtil::create_cached_geometry(ObIAllocator &allocator,
ObIAllocator &tmp_allocator,
ObGeometry *geo,
const ObSrsItem *srs,
ObCachedGeom *&cached_geo)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(geo)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("should not be null", K(ret));
} else {
switch (geo->type()) {
case ObGeoType::POINT:
case ObGeoType::MULTIPOINT: {
ret = create_cached_geometry<ObCachedGeoPoint>(allocator, geo, cached_geo, srs);
break;
}
case ObGeoType::LINESTRING:
case ObGeoType::MULTILINESTRING:
{
ret = create_cached_geometry<ObCachedGeoLinestring>(allocator, geo, cached_geo, srs);
break;
}
case ObGeoType::POLYGON:
case ObGeoType::MULTIPOLYGON: {
ret = create_cached_geometry<ObCachedGeoPolygon>(allocator, geo, cached_geo, srs);
break;
}
case ObGeoType::GEOMETRYCOLLECTION: {
ret = create_cached_geometry<ObCachedGeomBase>(allocator, geo, cached_geo, srs);
break;
}
default: {
ret = OB_NOT_SUPPORTED;
LOG_WARN("type not supported yet.", K(geo->type()) ,K(ret));
break;
}
}
}
return ret;
}
int ObGeoTypeUtil::get_geo_dimension(ObGeometry *geo, ObGeoDimension& dim)
{
int ret = OB_SUCCESS;
dim = ObGeoDimension::MAX_DIMENSION;
if (OB_ISNULL(geo)) {
ret = OB_BAD_NULL_ERROR;
LOG_WARN("should not be null.", K(ret));
} else {
switch (geo->type()) {
case ObGeoType::POINT:
case ObGeoType::MULTIPOINT: {
dim = ObGeoDimension::ZERO_DIMENSION;
break;
}
case ObGeoType::LINESTRING:
case ObGeoType::MULTILINESTRING:
{
dim = ObGeoDimension::ONE_DIMENSION;
break;
}
case ObGeoType::POLYGON:
case ObGeoType::MULTIPOLYGON: {
dim = ObGeoDimension::TWO_DIMENSION;
break;
}
case ObGeoType::GEOMETRYCOLLECTION: {
if (geo->crs() == ObGeoCRS::Cartesian) {
ret = get_collection_dimension<ObIWkbGeomCollection, ObWkbGeomCollection>(static_cast<ObIWkbGeomCollection*>(geo), dim);
} else {
ret = get_collection_dimension<ObIWkbGeogCollection, ObWkbGeogCollection>(static_cast<ObIWkbGeogCollection*>(geo), dim);
}
break;
}
default: {
ret = OB_NOT_SUPPORTED;
LOG_WARN("type not supported yet.", K(geo->type()), K(ret));
break;
}
}
if (OB_FAIL(ret)) {
} else if (dim == ObGeoDimension::MAX_DIMENSION) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get geo dimension.", K(ret));
}
}
return ret;
}
int ObGeoTypeUtil::has_dimension(ObGeometry& geo, ObGeoDimension dim, bool& res)
{
int ret = OB_SUCCESS;
res = false;
if (geo.type() == ObGeoType::GEOMETRYCOLLECTION) {
if (geo.crs() == ObGeoCRS::Cartesian) {
ret = collection_has_dimension<ObIWkbGeomCollection, ObWkbGeomCollection>(static_cast<ObIWkbGeomCollection*>(&geo), dim, res);
} else {
ret = collection_has_dimension<ObIWkbGeogCollection, ObWkbGeogCollection>(static_cast<ObIWkbGeogCollection*>(&geo), dim, res);
}
} else if (dim == ObGeoDimension::ZERO_DIMENSION) {
res = is_point(geo);
} else if (dim == ObGeoDimension::ONE_DIMENSION) {
res = is_line(geo);
} else if (dim == ObGeoDimension::TWO_DIMENSION) {
res = is_polygon(geo);
}
return ret;
}
bool ObGeoTypeUtil::use_point_polygon_short_circuit(const ObGeometry& geo1, const ObGeometry& geo2, ObItemType func_type)
{
bool ret_bool = false;
if (func_type == ObItemType::T_FUN_SYS_ST_INTERSECTS) {
ret_bool = (is_point(geo1) && is_polygon(geo2)) || (is_point(geo2) && is_polygon(geo1));
} else if (func_type == ObItemType::T_FUN_SYS_ST_COVERS || func_type == ObItemType::T_FUN_SYS_ST_CONTAINS){
ret_bool = is_polygon(geo1) && is_point(geo2);
} else if (func_type == ObItemType::T_FUN_SYS_ST_WITHIN) {
ret_bool = is_point(geo1) && is_polygon(geo2);
}
return ret_bool;
}
int ObGeoTypeUtil::point_polygon_short_circuit(ObGeometry *poly, ObGeometry *point, ObPointLocation& loc, bool& has_internal, bool get_fartest)
{
int ret = OB_SUCCESS;
if (point->type() == ObGeoType::POINT) {
ObIWkbPoint* tmp_p = static_cast<ObIWkbPoint*>(point);
ObPoint2d p;
p.x = tmp_p->x();
p.y = tmp_p->y();
ObGeoPointLocationVisitor point_loc_visitor(p);
if (OB_FAIL(poly->do_visit(point_loc_visitor))) {
LOG_WARN("failed to do point location visitor", K(ret));
} else {
loc = point_loc_visitor.get_point_location();
has_internal = (loc == ObPointLocation::INTERIOR);
}
} else {
// check if geo point on cached line
ObVertexes input_vertexes;
ObGeoVertexCollectVisitor vertex_visitor(input_vertexes);
if (OB_FAIL(point->do_visit(vertex_visitor))) {
LOG_WARN("failed to collect geo vertexes", K(ret));
} else {
ObPointLocation tmp_loc = ObPointLocation::INVALID;
int size = input_vertexes.size();
for (uint32_t i = 0; i < size && OB_SUCC(ret) && (loc == ObPointLocation::INVALID); i++) {
ObGeoPointLocationVisitor point_loc_visitor(input_vertexes[i]);
if (OB_FAIL(poly->do_visit(point_loc_visitor))) {
LOG_WARN("failed to do point location visitor", K(ret));
} else if (!get_fartest && (point_loc_visitor.get_point_location() == ObPointLocation::INTERIOR
|| point_loc_visitor.get_point_location() == ObPointLocation::BOUNDARY)) {
loc = point_loc_visitor.get_point_location();
} else if (get_fartest) {
if (!has_internal && point_loc_visitor.get_point_location() == ObPointLocation::INTERIOR) {
has_internal = true;
}
if (tmp_loc == ObPointLocation::INVALID || tmp_loc < point_loc_visitor.get_point_location()) {
tmp_loc = point_loc_visitor.get_point_location();
}
if (tmp_loc == ObPointLocation::EXTERIOR) {
loc = tmp_loc;
}
}
}
if (OB_SUCC(ret) && loc == ObPointLocation::INVALID) {
loc = get_fartest ? tmp_loc : ObPointLocation::EXTERIOR;
}
}
}
return ret;
}
int ObGeoTypeUtil::get_point_polygon_res(ObGeometry *geo1, ObGeometry *geo2, ObItemType func_type, bool& result)
{
int ret = OB_SUCCESS;
ObPointLocation loc = ObPointLocation::INVALID;
ObGeometry *poly = nullptr;
ObGeometry *point = nullptr;
if (OB_ISNULL(geo1) || OB_ISNULL(geo2)) {
ret = OB_BAD_NULL_ERROR;
LOG_WARN("should not be null.", K(ret));
} else {
point = is_point(*geo1) ? geo1 : geo2;
poly = is_point(*geo1) ? geo2 : geo1;
bool get_fartest = (func_type != ObItemType::T_FUN_SYS_ST_INTERSECTS);
bool has_internal = false;
if (OB_FAIL(point_polygon_short_circuit(poly, point, loc, has_internal, get_fartest))) {
LOG_WARN("fail to get point polygon position.", K(ret));
} else if (!get_fartest) {
result = (loc == ObPointLocation::INTERIOR || loc == ObPointLocation::BOUNDARY);
} else if (get_fartest) {
if (loc == ObPointLocation::EXTERIOR) {
result = false;
} else if (loc == ObPointLocation::INTERIOR || (loc == ObPointLocation::BOUNDARY && has_internal)) {
result = true;
} else {
result = (func_type == ObItemType::T_FUN_SYS_ST_COVERS);
}
}
}
return ret;
}
template<typename T_IBIN, typename T_BIN>
int ObGeoTypeUtil::get_collection_dimension(T_IBIN *geo, ObGeoDimension& dim)
{
int ret = OB_SUCCESS;
const T_BIN *collection = reinterpret_cast<const T_BIN*>(geo->val());
typename T_BIN::iterator iter = collection->begin();
uint64_t total_len = geo->length();
uint64_t pos = WKB_COMMON_WKB_HEADER_LEN;
dim = ObGeoDimension::MAX_DIMENSION;
for ( ; iter != collection->end() && OB_SUCC(ret) && !(dim == ObGeoDimension::TWO_DIMENSION); iter++) {
ObGeoDimension tmp_dim = ObGeoDimension::ZERO_DIMENSION;
typename ObWkbGeomCollection::const_pointer sub_ptr = iter.operator->();
if (pos + WKB_GEO_TYPE_SIZE + WKB_GEO_BO_SIZE > total_len) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid wkb geo", K(ret), K(total_len), K(pos), K(geo->val()));
} else {
ObGeoType sub_type = collection->get_sub_type(sub_ptr);
switch (sub_type) {
case ObGeoType::POINT:
case ObGeoType::MULTIPOINT : {
tmp_dim = ObGeoDimension::ZERO_DIMENSION;
break;
}
case ObGeoType::LINESTRING:
case ObGeoType::MULTILINESTRING : {
tmp_dim = ObGeoDimension::ONE_DIMENSION;
break;
}
case ObGeoType::POLYGON:
case ObGeoType::MULTIPOLYGON : {
tmp_dim = ObGeoDimension::TWO_DIMENSION;
break;
}
case ObGeoType::GEOMETRYCOLLECTION : {
const T_BIN *subgc = reinterpret_cast<const T_BIN *>(sub_ptr);
T_IBIN sub_collection;
ObString data(total_len - pos, reinterpret_cast<const char *>(subgc));
sub_collection.set_data(data);
ret = get_collection_dimension<T_IBIN, T_BIN>(&sub_collection, tmp_dim);
if (OB_FAIL(ret)) {
LOG_WARN("failed to do wkb geom sub collection visit", K(ret));
} else {
pos += sub_collection.length();
}
break;
}
default : {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid geo type", K(ret), K(sub_type));
break;
}
}
if (OB_FAIL(ret) || tmp_dim == ObGeoDimension::MAX_DIMENSION) {
} else if (dim == ObGeoDimension::MAX_DIMENSION
|| dim < tmp_dim) {
dim = tmp_dim;
}
}
}
return ret;
}
template<typename T_IBIN, typename T_BIN>
int ObGeoTypeUtil::collection_has_dimension(T_IBIN *geo, ObGeoDimension dim, bool& res)
{
int ret = OB_SUCCESS;
const T_BIN *collection = reinterpret_cast<const T_BIN*>(geo->val());
typename T_BIN::iterator iter = collection->begin();
uint64_t total_len = geo->length();
uint64_t pos = WKB_COMMON_WKB_HEADER_LEN;
for ( ; iter != collection->end() && OB_SUCC(ret) && !res; iter++) {
ObGeoDimension tmp_dim = ObGeoDimension::MAX_DIMENSION;
typename ObWkbGeomCollection::const_pointer sub_ptr = iter.operator->();
if (pos + WKB_GEO_TYPE_SIZE + WKB_GEO_BO_SIZE > total_len) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid wkb geo", K(ret), K(total_len), K(pos), K(geo->val()));
} else {
ObGeoType sub_type = collection->get_sub_type(sub_ptr);
switch (sub_type) {
case ObGeoType::POINT:
case ObGeoType::MULTIPOINT : {
res = (dim == ObGeoDimension::ZERO_DIMENSION);
break;
}
case ObGeoType::LINESTRING:
case ObGeoType::MULTILINESTRING : {
res = (dim == ObGeoDimension::ONE_DIMENSION);
break;
}
case ObGeoType::POLYGON:
case ObGeoType::MULTIPOLYGON : {
res = (dim == ObGeoDimension::TWO_DIMENSION);
break;
}
case ObGeoType::GEOMETRYCOLLECTION : {
ret = get_collection_dimension<T_IBIN, T_BIN>(geo, dim);
break;
}
default : {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid geo type", K(ret), K(sub_type));
break;
}
}
}
}
return ret;
}
bool ObGeoTypeUtil::need_get_srs(const uint32_t srid)
{
bool ret_bool = true;
if (lib::is_oracle_mode() && srid == UINT_MAX32) {
ret_bool = false;
} else if (0 == srid) {
ret_bool = false;
}
return ret_bool;
}
int ObGeoMVTUtil::snap_to_grid(ObGeometry *geo, const ObGeoGrid &grid, bool use_floor)
{
int ret = OB_SUCCESS;
@ -2718,6 +3243,5 @@ int ObGeoMVTUtil::simplify_geometry(ObGeometry *geo, double tolerance, bool keep
}
return ret;
}
} // namespace common
} // namespace oceanbase
} // namespace common
} // namespace oceanbase

View File

@ -25,6 +25,7 @@
#include "lib/number/ob_number_v2.h"
#include "common/object/ob_object.h"
#include "lib/geo/ob_geo_to_tree_visitor.h"
#include "objit/common/ob_item_type.h"
namespace oceanbase
{
@ -46,6 +47,79 @@ enum ObGeoBuildFlag: uint8_t {
GEO_RESERVE_3D = 0x20, // do not convert 3D Geometry to 2D
GEO_DEFAULT = GEO_NORMALIZE | GEO_CORRECT | GEO_CHECK_RANGE,
GEO_ALLOW_3D_DEFAULT = GEO_DEFAULT | GEO_ALLOW_3D,
GEO_CARTESIAN = GEO_CORRECT,
GEO_ALLOW_3D_CARTESIAN = GEO_CARTESIAN | GEO_ALLOW_3D
};
enum QuadDirection {
NORTH_WEST = 0,
NORTH_EAST = 1,
SOUTH_WEST = 2,
SOUTH_EAST =3,
INVALID_QUAD = 4,
};
enum ObGeoDimension {
ZERO_DIMENSION = 0,
ONE_DIMENSION = 1,
TWO_DIMENSION = 2,
MAX_DIMENSION,
};
typedef struct
{
double x;
double y;
int64_t to_string(char *buf, const int64_t buf_len) const
{
int64_t pos = 0;
J_KV(K(x), K(y));
return pos;
}
} ObPoint2d;
// line with 2 points
typedef struct
{
ObPoint2d begin;
ObPoint2d end;
int get_box(ObCartesianBox &box);
int64_t to_string(char *buf, const int64_t buf_len) const
{
int64_t pos = 0;
J_KV(K(begin), K(end));
return pos;
}
} ObSegment;
typedef PageArena<ObPoint2d, ModulePageAllocator> ObCachePointModuleArena;
typedef PageArena<ObSegment, ModulePageAllocator> ObCacheSegModuleArena;
typedef ObVector<ObPoint2d, ObCachePointModuleArena> ObVertexes;
typedef ObVector<ObSegment, ObCacheSegModuleArena> ObSegments;
// line with points in same quad_direction
typedef struct
{
ObVertexes *verts;
uint32_t begin;
uint32_t end;
int get_box(ObCartesianBox &box);
} ObLineSegment;
typedef PageArena<ObLineSegment, ModulePageAllocator> ObCacheSegmentModuleArena;
class ObCachedGeom;
class ObGeoEvalCtx;
class ObLineSegments{
public:
ObLineSegments() {}
ObLineSegments(ModulePageAllocator& page_allocator, ObCachePointModuleArena& point_mode_arena) :
segs_arena_(DEFAULT_PAGE_SIZE_GEO, page_allocator),
verts_(&point_mode_arena, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR),
segs_(&segs_arena_, common::ObModIds::OB_MODULE_PAGE_ALLOCATOR) {}
~ObLineSegments() {}
ObCacheSegmentModuleArena segs_arena_;
ObVertexes verts_;
ObVector<ObLineSegment, ObCacheSegmentModuleArena> segs_;
};
class ObGeoTypeUtil
@ -55,6 +129,7 @@ public:
static const uint32_t EWKB_M_FLAG = 0x40000000;
static const uint32_t EWKB_Z_FLAG = 0x80000000;
static const uint32_t WKB_3D_TYPE_OFFSET = 1000;
static const uint32_t RECHECK_ZOOM_IN_VALUE = 10;
static int create_geo_by_type(ObIAllocator &allocator,
ObGeoType geo_type,
bool is_geographical,
@ -79,6 +154,9 @@ public:
const ObSrsItem *srs,
ObGeometry *&geo,
bool has_srid = true);
static int copy_geometry(ObIAllocator &allocator,
ObGeometry &origin_geo,
ObGeometry *&copy_geo);
static int correct_polygon(ObIAllocator &alloc,
const ObSrsItem *srs,
bool is_ring_closed,
@ -153,6 +231,7 @@ public:
static int number_to_double(const number::ObNumber &num, double &res);
static bool is_3d_geo_type(ObGeoType geo_type);
static bool is_2d_geo_type(ObGeoType geo_type);
static bool is_multi_geo_type(ObGeoType geo_type);
static int rectangle_to_swkb(double xmin, double ymin, double xmax, double ymax, ObGeoSrid srid, bool with_version, ObWkbBuffer &wkb_buf);
static int check_empty(ObGeometry *geo, bool &is_empty);
static int get_st_geo_name_by_type(ObGeoType type, ObString &res);
@ -166,6 +245,22 @@ public:
// only check if polygon is a line or it's valid points are lesser than 4.
template<typename PyTree, typename MpyTree, typename CollTree>
static int is_polygon_valid_simple(const ObGeometry *geo, bool &res);
// 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 create_cached_geometry(ObIAllocator &allocator, ObIAllocator &tmp_allocator, ObGeometry *geo,
const ObSrsItem *srs, ObCachedGeom *&cached_geo);
template<typename CachedGeoType>
static int create_cached_geometry(ObIAllocator &allocator, ObGeometry *geo, ObCachedGeom *&cached_geo, const ObSrsItem *srs);
static int get_geo_dimension(ObGeometry *geo, ObGeoDimension& dim);
static int has_dimension(ObGeometry& geo, ObGeoDimension dim, bool& res);
static bool is_point(const ObGeometry& geo) { return geo.type() == ObGeoType::POINT || geo.type() == ObGeoType::MULTIPOINT;}
static bool is_line(const ObGeometry& geo) { return geo.type() == ObGeoType::LINESTRING || geo.type() == ObGeoType::MULTILINESTRING;}
static bool is_polygon(const ObGeometry& geo) { return geo.type() == ObGeoType::POLYGON || geo.type() == ObGeoType::MULTIPOLYGON;}
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);
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,
@ -194,6 +289,14 @@ private:
static int append_point(double x, double y, ObWkbBuffer &wkb_buf);
template<typename RingTree>
static bool is_valid_ring_simple(const RingTree &ring);
template<typename T_IBIN, typename T_BIN>
static int get_collection_dimension(T_IBIN *geo, ObGeoDimension& dim);
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 check_valid_and_self_intersects(ObGeoEvalCtx& gis_context, bool& invalid_for_cache, bool& need_recheck);
DISALLOW_COPY_AND_ASSIGN(ObGeoTypeUtil);
};
@ -215,12 +318,6 @@ typedef struct
double z;
} ObPoint3d;
typedef struct
{
double x;
double y;
} ObPoint2d;
enum class PG_SRID
{
WORLD_MERCATOR = 999000,

View File

@ -0,0 +1,53 @@
/**
* 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_vertex_collect_visitor.h"
#include "lib/geo/ob_geo_utils.h"
namespace oceanbase {
namespace common {
bool ObGeoVertexCollectVisitor::prepare(ObGeometry *geo)
{
bool bret = true;
if (OB_ISNULL(geo)) {
bret = false;
}
return bret;
}
int ObGeoVertexCollectVisitor::visit(ObIWkbPoint *geo)
{
int ret = OB_SUCCESS;
ObPoint2d vertex;
vertex.x = geo->x();
vertex.y = geo->y();
if (OB_FAIL(vertexes_.push_back(vertex))) {
LOG_WARN("failed to add vertex to cached geo", K(ret));
} else {
if (std::isnan(x_min_)) {
x_min_ = vertex.x;
} else {
x_min_ = std::min(x_min_, vertex.x);
}
if (std::isnan(x_max_)) {
x_max_ = vertex.x;
} else {
x_max_ = std::max(x_max_, vertex.x);
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

View File

@ -0,0 +1,44 @@
/**
* 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_VERTEX_COLLECT_VISITOR_
#define OCEANBASE_LIB_GEO_OB_GEO_VERTEX_COLLECT_VISITOR_
#include "lib/geo/ob_geo_visitor.h"
#include "lib/geo/ob_geo_utils.h"
namespace oceanbase
{
namespace common
{
class ObGeoVertexCollectVisitor : public ObEmptyGeoVisitor
{
public:
ObGeoVertexCollectVisitor(ObVertexes &vertexes) : vertexes_(vertexes), x_min_(NAN), x_max_(NAN) {}
virtual ~ObGeoVertexCollectVisitor() {}
bool prepare(ObGeometry *geo);
int visit(ObIWkbPoint *geo);
int visit(ObIWkbGeometry *geo) { UNUSED(geo); return OB_SUCCESS; }
inline double get_x_min() { return x_min_; }
inline double get_x_max() { return x_max_; }
private:
ObVertexes &vertexes_;
double x_min_;
double x_max_;
DISALLOW_COPY_AND_ASSIGN(ObGeoVertexCollectVisitor);
};
} // namespace common
} // namespace oceanbase
#endif

View File

@ -199,6 +199,7 @@ public:
virtual int finish(ObIWkbGeogCollection *geo) = 0;
virtual int finish(ObIWkbGeomCollection *geo) = 0;
virtual bool set_after_visitor() = 0;
};
class ObEmptyGeoVisitor : public ObIGeoVisitor
@ -377,7 +378,8 @@ public:
virtual int finish(ObIWkbGeomMultiPolygon *geo) override { return finish(static_cast<ObIWkbGeometry *>(geo)); }
virtual int finish(ObIWkbGeogCollection *geo) override { return finish(static_cast<ObIWkbGeometry *>(geo)); }
virtual int finish(ObIWkbGeomCollection *geo) override { return finish(static_cast<ObIWkbGeometry *>(geo)); }
// set true if the value of a point might be modified during linestring_do_visitor
virtual bool set_after_visitor() override { return true; }
};
class ObIWkbVisitorImplement {
@ -411,15 +413,17 @@ int ObIWkbVisitorImplement::linestring_do_visitor(T_IBIN *geo, ObIGeoVisitor &vi
T_POINT wkb_point;
wkb_point.byteorder(ObGeoWkbByteOrder::LittleEndian);
typename T_BIN::iterator iter = line->begin();
for ( ; iter != line->end() && OB_SUCC(ret) && !visitor.is_end(geo); iter++) {
wkb_point.template set<0>(iter->template get<0>());
wkb_point.template set<1>(iter->template get<1>());
T_IPOINT point;
typename T_BIN::iterator iter_end = line->end();
bool need_set = visitor.set_after_visitor();
T_IPOINT point;
for ( ; iter != iter_end && OB_SUCC(ret) && !visitor.is_end(geo); ++iter) {
wkb_point.template set<0>(iter->get_x());
wkb_point.template set<1>(iter->get_y());
ObString data(sizeof(wkb_point), reinterpret_cast<char *>(&wkb_point));
point.set_data(data);
if (OB_FAIL(point.do_visit(visitor))) {
OB_LOG(WARN,"failed to do wkb point visit", K(ret));
} else {
} else if (need_set) {
iter->template set<0>(point.x());
iter->template set<1>(point.y());
}
@ -446,8 +450,8 @@ int ObIWkbVisitorImplement::multipoint_do_visitor(T_IBIN *geo, ObIGeoVisitor &vi
} else {
const T_BIN *multi_point = reinterpret_cast<const T_BIN*>(geo->val());
typename T_BIN::iterator iter = multi_point->begin();
for ( ; iter != multi_point->end() && OB_SUCC(ret) && !visitor.is_end(geo); iter++) {
T_IPOINT point;
T_IPOINT point;
for ( ; iter != multi_point->end() && OB_SUCC(ret) && !visitor.is_end(geo); ++iter) {
ObString data(sizeof(T_POINT), reinterpret_cast<char *>(iter.operator->()));
point.set_data(data);
if (OB_FAIL(point.do_visit(visitor))) {
@ -483,7 +487,7 @@ int ObIWkbVisitorImplement::polygon_do_visitor(T_IBIN *geo, ObIGeoVisitor &visit
} else {
const T_INNER_RING &rings = polygon->inner_rings();
typename T_INNER_RING::iterator iter = rings.begin();
for ( ; iter != rings.end() && OB_SUCC(ret) && !visitor.is_end(geo); iter++) {
for ( ; iter != rings.end() && OB_SUCC(ret) && !visitor.is_end(geo); ++iter) {
data.assign_ptr(reinterpret_cast<const char *>(iter.operator->()), sizeof(T_RING));
ring.set_data(data);
if (OB_FAIL(ring.do_visit(visitor))) {
@ -508,8 +512,8 @@ int ObIWkbVisitorImplement::collection_do_visitor(T_IBIN *geo, ObIGeoVisitor &vi
} else {
const T_BIN *items = reinterpret_cast<const T_BIN*>(geo->val());
typename T_BIN::iterator iter = items->begin();
for ( ; iter != items->end() && OB_SUCC(ret) && !visitor.is_end(geo); iter++) {
T_IITEM item;
T_IITEM item;
for ( ; iter != items->end() && OB_SUCC(ret) && !visitor.is_end(geo); ++iter) {
ObString data(sizeof(T_ITEM), reinterpret_cast<char *>(iter.operator->()));
item.set_data(data);
if (OB_FAIL(item.do_visit(visitor))) {

View File

@ -40,5 +40,15 @@ int ObGeoZoomInVisitor::visit(ObIWkbGeogPoint *geo)
{
return zoom_in_point(geo);
}
int ObGeoZoomInVisitor::visit(ObCartesianPoint *geo)
{
return zoom_in_point(geo);
}
int ObGeoZoomInVisitor::visit(ObIWkbGeomPoint *geo)
{
return zoom_in_point(geo);
}
} // namespace common
} // namespace oceanbase

View File

@ -31,6 +31,8 @@ public:
int visit(ObGeometry *geo) override { UNUSED(geo); return OB_SUCCESS; }
int visit(ObGeographPoint *geo);
int visit(ObIWkbGeogPoint *geo);
int visit(ObCartesianPoint *geo);
int visit(ObIWkbGeomPoint *geo);
private:
template<typename T_Point>
int zoom_in_point(T_Point *geo);

View File

@ -0,0 +1,67 @@
/**
* 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_point_location_analyzer.h"
#include "ob_geo_topology_calculate.h"
namespace oceanbase {
namespace common {
int ObPointLocationAnalyzer::calculate_point_position(const ObPoint2d &test_point)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(rtree_index_) || OB_ISNULL(cache_geo_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("rtree index or cache geo is null", K(rtree_index_), K(cache_geo_), K(ret));
} else if (!rtree_index_->is_built()) {
if (OB_ISNULL(cache_geo_->get_segments())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("should not be null.", K(ret));
} else if (OB_FAIL(rtree_index_->construct_rtree_index(*(cache_geo_->get_segments())))) {
LOG_WARN("construct rtree index failed", K(ret));
}
}
if (OB_SUCC(ret)) {
clear_result();
std::vector<RtreeNodeValue> res;
ObCartesianBox box;
box.set_box(std::min(cache_geo_->get_x_min() - 1.0, test_point.x), test_point.y,
std::max(cache_geo_->get_x_max() + 1.0, test_point.x), test_point.y);
if (OB_FAIL(rtree_index_->query(QueryRelation::INTERSECTS, box, res))) {
LOG_WARN("failed to query rtree", K(ret));
} else {
bool is_on_boundary = false;
for (uint32_t i = 0; i < res.size() && OB_SUCC(ret) && !is_on_boundary; i++) {
const ObSegment* seg1 = res[i].second;
if (seg1 != NULL
&& LineIntersect::POINT_INTERSECT == ObGeoTopology::calculate_point_inersect_horizontally(seg1->begin, seg1->end,
test_point, is_on_boundary)) {
intersect_cnt_++;
}
}
if (OB_SUCC(ret)) {
if (is_on_boundary) {
position_ = ObPointLocation::BOUNDARY;
} else if ((intersect_cnt_ % 2) == 1) {
position_ = ObPointLocation::INTERIOR;
} else {
position_ = ObPointLocation::EXTERIOR;
}
}
}
}
return ret;
}
} // namespace common
} // namespace oceanbase

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.
*/
#ifndef OCEANBASE_LIB_GEO_POINT_LOCATION_ANALYZER_
#define OCEANBASE_LIB_GEO_POINT_LOCATION_ANALYZER_
#include "lib/geo/ob_geo_cache.h"
#include "lib/geo/ob_geo_rstar_tree.h"
namespace oceanbase {
namespace common {
class ObPointLocationAnalyzer {
public:
typedef std::pair<ObCartesianBox, ObSegment *> RtreeNodeValue;
public:
ObPointLocationAnalyzer(ObCachedGeomBase *cache_geo, ObRstarTree<ObSegment> *rtree_index)
: cache_geo_(cache_geo),
rtree_index_(rtree_index),
position_(ObPointLocation::INVALID),
intersect_cnt_(0) {}
virtual ~ObPointLocationAnalyzer() {}
int calculate_point_position(const ObPoint2d &test_point);
ObPointLocation get_position() { return position_; }
inline void clear_result() { position_ = ObPointLocation::INVALID; intersect_cnt_ = 0;}
void update_farthest_position();
private:
ObCachedGeomBase *cache_geo_;
ObRstarTree<ObSegment> *rtree_index_;
ObPointLocation position_;
uint32_t intersect_cnt_;
};
} // namespace common
} // namespace oceanbase
#endif // OCEANBASE_LIB_GEO_POINT_LOCATION_ANALYZER_

View File

@ -243,6 +243,15 @@ int64_t ObS2Adapter::get_cellids(ObS2Cellids &cells, bool is_query)
return ret;
}
int64_t ObS2Adapter::get_cellids_and_unrepeated_ancestors(ObS2Cellids &cells, ObS2Cellids &ancestors)
{
INIT_SUCC(ret);
if(OB_FAIL(visitor_->get_cellids_and_unrepeated_ancestors(cells, ancestors, need_buffer_, distance_))) {
LOG_WARN("fail to get cellid from visitor", K(ret));
}
return ret;
}
int64_t ObS2Adapter::get_inner_cover_cellids(ObS2Cellids &cells)
{
INIT_SUCC(ret);

View File

@ -101,7 +101,7 @@ public:
class ObS2Adapter final
{
public:
ObS2Adapter(ObIAllocator *allocator, bool is_geog)
ObS2Adapter(ObIAllocator *allocator, bool is_geog, bool is_query_window = false)
: allocator_(allocator),
visitor_(NULL),
geo_(NULL),
@ -109,9 +109,15 @@ public:
need_buffer_(false),
distance_()
{
options_.set_max_cells(OB_GEO_S2REGION_OPTION_MAX_CELL);
options_.set_max_level(OB_GEO_S2REGION_OPTION_MAX_LEVEL);
options_.set_level_mod(OB_GEO_S2REGION_OPTION_LEVEL_MOD);
if (!is_query_window) {
options_.set_max_cells(OB_GEO_S2REGION_OPTION_MAX_CELL);
options_.set_max_level(OB_GEO_S2REGION_OPTION_MAX_LEVEL);
options_.set_level_mod(OB_GEO_S2REGION_OPTION_LEVEL_MOD);
} else {
options_.set_max_cells(50);
options_.set_max_level(30);
options_.set_level_mod(OB_GEO_S2REGION_OPTION_LEVEL_MOD);
}
}
ObS2Adapter(ObIAllocator *allocator, bool is_geog, double distance)
: allocator_(allocator),
@ -131,6 +137,7 @@ public:
int64_t get_ancestors(uint64_t cell, ObS2Cellids &cells);
int64_t init(const ObString &wkb, const ObSrsBoundsItem *bound = NULL);
int64_t get_cellids(ObS2Cellids &cells, bool is_query);
int64_t get_cellids_and_unrepeated_ancestors(ObS2Cellids &cells, ObS2Cellids &ancestors);
int64_t get_inner_cover_cellids(ObS2Cellids &cells);
int64_t get_mbr(ObSpatialMBR &mbr);
private:

View File

@ -113,10 +113,14 @@ ObSrsCacheGuard::~ObSrsCacheGuard()
}
}
int ObSrsCacheGuard::get_srs_item(uint64_t srs_id, const ObSrsItem *&srs_item)
int ObSrsCacheGuard::get_srs_item(uint64_t original_srs_id, const ObSrsItem *&srs_item)
{
int ret = OB_SUCCESS;
const ObSrsItem *tmp_srs_item = NULL;
uint64_t srs_id = original_srs_id;
if (lib::is_oracle_mode() && srs_id == 8307) {
srs_id = 4326;
}
if (OB_ISNULL(srs_cache_)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("srs_cache is null", K(ret));

View File

@ -63,6 +63,7 @@
#include "pl/sys_package/ob_dbms_mview_stats.h"
#include "pl/sys_package/ob_json_array_type.h"
#include "pl/sys_package/ob_xml_type.h"
#include "pl/sys_package/ob_sdo_geom.h"
#include "pl/sys_package/ob_dbms_profiler.h"
#endif
#include "pl/sys_package/ob_pl_dbms_resource_manager.h"
@ -467,6 +468,10 @@
INTERFACE_DEF(INTERFACE_SDO_GEOMETRY_GET_GEOJSON, "SDO_GEOMETRY_GET_GEOJSON", (ObSdoGeometry::get_geojson))
//end of sdo_geometry
//start of sdo_geom
INTERFACE_DEF(INTERFACE_SDO_GEOM_DISTANCE, "SDO_GEOM_DISTANCE", (ObSdoGeom::sdo_distance))
//end of sdo_geom
//start of xmltype
INTERFACE_DEF(INTERFACE_XML_TYPE_TRANSFORM, "XML_TYPE_TRANSFORM", (ObXmlType::transform))
INTERFACE_DEF(INTERFACE_XML_TYPE_GETCLOBVAL, "XML_TYPE_GETCLOBVAL", (ObXmlType::getclobval))

View File

@ -264,6 +264,7 @@ static ObSysPackageFile oracle_sys_package_file_table[] = {
{"json_array_t", "json_array_type.sql", "json_array_type_body.sql"},
{"xmlsequence", "xml_sequence_type.sql", "xml_sequence_type_body.sql"},
{"sdo_geometry", "sdo_geometry.sql", "sdo_geometry_body.sql"},
{"sdo_geom", "sdo_geom.sql", "sdo_geom_body.sql"},
{"dbms_external_table", "dbms_external_table.sql", "dbms_external_table_body.sql"},
{"dbms_profiler", "dbms_profiler.sql", "dbms_profiler_body.sql"},
#endif

View File

@ -3715,6 +3715,277 @@ int ObInnerTableSchema::all_virtual_nic_info_schema(ObTableSchema &table_schema)
return ret;
}
int ObInnerTableSchema::all_virtual_spatial_reference_systems_schema(ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1;
//generated fields:
table_schema.set_tenant_id(OB_SYS_TENANT_ID);
table_schema.set_tablegroup_id(OB_INVALID_ID);
table_schema.set_database_id(OB_SYS_DATABASE_ID);
table_schema.set_table_id(OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TID);
table_schema.set_rowkey_split_pos(0);
table_schema.set_is_use_bloomfilter(false);
table_schema.set_progressive_merge_num(0);
table_schema.set_rowkey_column_num(2);
table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK);
table_schema.set_table_type(VIRTUAL_TABLE);
table_schema.set_index_type(INDEX_TYPE_IS_NOT);
table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL);
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_table_name(OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TNAME))) {
LOG_ERROR("fail to set table_name", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) {
LOG_ERROR("fail to set compress_func_name", K(ret));
}
}
table_schema.set_part_level(PARTITION_LEVEL_ZERO);
table_schema.set_charset_type(ObCharset::get_default_charset());
table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("tenant_id", //column_name
++column_id, //column_id
1, //rowkey_id
0, //index_id
0, //part_key_pos
ObIntType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(int64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("srs_id", //column_name
++column_id, //column_id
2, //rowkey_id
0, //index_id
0, //part_key_pos
ObUInt64Type, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(uint64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA_TS("gmt_create", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObTimestampType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(ObPreciseDateTime), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false, //is_autoincrement
false); //is_on_update_for_timestamp
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA_TS("gmt_modified", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObTimestampType, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(ObPreciseDateTime), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false, //is_autoincrement
false); //is_on_update_for_timestamp
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("srs_version", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObUInt64Type, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(uint64_t), //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("srs_name", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
128, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("organization", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
256, //column_length
-1, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("organization_coordsys_id", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObUInt64Type, //column_type
CS_TYPE_INVALID, //column_collation_type
sizeof(uint64_t), //column_length
-1, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("definition", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
4096, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("minX", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("maxX", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("minY", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("maxY", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("proj4text", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
2048, //column_length
-1, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("description", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_INVALID, //column_collation_type
2048, //column_length
-1, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
table_schema.set_index_using_type(USING_BTREE);
table_schema.set_row_store_type(ENCODING_ROW_STORE);
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
table_schema.set_progressive_merge_round(1);
table_schema.set_storage_format_version(3);
table_schema.set_tablet_id(0);
table_schema.set_max_used_column_id(column_id);
return ret;
}
} // end namespace share
} // end namespace oceanbase

View File

@ -487,6 +487,260 @@ int ObInnerTableSchema::all_virtual_nic_info_ora_schema(ObTableSchema &table_sch
return ret;
}
int ObInnerTableSchema::all_virtual_spatial_reference_systems_real_agent_ora_schema(ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1;
//generated fields:
table_schema.set_tenant_id(OB_SYS_TENANT_ID);
table_schema.set_tablegroup_id(OB_INVALID_ID);
table_schema.set_database_id(OB_ORA_SYS_DATABASE_ID);
table_schema.set_table_id(OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID);
table_schema.set_rowkey_split_pos(0);
table_schema.set_is_use_bloomfilter(false);
table_schema.set_progressive_merge_num(0);
table_schema.set_rowkey_column_num(1);
table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK);
table_schema.set_table_type(VIRTUAL_TABLE);
table_schema.set_index_type(INDEX_TYPE_IS_NOT);
table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL);
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_table_name(OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TNAME))) {
LOG_ERROR("fail to set table_name", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) {
LOG_ERROR("fail to set compress_func_name", K(ret));
}
}
table_schema.set_part_level(PARTITION_LEVEL_ZERO);
table_schema.set_charset_type(ObCharset::get_default_charset());
table_schema.set_collation_type(ObCollationType::CS_TYPE_UTF8MB4_BIN);
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("SRS_ID", //column_name
++column_id, //column_id
1, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
0, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("SRS_VERSION", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
0, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("SRS_NAME", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_UTF8MB4_BIN, //column_collation_type
128, //column_length
2, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("ORGANIZATION", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_UTF8MB4_BIN, //column_collation_type
256, //column_length
2, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("ORGANIZATION_COORDSYS_ID", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
0, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("DEFINITION", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_UTF8MB4_BIN, //column_collation_type
4096, //column_length
2, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("MINX", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("MAXX", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("MINY", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("MAXY", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObNumberType, //column_type
CS_TYPE_INVALID, //column_collation_type
38, //column_length
38, //column_precision
10, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("PROJ4TEXT", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_UTF8MB4_BIN, //column_collation_type
2048, //column_length
2, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("DESCRIPTION", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObVarcharType, //column_type
CS_TYPE_UTF8MB4_BIN, //column_collation_type
2048, //column_length
2, //column_precision
-1, //column_scale
true, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("GMT_CREATE", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObTimestampLTZType, //column_type
CS_TYPE_INVALID, //column_collation_type
0, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
if (OB_SUCC(ret)) {
ADD_COLUMN_SCHEMA("GMT_MODIFIED", //column_name
++column_id, //column_id
0, //rowkey_id
0, //index_id
0, //part_key_pos
ObTimestampLTZType, //column_type
CS_TYPE_INVALID, //column_collation_type
0, //column_length
-1, //column_precision
-1, //column_scale
false, //is_nullable
false); //is_autoincrement
}
table_schema.set_index_using_type(USING_BTREE);
table_schema.set_row_store_type(ENCODING_ROW_STORE);
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
table_schema.set_progressive_merge_round(1);
table_schema.set_storage_format_version(3);
table_schema.set_tablet_id(0);
table_schema.set_max_used_column_id(column_id);
return ret;
}
} // end namespace share
} // end namespace oceanbase

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -775,6 +775,56 @@ int ObInnerTableSchema::v_ob_nic_info_ora_schema(ObTableSchema &table_schema)
return ret;
}
int ObInnerTableSchema::dba_ob_spatial_columns_ora_schema(ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1;
//generated fields:
table_schema.set_tenant_id(OB_SYS_TENANT_ID);
table_schema.set_tablegroup_id(OB_INVALID_ID);
table_schema.set_database_id(OB_ORA_SYS_DATABASE_ID);
table_schema.set_table_id(OB_DBA_OB_SPATIAL_COLUMNS_ORA_TID);
table_schema.set_rowkey_split_pos(0);
table_schema.set_is_use_bloomfilter(false);
table_schema.set_progressive_merge_num(0);
table_schema.set_rowkey_column_num(0);
table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK);
table_schema.set_table_type(SYSTEM_VIEW);
table_schema.set_index_type(INDEX_TYPE_IS_NOT);
table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL);
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_table_name(OB_DBA_OB_SPATIAL_COLUMNS_ORA_TNAME))) {
LOG_ERROR("fail to set table_name", K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) {
LOG_ERROR("fail to set compress_func_name", K(ret));
}
}
table_schema.set_part_level(PARTITION_LEVEL_ZERO);
table_schema.set_charset_type(ObCharset::get_default_charset());
table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
if (OB_SUCC(ret)) {
if (OB_FAIL(table_schema.set_view_definition(R"__( select G.TABLE_SCHEMA AS TABLE_SCHEMA, G.TABLE_NAME AS TABLE_NAME, G.COLUMN_NAME AS COLUMN_NAME, G.SRS_NAME AS SRS_NAME, G.SRS_ID AS SRS_ID, G.GEOMETRY_TYPE_NAME AS GEOMETRY_TYPE_NAME, CAST('SDO_DIM_ARRAY(SDO_DIM_ELEMENT(NULL, -180, 180, 0.5), SDO_DIM_ELEMENT(NULL, -90, 90, 0.5))' AS VARCHAR2(512)) AS DIMINFO, D.INDEX_NAME AS INDEX_NAME from (select CAST(db.database_name AS VARCHAR2(128)) as TABLE_SCHEMA, CAST(tbl.table_name AS VARCHAR2(256)) as TABLE_NAME, CAST(col.column_name AS VARCHAR2(128)) as COLUMN_NAME, CAST(srs.srs_name AS VARCHAR2(128)) as SRS_NAME, CAST( CASE WHEN TRUNC(col.srs_id / POWER(2, 32)) = 4294967295 THEN NULL ELSE TRUNC(col.srs_id / POWER(2, 32)) END AS NUMBER(10)) AS SRS_ID, CAST( CASE WHEN (BITAND(col.srs_id, 31) IN (0, 1, 2, 3, 4, 5, 6, 7)) THEN 'SDO_GEOMETRY' ELSE 'invalid' END AS VARCHAR2(128)) AS GEOMETRY_TYPE_NAME, db.tenant_id as TENANT_ID, tbl.table_id AS TABLE_ID, tbl.database_id AS DATABASE_ID from SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT col left join SYS.ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT srs on TRUNC(col.srs_id / POWER(2, 32)) = srs.srs_id join SYS.ALL_VIRTUAL_TABLE_REAL_AGENT tbl on (tbl.table_id = col.table_id and tbl.tenant_id = col.tenant_id) join SYS.ALL_VIRTUAL_DATABASE_REAL_AGENT db on (db.database_id = tbl.database_id and db.tenant_id = tbl.tenant_id) and db.database_name != '__recyclebin' where col.data_type = 48 AND BITAND(TRUNC(tbl.table_mode / POWER(2, 12)), 15) IN (0, 1)) G left join (select T.TABLE_NAME AS TABLE_NAME, T.INDEX_NAME AS INDEX_NAME, C.COLUMN_NAME AS COLUMN_NAME, C.COLUMN_ID AS COLUMN_ID, T.DATABASE_ID AS DATABASE_ID, T.TENANT_ID AS TENANT_ID, C.TABLE_ID AS TABLE_ID from (select A.TABLE_NAME AS TABLE_NAME, A.INDEX_NAME AS INDEX_NAME, A.COLUMN_NAME AS COLUMN_NAME, B.COLUMN_ID AS COLUMN_ID, B.TENANT_ID as TENANT_ID, B.TABLE_ID as TABLE_ID, B.DATABASE_ID AS DATABASE_ID, B.SRS_ID AS SRS_ID from (select TABLE_NAME, INDEX_NAME, COLUMN_NAME from ALL_IND_COLUMNS idx_col) A join (select cl.COLUMN_ID as COLUMN_ID, cl.COLUMN_NAME as COLUMN_NAME, cl.TENANT_ID as TENANT_ID, cl.TABLE_ID as TABLE_ID, tb.TABLE_NAME as TABLE_NAME, cl.IS_HIDDEN as IS_HIDDEN, cl.SRS_ID as SRS_ID, tb.DATABASE_ID as DATABASE_ID from SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT cl join SYS.ALL_VIRTUAL_TABLE_REAL_AGENT tb on (tb.table_id = cl.table_id and tb.tenant_id = cl.tenant_id)) B on (B.COLUMN_NAME = A.COLUMN_NAME AND B.TABLE_NAME = A.TABLE_NAME) where b.IS_HIDDEN = 1 and SUBSTR(A.COLUMN_NAME, 1, 5) = '__mbr') T join SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT C on (T.SRS_ID = C.COLUMN_ID and T.TENANT_ID = C.TENANT_ID) where C.DATA_TYPE = 48) D ON D.TABLE_ID = G.TABLE_ID and D.TENANT_ID = G.TENANT_ID and D.DATABASE_ID = G.DATABASE_ID and D.COLUMN_NAME = G.COLUMN_NAME ORDER BY 1, 2, 3 )__"))) {
LOG_ERROR("fail to set view_definition", K(ret));
}
}
table_schema.set_index_using_type(USING_BTREE);
table_schema.set_row_store_type(ENCODING_ROW_STORE);
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
table_schema.set_progressive_merge_round(1);
table_schema.set_storage_format_version(3);
table_schema.set_tablet_id(0);
table_schema.set_max_used_column_id(column_id);
return ret;
}
int ObInnerTableSchema::all_table_idx_data_table_id_schema(ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;

View File

@ -1041,6 +1041,7 @@ public:
static int all_virtual_tenant_resource_limit_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_tenant_resource_limit_detail_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_nic_info_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_spatial_reference_systems_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_sql_audit_ora_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_plan_stat_ora_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_plan_cache_plan_explain_ora_schema(share::schema::ObTableSchema &table_schema);
@ -1312,6 +1313,7 @@ public:
static int all_virtual_tenant_resource_limit_ora_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_tenant_resource_limit_detail_ora_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_nic_info_ora_schema(share::schema::ObTableSchema &table_schema);
static int all_virtual_spatial_reference_systems_real_agent_ora_schema(share::schema::ObTableSchema &table_schema);
static int gv_ob_plan_cache_stat_schema(share::schema::ObTableSchema &table_schema);
static int gv_ob_plan_cache_plan_stat_schema(share::schema::ObTableSchema &table_schema);
static int schemata_schema(share::schema::ObTableSchema &table_schema);
@ -2210,6 +2212,7 @@ public:
static int v_ob_tenant_resource_limit_detail_ora_schema(share::schema::ObTableSchema &table_schema);
static int gv_ob_nic_info_ora_schema(share::schema::ObTableSchema &table_schema);
static int v_ob_nic_info_ora_schema(share::schema::ObTableSchema &table_schema);
static int dba_ob_spatial_columns_ora_schema(share::schema::ObTableSchema &table_schema);
static int all_table_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema);
static int all_column_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema);
static int all_ddl_operation_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema);
@ -3773,6 +3776,7 @@ const schema_create_func virtual_table_schema_creators [] = {
ObInnerTableSchema::all_virtual_tenant_resource_limit_schema,
ObInnerTableSchema::all_virtual_tenant_resource_limit_detail_schema,
ObInnerTableSchema::all_virtual_nic_info_schema,
ObInnerTableSchema::all_virtual_spatial_reference_systems_schema,
ObInnerTableSchema::all_virtual_ash_all_virtual_ash_i1_schema,
ObInnerTableSchema::all_virtual_sql_plan_monitor_all_virtual_sql_plan_monitor_i1_schema,
ObInnerTableSchema::all_virtual_sql_audit_all_virtual_sql_audit_i1_schema,
@ -4054,6 +4058,7 @@ const schema_create_func virtual_table_schema_creators [] = {
ObInnerTableSchema::all_virtual_tenant_resource_limit_ora_schema,
ObInnerTableSchema::all_virtual_tenant_resource_limit_detail_ora_schema,
ObInnerTableSchema::all_virtual_nic_info_ora_schema,
ObInnerTableSchema::all_virtual_spatial_reference_systems_real_agent_ora_schema,
ObInnerTableSchema::all_virtual_table_real_agent_ora_idx_data_table_id_real_agent_schema,
ObInnerTableSchema::all_virtual_table_real_agent_ora_idx_db_tb_name_real_agent_schema,
ObInnerTableSchema::all_virtual_table_real_agent_ora_idx_tb_name_real_agent_schema,
@ -5037,6 +5042,7 @@ const schema_create_func sys_view_schema_creators [] = {
ObInnerTableSchema::v_ob_tenant_resource_limit_detail_ora_schema,
ObInnerTableSchema::gv_ob_nic_info_ora_schema,
ObInnerTableSchema::v_ob_nic_info_ora_schema,
ObInnerTableSchema::dba_ob_spatial_columns_ora_schema,
NULL,};
const schema_create_func core_index_table_schema_creators [] = {
@ -5947,6 +5953,7 @@ const uint64_t tenant_space_tables [] = {
OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_ORA_TID,
OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TID,
OB_ALL_VIRTUAL_NIC_INFO_ORA_TID,
OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID,
OB_GV_OB_PLAN_CACHE_STAT_TID,
OB_GV_OB_PLAN_CACHE_PLAN_STAT_TID,
OB_SCHEMATA_TID,
@ -6726,6 +6733,7 @@ const uint64_t tenant_space_tables [] = {
OB_V_OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TID,
OB_GV_OB_NIC_INFO_ORA_TID,
OB_V_OB_NIC_INFO_ORA_TID,
OB_DBA_OB_SPATIAL_COLUMNS_ORA_TID,
OB_ALL_TABLE_IDX_DATA_TABLE_ID_TID,
OB_ALL_TABLE_IDX_DB_TB_NAME_TID,
OB_ALL_TABLE_IDX_TB_NAME_TID,
@ -8543,6 +8551,7 @@ const char* const tenant_space_table_names [] = {
OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_ORA_TNAME,
OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TNAME,
OB_ALL_VIRTUAL_NIC_INFO_ORA_TNAME,
OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TNAME,
OB_GV_OB_PLAN_CACHE_STAT_TNAME,
OB_GV_OB_PLAN_CACHE_PLAN_STAT_TNAME,
OB_SCHEMATA_TNAME,
@ -9322,6 +9331,7 @@ const char* const tenant_space_table_names [] = {
OB_V_OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TNAME,
OB_GV_OB_NIC_INFO_ORA_TNAME,
OB_V_OB_NIC_INFO_ORA_TNAME,
OB_DBA_OB_SPATIAL_COLUMNS_ORA_TNAME,
OB_ALL_TABLE_IDX_DATA_TABLE_ID_TNAME,
OB_ALL_TABLE_IDX_DB_TB_NAME_TNAME,
OB_ALL_TABLE_IDX_TB_NAME_TNAME,
@ -10404,7 +10414,8 @@ const uint64_t restrict_access_virtual_tables[] = {
OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_REAL_AGENT_ORA_TID,
OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_ORA_TID,
OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TID,
OB_ALL_VIRTUAL_NIC_INFO_ORA_TID };
OB_ALL_VIRTUAL_NIC_INFO_ORA_TID,
OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID };
static inline bool is_restrict_access_virtual_table(const uint64_t tid)
@ -12973,11 +12984,11 @@ static inline int get_sys_table_lob_aux_schema(const uint64_t tid,
const int64_t OB_CORE_TABLE_COUNT = 4;
const int64_t OB_SYS_TABLE_COUNT = 295;
const int64_t OB_VIRTUAL_TABLE_COUNT = 814;
const int64_t OB_SYS_VIEW_COUNT = 898;
const int64_t OB_SYS_TENANT_TABLE_COUNT = 2012;
const int64_t OB_VIRTUAL_TABLE_COUNT = 816;
const int64_t OB_SYS_VIEW_COUNT = 899;
const int64_t OB_SYS_TENANT_TABLE_COUNT = 2015;
const int64_t OB_CORE_SCHEMA_VERSION = 1;
const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 2015;
const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 2018;
} // end namespace share
} // end namespace oceanbase

View File

@ -700,6 +700,13 @@ bool vt_mapping_init()
tmp_vt_mapping.is_real_vt_ = true;
}
{
int64_t idx = OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID - start_idx;
VTMapping &tmp_vt_mapping = vt_mappings[idx];
tmp_vt_mapping.mapping_tid_ = OB_ALL_SPATIAL_REFERENCE_SYSTEMS_TID;
tmp_vt_mapping.is_real_vt_ = true;
}
{
int64_t idx = OB_ALL_VIRTUAL_SPM_CONFIG_REAL_AGENT_ORA_TID - start_idx;
VTMapping &tmp_vt_mapping = vt_mappings[idx];

View File

@ -777,6 +777,7 @@ const uint64_t OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID = 12477; // "__al
const uint64_t OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_TID = 12481; // "__all_virtual_tenant_resource_limit"
const uint64_t OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_TID = 12482; // "__all_virtual_tenant_resource_limit_detail"
const uint64_t OB_ALL_VIRTUAL_NIC_INFO_TID = 12487; // "__all_virtual_nic_info"
const uint64_t OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TID = 12490; // "__all_virtual_spatial_reference_systems"
const uint64_t OB_ALL_VIRTUAL_SQL_AUDIT_ORA_TID = 15009; // "ALL_VIRTUAL_SQL_AUDIT_ORA"
const uint64_t OB_ALL_VIRTUAL_PLAN_STAT_ORA_TID = 15010; // "ALL_VIRTUAL_PLAN_STAT_ORA"
const uint64_t OB_ALL_VIRTUAL_PLAN_CACHE_PLAN_EXPLAIN_ORA_TID = 15012; // "ALL_VIRTUAL_PLAN_CACHE_PLAN_EXPLAIN_ORA"
@ -1048,6 +1049,7 @@ const uint64_t OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_REAL_AGENT_ORA_TID = 15447; /
const uint64_t OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_ORA_TID = 15450; // "ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_ORA"
const uint64_t OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TID = 15451; // "ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_ORA"
const uint64_t OB_ALL_VIRTUAL_NIC_INFO_ORA_TID = 15456; // "ALL_VIRTUAL_NIC_INFO_ORA"
const uint64_t OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID = 15459; // "ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA"
const uint64_t OB_GV_OB_PLAN_CACHE_STAT_TID = 20001; // "GV$OB_PLAN_CACHE_STAT"
const uint64_t OB_GV_OB_PLAN_CACHE_PLAN_STAT_TID = 20002; // "GV$OB_PLAN_CACHE_PLAN_STAT"
const uint64_t OB_SCHEMATA_TID = 20003; // "SCHEMATA"
@ -1946,6 +1948,7 @@ const uint64_t OB_GV_OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TID = 28226; // "GV$OB_
const uint64_t OB_V_OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TID = 28227; // "V$OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA"
const uint64_t OB_GV_OB_NIC_INFO_ORA_TID = 28230; // "GV$OB_NIC_INFO_ORA"
const uint64_t OB_V_OB_NIC_INFO_ORA_TID = 28231; // "V$OB_NIC_INFO_ORA"
const uint64_t OB_DBA_OB_SPATIAL_COLUMNS_ORA_TID = 28234; // "DBA_OB_SPATIAL_COLUMNS_ORA"
const uint64_t OB_ALL_TABLE_AUX_LOB_META_TID = 50003; // "__all_table_aux_lob_meta"
const uint64_t OB_ALL_COLUMN_AUX_LOB_META_TID = 50004; // "__all_column_aux_lob_meta"
const uint64_t OB_ALL_DDL_OPERATION_AUX_LOB_META_TID = 50005; // "__all_ddl_operation_aux_lob_meta"
@ -3493,6 +3496,7 @@ const char *const OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TNAME = "__all_vir
const char *const OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_TNAME = "__all_virtual_tenant_resource_limit";
const char *const OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_TNAME = "__all_virtual_tenant_resource_limit_detail";
const char *const OB_ALL_VIRTUAL_NIC_INFO_TNAME = "__all_virtual_nic_info";
const char *const OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TNAME = "__all_virtual_spatial_reference_systems";
const char *const OB_ALL_VIRTUAL_SQL_AUDIT_ORA_TNAME = "ALL_VIRTUAL_SQL_AUDIT";
const char *const OB_ALL_VIRTUAL_PLAN_STAT_ORA_TNAME = "ALL_VIRTUAL_PLAN_STAT";
const char *const OB_ALL_VIRTUAL_PLAN_CACHE_PLAN_EXPLAIN_ORA_TNAME = "ALL_VIRTUAL_PLAN_CACHE_PLAN_EXPLAIN";
@ -3764,6 +3768,7 @@ const char *const OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_REAL_AGENT_ORA_TNAME = "AL
const char *const OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_ORA_TNAME = "ALL_VIRTUAL_TENANT_RESOURCE_LIMIT";
const char *const OB_ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TNAME = "ALL_VIRTUAL_TENANT_RESOURCE_LIMIT_DETAIL";
const char *const OB_ALL_VIRTUAL_NIC_INFO_ORA_TNAME = "ALL_VIRTUAL_NIC_INFO";
const char *const OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TNAME = "ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT";
const char *const OB_GV_OB_PLAN_CACHE_STAT_TNAME = "GV$OB_PLAN_CACHE_STAT";
const char *const OB_GV_OB_PLAN_CACHE_PLAN_STAT_TNAME = "GV$OB_PLAN_CACHE_PLAN_STAT";
const char *const OB_SCHEMATA_TNAME = "SCHEMATA";
@ -4662,6 +4667,7 @@ const char *const OB_GV_OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TNAME = "GV$OB_TENAN
const char *const OB_V_OB_TENANT_RESOURCE_LIMIT_DETAIL_ORA_TNAME = "V$OB_TENANT_RESOURCE_LIMIT_DETAIL";
const char *const OB_GV_OB_NIC_INFO_ORA_TNAME = "GV$OB_NIC_INFO";
const char *const OB_V_OB_NIC_INFO_ORA_TNAME = "V$OB_NIC_INFO";
const char *const OB_DBA_OB_SPATIAL_COLUMNS_ORA_TNAME = "DBA_OB_SPATIAL_COLUMNS";
const char *const OB_ALL_TABLE_AUX_LOB_META_TNAME = "__all_table_aux_lob_meta";
const char *const OB_ALL_COLUMN_AUX_LOB_META_TNAME = "__all_column_aux_lob_meta";
const char *const OB_ALL_DDL_OPERATION_AUX_LOB_META_TNAME = "__all_ddl_operation_aux_lob_meta";

View File

@ -14464,7 +14464,10 @@ def_table_schema(
# 12488: __all_virtual_scheduler_job_run_detail_v2
# 12489: __all_virtual_deadlock_detector_stat
# 12490: __all_virtual_spatial_reference_systems
def_table_schema(**gen_iterate_virtual_table_def(
table_id = '12490',
table_name = '__all_virtual_spatial_reference_systems',
keywords = all_def_keywords['__all_spatial_reference_systems']))
# 余留位置(此行之前占位)
# 本区域占位建议:采用真实表名进行占位
@ -14946,7 +14949,7 @@ def_table_schema(**no_direct_access(gen_oracle_mapping_virtual_table_def('15451'
def_table_schema(**no_direct_access(gen_oracle_mapping_virtual_table_def('15456', all_def_keywords['__all_virtual_nic_info'])))
# 15457: __all_virtual_query_response_time
# 15458: __all_scheduler_job_run_detail_v2
# 15459: __all_spatial_reference_systems
def_table_schema(**no_direct_access(gen_oracle_mapping_real_virtual_table_def('15459', all_def_keywords['__all_spatial_reference_systems'])))
# 15460: idx_scheduler_job_run_detail_v2_time_real_agent
#
# 余留位置(此行之前占位)
@ -21067,7 +21070,7 @@ def_table_schema(
CAST(NULL AS CHAR(15)) AS DURATION,
CAST(NULL AS NUMBER) AS PCT_DIRECT_ACCESS,
CAST(NULL AS CHAR(128)) AS ITYP_OWNER,
CAST(NULL AS CHAR(128)) AS ITYP_NAME,
CAST(INDEX_ITYP_NAME AS CHAR(128)) AS ITYP_NAME,
CAST(NULL AS CHAR(1000)) AS PARAMETERS,
CAST(NULL AS CHAR(3)) AS GLOBAL_STATS,
CAST(NULL AS CHAR(12)) AS DOMIDX_STATUS,
@ -21096,7 +21099,7 @@ def_table_schema(
ELSE (CONS_TAB.CONSTRAINT_NAME) END AS INDEX_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12, 15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND EXISTS (
SELECT 1
FROM OCEANBASE.__ALL_VIRTUAL_COLUMN T_COL_INDEX,
@ -21112,6 +21115,11 @@ def_table_schema(
ELSE 'NORMAL'
END AS INDEX_TYPE_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12) THEN 'SPATIAL_INDEX'
ELSE 'NULL'
END AS INDEX_ITYP_NAME,
DATABASE_NAME AS TABLE_OWNER,
CASE WHEN (TABLE_TYPE = 3) THEN A.TABLE_ID
@ -39573,7 +39581,7 @@ def_table_schema(
CAST(NULL AS VARCHAR2(15)) AS DURATION,
CAST(NULL AS NUMBER) AS PCT_DIRECT_ACCESS,
CAST(NULL AS VARCHAR2(128)) AS ITYP_OWNER,
CAST(NULL AS VARCHAR2(128)) AS ITYP_NAME,
CAST(INDEX_ITYP_NAME AS VARCHAR2(128)) AS ITYP_NAME,
CAST(NULL AS VARCHAR2(1000)) AS PARAMETERS,
CAST(NULL AS VARCHAR2(3)) AS GLOBAL_STATS,
CAST(NULL AS VARCHAR2(12)) AS DOMIDX_STATUS,
@ -39600,7 +39608,7 @@ def_table_schema(
ELSE (CONS_TAB.CONSTRAINT_NAME) END AS INDEX_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12, 15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND EXISTS (
SELECT 1
FROM SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT T_COL_INDEX,
@ -39616,6 +39624,11 @@ def_table_schema(
ELSE 'NORMAL'
END AS INDEX_TYPE_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12) THEN 'SPATIAL_INDEX'
ELSE 'NULL'
END AS INDEX_ITYP_NAME,
DATABASE_NAME AS TABLE_OWNER,
CASE WHEN (TABLE_TYPE IN (3, 15)) THEN A.TABLE_ID
@ -39741,7 +39754,7 @@ def_table_schema(
CAST(NULL AS VARCHAR2(15)) AS DURATION,
CAST(NULL AS NUMBER) AS PCT_DIRECT_ACCESS,
CAST(NULL AS VARCHAR2(128)) AS ITYP_OWNER,
CAST(NULL AS VARCHAR2(128)) AS ITYP_NAME,
CAST(INDEX_ITYP_NAME AS VARCHAR2(128)) AS ITYP_NAME,
CAST(NULL AS VARCHAR2(1000)) AS PARAMETERS,
CAST(NULL AS VARCHAR2(3)) AS GLOBAL_STATS,
CAST(NULL AS VARCHAR2(12)) AS DOMIDX_STATUS,
@ -39768,7 +39781,7 @@ def_table_schema(
ELSE (CONS_TAB.CONSTRAINT_NAME) END AS INDEX_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12, 15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND EXISTS (
SELECT 1
FROM SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT T_COL_INDEX,
@ -39784,6 +39797,11 @@ def_table_schema(
ELSE 'NORMAL'
END AS INDEX_TYPE_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12) THEN 'SPATIAL_INDEX'
ELSE 'NULL'
END AS INDEX_ITYP_NAME,
DATABASE_NAME AS TABLE_OWNER,
CASE WHEN (TABLE_TYPE IN (3, 15)) THEN A.TABLE_ID
@ -39912,7 +39930,7 @@ def_table_schema(
CAST(NULL AS VARCHAR2(15)) AS DURATION,
CAST(NULL AS NUMBER) AS PCT_DIRECT_ACCESS,
CAST(NULL AS VARCHAR2(128)) AS ITYP_OWNER,
CAST(NULL AS VARCHAR2(128)) AS ITYP_NAME,
CAST(INDEX_ITYP_NAME AS VARCHAR2(128)) AS ITYP_NAME,
CAST(NULL AS VARCHAR2(1000)) AS PARAMETERS,
CAST(NULL AS VARCHAR2(3)) AS GLOBAL_STATS,
CAST(NULL AS VARCHAR2(12)) AS DOMIDX_STATUS,
@ -39939,7 +39957,7 @@ def_table_schema(
ELSE (CONS_TAB.CONSTRAINT_NAME) END AS INDEX_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12, 15, 18, 21) THEN 'DOMAIN'
WHEN A.TABLE_TYPE = 5 AND EXISTS (
SELECT 1
FROM SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT T_COL_INDEX,
@ -39955,6 +39973,11 @@ def_table_schema(
ELSE 'NORMAL'
END AS INDEX_TYPE_NAME,
CASE
WHEN A.TABLE_TYPE = 5 AND A.INDEX_TYPE IN (10, 11, 12) THEN 'SPATIAL_INDEX'
ELSE 'NULL'
END AS INDEX_ITYP_NAME,
DATABASE_NAME AS TABLE_OWNER,
CASE WHEN (TABLE_TYPE IN (3, 15)) THEN A.TABLE_ID
@ -62741,7 +62764,85 @@ def_table_schema(
)
# 28232: GV$OB_QUERY_RESPONSE_TIME_HISTOGRAM
# 28233: V$OB_QUERY_RESPONSE_TIME_HISTOGRAM
# 28234: DBA_OB_SPATIAL_COLUMNS
def_table_schema(
owner = 'wuxingying.wxy',
table_name = 'DBA_OB_SPATIAL_COLUMNS',
name_postfix = '_ORA',
database_id = 'OB_ORA_SYS_DATABASE_ID',
table_id = '28234',
table_type = 'SYSTEM_VIEW',
rowkey_columns = [],
normal_columns = [],
gm_columns = [],
in_tenant_space = True,
view_definition = """
select G.TABLE_SCHEMA AS TABLE_SCHEMA,
G.TABLE_NAME AS TABLE_NAME,
G.COLUMN_NAME AS COLUMN_NAME,
G.SRS_NAME AS SRS_NAME,
G.SRS_ID AS SRS_ID,
G.GEOMETRY_TYPE_NAME AS GEOMETRY_TYPE_NAME,
CAST('SDO_DIM_ARRAY(SDO_DIM_ELEMENT(NULL, -180, 180, 0.5), SDO_DIM_ELEMENT(NULL, -90, 90, 0.5))'
AS VARCHAR2(512)) AS DIMINFO,
D.INDEX_NAME AS INDEX_NAME
from
(select CAST(db.database_name AS VARCHAR2(128)) as TABLE_SCHEMA,
CAST(tbl.table_name AS VARCHAR2(256)) as TABLE_NAME,
CAST(col.column_name AS VARCHAR2(128)) as COLUMN_NAME,
CAST(srs.srs_name AS VARCHAR2(128)) as SRS_NAME,
CAST(
CASE
WHEN TRUNC(col.srs_id / POWER(2, 32)) = 4294967295 THEN NULL
ELSE TRUNC(col.srs_id / POWER(2, 32))
END
AS NUMBER(10)) AS SRS_ID,
CAST(
CASE
WHEN (BITAND(col.srs_id, 31) IN (0, 1, 2, 3, 4, 5, 6, 7)) THEN 'SDO_GEOMETRY'
ELSE 'invalid'
END
AS VARCHAR2(128)) AS GEOMETRY_TYPE_NAME,
db.tenant_id as TENANT_ID,
tbl.table_id AS TABLE_ID,
tbl.database_id AS DATABASE_ID
from
SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT col left join SYS.ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT srs on TRUNC(col.srs_id / POWER(2, 32)) = srs.srs_id
join SYS.ALL_VIRTUAL_TABLE_REAL_AGENT tbl on (tbl.table_id = col.table_id and tbl.tenant_id = col.tenant_id)
join SYS.ALL_VIRTUAL_DATABASE_REAL_AGENT db on (db.database_id = tbl.database_id and db.tenant_id = tbl.tenant_id)
and db.database_name != '__recyclebin'
where col.data_type = 48
AND BITAND(TRUNC(tbl.table_mode / POWER(2, 12)), 15) IN (0, 1)) G
left join
(select T.TABLE_NAME AS TABLE_NAME,
T.INDEX_NAME AS INDEX_NAME,
C.COLUMN_NAME AS COLUMN_NAME,
C.COLUMN_ID AS COLUMN_ID,
T.DATABASE_ID AS DATABASE_ID,
T.TENANT_ID AS TENANT_ID,
C.TABLE_ID AS TABLE_ID
from
(select A.TABLE_NAME AS TABLE_NAME,
A.INDEX_NAME AS INDEX_NAME,
A.COLUMN_NAME AS COLUMN_NAME,
B.COLUMN_ID AS COLUMN_ID,
B.TENANT_ID as TENANT_ID,
B.TABLE_ID as TABLE_ID,
B.DATABASE_ID AS DATABASE_ID,
B.SRS_ID AS SRS_ID
from (select TABLE_NAME, INDEX_NAME, COLUMN_NAME from ALL_IND_COLUMNS idx_col) A
join (select cl.COLUMN_ID as COLUMN_ID, cl.COLUMN_NAME as COLUMN_NAME, cl.TENANT_ID as TENANT_ID, cl.TABLE_ID as TABLE_ID,
tb.TABLE_NAME as TABLE_NAME, cl.IS_HIDDEN as IS_HIDDEN,
cl.SRS_ID as SRS_ID, tb.DATABASE_ID as DATABASE_ID from SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT cl
join SYS.ALL_VIRTUAL_TABLE_REAL_AGENT tb on (tb.table_id = cl.table_id and tb.tenant_id = cl.tenant_id)) B on
(B.COLUMN_NAME = A.COLUMN_NAME AND B.TABLE_NAME = A.TABLE_NAME)
where b.IS_HIDDEN = 1 and SUBSTR(A.COLUMN_NAME, 1, 5) = '__mbr') T
join SYS.ALL_VIRTUAL_COLUMN_REAL_AGENT C on (T.SRS_ID = C.COLUMN_ID and T.TENANT_ID = C.TENANT_ID)
where C.DATA_TYPE = 48) D
ON D.TABLE_ID = G.TABLE_ID and D.TENANT_ID = G.TENANT_ID and D.DATABASE_ID = G.DATABASE_ID and D.COLUMN_NAME = G.COLUMN_NAME
ORDER BY 1, 2, 3
""".replace("\n", " ")
)
#
# 28235 - 28237 placeholder by gaishun.gs
# 28235: DBA_OB_SERVER_SPACE_USAGE_ORA

View File

@ -1866,6 +1866,7 @@ case OB_ALL_VIRTUAL_SECURITY_AUDIT_RECORD_TID:
case OB_ALL_VIRTUAL_SEQUENCE_OBJECT_TID:
case OB_ALL_VIRTUAL_SEQUENCE_OBJECT_HISTORY_TID:
case OB_ALL_VIRTUAL_SEQUENCE_VALUE_TID:
case OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TID:
case OB_ALL_VIRTUAL_SPM_CONFIG_TID:
case OB_ALL_VIRTUAL_SUB_PART_TID:
case OB_ALL_VIRTUAL_SUB_PART_HISTORY_TID:
@ -3614,6 +3615,21 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
break;
}
case OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
SERVER_LOG(WARN, "create virtual table iterator failed", K(ret));
} else if (OB_FAIL(iter->init(OB_ALL_SPATIAL_REFERENCE_SYSTEMS_TID, index_schema, params))) {
SERVER_LOG(WARN, "virtual table iter init failed", K(ret));
iter->~ObIterateVirtualTable();
allocator.free(iter);
iter = NULL;
} else {
vt_iter = iter;
}
break;
}
case OB_ALL_VIRTUAL_SPM_CONFIG_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
@ -3733,7 +3749,9 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
}
break;
}
END_CREATE_VT_ITER_SWITCH_LAMBDA
BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA
case OB_ALL_VIRTUAL_SYSAUTH_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
@ -3748,9 +3766,7 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
}
break;
}
END_CREATE_VT_ITER_SWITCH_LAMBDA
BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA
case OB_ALL_VIRTUAL_SYSAUTH_HISTORY_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
@ -4035,7 +4051,9 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
}
break;
}
END_CREATE_VT_ITER_SWITCH_LAMBDA
BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA
case OB_ALL_VIRTUAL_TENANT_OLS_COMPONENT_HISTORY_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
@ -4050,9 +4068,7 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
}
break;
}
END_CREATE_VT_ITER_SWITCH_LAMBDA
BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA
case OB_ALL_VIRTUAL_TENANT_OLS_LABEL_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
@ -4337,7 +4353,9 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
}
break;
}
END_CREATE_VT_ITER_SWITCH_LAMBDA
BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA
case OB_ALL_VIRTUAL_TIME_ZONE_TRANSITION_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {
@ -4352,9 +4370,7 @@ case OB_ALL_VIRTUAL_USER_PROXY_ROLE_INFO_HISTORY_TID:
}
break;
}
END_CREATE_VT_ITER_SWITCH_LAMBDA
BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA
case OB_ALL_VIRTUAL_TIME_ZONE_TRANSITION_TYPE_TID: {
ObIterateVirtualTable *iter = NULL;
if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIterateVirtualTable, iter))) {

View File

@ -1118,6 +1118,8 @@
# 12481: __all_virtual_tenant_resource_limit
# 12482: __all_virtual_tenant_resource_limit_detail
# 12487: __all_virtual_nic_info
# 12490: __all_virtual_spatial_reference_systems
# 12490: __all_spatial_reference_systems # BASE_TABLE_NAME
# 15009: ALL_VIRTUAL_SQL_AUDIT
# 15009: __all_virtual_sql_audit # BASE_TABLE_NAME
# 15010: ALL_VIRTUAL_PLAN_STAT
@ -1717,6 +1719,8 @@
# 15451: __all_virtual_tenant_resource_limit_detail # BASE_TABLE_NAME
# 15456: ALL_VIRTUAL_NIC_INFO
# 15456: __all_virtual_nic_info # BASE_TABLE_NAME
# 15459: ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT
# 15459: __all_spatial_reference_systems # BASE_TABLE_NAME
# 20001: GV$OB_PLAN_CACHE_STAT
# 20002: GV$OB_PLAN_CACHE_PLAN_STAT
# 20003: SCHEMATA
@ -2615,6 +2619,7 @@
# 28227: V$OB_TENANT_RESOURCE_LIMIT_DETAIL
# 28230: GV$OB_NIC_INFO
# 28231: V$OB_NIC_INFO
# 28234: DBA_OB_SPATIAL_COLUMNS
# 14999: __idx_11003_all_virtual_plan_cache_stat_i1
# 14999: all_virtual_plan_cache_stat_i1 # INDEX_NAME
# 14999: __all_virtual_plan_cache_stat # DATA_BASE_TABLE_NAME

View File

@ -609,12 +609,14 @@ int ObDDLUtil::generate_order_by_str(
} else if (OB_FAIL(sql_string.append("order by "))) {
LOG_WARN("append failed", K(ret));
} else {
bool append_comma = false;
for (int64_t i = 0; OB_SUCC(ret) && i < order_column_ids.count(); ++i) {
for (int64_t j = 0; OB_SUCC(ret) && j < select_column_ids.count(); ++j) {
const bool append_comma = 0 != i;
if (select_column_ids.at(j) == order_column_ids.at(i)) {
if (OB_FAIL(sql_string.append_fmt("%s %ld", append_comma ? ",": "", j + 1))) {
LOG_WARN("append fmt failed", K(ret));
} else if (!append_comma) {
append_comma = true;
}
}
}

View File

@ -1103,7 +1103,12 @@ int ObIndexBuilderUtil::adjust_spatial_args(
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get invalid arguments", K(ret));
} else if (OB_FAIL(generate_spatial_columns(sort_items.at(0).column_name_, data_schema, spatial_cols))) {
LOG_WARN("generate spatial column failed", K(ret));
if (lib::is_oracle_mode() && ret == OB_ERR_COLUMN_DUPLICATE) { // error code adaptation
ret = OB_ERR_DOMAIN_COLUMN_DUPLICATE;
LOG_WARN("cannot create multiple domain indexes on a column list using same", K(ret));
} else {
LOG_WARN("generate spatial column failed", K(ret));
}
} else if (OB_UNLIKELY(spatial_cols.count() != 2) ||
OB_ISNULL(spatial_cols.at(0)) || OB_ISNULL(spatial_cols.at(1))) {
ret = OB_ERR_UNEXPECTED;
@ -1172,9 +1177,12 @@ int ObIndexBuilderUtil::generate_spatial_cellid_column(
} else if (OB_FAIL(databuff_printf(col_name_buf, OB_MAX_COLUMN_NAMES_LENGTH,
name_pos, "_%ld", geo_col_id))) {
LOG_WARN("print column id to col_name_buf failed", K(ret), K(geo_col_id));
} else if (OB_FAIL(databuff_printf(cellid_expr_def, OB_MAX_DEFAULT_VALUE_LENGTH,
} else if (lib::is_mysql_mode() && OB_FAIL(databuff_printf(cellid_expr_def, OB_MAX_DEFAULT_VALUE_LENGTH,
def_pos, "SPATIAL_CELLID(`%s`)", col_schema.get_column_name()))) {
LOG_WARN("print cellid expr to cellid_expr_def failed", K(ret), K(col_schema.get_column_name()));
} else if (lib::is_oracle_mode() && OB_FAIL(databuff_printf(cellid_expr_def, OB_MAX_DEFAULT_VALUE_LENGTH,
def_pos, "SPATIAL_CELLID(%s)", col_schema.get_column_name()))) {
LOG_WARN("print cellid expr to cellid_expr_def failed", K(ret), K(col_schema.get_column_name()));
} else if (OB_FAIL(column_schema.add_cascaded_column_id(geo_col_id))) {
LOG_WARN("add cascaded column to generated column failed", K(ret));
} else {
@ -1232,9 +1240,12 @@ int ObIndexBuilderUtil::generate_spatial_mbr_column(
} else if (OB_FAIL(databuff_printf(col_name_buf, OB_MAX_COLUMN_NAMES_LENGTH,
name_pos, "_%ld", geo_col_id))) {
LOG_WARN("print column id to buffer failed", K(ret), K(geo_col_id));
} else if (OB_FAIL(databuff_printf(mbr_expr_def, OB_MAX_DEFAULT_VALUE_LENGTH,
} else if (lib::is_mysql_mode() && OB_FAIL(databuff_printf(mbr_expr_def, OB_MAX_DEFAULT_VALUE_LENGTH,
def_pos, "SPATIAL_MBR(`%s`)", col_schema.get_column_name()))) {
LOG_WARN("print mbr expr to mbr_expr_def failed", K(ret), K(col_schema.get_column_name()));
} else if (lib::is_oracle_mode() && OB_FAIL(databuff_printf(mbr_expr_def, OB_MAX_DEFAULT_VALUE_LENGTH,
def_pos, "SPATIAL_MBR(%s)", col_schema.get_column_name()))) {
LOG_WARN("print mbr expr to mbr_expr_def failed", K(ret), K(col_schema.get_column_name()));
} else if (OB_FAIL(column_schema.add_cascaded_column_id(geo_col_id))) {
LOG_WARN("add cascaded column to generated column failed", K(ret));
} else {

View File

@ -664,6 +664,7 @@ ob_set_subtarget(ob_sql engine_expr
engine/expr/ob_expr_spatial_collection.cpp
engine/expr/ob_expr_st_geomfromtext.cpp
engine/expr/ob_expr_st_intersects.cpp
engine/expr/ob_expr_sdo_relate.cpp
engine/expr/ob_expr_st_area.cpp
engine/expr/ob_expr_st_x.cpp
engine/expr/ob_expr_st_transform.cpp

View File

@ -43,7 +43,9 @@ int ObDASDomainUtils::generate_spatial_index_rows(
uint64_t rowkey_num = das_ctdef.table_param_.get_data_table().get_rowkey_column_num();
lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), "S2Adapter"));
if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(wkb_str, srid))) {
if (lib::is_oracle_mode() && wkb_str.length() == 0) {
// in oracle mode, ignore null value
} else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(wkb_str, srid))) {
LOG_WARN("failed to get srid", K(ret), K(wkb_str));
} else if (srid != 0 &&
OB_FAIL(OTSRS_MGR->get_tenant_srs_guard(srs_guard))) {

View File

@ -58,6 +58,8 @@ int ObSpatialIndexLookupOp::init(const ObDASScanCtDef *lookup_ctdef,
}
}
is_whole_range_ |= (mbr_filters_->count() == 0);
mbr_filter_cnt_ = 0;
index_back_cnt_ = 0;
}
return ret;
}
@ -140,6 +142,7 @@ int ObSpatialIndexLookupOp::save_rowkeys()
LOG_WARN("store lookup key range failed", K(ret), K(scan_param_));
}
last_rowkey_ = *idx_row;
index_back_cnt_++;
LOG_DEBUG("build data table range", K(ret), K(*idx_row), K(lookup_range), K(scan_param_.key_ranges_.count()));
}
}
@ -195,7 +198,10 @@ int ObSpatialIndexLookupOp::get_next_row()
if (OB_SUCC(ret) || OB_ITER_END == ret) {
state_ = DO_LOOKUP;
index_end_ = (OB_ITER_END == ret);
ret = OB_SUCCESS;
if (ret == OB_ITER_END) {
LOG_INFO("test spatial index back cnt", K(lookup_rowkey_cnt_), K(index_back_cnt_), K(mbr_filter_cnt_));
ret = OB_SUCCESS;
}
}
break;
}
@ -251,34 +257,37 @@ int ObSpatialIndexLookupOp::get_next_row()
int ObSpatialIndexLookupOp::process_data_table_rowkey()
{
int ret = OB_SUCCESS;
// result_output: rowkey + mbr_expr + transaction_inf_expr
int64_t rowkey_cnt = index_ctdef_->result_output_.count() - 1;
if (index_ctdef_->trans_info_expr_ != nullptr) {
rowkey_cnt = rowkey_cnt - 1;
int64_t rowkey_cnt = max_rowkey_cnt_;
if (max_rowkey_cnt_ < 0 || OB_ISNULL(obj_ptr_)) {
rowkey_cnt = index_ctdef_->result_output_.count() - 1;
void *buf = nullptr;
if (index_ctdef_->trans_info_expr_ != nullptr) {
rowkey_cnt = rowkey_cnt - 1;
}
max_rowkey_cnt_ = rowkey_cnt;
if (OB_ISNULL(allocator_)) {
ret = OB_ERR_UNEXPECTED;
} else if (OB_ISNULL(buf = allocator_->alloc(sizeof(ObObj) * rowkey_cnt))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate buffer failed", K(ret), K(rowkey_cnt));
} else {
obj_ptr_ = new(buf) ObObj[rowkey_cnt];
}
}
ObObj *obj_ptr = nullptr;
void *buf = nullptr;
ObNewRange lookup_range;
ObArenaAllocator tmp_allocator("GisLookup");
if (OB_ISNULL(buf = tmp_allocator.alloc(sizeof(ObObj) * rowkey_cnt))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate buffer failed", K(ret), K(rowkey_cnt));
} else {
obj_ptr = new(buf) ObObj[rowkey_cnt];
}
for (int64_t i = 0; OB_SUCC(ret) && i < rowkey_cnt; ++i) {
ObExpr *expr = index_ctdef_->result_output_.at(i);
if (T_PSEUDO_GROUP_ID == expr->type_) {
// do nothing
} else {
ObDatum &col_datum = expr->locate_expr_datum(*lookup_rtdef_->eval_ctx_);
if (OB_FAIL(col_datum.to_obj(obj_ptr[i], expr->obj_meta_, expr->obj_datum_map_))) {
if (OB_FAIL(col_datum.to_obj(obj_ptr_[i], expr->obj_meta_, expr->obj_datum_map_))) {
LOG_WARN("convert datum to obj failed", K(ret));
}
}
}
if (OB_SUCC(ret)) {
ObRowkey table_rowkey(obj_ptr, rowkey_cnt);
ObRowkey table_rowkey(obj_ptr_, rowkey_cnt);
ObObj mbr_obj;
bool pass_through = true;
ObExpr *mbr_expr = index_ctdef_->result_output_.at(rowkey_cnt);
@ -289,10 +298,11 @@ int ObSpatialIndexLookupOp::process_data_table_rowkey()
LOG_WARN("filter mbr failed", K(ret));
} else if (!is_whole_range_ && pass_through) {
// not target
mbr_filter_cnt_++;
} else if (OB_FAIL(sorter_.add_item(table_rowkey))) {
LOG_WARN("filter mbr failed", K(ret));
} else {
LOG_TRACE("add rowkey success", K(table_rowkey), K(obj_ptr), K(obj_ptr[0]), K(rowkey_cnt));
LOG_TRACE("geo idx add rowkey success", K(table_rowkey), KP(obj_ptr_), K(obj_ptr_[0]), K(rowkey_cnt));
}
}
return ret;

View File

@ -39,7 +39,12 @@ public:
sorter_(allocator),
is_sorted_(false),
is_whole_range_(false),
is_inited_(false) {}
is_inited_(false),
mbr_filter_cnt_(0),
index_back_cnt_(0),
max_rowkey_cnt_(-1),
allocator_(&allocator),
obj_ptr_(nullptr) {}
virtual ~ObSpatialIndexLookupOp();
int init(const ObDASScanCtDef *lookup_ctdef,
@ -59,7 +64,7 @@ private:
int save_rowkeys();
private:
static const int64_t SORT_MEMORY_LIMIT = 32L * 1024L * 1024L;
static const int64_t MAX_NUM_PER_BATCH = 1000;
static const int64_t MAX_NUM_PER_BATCH = 10000;
const ObMbrFilterArray *mbr_filters_;
int cmp_ret_;
@ -69,6 +74,11 @@ private:
bool is_sorted_;
bool is_whole_range_;
bool is_inited_;
int64_t mbr_filter_cnt_;
int64_t index_back_cnt_;
int64_t max_rowkey_cnt_;
ObIAllocator* allocator_;
ObObj *obj_ptr_;
};
} // namespace sql

View File

@ -375,6 +375,7 @@
#include "ob_expr_st_symdifference.h"
#include "ob_expr_priv_st_asmvtgeom.h"
#include "ob_expr_priv_st_makevalid.h"
#include "ob_expr_sdo_relate.h"
#include "ob_expr_inner_table_option_printer.h"
#include "ob_expr_password.h"
@ -1195,7 +1196,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
NULL, // ObExprRbAndNull2empty::eval_rb_and_null2empty, /* 713 */
NULL, // ObExprRbOrNull2empty::eval_rb_or_null2empty, /* 714 */
NULL, // ObExprRbAndnotNull2empty::eval_rb_andnot_null2empty, /* 715 */
NULL, //ObExprSdoRelate::eval_sdo_relate /* 716 */
ObExprSdoRelate::eval_sdo_relate, /* 716 */
NULL, // ObExprRbToString::eval_rb_to_string, /* 717 */
NULL, // ObExprRbFromString::eval_rb_from_string, /* 718 */
NULL, // ObExprRbIterate::eval_rb_iterate, /* 719 */

View File

@ -373,6 +373,7 @@
#include "sql/engine/expr/ob_expr_st_buffer.h"
#include "sql/engine/expr/ob_expr_spatial_cellid.h"
#include "sql/engine/expr/ob_expr_spatial_mbr.h"
#include "sql/engine/expr/ob_expr_sdo_relate.h"
#include "sql/engine/expr/ob_expr_st_geomfromewkb.h"
#include "sql/engine/expr/ob_expr_st_geomfromwkb.h"
#include "sql/engine/expr/ob_expr_st_geomfromewkt.h"
@ -1267,8 +1268,8 @@ void ObExprOperatorFactory::register_expr_operators()
REG_OP_ORCL(ObExprSysExtractUtc);
REG_OP_ORCL(ObExprTzOffset);
REG_OP_ORCL(ObExprFromTz);
// REG_OP_ORCL(ObExprSpatialCellid);
// REG_OP_ORCL(ObExprSpatialMbr);
REG_OP_ORCL(ObExprSpatialCellid);
REG_OP_ORCL(ObExprSpatialMbr);
//label security
REG_OP_ORCL(ObExprOLSPolicyCreate);
REG_OP_ORCL(ObExprOLSPolicyAlter);
@ -1406,7 +1407,7 @@ void ObExprOperatorFactory::register_expr_operators()
REG_OP_ORCL(ObExprInnerTableOptionPrinter);
REG_OP_ORCL(ObExprInnerTableSequenceGetter);
// REG_OP_ORCL(ObExprTopNFilter);
// REG_OP_ORCL(ObExprSdoRelate);
REG_OP_ORCL(ObExprSdoRelate);
}
bool ObExprOperatorFactory::is_expr_op_type_valid(ObExprOperatorType type)

View File

@ -0,0 +1,291 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
* This file contains implementation for eval_sdo_relate.
*/
#define USING_LOG_PREFIX SQL_ENG
#include "lib/geo/ob_geo_func_register.h"
#include "lib/geo/ob_geo_ibin.h"
#include "sql/engine/ob_exec_context.h"
#include "observer/omt/ob_tenant_srs.h"
#include "ob_expr_sdo_relate.h"
#include "lib/geo/ob_geo_cache.h"
#include "sql/engine/expr/ob_geo_expr_utils.h"
using namespace oceanbase::common;
using namespace oceanbase::sql;
namespace oceanbase
{
namespace sql
{
ObExprSdoRelate::ObExprSdoRelate(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_SDO_RELATE, N_SDO_RELATE, 3, VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION)
{
}
ObExprSdoRelate::~ObExprSdoRelate()
{
}
int ObExprSdoRelate::calc_result_type3(ObExprResType &type,
ObExprResType &type1,
ObExprResType &type2,
ObExprResType &type3,
common::ObExprTypeCtx &type_ctx) const
{
INIT_SUCC(ret);
if (type1.get_type() == ObNullType) {
} else if (ob_is_nchar(type1.get_type())) {
ret = OB_ERR_OPERATOR_NOT_EXIST;
LOG_WARN("operator binding does not exist", K(ret));
} else if (!ob_is_geometry(type1.get_type()) && !ob_is_string_type(type1.get_type())) {
type1.set_calc_type(ObVarcharType);
type1.set_calc_collation_type(CS_TYPE_BINARY);
}
if (OB_FAIL(ret)) {
} else if (type2.get_type() == ObNullType) {
} else if (ob_is_nchar(type2.get_type())) {
ret = OB_ERR_OPERATOR_NOT_EXIST;
LOG_WARN("operator binding does not exist", K(ret));
} else if (!ob_is_geometry(type2.get_type()) && !ob_is_string_type(type2.get_type())) {
type2.set_calc_type(ObVarcharType);
type2.set_calc_collation_type(CS_TYPE_BINARY);
}
if (OB_FAIL(ret)) {
} else if (type3.get_type() == ObNullType ) {
ret = OB_INVALID_MASK;
LOG_WARN("invalid mask param", K(ret), K(type3.get_type()));
} else if (ob_is_blob(type3.get_type(), type3.get_collation_type())
|| ob_is_json(type3.get_type()) || ob_is_user_defined_type(type3.get_type())) {
ret = OB_ERR_OPERATOR_NOT_EXIST;
LOG_WARN("operator binding does not exist", K(ret));
} else if (!ob_is_string_type(type3.get_type())) {
type3.set_calc_type(ObVarcharType);
type3.set_calc_collation_type(CS_TYPE_BINARY);
}
if (OB_SUCC(ret)) {
type.set_type(ObObjType::ObVarcharType);
type.set_collation_type(type_ctx.get_coll_type());
type.set_collation_level(CS_LEVEL_IMPLICIT);
type.set_full_length(strlen("false") + 1, 1);
}
return ret;
}
int ObExprSdoRelate::get_params(ObExpr *param_expr, ObArenaAllocator& temp_allocator, ObEvalCtx &ctx, ObSdoRelateMask& mask)
{
INIT_SUCC(ret);
ObDatum *param_datum = nullptr;
if (OB_ISNULL(param_expr)) {
ret = OB_BAD_NULL_ERROR;
LOG_WARN("should not be null", K(ret), KP(param_expr));
} else if (OB_FAIL(param_expr->eval(ctx, param_datum))) {
LOG_WARN("eval param args failed", K(ret));
} else if (param_datum->is_null()) {
ret = OB_INVALID_MASK;
LOG_WARN("invalid mask param", K(ret));
} else {
ObString original_str = param_datum->get_string();
ObString upper_str;
if (OB_FAIL(ob_simple_low_to_up(temp_allocator, original_str, upper_str))) {
LOG_WARN("failed to get upper string", K(ret));
} else {
char cmp_str[upper_str.length() + 1];
cmp_str[upper_str.length()] = '\0';
MEMCPY(cmp_str, upper_str.ptr(), upper_str.length());
if (nullptr != strstr(cmp_str, ObSdoRelationship::ANYINTERACT) && OB_FALSE_IT(mask.anyinteract_ = 1)) {
} else if (mask.anyinteract_ != 1
&& (strstr(cmp_str, ObSdoRelationship::CONTAINS)
|| strstr(cmp_str, ObSdoRelationship::COVEREDBY)
|| strstr(cmp_str, ObSdoRelationship::COVERS)
|| strstr(cmp_str, ObSdoRelationship::EQUAL)
|| strstr(cmp_str, ObSdoRelationship::ON)
|| strstr(cmp_str, ObSdoRelationship::OVERLAPBDYDISJOINT)
|| strstr(cmp_str, ObSdoRelationship::OVERLAPBDYINTERSECT)
|| strstr(cmp_str, ObSdoRelationship::INSIDE)
|| strstr(cmp_str, ObSdoRelationship::TOUCH))) {
// other spatial relationsh is not supported yet, no need to continue
ret = OB_NOT_SUPPORTED;
LOG_WARN("not sopported yet.", K(ret));
}
}
}
return ret;
}
int ObExprSdoRelate::set_relate_result(ObIAllocator &res_alloc, ObDatum &res, bool result)
{
INIT_SUCC(ret);
ObString data = result ? "TRUE" : "FALSE";
ObString str_value;
char *str_buf = nullptr;
if (OB_ISNULL(str_buf = static_cast<char*>(res_alloc.alloc(data.length())))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc failed", K(ret));
} else if (OB_FALSE_IT(str_value.assign_buffer(str_buf, data.length()))) {
} else if (OB_UNLIKELY(data.length() != str_value.write(data.ptr(), data.length()))) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("write amp char failed", K(ret));
} else {
res.set_string(str_value);
}
return ret;
}
int ObExprSdoRelate::eval_sdo_relate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res)
{
INIT_SUCC(ret);
ObSdoRelateMask mask;
mask.flags_ = 0;
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator();
bool result = false;
ObExprStrResAlloc res_alloc(expr, ctx);
if (ob_is_string_type(expr.args_[2]->datum_meta_.type_) && OB_FAIL(get_params(expr.args_[2], temp_allocator, ctx, mask))) {
LOG_WARN("fail to get mask param", K(ret), K(mask.flags_));
} else if (mask.flags_ == 0) {
ret = set_relate_result(res_alloc, res, false);
} else {
ObDatum *gis_datum1 = NULL;
ObDatum *gis_datum2 = NULL;
ObExpr *gis_arg1 = expr.args_[0];
ObExpr *gis_arg2 = expr.args_[1];
ObObjType input_type1 = gis_arg1->datum_meta_.type_;
ObObjType input_type2 = gis_arg2->datum_meta_.type_;
if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) {
LOG_WARN("eval geo args failed", K(ret));
} else if (gis_datum1->is_null() || gis_datum2->is_null()) {
ret = OB_ERR_OPERATOR_NOT_EXIST;
LOG_WARN("operator binding does not exist", K(ret));
} else {
ObDatum *gis_datum1 = NULL;
ObDatum *gis_datum2 = NULL;
ObExpr *gis_arg1 = expr.args_[0];
ObExpr *gis_arg2 = expr.args_[1];
int num_args = expr.arg_cnt_;
ObObjType input_type1 = gis_arg1->datum_meta_.type_;
ObObjType input_type2 = gis_arg2->datum_meta_.type_;
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator();
if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) {
LOG_WARN("eval geo args failed", K(ret));
} else if (gis_datum1->is_null() || gis_datum2->is_null()) {
res.set_null();
} else {
ObGeoConstParamCache* const_param_cache = ObGeoExprUtils::get_geo_constParam_cache(expr.expr_ctx_id_, &ctx.exec_ctx_);
bool is_geo1_empty = false;
bool is_geo2_empty = false;
ObGeometry *geo1 = NULL;
ObGeometry *geo2 = NULL;
ObGeoType type1;
ObGeoType type2;
uint32_t srid1;
uint32_t srid2;
ObString wkb1 = gis_datum1->get_string();
ObString wkb2 = gis_datum2->get_string();
omt::ObSrsCacheGuard srs_guard;
const ObSrsItem *srs = NULL;
bool is_geo1_cached = false;
bool is_geo2_cached = false;
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
bool box_intersects = true;
if (gis_arg1->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo1, srid1, is_geo1_cached, 0);
}
if (gis_arg2->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo2, srid2, is_geo2_cached, 1);
}
if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum1, *gis_arg1, wkb1, type1, srid1))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
ret = OB_ERR_OPERATOR_NOT_EXIST;
LOG_WARN("operator binding does not exist", K(ret));
}
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum2, *gis_arg2, wkb2, type2, srid2))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
ret = OB_ERR_OPERATOR_NOT_EXIST;
LOG_WARN("operator binding does not exist", K(ret));
}
} else if (srid1 != srid2) {
if (srid1 == UINT_MAX32 || srid2 == UINT_MAX32) {
ret = OB_GEO_IN_DIFFERENT_COORDINATE;
LOG_WARN("srid not the same", K(srid1), K(srid2));
} else {
ret = set_relate_result(res_alloc, res, false);
}
} else if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get session", K(ret));
} else if (!is_geo1_cached && !is_geo2_cached && OB_FAIL(ObGeoExprUtils::get_srs_item(session->get_effective_tenant_id(), srs_guard, srid1, srs))) {
LOG_WARN("fail to get srs item", K(ret), K(srid1));
} else if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, nullptr, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get first geo by wkb failed", K(ret));
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get second geo by wkb failed", K(ret));
} else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)))
|| (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) {
LOG_WARN("check geo empty failed", K(ret));
} else if (is_geo1_empty || is_geo2_empty) {
res.set_null();
} else if (ObGeoTypeUtil::is_3d_geo_type(geo1->type()) || ObGeoTypeUtil::is_3d_geo_type(geo2->type())) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("only support 2D spatial relationship", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) {
LOG_WARN("zoom in geos failed", K(ret));
} else {
// add cache if need
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_ && !is_geo1_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(0, *geo1))) {
LOG_WARN("add geo1 to const cache failed", K(ret));
} else if (gis_arg2->is_static_const_ && !is_geo2_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(1, *geo2))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
}
}
// check each relation ship, util res is true
if (OB_FAIL(ret)) {
} else if (!result && mask.anyinteract_ == 1) {
bool tmp_result = false;
if (OB_FAIL(ObGeoExprUtils::get_intersects_res(*geo1, *geo2, gis_arg1, gis_arg2, const_param_cache, srs, temp_allocator, tmp_result))) {
LOG_WARN("fail to get interact res", K(ret));
} else {
result = (result || tmp_result);
}
}
// set result
if (OB_FAIL(ret)) {
} else {
ret = set_relate_result(res_alloc, res, result);
}
} // add cache and set res
}
}// deal gis param
}
return ret;
}
int ObExprSdoRelate::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_sdo_relate;
return OB_SUCCESS;
}
}
}

View File

@ -0,0 +1,77 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
* This file contains implementation for eval_sdo_relate.
*/
#ifndef OCEANBASE_SQL_OB_EXPR_SDO_RELATE_H_
#define OCEANBASE_SQL_OB_EXPR_SDO_RELATE_H_
#include "sql/engine/expr/ob_expr_operator.h"
namespace oceanbase
{
namespace sql
{
typedef union ObSdoRelateMask
{
struct {
uint16_t anyinteract_ : 1;
uint16_t contains_ : 1;
uint16_t coveredby_ : 1;
uint16_t covers_ : 1;
uint16_t equal_ : 1;
uint16_t on_ : 1;
uint16_t overlapbdydisjoint_ : 1;
uint16_t overlapbdyintersect_ : 1;
uint16_t inside_ : 1;
uint16_t touch_ : 1;
uint16_t reserved_ : 6;
};
uint16_t flags_;
} ObSdoRelateMask;
class ObSdoRelationship
{
public:
static constexpr char* ANYINTERACT = const_cast<char*>("ANYINTERACT");
static constexpr char* CONTAINS = const_cast<char*>("CONTAINS");
static constexpr char* COVEREDBY = const_cast<char*>("COVEREDBY");
static constexpr char* COVERS = const_cast<char*>("COVERS");
static constexpr char* EQUAL = const_cast<char*>("EQUAL");
static constexpr char* ON = const_cast<char*>("ON");
static constexpr char* OVERLAPBDYDISJOINT = const_cast<char*>("OVERLAPBDYDISJOINT");
static constexpr char* OVERLAPBDYINTERSECT = const_cast<char*>("OVERLAPBDYINTERSECT");
static constexpr char* INSIDE = const_cast<char*>("INSIDE");
static constexpr char* TOUCH = const_cast<char*>("TOUCH");
};
class ObExprSdoRelate : public ObFuncExprOperator
{
public:
explicit ObExprSdoRelate(common::ObIAllocator &alloc);
virtual ~ObExprSdoRelate();
virtual int calc_result_type3(ObExprResType &type,
ObExprResType &type1,
ObExprResType &type2,
ObExprResType &type3,
common::ObExprTypeCtx &type_ctx) const;
static int eval_sdo_relate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res);
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
const ObRawExpr &raw_expr,
ObExpr &rt_expr) const override;
private:
static int get_params(ObExpr *param_expr, ObArenaAllocator& temp_allocator, ObEvalCtx &ctx, ObSdoRelateMask& mask);
static int set_relate_result(ObIAllocator &res_alloc, ObDatum &res, bool result);
DISALLOW_COPY_AND_ASSIGN(ObExprSdoRelate);
};
} // sql
} // oceanbase
#endif // OCEANBASE_SQL_OB_EXPR_ST_INTERSECTS_H_

View File

@ -19,7 +19,7 @@
#include "sql/engine/ob_exec_context.h"
#include "observer/omt/ob_tenant_srs.h"
#include "ob_expr_st_contains.h"
#include "lib/geo/ob_geo_utils.h"
#include "lib/geo/ob_geo_cache.h"
#include "sql/engine/expr/ob_geo_expr_utils.h"
using namespace oceanbase::common;
@ -77,6 +77,7 @@ int ObExprSTContains::eval_st_contains(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (gis_datum1->is_null() || gis_datum2->is_null()) {
res.set_null();
} else {
ObGeoConstParamCache* const_param_cache = ObGeoExprUtils::get_geo_constParam_cache(expr.expr_ctx_id_, &ctx.exec_ctx_);
bool is_geo1_empty = false;
bool is_geo2_empty = false;
ObGeometry *geo1 = NULL;
@ -89,49 +90,101 @@ int ObExprSTContains::eval_st_contains(const ObExpr &expr, ObEvalCtx &ctx, ObDat
ObString wkb2 = gis_datum2->get_string();
omt::ObSrsCacheGuard srs_guard;
const ObSrsItem *srs = NULL;
bool is_geo1_cached = false;
bool is_geo2_cached = false;
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum1,
gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb1));
} else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2,
gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb2));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) {
if (gis_arg1->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo1, srid1, is_geo1_cached, 0);
}
if (gis_arg2->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo2, srid2, is_geo2_cached, 1);
}
if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum1, *gis_arg1, wkb1, type1, srid1))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_CONTAINS);
}
LOG_WARN("get type and srid from wkb failed", K(wkb1), K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb2, type2, srid2))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum2, *gis_arg2, wkb2, type2, srid2))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_CONTAINS);
}
LOG_WARN("get type and srid from wkb failed", K(wkb2), K(ret));
} else if (srid1 != srid2) {
LOG_WARN("srid not the same", K(srid1), K(srid2));
ret = OB_ERR_GIS_DIFFERENT_SRIDS;
} else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs, true, N_ST_CONTAINS))) {
LOG_WARN("fail to get srs item", K(ret), K(wkb1));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_ST_CONTAINS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) {
} else if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get session", K(ret));
} else if (!is_geo1_cached && !is_geo2_cached && OB_FAIL(ObGeoExprUtils::get_srs_item(session->get_effective_tenant_id(), srs_guard, srid1, srs))) {
LOG_WARN("fail to get srs item", K(ret), K(srid1));
} else if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, nullptr, N_ST_CONTAINS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get first geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_ST_CONTAINS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_CONTAINS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get second geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))
|| OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) {
} else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)))
|| (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) {
LOG_WARN("check geo empty failed", K(ret));
} else if (is_geo1_empty || is_geo2_empty) {
res.set_null();
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) {
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) {
LOG_WARN("zoom in geos failed", K(ret));
} else {
ObGeoEvalCtx gis_context(&temp_allocator, srs);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Within>::gis_func::eval(gis_context, result))) {
LOG_WARN("eval Within functor failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_ST_CONTAINS);
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_ && !is_geo1_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(0, *geo1))) {
LOG_WARN("add geo1 to const cache failed", K(ret));
} else if (gis_arg2->is_static_const_ && !is_geo2_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(1, *geo2))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
}
}
if (OB_FAIL(ret)) {
} else {
res.set_bool(result);
ObGeoEvalCtx gis_context(&temp_allocator);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else {
ObCachedGeom *cache_geo = NULL;
ObGeometry *geo;
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_) {
cache_geo = const_param_cache->get_cached_geo(0);
if (cache_geo == NULL
&& OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(),
temp_allocator,
const_param_cache->get_const_param_cache(0),
srs,
cache_geo))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
} else {
geo = geo2;
const_param_cache->add_cached_geo(0, cache_geo);
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_NOT_NULL(cache_geo)) {
if (OB_FAIL(cache_geo->contains(*geo, gis_context, result))) {
LOG_WARN("get contains result failed", K(ret));
} else {
res.set_bool(result);
}
} else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_CONTAINS)) {
bool result = false;
if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_CONTAINS, result))) {
LOG_WARN("fail to get res.", K(ret));
} else {
res.set_bool(result);
}
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Within>::gis_func::eval(gis_context, result))) {
LOG_WARN("eval Within functor failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_ST_CONTAINS);
} else {
res.set_bool(result);
}
}
}
}
}

View File

@ -33,6 +33,7 @@ public:
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
const ObRawExpr &raw_expr,
ObExpr &rt_expr) const override;
virtual bool need_rt_ctx() const override { return true; }
private:
DISALLOW_COPY_AND_ASSIGN(ObExprSTContains);
};

View File

@ -19,7 +19,7 @@
#include "sql/engine/ob_exec_context.h"
#include "observer/omt/ob_tenant_srs.h"
#include "ob_expr_st_covers.h"
#include "lib/geo/ob_geo_utils.h"
#include "lib/geo/ob_geo_cache.h"
#include "sql/engine/expr/ob_geo_expr_utils.h"
using namespace oceanbase::common;
@ -64,7 +64,7 @@ int ObExprPrivSTCovers::calc_result_type2(ObExprResType &type,
}
template<typename ResType>
int ObExprPrivSTCovers::eval_st_covers_common(ObEvalCtx &ctx,
int ObExprPrivSTCovers::eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx,
ObArenaAllocator &temp_allocator,
ObString wkb1,
ObString wkb2,
@ -81,6 +81,27 @@ int ObExprPrivSTCovers::eval_st_covers_common(ObEvalCtx &ctx,
bool is_geo2_empty = false;
omt::ObSrsCacheGuard srs_guard;
const ObSrsItem *srs = NULL;
bool is_geo1_cached = false;
bool is_geo2_cached = false;
ObExpr *gis_arg1 = expr.args_[0];
ObExpr *gis_arg2 = expr.args_[1];
ObGeoConstParamCache* const_param_cache = ObGeoExprUtils::get_geo_constParam_cache(expr.expr_ctx_id_, &ctx.exec_ctx_);
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
if (OB_NOT_NULL(const_param_cache) && gis_arg1->is_static_const_) {
geo1 = const_param_cache->get_const_param_cache(0);
if (geo1 != NULL) {
srid1 = geo1->get_srid();
is_geo1_cached = true;
}
}
if (OB_NOT_NULL(const_param_cache) && gis_arg2->is_static_const_) {
geo2 = const_param_cache->get_const_param_cache(1);
if (geo2 != NULL) {
srid2 = geo2->get_srid();
is_geo2_cached = true;
}
}
if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) {
LOG_WARN("get type and srid from wkb failed", K(wkb1), K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb2, type2, srid2))) {
@ -89,33 +110,84 @@ int ObExprPrivSTCovers::eval_st_covers_common(ObEvalCtx &ctx,
LOG_WARN("srid not the same", K(srid1), K(srid2));
ret = OB_ERR_GIS_DIFFERENT_SRIDS;
LOG_USER_ERROR(OB_ERR_GIS_DIFFERENT_SRIDS, N_PRIV_ST_COVERS, srid1, srid2);
} else if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get session", K(ret));
} else if (!is_geo1_cached && !is_geo2_cached && OB_FAIL(ObGeoExprUtils::get_srs_item(session->get_effective_tenant_id(), srs_guard, srid1, srs))) {
LOG_WARN("fail to get srs item", K(ret), K(srid1));
} else if (ObGeoTypeUtil::is_geo1_dimension_higher_than_geo2(type2, type1)) {
res.set_bool(false);
} else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs, true, N_PRIV_ST_COVERS))) {
LOG_WARN("fail to get srs item", K(ret), K(wkb1));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_PRIV_ST_COVERS,
ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_CHECK_RING))) {
} else if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, nullptr, N_PRIV_ST_COVERS,
ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_CHECK_RING))) {
LOG_WARN("get first geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_PRIV_ST_COVERS,
ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_CHECK_RING))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_PRIV_ST_COVERS,
ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT | ObGeoBuildFlag::GEO_CHECK_RING))) {
LOG_WARN("get second geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))
|| OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) {
} else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)))
|| (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) {
LOG_WARN("check geo empty failed", K(ret));
} else if (is_geo1_empty || is_geo2_empty) {
res.set_null();
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) {
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) {
LOG_WARN("zoom in geos failed", K(ret));
} else {
ObGeoEvalCtx gis_context(&temp_allocator, srs);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::CoveredBy>::geo_func::eval(gis_context, result))) {
LOG_WARN("eval st coveredBy failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_PRIV_ST_COVERS);
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_ && !is_geo1_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(0, *geo1))) {
LOG_WARN("add geo1 to const cache failed", K(ret));
} else if (gis_arg2->is_static_const_ && !is_geo2_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(1, *geo2))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
}
}
if (OB_FAIL(ret)) {
} else {
res.set_bool(result);
ObGeoEvalCtx gis_context(&temp_allocator);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo2)) || OB_FAIL(gis_context.append_geo_arg(geo1))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else {
ObCachedGeom *cache_geo = NULL;
ObGeometry *geo;
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_) {
cache_geo = const_param_cache->get_cached_geo(0);
if (cache_geo == NULL
&& OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(),
temp_allocator,
const_param_cache->get_const_param_cache(0),
srs,
cache_geo))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
} else {
geo = geo2;
const_param_cache->add_cached_geo(0, cache_geo);
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_NOT_NULL(cache_geo)) {
if (OB_FAIL(cache_geo->cover(*geo, gis_context, result))) {
LOG_WARN("get contains result failed", K(ret));
} else {
res.set_bool(result);
}
} else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_COVERS)) {
bool result = false;
if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_COVERS, result))) {
LOG_WARN("fail to get res.", K(ret));
} else {
res.set_bool(result);
}
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::CoveredBy>::geo_func::eval(gis_context, result))) {
LOG_WARN("eval st coveredBy failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_PRIV_ST_COVERS);
} else {
res.set_bool(result);
}
}
}
}
return ret;
@ -146,7 +218,7 @@ int ObExprPrivSTCovers::eval_st_covers(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2,
gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb2));
} else if (OB_FAIL(ObExprPrivSTCovers::eval_st_covers_common(ctx,
} else if (OB_FAIL(ObExprPrivSTCovers::eval_st_covers_common(expr, ctx,
temp_allocator,
wkb1,
wkb2,

View File

@ -31,7 +31,7 @@ public:
common::ObExprTypeCtx &type_ctx) const override;
static int eval_st_covers(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res);
template<typename ResType>
static int eval_st_covers_common(ObEvalCtx &ctx,
static int eval_st_covers_common(const ObExpr &expr, ObEvalCtx &ctx,
ObArenaAllocator &temp_allocator,
ObString wkb1,
ObString wkb2,
@ -39,6 +39,7 @@ public:
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
const ObRawExpr &raw_expr,
ObExpr &rt_expr) const override;
virtual bool need_rt_ctx() const override { return true; }
private:
DISALLOW_COPY_AND_ASSIGN(ObExprPrivSTCovers);
};

View File

@ -93,7 +93,7 @@ int ObExprPrivSTGeomFromEwkt::eval_st_geomfromewkt(const ObExpr &expr, ObEvalCtx
} else if (srid < 0 || srid > UINT_MAX32) {
ret = OB_OPERATE_OVERFLOW;
LOG_WARN("srid input value out of range", K(ret), K(datum->get_int()));
} else if (0 != srid) {
} else if (ObGeoTypeUtil::need_get_srs(srid)) {
if (OB_FAIL(OTSRS_MGR->get_tenant_srs_guard(srs_guard))) {
LOG_WARN("failed to get srs guard", K(ret));
} else if (OB_FAIL(srs_guard.get_srs_item(srid, srs_item))) {

View File

@ -18,8 +18,7 @@
#include "sql/engine/ob_exec_context.h"
#include "observer/omt/ob_tenant_srs.h"
#include "ob_expr_st_intersects.h"
#include "lib/geo/ob_geo_utils.h"
#include "sql/engine/expr/ob_geo_expr_utils.h"
#include "lib/geo/ob_geo_cache.h"
using namespace oceanbase::common;
using namespace oceanbase::sql;
@ -28,7 +27,6 @@ namespace oceanbase
{
namespace sql
{
ObExprSTIntersects::ObExprSTIntersects(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_ST_INTERSECTS, N_ST_INTERSECTS, 2, VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION)
{
@ -64,20 +62,23 @@ int ObExprSTIntersects::calc_result_type2(ObExprResType &type,
int ObExprSTIntersects::eval_st_intersects(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res)
{
int ret = OB_SUCCESS;
//int64_t start_time = common::ObTimeUtility::current_time();
ObDatum *gis_datum1 = NULL;
ObDatum *gis_datum2 = NULL;
ObExpr *gis_arg1 = expr.args_[0];
ObExpr *gis_arg2 = expr.args_[1];
int num_args = expr.arg_cnt_;
ObObjType input_type1 = gis_arg1->datum_meta_.type_;
ObObjType input_type2 = gis_arg2->datum_meta_.type_;
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator();
bool inter_result = false;
if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) {
LOG_WARN("eval geo args failed", K(ret));
} else if (gis_datum1->is_null() || gis_datum2->is_null()) {
res.set_null();
} else {
ObGeoConstParamCache* const_param_cache = ObGeoExprUtils::get_geo_constParam_cache(expr.expr_ctx_id_, &ctx.exec_ctx_);
bool is_geo1_empty = false;
bool is_geo2_empty = false;
ObGeometry *geo1 = NULL;
@ -90,55 +91,63 @@ int ObExprSTIntersects::eval_st_intersects(const ObExpr &expr, ObEvalCtx &ctx, O
ObString wkb2 = gis_datum2->get_string();
omt::ObSrsCacheGuard srs_guard;
const ObSrsItem *srs = NULL;
bool is_geo1_cached = false;
bool is_geo2_cached = false;
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
bool box_intersects = true;
if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum1,
gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb1));
} else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2,
gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb2));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) {
if (gis_arg1->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo1, srid1, is_geo1_cached, 0);
}
if (gis_arg2->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo2, srid2, is_geo2_cached, 1);
}
if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum1, *gis_arg1, wkb1, type1, srid1))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_INTERSECTS);
}
LOG_WARN("get type and srid from wkb failed", K(wkb1), K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb2, type2, srid2))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum2, *gis_arg2, wkb2, type2, srid2))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_INTERSECTS);
}
LOG_WARN("get type and srid from wkb failed", K(wkb2), K(ret));
} else if (srid1 != srid2) {
LOG_WARN("srid not the same", K(srid1), K(srid2));
ret = OB_ERR_GIS_DIFFERENT_SRIDS;
} else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs, true, N_ST_INTERSECTS))) {
LOG_WARN("fail to get srs item", K(ret), K(wkb1));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) {
} else if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get session", K(ret));
} else if (!is_geo1_cached && !is_geo2_cached && OB_FAIL(ObGeoExprUtils::get_srs_item(session->get_effective_tenant_id(), srs_guard, srid1, srs))) {
LOG_WARN("fail to get srs item", K(ret), K(srid1));
} else if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, nullptr, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get first geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_INTERSECTS, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get second geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))
|| OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) {
} else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)))
|| (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) {
LOG_WARN("check geo empty failed", K(ret));
} else if (is_geo1_empty || is_geo2_empty) {
res.set_null();
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) {
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) {
LOG_WARN("zoom in geos failed", K(ret));
} else {
ObGeoEvalCtx gis_context(&temp_allocator, srs);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Intersects>::geo_func::eval(gis_context, result))) {
LOG_WARN("eval st intersection failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_ST_INTERSECTS);
} else {
if (geo1->type() == ObGeoType::POINT
&& geo2->type() == ObGeoType::POINT
&& result == true
&& OB_FAIL(ObGeoTypeUtil::eval_point_box_intersects(srs, geo1, geo2, result))) {
LOG_WARN("eval box intersection failed", K(ret));
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_ && !is_geo1_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(0, *geo1))) {
LOG_WARN("add geo1 to const cache failed", K(ret));
} else if (gis_arg2->is_static_const_ && !is_geo2_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(1, *geo2))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
}
res.set_bool(result);
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ObGeoExprUtils::get_intersects_res(*geo1, *geo2, gis_arg1, gis_arg2,
const_param_cache, srs,
temp_allocator, inter_result))) {
LOG_WARN("fail to get intersects res", K(ret));
} else {
res.set_bool(inter_result);
}
}
}

View File

@ -15,6 +15,7 @@
#define OCEANBASE_SQL_OB_EXPR_ST_INTERSECTS_H_
#include "sql/engine/expr/ob_expr_operator.h"
#include "sql/engine/expr/ob_geo_expr_utils.h"
namespace oceanbase
{
@ -33,6 +34,7 @@ public:
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
const ObRawExpr &raw_expr,
ObExpr &rt_expr) const override;
virtual bool need_rt_ctx() const override { return true; }
private:
DISALLOW_COPY_AND_ASSIGN(ObExprSTIntersects);
};

View File

@ -150,7 +150,7 @@ int ObExprSTSRID::eval_st_srid_common(const ObExpr &expr, ObEvalCtx &ctx, ObDatu
LOG_WARN("failed to parse geometry from wkb", K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_srid_from_wkb(wkb, srid))) {
LOG_WARN("failed to get srid from wkb", K(ret));
} else if (0 != srid && srs == NULL) {
} else if (ObGeoTypeUtil::need_get_srs(srid) && srs == NULL) {
LOG_USER_WARN(OB_ERR_WARN_SRS_NOT_FOUND, srid);
LOG_WARN("srs not found");
}

View File

@ -19,7 +19,7 @@
#include "sql/engine/ob_exec_context.h"
#include "observer/omt/ob_tenant_srs.h"
#include "ob_expr_st_within.h"
#include "lib/geo/ob_geo_utils.h"
#include "lib/geo/ob_geo_cache.h"
#include "sql/engine/expr/ob_geo_expr_utils.h"
using namespace oceanbase::common;
@ -69,7 +69,6 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &
ObDatum *gis_datum2 = NULL;
ObExpr *gis_arg1 = expr.args_[0];
ObExpr *gis_arg2 = expr.args_[1];
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator();
if (OB_FAIL(gis_arg1->eval(ctx, gis_datum1)) || OB_FAIL(gis_arg2->eval(ctx, gis_datum2))) {
@ -77,6 +76,7 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &
} else if (gis_datum1->is_null() || gis_datum2->is_null()) {
res.set_null();
} else {
ObGeoConstParamCache* const_param_cache = ObGeoExprUtils::get_geo_constParam_cache(expr.expr_ctx_id_, &ctx.exec_ctx_);
bool is_geo1_empty = false;
bool is_geo2_empty = false;
ObGeometry *geo1 = NULL;
@ -89,49 +89,101 @@ int ObExprSTWithin::eval_st_within(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &
ObString wkb2 = gis_datum2->get_string();
omt::ObSrsCacheGuard srs_guard;
const ObSrsItem *srs = NULL;
bool is_geo1_cached = false;
bool is_geo2_cached = false;
ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum1,
gis_arg1->datum_meta_, gis_arg1->obj_meta_.has_lob_header(), wkb1))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb1));
} else if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *gis_datum2,
gis_arg2->datum_meta_, gis_arg2->obj_meta_.has_lob_header(), wkb2))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb2));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb1, type1, srid1))) {
if (gis_arg1->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo1, srid1, is_geo1_cached, 0);
}
if (gis_arg2->is_static_const_) {
ObGeoExprUtils::expr_get_const_param_cache(const_param_cache, geo2, srid2, is_geo2_cached, 1);
}
if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum1, *gis_arg1, wkb1, type1, srid1))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_WITHIN);
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_INTERSECTS);
}
LOG_WARN("get type and srid from wkb failed", K(wkb1), K(ret));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb2, type2, srid2))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::expr_prepare_build_geometry(temp_allocator, *gis_datum2, *gis_arg2, wkb2, type2, srid2))) {
if (ret == OB_ERR_GIS_INVALID_DATA) {
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_WITHIN);
LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, N_ST_INTERSECTS);
}
LOG_WARN("get type and srid from wkb failed", K(wkb2), K(ret));
} else if (srid1 != srid2) {
LOG_WARN("srid not the same", K(srid1), K(srid2));
ret = OB_ERR_GIS_DIFFERENT_SRIDS;
} else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb1, srs, true))) {
LOG_WARN("fail to get srs item", K(ret), K(wkb1));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, srs, N_ST_WITHIN, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) {
} else if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get session", K(ret));
} else if (!is_geo1_cached && !is_geo2_cached && OB_FAIL(ObGeoExprUtils::get_srs_item(session->get_effective_tenant_id(), srs_guard, srid1, srs))) {
LOG_WARN("fail to get srs item", K(ret), K(srid1));
} else if (!is_geo1_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb1, geo1, nullptr, N_ST_WITHIN, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get first geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, srs, N_ST_WITHIN, ObGeoBuildFlag::GEO_ALLOW_3D_DEFAULT))) {
} else if (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, wkb2, geo2, nullptr, N_ST_WITHIN, ObGeoBuildFlag::GEO_ALLOW_3D_CARTESIAN))) {
LOG_WARN("get second geo by wkb failed", K(ret));
} else if (OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty))
|| OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty))) {
} else if ((!is_geo1_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo1, is_geo1_empty)))
|| (!is_geo2_cached && OB_FAIL(ObGeoExprUtils::check_empty(geo2, is_geo2_empty)))) {
LOG_WARN("check geo empty failed", K(ret));
} else if (is_geo1_empty || is_geo2_empty) {
res.set_null();
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2))) {
} else if (OB_FAIL(ObGeoExprUtils::zoom_in_geos_for_relation(*geo1, *geo2, is_geo1_cached, is_geo2_cached))) {
LOG_WARN("zoom in geos failed", K(ret));
} else {
ObGeoEvalCtx gis_context(&temp_allocator, srs);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Within>::gis_func::eval(gis_context, result))) {
LOG_WARN("eval st intersection failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_ST_WITHIN);
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_ && !is_geo1_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(0, *geo1))) {
LOG_WARN("add geo1 to const cache failed", K(ret));
} else if (gis_arg2->is_static_const_ && !is_geo2_cached &&
OB_FAIL(const_param_cache->add_const_param_cache(1, *geo2))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
}
}
if (OB_FAIL(ret)) {
} else {
res.set_bool(result);
ObGeoEvalCtx gis_context(&temp_allocator);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(geo1)) || OB_FAIL(gis_context.append_geo_arg(geo2))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else {
ObCachedGeom *cache_geo = NULL;
ObGeometry *geo;
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg2->is_static_const_) {
cache_geo = const_param_cache->get_cached_geo(1);
if (cache_geo == NULL
&& OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(),
temp_allocator,
const_param_cache->get_const_param_cache(1),
srs,
cache_geo))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
} else {
geo = geo1;
const_param_cache->add_cached_geo(1, cache_geo);
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_NOT_NULL(cache_geo)) {
if (OB_FAIL(cache_geo->contains(*geo, gis_context, result))) {
LOG_WARN("get contains result failed", K(ret));
} else {
res.set_bool(result);
}
} else if (ObGeoTypeUtil::use_point_polygon_short_circuit(*geo1, *geo2, T_FUN_SYS_ST_WITHIN)) {
bool result = false;
if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(geo1, geo2, T_FUN_SYS_ST_WITHIN, result))) {
LOG_WARN("fail to get res.", K(ret));
} else {
res.set_bool(result);
}
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Within>::gis_func::eval(gis_context, result))) {
LOG_WARN("eval st intersection failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_ST_WITHIN);
} else {
res.set_bool(result);
}
}
}
}
}

View File

@ -33,6 +33,8 @@ public:
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
const ObRawExpr &raw_expr,
ObExpr &rt_expr) const override;
virtual bool need_rt_ctx() const override { return true; }
private:
DISALLOW_COPY_AND_ASSIGN(ObExprSTWithin);
};

View File

@ -29,12 +29,13 @@
#include "lib/geo/ob_geo_utils.h"
#include "lib/geo/ob_geo_3d.h"
#include "lib/geo/ob_geo_reverse_coordinate_visitor.h"
#include "lib/geo/ob_geo_cache_polygon.h"
using namespace oceanbase::common;
namespace oceanbase
{
namespace sql
{
int ObGeoExprUtils::get_srs_item(uint64_t tenant_id,
omt::ObSrsCacheGuard &srs_guard,
const uint32_t srid,
@ -42,9 +43,11 @@ int ObGeoExprUtils::get_srs_item(uint64_t tenant_id,
{
int ret = OB_SUCCESS;
if (0 != srid && OB_FAIL(OTSRS_MGR->get_tenant_srs_guard(srs_guard))) {
if (!ObGeoTypeUtil::need_get_srs(srid)) {
// do nothing
} else if (OB_FAIL(OTSRS_MGR->get_tenant_srs_guard(srs_guard))) {
LOG_WARN("fail to get srs guard", K(ret), K(tenant_id));
} else if (0 != srid && OB_FAIL(srs_guard.get_srs_item(srid, srs))) {
} else if (OB_FAIL(srs_guard.get_srs_item(srid, srs))) {
LOG_WARN("fail to get srs", K(ret), K(srid));
}
@ -403,13 +406,15 @@ int ObGeoExprUtils::check_empty(ObGeometry *geo,
if (OB_FAIL(geo3D->check_empty(is_empty))) {
LOG_WARN("fail to check 3D geometry empty", K(ret));
}
} else {
} else if (ObGeoTypeUtil::is_multi_geo_type(geo->type())) {
ObGeoCheckEmptyVisitor check_empty_visitor;
if (OB_FAIL(geo->do_visit(check_empty_visitor))) {
LOG_WARN("check empty geo failed", K(ret));
} else {
is_empty = check_empty_visitor.get_result();
}
} else {
is_empty = geo->is_empty();
}
return ret;
}
@ -745,16 +750,17 @@ void ObGeoExprUtils::geo_func_error_handle(int error_ret, const char* func_name)
}
}
int ObGeoExprUtils::zoom_in_geos_for_relation(ObGeometry &geo1, ObGeometry &geo2)
int ObGeoExprUtils::zoom_in_geos_for_relation(ObGeometry &geo1, ObGeometry &geo2,
bool is_geo1_cached, bool is_geo2_cached)
{
int ret = OB_SUCCESS;
if (geo1.get_zoom_in_value() > 0 || geo2.get_zoom_in_value() > 0) {
uint32_t zoom_in = geo1.get_zoom_in_value();
zoom_in = zoom_in > geo2.get_zoom_in_value() ? zoom_in : geo2.get_zoom_in_value();
ObGeoZoomInVisitor zoom_in_visitor(zoom_in);
if (OB_FAIL(geo1.do_visit(zoom_in_visitor))) {
if (!is_geo1_cached && OB_FAIL(geo1.do_visit(zoom_in_visitor))) {
LOG_WARN("failed to zoom in visit", K(ret), K(zoom_in));
} else if (OB_FAIL(geo2.do_visit(zoom_in_visitor))) {
} else if (!is_geo2_cached && OB_FAIL(geo2.do_visit(zoom_in_visitor))) {
LOG_WARN("failed to zoom in visit", K(ret), K(zoom_in));
}
}
@ -845,7 +851,12 @@ int ObGeoExprUtils::length_unit_conversion(const ObString &unit_str, const ObSrs
MEMCPY(name_str, unit_str.ptr(), unit_str.length());
LOG_USER_ERROR(OB_ERR_GEOMETRY_IN_UNKNOWN_LENGTH_UNIT, N_ST_DISTANCE, name_str);
} else if (OB_FAIL(ob_geo_find_unit(OB_GEO_UNITS, unit_str, factor))) {
LOG_WARN("invalid geo unit name", K(ret), K(unit_str));
if (lib::is_oracle_mode() && ret == OB_ERR_UNIT_NOT_FOUND) {
ret = OB_SUCCESS;
out_num = in_num * (srs->linear_uint());
} else {
LOG_WARN("invalid geo unit name", K(ret), K(unit_str));
}
} else {
out_num = in_num * (srs->linear_uint() / factor);
}
@ -1065,6 +1076,165 @@ int ObGeoExprUtils::make_valid_polygon_inner(
}
return ret;
}
ObGeoConstParamCache* ObGeoExprUtils::get_geo_constParam_cache(const uint64_t& id, ObExecContext *exec_ctx)
{
INIT_SUCC(ret);
ObGeoConstParamCache* cache_ctx = NULL;
uint64_t data_version = 0;
if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_2_1_2 || (GET_MIN_CLUSTER_VERSION() > CLUSTER_VERSION_4_3_0_0 && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_2_0)) {
// geo para cache not available, return null
} else if (ObExpr::INVALID_EXP_CTX_ID != id) {
cache_ctx = static_cast<ObGeoConstParamCache*>(exec_ctx->get_expr_op_ctx(id));
if (OB_ISNULL(cache_ctx)) {
// if geoparamcache not exist, create one
void *cache_ctx_buf = NULL;
if (OB_FAIL(exec_ctx->create_expr_op_ctx(id, sizeof(ObGeoConstParamCache), cache_ctx_buf))) {
LOG_WARN("failed to create expr op ctx", K(ret));
} else if (OB_ISNULL(cache_ctx_buf)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("cache ctx is null", K(ret));
} else {
cache_ctx = new (cache_ctx_buf) ObGeoConstParamCache(&exec_ctx->get_allocator());
}
}
}
return cache_ctx;
}
void ObGeoExprUtils::expr_get_const_param_cache(ObGeoConstParamCache* const_param_cache, ObGeometry *&geo, uint32_t& srid, bool& is_geo_cached, int cache_idx)
{
if (OB_NOT_NULL(const_param_cache)) {
geo = const_param_cache->get_const_param_cache(cache_idx);
if (geo != NULL) {
srid = geo->get_srid();
is_geo_cached = true;
}
}
}
int ObGeoExprUtils::expr_prepare_build_geometry(ObIAllocator &allocator, const ObDatum &datum, const ObExpr &gis_arg, ObString& wkb, ObGeoType& type, uint32_t& srid)
{
INIT_SUCC(ret);
if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, datum,
gis_arg.datum_meta_, gis_arg.obj_meta_.has_lob_header(), wkb))) {
LOG_WARN("fail to get real string data", K(ret), K(wkb));
} else if (OB_FAIL(ObGeoTypeUtil::get_type_srid_from_wkb(wkb, type, srid))) {
LOG_WARN("get type and srid from wkb failed", K(wkb), K(ret));
}
return ret;
}
void ObGeoExprUtils::init_box_by_cache(ObGeogBox *&box_ptr, ObGeogBox& box, ObCachedGeom* cache_geo)
{
if (OB_NOT_NULL(cache_geo)) {
box.xmax = cache_geo->get_x_max();
box.xmin = cache_geo->get_x_min();
box_ptr = &box;
}
}
void ObGeoExprUtils::init_boxes_by_cache(ObGeogBox *&box_ptr1, ObGeogBox& box1,
ObGeogBox *&box_ptr2, ObGeogBox& box2,
ObGeoConstParamCache* const_param_cache,
bool is_geo1_cached, bool is_geo2_cached)
{
if (OB_NOT_NULL(const_param_cache) && (is_geo1_cached || is_geo2_cached)) {
if (is_geo1_cached) {
ObCachedGeom *cache_geo = const_param_cache->get_cached_geo(0);
if (cache_geo != nullptr && cache_geo->is_inited()) {
init_box_by_cache(box_ptr1, box1, cache_geo);
}
}
if (is_geo2_cached) {
ObCachedGeom *cache_geo = const_param_cache->get_cached_geo(1);
if (cache_geo != nullptr && cache_geo->is_inited()) {
init_box_by_cache(box_ptr2, box2, cache_geo);
}
}
}
}
int ObGeoExprUtils::init_box_by_geo(ObGeometry &geo, ObIAllocator &allocator, ObGeogBox *&box_ptr)
{
int ret = OB_SUCCESS;
ObGeoEvalCtx gis_context(&allocator);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(&geo))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Box>::geo_func::eval(gis_context, box_ptr))) {
LOG_WARN("get box failed", K(ret));
}
return ret;
}
int ObGeoExprUtils::check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, ObIAllocator &allocator,
ObGeoConstParamCache* const_param_cache,
bool is_geo1_cached, bool is_geo2_cached, bool& box_intersects)
{
int ret = OB_SUCCESS;
box_intersects = true;
ObGeogBox* box_ptr1 = nullptr;
ObGeogBox* box_ptr2 = nullptr;
ObGeogBox box1;
ObGeogBox box2;
init_boxes_by_cache(box_ptr1, box1, box_ptr2, box2, const_param_cache, is_geo1_cached, is_geo2_cached);
if ((OB_ISNULL(box_ptr1) && OB_FAIL(init_box_by_geo(geo1, allocator, box_ptr1)))
|| (OB_ISNULL(box_ptr2) && OB_FAIL(init_box_by_geo(geo2, allocator, box_ptr2)))) {
LOG_WARN("get failed", K(ret));
} else if (OB_ISNULL(box_ptr1) || OB_ISNULL(box_ptr2)) {
ret = OB_BAD_NULL_ERROR;
LOG_WARN("should not be null", K(ret));
} else {
box_intersects = ObGeoBoxUtil::boxes_overlaps(*box_ptr1, *box_ptr2);
}
return ret;
}
ObGeometry * ObGeoConstParamCache::get_const_param_cache(int arg_idx)
{
ObGeometry * res = nullptr;
INIT_SUCC(ret);
if (arg_idx == 1) {
res = param2_;
} else if (arg_idx == 0) {
res = param1_;
}
return res;
}
ObCachedGeom *ObGeoConstParamCache::get_cached_geo(int arg_idx)
{
ObCachedGeom *res = nullptr;
if (arg_idx == 1) {
res = cached_param2_;
} else if (arg_idx == 0) {
res = cached_param1_;
}
return res;
}
int ObGeoConstParamCache::add_const_param_cache(int arg_idx, const common::ObGeometry &cache)
{
INIT_SUCC(ret);
ObGeometry *geo = nullptr;
ObString data;
if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(*allocator_, cache.type(), cache.crs() == ObGeoCRS::Geographic, true, geo))) {
LOG_WARN("fail to create geo by type", K(ret));
} else if (OB_FAIL(ob_write_string(*allocator_, ObString(cache.length(), cache.val()), data))) {
LOG_WARN("fail to copy geo data", K(ret));
} else {
geo->set_data(data);
geo->set_srid(cache.get_srid());
geo->set_zoom_in_value(cache.get_zoom_in_value());
if (arg_idx == 0) {
param1_ = geo;
} else if (arg_idx == 1) {
param2_ = geo;
}
}
return ret;
}
int ObGeoExprUtils::create_3D_empty_collection(ObIAllocator &allocator, uint32_t srid, bool is_3d, bool is_geog, ObGeometry *&geo)
{
@ -1078,6 +1248,87 @@ int ObGeoExprUtils::create_3D_empty_collection(ObIAllocator &allocator, uint32_t
return ret;
}
void ObGeoConstParamCache::add_cached_geo(int arg_idx, common::ObCachedGeom *cache)
{
if (arg_idx == 0) {
cached_param1_ = cache;
} else if (arg_idx == 1) {
cached_param2_ = cache;
}
}
int ObGeoExprUtils::get_intersects_res(ObGeometry &geo1, ObGeometry &geo2,
ObExpr *gis_arg1, ObExpr *gis_arg2,
ObGeoConstParamCache* const_param_cache,
const ObSrsItem *srs,
ObArenaAllocator& temp_allocator, bool& res)
{
INIT_SUCC(ret);
ObGeoEvalCtx gis_context(&temp_allocator);
bool result = false;
if (OB_FAIL(gis_context.append_geo_arg(&geo1)) || OB_FAIL(gis_context.append_geo_arg(&geo2))) {
LOG_WARN("build gis context failed", K(ret), K(gis_context.get_geo_count()));
} else {
ObCachedGeom *cache_geo = NULL;
ObGeometry *geo;
if (OB_NOT_NULL(const_param_cache)) {
if (gis_arg1->is_static_const_) {
cache_geo = const_param_cache->get_cached_geo(0);
if (cache_geo == NULL
&& OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(),
temp_allocator,
const_param_cache->get_const_param_cache(0),
srs,
cache_geo))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
} else {
geo = &geo2;
const_param_cache->add_cached_geo(0, cache_geo);
}
} else if (gis_arg2->is_static_const_) {
cache_geo = const_param_cache->get_cached_geo(1);
if (cache_geo == NULL
&& OB_FAIL(ObGeoTypeUtil::create_cached_geometry(*const_param_cache->get_allocator(),
temp_allocator,
const_param_cache->get_const_param_cache(1),
srs,
cache_geo))) {
LOG_WARN("add geo2 to const cache failed", K(ret));
} else {
geo = &geo1;
const_param_cache->add_cached_geo(1, cache_geo);
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_NOT_NULL(cache_geo)) {
if (OB_FAIL(cache_geo->intersects(*geo, gis_context, result))) {
LOG_WARN("get intersects result failed", K(ret));
} else {
res = result;
}
} else if (ObGeoTypeUtil::use_point_polygon_short_circuit(geo1, geo2, T_FUN_SYS_ST_INTERSECTS)) {
result = false;
if (OB_FAIL(ObGeoTypeUtil::get_point_polygon_res(&geo1, &geo2, T_FUN_SYS_ST_INTERSECTS, result))) {
LOG_WARN("fail to get res.", K(ret));
}
} else if (OB_FAIL(ObGeoFunc<ObGeoFuncType::Intersects>::geo_func::eval(gis_context, result))) {
LOG_WARN("eval st intersection failed", K(ret));
ObGeoExprUtils::geo_func_error_handle(ret, N_ST_INTERSECTS);
} else if (lib::is_mysql_mode() && geo1.type() == ObGeoType::POINT
&& geo2.type() == ObGeoType::POINT
&& result == true
&& OB_FAIL(ObGeoTypeUtil::eval_point_box_intersects(srs, &geo1, &geo2, result))) {
LOG_WARN("eval box intersection failed", K(ret));
}
if (OB_FAIL(ret)) {
} else {
res = result;
}
}
return ret;
}
} // sql
} // oceanbase

View File

@ -28,6 +28,11 @@
namespace oceanbase
{
namespace common
{
class ObCachedGeom;
}
namespace sql
{
struct ObGeoUnit
@ -62,6 +67,7 @@ const ObGeoUnit OB_GEO_UNITS[] = {
{ "Clarke's foot", 0.3047972654 },
{ "Clarke's link", 0.201166195164 },
{ "Clarke's yard", 0.9143917962 },
{ "cm", 0.01 },
{ "fathom", 1.8288 },
{ "foot", 0.3048 },
{ "German legal metre", 1.0000135965 },
@ -75,6 +81,7 @@ const ObGeoUnit OB_GEO_UNITS[] = {
{ "Indian yard (1962)", 0.9143988 },
{ "Indian yard (1975)", 0.9143985 },
{ "kilometre", 1000 },
{ "km", 1000 },
{ "link", 0.201168 },
{ "metre", 1 },
{ "millimetre", 0.001 },
@ -87,6 +94,7 @@ const ObGeoUnit OB_GEO_UNITS[] = {
{ "yard", 0.9144 }
};
class ObGeoConstParamCache;
enum class ObGeoAxisOrder
{
LONG_LAT = 0,
@ -175,7 +183,8 @@ public:
common::ObString &res_wkb,
uint32_t srs_id = 0);
static void geo_func_error_handle(int ret, const char* func_name);
static int zoom_in_geos_for_relation(common::ObGeometry &geo1, common::ObGeometry &geo2);
static int zoom_in_geos_for_relation(common::ObGeometry &geo1, common::ObGeometry &geo2,
bool is_geo1_cached = false, bool is_geo2_cached = false);
static int pack_geo_res(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res, const ObString &str);
static int reverse_coordinate(ObGeometry *geo, const char *func_name);
@ -189,8 +198,52 @@ public:
ObIAllocator &allocator, const ObGeometry &poly, ObGeometry *&polygons_union);
static int make_valid_polygon(ObGeometry *poly, ObIAllocator &allocator, ObGeometry *&valid_poly);
static int create_3D_empty_collection(ObIAllocator &allocator, uint32_t srid, bool is_3d, bool is_geog, ObGeometry *&geo);
static ObGeoConstParamCache* get_geo_constParam_cache(const uint64_t& id, ObExecContext *exec_ctx);
static void expr_get_const_param_cache(ObGeoConstParamCache* const_param_cache, ObGeometry *&geo, uint32_t& srid, bool& is_geo_cached, int cache_idx);
static int expr_prepare_build_geometry(ObIAllocator &allocator, const ObDatum &datum, const ObExpr &gis_arg, ObString& wkb, ObGeoType& type, uint32_t& srid);
static int check_box_intersects(ObGeometry &geo1, ObGeometry &geo2, ObIAllocator &allocator,
ObGeoConstParamCache* const_param_cache,
bool is_geo1_cached, bool is_geo2_cached, bool& box_intersects);
static int get_intersects_res(ObGeometry &geo1, ObGeometry &geo2,
ObExpr *gis_arg1, ObExpr *gis_arg2,
ObGeoConstParamCache* const_param_cache,
const ObSrsItem *srs,
ObArenaAllocator& temp_allocator, bool& res);
private:
static int ob_geo_find_unit(const ObGeoUnit *units, const ObString &name, double &factor);
static int init_box_by_geo(ObGeometry &geo, ObIAllocator &allocator, ObGeogBox *&box_ptr);
static void init_boxes_by_cache(ObGeogBox *&box_ptr1, ObGeogBox& box1,
ObGeogBox *&box_ptr2, ObGeogBox& box2,
ObGeoConstParamCache* const_param_cache,
bool is_geo1_cached, bool is_geo2_cached);
static void init_box_by_cache(ObGeogBox *&box_ptr, ObGeogBox& box, ObCachedGeom* cache);
};
class ObGeoConstParamCache : public ObExprOperatorCtx {
public:
ObGeoConstParamCache(common::ObIAllocator *allocator) :
ObExprOperatorCtx(),
allocator_(allocator),
param1_(nullptr),
cached_param1_(nullptr),
param2_(nullptr),
cached_param2_(nullptr) {}
~ObGeoConstParamCache() {};
ObGeometry *get_const_param_cache(int arg_idx);
ObCachedGeom *get_cached_geo(int arg_idx);
int add_const_param_cache(int arg_idx, const common::ObGeometry &cache);
void add_cached_geo(int arg_idx, common::ObCachedGeom *cache);
void set_allocator(common::ObIAllocator *allocator);
common::ObIAllocator* get_allocator() { return allocator_; }
private:
common::ObIAllocator *allocator_;
common::ObGeometry * param1_; // ObGeometry * param1_ 与 ObCachedGeom *cached_param1_的区别
common::ObCachedGeom *cached_param1_;
common::ObGeometry * param2_;
common::ObCachedGeom *cached_param2_;
};
} // sql

View File

@ -3138,6 +3138,7 @@ int ObTableScanOp::inner_get_next_row()
int ObTableScanOp::inner_get_next_spatial_index_row()
{
int ret = OB_SUCCESS;
bool need_ignore_null = false;
if (OB_ISNULL(spat_index_.spat_rows_)) {
if (OB_FAIL(init_spatial_index_rows())) {
LOG_WARN("init spatial row store failed", K(ret));
@ -3155,10 +3156,11 @@ int ObTableScanOp::inner_get_next_spatial_index_row()
const ObExprPtrIArray &exprs = MY_SPEC.output_;
ObExpr *expr = exprs.at(3);
ObDatum *in_datum = NULL;
ObString geo_wkb;
if (OB_FAIL(expr->eval(eval_ctx_, in_datum))) {
LOG_WARN("expression evaluate failed", K(ret));
} else {
ObString geo_wkb = in_datum->get_string();
} else if (OB_FALSE_IT(geo_wkb = in_datum->get_string())) {
} else if (geo_wkb.length() > 0) {
uint32_t srid = UINT32_MAX;
omt::ObSrsCacheGuard srs_guard;
const ObSrsItem *srs_item = NULL;
@ -3211,10 +3213,12 @@ int ObTableScanOp::inner_get_next_spatial_index_row()
}
}
}
} else {
need_ignore_null = true;
}
}
}
if (OB_SUCC(ret)) {
if (OB_SUCC(ret) && !need_ignore_null) {
ObNewRow &row = (*(spat_index_.spat_rows_))[spat_index_.spat_row_index_++];
ObObj &cellid= row.get_cell(0);
ObObj &mbr = row.get_cell(1);

View File

@ -881,7 +881,10 @@ int ObJoinOrder::compute_base_table_parallel_and_server_info(const OpParallelRul
if (OpParallelRule::OP_TABLE_DOP == op_parallel_rule) {
final_parallel = index_schema->get_dop();
}
if (index_schema->is_spatial_index() || final_parallel < ObGlobalHint::DEFAULT_PARALLEL) {
if (index_schema->is_spatial_index() && index_schema->get_partition_num() < final_parallel) {
final_parallel = index_schema->get_partition_num();
}
if (final_parallel < ObGlobalHint::DEFAULT_PARALLEL) {
final_parallel = ObGlobalHint::DEFAULT_PARALLEL;
}
path->op_parallel_rule_ = op_parallel_rule;

View File

@ -2105,7 +2105,8 @@ int ObLogTableScan::allocate_granule_post(AllocGIContext &ctx)
ctx.hash_part_ = table_schema->is_hash_part() || table_schema->is_hash_subpart()
|| table_schema->is_key_subpart() || table_schema->is_key_subpart();
//Before GI is adapted to the real agent table, block gi cannot be assigned to it
if (share::is_oracle_mapping_real_virtual_table(table_schema->get_table_id())) {
if (share::is_oracle_mapping_real_virtual_table(table_schema->get_table_id())
|| table_schema->is_spatial_index()) {
ctx.set_force_partition();
}
} else { /*do nothing*/ }

View File

@ -806,3 +806,22 @@ bool nodename_equal(const ParseNode *node, const char *pattern, int64_t pat_len)
}
return result;
}
extern bool nodename_is_sdo_geometry_type(const ParseNode *node)
{
bool result = true;
if (NULL == node || NULL == node->str_value_) {
result = false;
} else if (nodename_equal(node, "SDO_GEOMETRY", strlen("SDO_GEOMETRY"))) {
result = true;
} else if (nodename_equal(node, "SDO_POINT_TYPE", strlen("SDO_POINT_TYPE"))) {
result = true;
} else if (nodename_equal(node, "SDO_ORDINATE_ARRAY", strlen("SDO_ORDINATE_ARRAY"))) {
result = true;
} else if (nodename_equal(node, "SDO_ELEM_INFO_ARRAY", strlen("SDO_ELEM_INFO_ARRAY"))) {
result = true;
} else {
result = false;
}
return result;
}

View File

@ -419,6 +419,7 @@ extern int64_t get_question_mark_by_defined_name(ObQuestionMarkCtx *ctx, const c
// @param [in] pat_len length of pattern
extern bool nodename_equal(const ParseNode *node, const char *pattern, int64_t pat_len);
extern bool nodename_is_sdo_geometry_type(const ParseNode *node);
#define OB_NODE_CAST_TYPE_IDX 0
#define OB_NODE_CAST_COLL_IDX 1
#define OB_NODE_CAST_N_PREC_IDX 2

View File

@ -4180,7 +4180,7 @@ int ObDDLResolver::resolve_srid_node(share::schema::ObColumnSchemaV2 &column,
ret = OB_INVALID_ARGUMENT;
SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(srid_node.type_));
} else {
if (is_oracle_mode()) {
if (is_oracle_mode() && tenant_data_version < DATA_VERSION_4_3_2_0) {
ret = OB_NOT_SUPPORTED;
SQL_RESV_LOG(WARN, "srid column attribute is not supported in oracle mode",
K(ret), K(srid_node.type_));
@ -6925,10 +6925,15 @@ int ObDDLResolver::resolve_spatial_index_constraint(
int ret = OB_SUCCESS;
const ObColumnSchemaV2 *column_schema = NULL;
bool is_oracle_mode = false;
uint64_t tenant_data_version = 0;
uint64_t tenant_id = 0;
if (OB_ISNULL(session_info_) || OB_ISNULL(allocator_)) {
if (OB_ISNULL(session_info_) || OB_ISNULL(allocator_) || OB_ISNULL(session_info_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(session_info_), K(allocator_));
} else if (OB_FALSE_IT(tenant_id = session_info_->get_effective_tenant_id())) {
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
LOG_WARN("get tenant data version failed", K(ret));
} else if (OB_FAIL(table_schema.check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("check oracle compat mode failed", K(ret));
} else if (is_func_index && is_mysql_mode()) {
@ -6977,14 +6982,6 @@ int ObDDLResolver::resolve_spatial_index_constraint(
}
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(column_schema) && OB_FALSE_IT(column_schema = table_schema.get_column_schema(column_name))) {
} else if (is_oracle_mode) {
if (OB_NOT_NULL(column_schema) && ob_is_geometry_tc(column_schema->get_data_type())) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("oracle spatial index not supported", K(ret));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "oracle spatial index");
} else {
// do nothing
}
} else if (OB_ISNULL(column_schema)) {
if (index_keyname_value != static_cast<int64_t>(INDEX_KEYNAME::SPATIAL_KEY)) {
// do nothing
@ -7031,7 +7028,9 @@ int ObDDLResolver::resolve_spatial_index_constraint(
bool is_geo_column = ob_is_geometry_tc(column_schema.get_data_type());
uint64_t tenant_data_version = 0;
if (is_oracle_mode) {
if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
LOG_WARN("get tenant data version failed", K(ret));
} else if (is_oracle_mode && tenant_data_version < DATA_VERSION_4_3_2_0) {
if (is_geo_column) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("oracle spatial index not supported", K(ret), K(is_geo_column), K(is_spatial_index));
@ -7039,13 +7038,11 @@ int ObDDLResolver::resolve_spatial_index_constraint(
} else {
// do nothing
}
} else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, tenant_data_version))) {
LOG_WARN("get tenant data version failed", K(ret));
} else if ((is_geo_column || is_spatial_index) && tenant_data_version < DATA_VERSION_4_1_0_0) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("tenant version is less than 4.1, spatial index not supported", K(ret), K(is_geo_column), K(is_spatial_index));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant version is less than 4.1, spatial index");
} else { // mysql mode
} else {
if (is_spatial_index) { // has 'SPATIAL' keyword
if (is_geo_column) {
index_keyname_ = SPATIAL_KEY;
@ -7054,7 +7051,7 @@ int ObDDLResolver::resolve_spatial_index_constraint(
LOG_USER_ERROR(OB_ERR_SPATIAL_MUST_HAVE_GEOM_COL);
LOG_WARN("spatial index can only be built on spatial column", K(ret), K(column_schema));
}
} else if (is_default_index) { // there are no keyword
} else if (is_default_index && lib::is_mysql_mode()) { // there are no keyword, not allowed in oracle mode
if (is_geo_column) {
index_keyname_ = SPATIAL_KEY;
} else {
@ -7062,10 +7059,17 @@ int ObDDLResolver::resolve_spatial_index_constraint(
}
} else { // other index type (UNIQUE_KEY, FULLTEXT)
if (is_geo_column) {
ret = OB_ERR_SPATIAL_UNIQUE_INDEX;
LOG_USER_ERROR(OB_ERR_SPATIAL_UNIQUE_INDEX);
LOG_WARN("spatial column can only be indexed spatial index, can't build other index.",
K(ret), K(column_schema));
if (lib::is_mysql_mode()) {
ret = OB_ERR_SPATIAL_UNIQUE_INDEX;
LOG_USER_ERROR(OB_ERR_SPATIAL_UNIQUE_INDEX);
LOG_WARN("spatial column can only be indexed spatial index, can't build other index.",
K(ret), K(column_schema));
} else {
ret = OB_ERR_XML_INDEX;
LOG_USER_ERROR(OB_ERR_XML_INDEX, column_schema.get_column_name_str().length(), column_schema.get_column_name_str().ptr());
LOG_WARN("cannot create index on expression with datatype ADT.",
K(ret), K(column_schema));
}
} else {
// do nothing
}
@ -7082,7 +7086,7 @@ int ObDDLResolver::resolve_spatial_index_constraint(
} else if (is_explicit_order) {
ret = OB_ERR_INDEX_ORDER_WRONG_USAGE;
LOG_USER_ERROR(OB_ERR_INDEX_ORDER_WRONG_USAGE);
} else if (column_schema.is_nullable()) {
} else if (lib::is_mysql_mode() && column_schema.is_nullable()) {
ret = OB_ERR_SPATIAL_CANT_HAVE_NULL;
LOG_USER_ERROR(OB_ERR_SPATIAL_CANT_HAVE_NULL);
LOG_WARN("column of a spatial index must be NOT NULL.", K(ret), K(column_schema));

View File

@ -603,6 +603,32 @@ bool ObRawExpr::is_spatial_expr() const
return IS_SPATIAL_OP(expr->get_expr_type());
}
bool ObRawExpr::is_oracle_spatial_expr() const
{
bool ret_bool = false;
if (lib::is_oracle_mode() && get_expr_type() == T_OP_EQ) {
const ObRawExpr *l_expr = get_param_expr(0);
const ObRawExpr *r_expr = get_param_expr(1);
if (OB_NOT_NULL(l_expr) && OB_NOT_NULL(r_expr)) {
const ObRawExpr *l_inner = ObRawExprUtils::skip_inner_added_expr(l_expr);
const ObRawExpr *r_inner = ObRawExprUtils::skip_inner_added_expr(r_expr);
const ObRawExpr *const_expr = nullptr;
const ObRawExpr *geo_expr = nullptr;
if (l_inner->get_expr_type() == T_FUN_SYS_SDO_RELATE && r_inner->is_const_expr()) {
geo_expr = l_inner;
const_expr = r_inner;
} else if (r_inner->get_expr_type() == T_FUN_SYS_SDO_RELATE && l_inner->is_const_expr()) {
geo_expr = r_inner;
const_expr = l_inner;
}
if (OB_NOT_NULL(const_expr) && OB_NOT_NULL(geo_expr)) {
ret_bool = true;
}
} // do nothing
}
return ret_bool;
}
bool ObRawExpr::is_json_domain_expr() const
{
const ObRawExpr *expr = ObRawExprUtils::skip_inner_added_expr(this);

View File

@ -1958,6 +1958,7 @@ public:
bool is_deterministic() const { return is_deterministic_; }
bool is_bool_expr() const;
bool is_spatial_expr() const;
bool is_oracle_spatial_expr() const;
bool is_json_domain_expr() const;
ObRawExpr* get_json_domain_param_expr();
bool is_geo_expr() const;

View File

@ -3639,6 +3639,46 @@ int ObRawExprResolverImpl::process_operator_node(const ParseNode *node, ObRawExp
ctx_.op_exprs_->push_back(b_expr);
LOG_DEBUG("ctx_.op_exprs_ push", K(b_expr->get_param_count()), K(*b_expr));
}
} else if (lib::is_oracle_mode()
&& ((T_FUN_SYS_SDO_RELATE == sub_expr1->get_expr_type() && sub_expr2->is_const_expr())
|| (T_FUN_SYS_SDO_RELATE == sub_expr2->get_expr_type() && sub_expr1->is_const_expr()))) {
ParseNode* const_node = sub_expr1->is_const_expr() ? node->children_[0] : node->children_[1];
if (OB_ISNULL(const_node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), KP(const_node));
} else if (T_QUESTIONMARK == const_node->type_) {
if (OB_ISNULL(ctx_.param_list_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("param_list_ is null", K(ret), K(ctx_.param_list_));
} else if (ctx_.param_list_->count() == 0) {
//prepare phase of ps protocol, do nothing
} else if (OB_UNLIKELY(const_node->value_ < 0 || const_node->value_ >= ctx_.param_list_->count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("index is out of range", K(const_node->value_), K(ctx_.param_list_->count()));
} else {
const int64_t idx = const_node->value_;
ObPCConstParamInfo const_param_info;
ObObj val;
ObString str_value;
char *str_buf = nullptr;
if (OB_ISNULL(str_buf = static_cast<char*>(ctx_.expr_factory_.get_allocator().alloc(strlen("TRUE"))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc failed", K(ret));
} else if (OB_FALSE_IT(str_value.assign_buffer(str_buf, strlen("TRUE")))) {
} else if (OB_UNLIKELY(strlen("TRUE") != str_value.write("TRUE", strlen("TRUE")))) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("write amp char failed", K(ret));
} else {
val.set_string(ObVarcharType, str_value);
if (OB_FAIL(const_param_info.const_idx_.push_back(idx))
|| OB_FAIL(const_param_info.const_params_.push_back(val))) {
LOG_WARN("failed to push back param idx and value", K(ret));
} else if (OB_FAIL(ctx_.query_ctx_->all_plan_const_param_constraints_.push_back(const_param_info))) {
LOG_WARN("failed to push back const param info", K(ret));
}
}
}
}
}
return ret;
}

View File

@ -347,7 +347,7 @@ public:
inline bool is_like_key() const { return T_LIKE_KEY == key_type_ && like_keypart_ != NULL; }
inline bool is_in_key() const {return T_IN_KEY == key_type_ && in_keypart_ != NULL && in_keypart_->in_type_ == T_IN_KEY_PART; }
inline bool is_not_in_key() const {return T_IN_KEY == key_type_ && in_keypart_ != NULL && in_keypart_->in_type_ == T_NOT_IN_KEY_PART; }
inline bool is_geo_key() const { return T_DOMAIN_KEY == key_type_ && domain_keypart_ != NULL && (domain_keypart_->domain_op_ >= ObDomainOpType::T_GEO_COVERS && domain_keypart_->domain_op_ <= ObDomainOpType::T_GEO_COVEREDBY); }
inline bool is_geo_key() const { return T_DOMAIN_KEY == key_type_ && domain_keypart_ != NULL && (domain_keypart_->domain_op_ >= ObDomainOpType::T_GEO_COVERS && domain_keypart_->domain_op_ <= ObDomainOpType::T_GEO_RELATE); }
inline bool is_domain_key() const { return T_DOMAIN_KEY == key_type_ && domain_keypart_ != NULL; }
int create_normal_key();

View File

@ -429,7 +429,7 @@ int ObQueryRange::check_cur_expr(const ObRawExpr *cur_expr, ObIArray<int64_t> &o
LOG_WARN("failed to check and or", K(ret));
}
}
} else if (cur_expr->is_domain_expr()) {
} else if (cur_expr->is_domain_expr() || cur_expr->is_oracle_spatial_expr()) {
is_valid_expr = true;
} else if (IS_BASIC_CMP_OP(cmp_type) || T_OP_NE == cmp_type ||
T_OP_IS == cmp_type || T_OP_IN == cmp_type || T_OP_NOT_IN == cmp_type) {
@ -2227,7 +2227,27 @@ int ObQueryRange::get_basic_query_range(const ObRawExpr *l_expr,
} else if (l_expr->has_flag(IS_COLUMN) && r_expr->has_flag(IS_COLUMN)) {
GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part);
} else {
GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part);
const ObRawExpr *l_inner = ObRawExprUtils::skip_inner_added_expr(l_expr);
const ObRawExpr *r_inner = ObRawExprUtils::skip_inner_added_expr(r_expr);
if (T_OP_EQ == cmp_type
&& ((l_inner->get_expr_type() == T_FUN_SYS_SDO_RELATE && r_inner->is_const_expr())
|| (l_inner->is_const_expr() && r_inner->get_expr_type() == T_FUN_SYS_SDO_RELATE))) {
bool need_extract = false;
const ObRawExpr *const_expr = r_inner->is_const_expr() ? r_inner : l_inner;
const ObRawExpr *geo_expr = r_inner->is_const_expr() ? l_inner : r_inner;
if (OB_FAIL(can_be_extract_orcl_spatial_range(const_expr, need_extract))) {
LOG_WARN("fail to check can extract orcl spatial range.", K(ret));
} else if (need_extract) {
const ObOpRawExpr *b_expr = static_cast<const ObOpRawExpr *>(geo_expr);
if (OB_FAIL(pre_extract_geo_op(b_expr, out_key_part, dtc_params))) {
LOG_WARN("fail to pre extract domain op.", K(ret));
}
} else {
GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part);
}
} else {
GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part);
}
}
} else if (OB_FAIL(get_row_key_part(l_expr, r_expr, cmp_type, result_type,
out_key_part, dtc_params))) {// 2. row compare
@ -3738,9 +3758,9 @@ int ObQueryRange::pre_extract_geo_op(const ObOpRawExpr *geo_expr,
contain_geo_filters_ = true;
out_key_part->id_ = key_part_id;
out_key_part->pos_ = *key_part_pos;
if (op_type == ObDomainOpType::T_GEO_DWITHIN) {
if (op_type == ObDomainOpType::T_GEO_DWITHIN || op_type == ObDomainOpType::T_GEO_RELATE) {
if (OB_FAIL(get_extra_param(expr, extra_item))) {
LOG_WARN("failed to get dwithin item", K(ret));
LOG_WARN("failed to get extra item", K(ret));
}
}
@ -3762,7 +3782,7 @@ int ObQueryRange::pre_extract_geo_op(const ObOpRawExpr *geo_expr,
} else if (!is_valid) {
GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part);
} else {
if (!const_item->is_immutable_const_expr()) {
if (!const_item->is_immutable_const_expr() || (OB_NOT_NULL(extra_item) && !extra_item->is_immutable_const_expr())) {
ObObj val;
out_key_part->domain_keypart_->domain_op_ = op_type;
if (OB_FAIL(get_final_expr_val(const_item, out_key_part->domain_keypart_->const_param_))) {
@ -3826,7 +3846,7 @@ int ObQueryRange::reset_domain_op_by_param_pos(const bool is_left_column, ObDoma
bool ObQueryRange::need_extra_param(ObDomainOpType& op_type)
{
bool ret_bool = false;
if (op_type == ObDomainOpType::T_GEO_DWITHIN) {
if (op_type == ObDomainOpType::T_GEO_DWITHIN || op_type == ObDomainOpType::T_GEO_RELATE) {
ret_bool = true;
}
return ret_bool;
@ -3844,6 +3864,37 @@ bool ObQueryRange::is_single_op(const ObRawExpr *expr_root)
return ret_bool;
}
/*
oracle spatial expr return varchar, the spatial index is utilized if and only if the const_expr is 'TRUE'.
if the const is parameterized, it is first assumed to be 'TRUE', with special handling during resolution.
*/
int ObQueryRange::can_be_extract_orcl_spatial_range(const ObRawExpr *const_expr, bool& can_extract)
{
INIT_SUCC(ret);
can_extract = false;
if (OB_ISNULL(const_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Wrong input params to get basic query range",
K(ret), KP(const_expr));
} else {
if (const_expr->is_immutable_const_expr()) {
ObObj const_val;
bool is_valid = true;
if (OB_FAIL(get_calculable_expr_val(const_expr, const_val, is_valid))) {
LOG_WARN("failed to get calculable expr val", K(ret));
} else if (!is_valid || !ob_is_string_type(const_val.get_type())) {
can_extract = false;
} else {
ObString str = const_val.get_string();
can_extract = (str.compare("TRUE") == 0);
}
} else {
can_extract = true;
}
}
return ret;
}
// op that be rewritten as normal key-part, need to check if can cast
bool ObQueryRange::can_domain_be_extract_range(const ObDomainOpType &op_type, const ObExprResType &col_type,
const ObExprCalcType &res_type, common::ObObjType data_type,
@ -6047,7 +6098,8 @@ int ObQueryRange::union_single_equal_cond(ObExecContext *exec_ctx,
// do two path and operation
int ObQueryRange::or_single_head_graphs(ObKeyPartList &or_list,
ObExecContext *exec_ctx,
const ObDataTypeCastParams &dtc_params)
const ObDataTypeCastParams &dtc_params,
const bool& need_geo_rebuild)
{
int ret = OB_SUCCESS;
bool is_stack_overflow = false;
@ -6221,6 +6273,11 @@ int ObQueryRange::or_single_head_graphs(ObKeyPartList &or_list,
cur1 = cur1_next;
}
}
} else if (need_geo_rebuild) {
// if need geo rebuild, the normal keypart must have or_next_
// can't use key_node_is_equal
// if it's single geo keypart, already make sure there is no duplicate keypart
// if not single geo keypart, will do or_range_graph again
} else if (cur1->key_node_is_equal(cur2)) {
if (OB_FAIL(union_single_equal_cond(exec_ctx, dtc_params, cur1, cur2))) {
LOG_WARN("union single equal cond failed", K(ret));
@ -6642,7 +6699,7 @@ int ObQueryRange::or_range_graph(ObKeyPartList &ranges,
} else {
out_key_part = find_false;
}
} else if (OB_FAIL(SMART_CALL(or_single_head_graphs(or_list, exec_ctx, dtc_params)))) {
} else if (OB_FAIL(SMART_CALL(or_single_head_graphs(or_list, exec_ctx, dtc_params, need_geo_rebuild)))) {
LOG_WARN("Or single head graphs failed", K(ret));
} else {
bool has_geo_key = false;
@ -6655,8 +6712,12 @@ int ObQueryRange::or_range_graph(ObKeyPartList &ranges,
// if contain ObGeoKeyPart, need do or_range_graph for deduplication with different spatial filters
if (!need_geo_rebuild && OB_FAIL(link_or_graphs(or_list, out_key_part))) {
LOG_WARN("Or single head graphs failed", K(ret));
} else if (need_geo_rebuild && OB_FAIL(or_range_graph(or_list, exec_ctx, out_key_part, dtc_params))) {
LOG_WARN("Or single head graphs failed", K(ret));
} else if (need_geo_rebuild) {
if (or_list.get_size() == 1) {
out_key_part = or_list.get_first();
} else if (OB_FAIL(or_range_graph(or_list, exec_ctx, out_key_part, dtc_params))) {
LOG_WARN("Or single head graphs failed", K(ret));
}
} else {
// do nothing
}
@ -9634,6 +9695,10 @@ common::ObDomainOpType ObQueryRange::get_geo_relation(ObItemType type) const
rel_type = common::ObDomainOpType::T_GEO_COVEREDBY;
break;
}
case T_FUN_SYS_SDO_RELATE : {
rel_type = common::ObDomainOpType::T_GEO_RELATE;
break;
}
default:
break;
}
@ -9681,6 +9746,10 @@ common::ObDomainOpType ObQueryRange::get_domain_op_type(ObItemType type) const
rel_type = common::ObDomainOpType::T_GEO_INTERSECTS;
break;
}
case T_FUN_SYS_SDO_RELATE : {
rel_type = common::ObDomainOpType::T_GEO_RELATE;
break;
}
default:
break;
}
@ -9695,7 +9764,7 @@ int ObQueryRange::get_geo_intersects_keypart(uint32_t input_srid,
INIT_SUCC(ret);
common::ObArenaAllocator tmp_alloc(lib::ObLabel("GisIndex"));
ObS2Cellids cells;
ObS2Cellids cells_with_ancestors;
ObS2Cellids ancestors;
ObSpatialMBR mbr_filter(op_type);
ObGeoType geo_type = ObGeoType::GEOMETRY;
const ObSrsItem *srs_item = NULL;
@ -9739,7 +9808,7 @@ int ObQueryRange::get_geo_intersects_keypart(uint32_t input_srid,
}
}
if (s2object == NULL && OB_SUCC(ret)) {
s2object = OB_NEWx(ObS2Adapter, (&tmp_alloc), (&tmp_alloc), (input_srid != 0 ? srs_item->is_geographical_srs() : false));
s2object = OB_NEWx(ObS2Adapter, (&tmp_alloc), (&tmp_alloc), (input_srid != 0 ? srs_item->is_geographical_srs() : false), true);
if (OB_ISNULL(s2object)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc s2 object", K(ret));
@ -9753,10 +9822,8 @@ int ObQueryRange::get_geo_intersects_keypart(uint32_t input_srid,
LOG_WARN("fail to get geo type by wkb", K(ret));
} else if (OB_FAIL(s2object->init((buffer_geo.empty() ? wkb_str : buffer_geo), srs_bound))) {
LOG_WARN("Init s2object failed", K(ret));
} else if (OB_FAIL(s2object->get_cellids(cells, false))) {
} else if (OB_FAIL(s2object->get_cellids_and_unrepeated_ancestors(cells, ancestors))) {
LOG_WARN("Get cellids from s2object failed", K(ret));
} else if (OB_FAIL(s2object->get_cellids(cells_with_ancestors, true))) {
LOG_WARN("Get cellids with ancestors from s2object failed", K(ret));
} else if (OB_FAIL(s2object->get_mbr(mbr_filter))) {
LOG_WARN("Get mbr from s2object failed", K(ret));
} else if (OB_FAIL(mbr_filters_.push_back(mbr_filter))) {
@ -9776,14 +9843,16 @@ int ObQueryRange::get_geo_intersects_keypart(uint32_t input_srid,
query_range_ctx_->cur_expr_is_precise_ = false;
}
ObKeyPart *last = out_key_part;
bool replace_out_keypart = false;
// build keypart from cells_with_ancestors
for (uint64_t i = 0; OB_SUCC(ret) && i < cells_with_ancestors.size(); i++) {
for (uint64_t i = 0; OB_SUCC(ret) && i < ancestors.size(); i++) {
ObObj val;
val.set_uint64(cells_with_ancestors[i]);
val.set_uint64(ancestors[i]);
if (i == 0) {
if (OB_FAIL(get_domain_equal_keypart(val, val, *out_key_part))) {
LOG_WARN("get normal cmp keypart failed", K(ret));
}
replace_out_keypart = true;
} else {
ObKeyPart *tmp = NULL;
if (OB_ISNULL((tmp = create_new_key_part()))) {
@ -9809,21 +9878,55 @@ int ObQueryRange::get_geo_intersects_keypart(uint32_t input_srid,
uint64_t start_id = 0;
uint64_t end_id = 0;
ObS2Adapter::get_child_of_cellid(cellid, start_id, end_id);
ObKeyPart *tmp = NULL;
if (OB_ISNULL((tmp = create_new_key_part()))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else {
tmp->id_ = out_key_part->id_;
tmp->pos_ = out_key_part->pos_;
ObObj val_start, val_end;
val_start.set_uint64(start_id);
val_end.set_uint64(end_id);
if (OB_FAIL(get_domain_equal_keypart(val_start, val_end, *tmp))) {
ObObj val_start, val_end;
val_start.set_uint64(start_id);
val_end.set_uint64(end_id);
if (!replace_out_keypart) { // if ancestor is empty, replace first keypart
if (OB_FAIL(get_domain_equal_keypart(val_start, val_end, *out_key_part))) {
LOG_WARN("get normal cmp keypart failed", K(ret));
}
replace_out_keypart = true;
} else {
ObKeyPart *tmp = NULL;
if (OB_ISNULL((tmp = create_new_key_part()))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else {
last->or_next_ = tmp;
last = tmp;
tmp->id_ = out_key_part->id_;
tmp->pos_ = out_key_part->pos_;
if (OB_FAIL(get_domain_equal_keypart(val_start, val_end, *tmp))) {
LOG_WARN("get normal cmp keypart failed", K(ret));
} else {
last->or_next_ = tmp;
last = tmp;
}
}
}
}
} else {
// build keypart to index child_of_cellid
for (uint64_t i = 0; OB_SUCC(ret) && i < cells.size(); i++) {
ObObj val;
val.set_uint64(cells[i]);
if (!replace_out_keypart) { // if ancestor is empty, replace first keypart
if (OB_FAIL(get_domain_equal_keypart(val, val, *out_key_part))) {
LOG_WARN("get normal cmp keypart failed", K(ret));
}
replace_out_keypart = true;
} else {
ObKeyPart *tmp = NULL;
if (OB_ISNULL((tmp = create_new_key_part()))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else {
tmp->id_ = out_key_part->id_;
tmp->pos_ = out_key_part->pos_;
if (OB_FAIL(get_domain_equal_keypart(val, val, *tmp))) {
LOG_WARN("get normal cmp keypart failed", K(ret));
} else {
last->or_next_ = tmp;
last = tmp;
}
}
}
}
@ -9982,33 +10085,6 @@ int ObQueryRange::get_geo_coveredby_keypart(uint32_t input_srid,
query_range_ctx_ = new(ptr) ObQueryRangeCtx(exec_ctx, NULL, NULL);
}
ObS2Cellids cells_cover_geo;
for (uint64_t i = 0; OB_SUCC(ret) && i < cells_cover_geo.size(); i++) {
int hash_ret = cellid_set.exist_refactored(cells_cover_geo[i]);
if (OB_HASH_NOT_EXIST == hash_ret) {
ObKeyPart *tmp = NULL;
if (OB_FAIL(cellid_set.set_refactored(cells_cover_geo[i]))) {
LOG_WARN("failed to add cellid into set", K(ret));
} else if (OB_ISNULL((tmp = create_new_key_part()))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else {
ObObj val;
val.set_uint64(cells_cover_geo[i]);
tmp->id_ = out_key_part->id_;
tmp->pos_ = out_key_part->pos_;
if (OB_FAIL(get_domain_equal_keypart(val, val, *tmp))) {
LOG_WARN("get normal cmp keypart failed", K(ret));
} else {
last->or_next_ = tmp;
last = tmp;
}
}
} else if (OB_HASH_EXIST != hash_ret) {
ret = hash_ret;
LOG_WARN("fail to check if key exist", K(ret), K(cells_cover_geo[i]), K(i));
}
}
// copy temp_result to out_key_part
if (OB_FAIL(ret)) {
} else if (OB_FAIL(out_key_part->create_normal_key())) {
@ -10029,7 +10105,8 @@ int ObQueryRange::get_geo_coveredby_keypart(uint32_t input_srid,
out_key_part->and_next_ = head->and_next_;
}
// clear hashset
if (cellid_set.created()) {
if (OB_FAIL(ret)) {
} else if (cellid_set.created()) {
int tmp_ret = cellid_set.destroy();
if (OB_SUCC(ret) && OB_FAIL(tmp_ret)) {
LOG_WARN("failed to destory param set", K(ret));
@ -10044,17 +10121,52 @@ int ObQueryRange::get_geo_coveredby_keypart(uint32_t input_srid,
return ret;
}
int ObQueryRange::get_spatial_relationship_by_mask(ObKeyPart *out_key_part, ObDomainOpType& op_type)
{
INIT_SUCC(ret);
if (!ob_is_string_type(out_key_part->domain_keypart_->extra_param_.get_type())) {
op_type = ObDomainOpType::T_DOMAIN_OP_END;
} else {
ObString mask_str(out_key_part->domain_keypart_->extra_param_.get_string());
common::ObArenaAllocator temp_allocator(lib::ObLabel("GisIndex"));
ObString upper_str;
if (OB_FAIL(ob_simple_low_to_up(temp_allocator, mask_str, upper_str))) {
LOG_WARN("failed to get upper string", K(ret));
} else {
char cmp_str[upper_str.length() + 1];
cmp_str[upper_str.length()] = '\0';
MEMCPY(cmp_str, upper_str.ptr(), upper_str.length());
if (nullptr != strstr(cmp_str, "ANYINTERACT")) {
op_type = ObDomainOpType::T_GEO_INTERSECTS;
} else {
// other spatial relationsh is not supported yet, no need to continue
op_type = ObDomainOpType::T_DOMAIN_OP_END;
}
}
}
return ret;
}
int ObQueryRange::get_geo_range(const common::ObObj &wkb, const common::ObDomainOpType op_type,
ObKeyPart *out_key_part)
{
INIT_SUCC(ret);
ObString wkb_str(wkb.get_string());
common::ObDomainOpType new_op_type = op_type;
if (OB_ISNULL(wkb_str.ptr()) || wkb.is_unknown()) {
// if this spatial relation function is pushdown filter of nl, wkb_str ptr is not null.
// set whole range when can not get wkb
if (OB_FAIL(set_geo_keypart_whole_range(*out_key_part))) {
LOG_WARN("set keypart whole range failed", K(ret));
}
} else if (op_type == ObDomainOpType::T_GEO_RELATE
&& (OB_FAIL(get_spatial_relationship_by_mask(out_key_part, new_op_type)) || new_op_type != ObDomainOpType::T_GEO_INTERSECTS)) {
// set whole range when can not get mask of sdo_relate
if (OB_FAIL(ret)) {
LOG_WARN("get invalid spatial_relationship_by_mask", K(ret), K(new_op_type));
} else if (OB_FAIL(set_geo_keypart_whole_range(*out_key_part))) {
LOG_WARN("set keypart whole range failed", K(ret));
}
} else {
// check srid
uint64_t columnid = out_key_part->id_.column_id_;
@ -10072,16 +10184,16 @@ int ObQueryRange::get_geo_range(const common::ObObj &wkb, const common::ObDomain
LOG_USER_ERROR(OB_ERR_WRONG_SRID_FOR_COLUMN, static_cast<uint64_t>(input_srid),
static_cast<uint64_t>(column_info.srid_));
} else {
switch (op_type) {
switch (new_op_type) {
case ObDomainOpType::T_GEO_INTERSECTS:
case ObDomainOpType::T_GEO_COVERS:
case ObDomainOpType::T_GEO_DWITHIN:
if (OB_FAIL(get_geo_intersects_keypart(input_srid, wkb_str, op_type, out_key_part))) {
if (OB_FAIL(get_geo_intersects_keypart(input_srid, wkb_str, new_op_type, out_key_part))) {
LOG_WARN("failed to get keypart from intersects_keypart", K(ret), K(op_type));
}
break;
case ObDomainOpType::T_GEO_COVEREDBY:
if (OB_FAIL(get_geo_coveredby_keypart(input_srid, wkb_str, op_type, out_key_part))) {
if (OB_FAIL(get_geo_coveredby_keypart(input_srid, wkb_str, new_op_type, out_key_part))) {
LOG_WARN("failed to get keypart from intersects_keypart", K(ret), K(op_type));
}
break;

View File

@ -651,6 +651,7 @@ private:
int pre_extract_geo_op(const ObOpRawExpr *geo_expr,
ObKeyPart *&out_key_part,
const ObDataTypeCastParams &dtc_params);
int can_be_extract_orcl_spatial_range(const ObRawExpr *const_expr, bool& can_extract);
int prepare_multi_in_info(const ObOpRawExpr *l_expr,
const ObOpRawExpr *r_expr,
ObKeyPart *&tmp_key_part,
@ -729,7 +730,8 @@ private:
const common::ObDataTypeCastParams &dtc_params,
bool &is_bound_modified);
int or_single_head_graphs(ObKeyPartList &or_list, ObExecContext *exec_ctx,
const common::ObDataTypeCastParams &dtc_params);
const common::ObDataTypeCastParams &dtc_params,
const bool& need_geo_rebuild);
int union_in_with_in(ObKeyPartList &or_list,
ObKeyPart *cur1,
ObKeyPart *cur2,
@ -858,7 +860,7 @@ private:
ObExecContext *exec_ctx, const ObDataTypeCastParams &dtc_params);
// functions used for geo predicate
int get_geo_range(const common::ObObj &wkb, const ObDomainOpType op_type, ObKeyPart *out_key_part);
int get_dwithin_item(const ObRawExpr *expr, const ObConstRawExpr *&extra_item);
int get_spatial_relationship_by_mask(ObKeyPart *out_key_part, ObDomainOpType& op_type);
int get_domain_equal_keypart(const ObObj &val_start, const ObObj &val_end, ObKeyPart &out_keypart) const;
int get_geo_intersects_keypart(uint32_t input_srid,
const common::ObString &wkb,

View File

@ -319,7 +319,7 @@ ERROR 22023: Invalid GIS data provided to function.
SELECT ST_CONTAINS(
ST_GEOMFROMTEXT('MULTIPOLYGON(((0 1e+19,0 0,0 0,0 1e+19)))'),
ST_GEOMFROMTEXT('POLYGON((0 0,0 0,0 0,0 0))'));
ERROR 22003: coordinate value is out of range in 'st_contains'
ERROR 22003: value is out of range
SELECT ST_CONTAINS(
ST_GEOMFROMTEXT('MULTIPOLYGON(((0 9.22e+18,0 0,0 0,0 9.22e+18)))'),
ST_GEOMFROMTEXT('POLYGON((0 0,0 0,0 0,0 0))'));
@ -396,19 +396,19 @@ Outputs & filters:
0 - output([tt1.id]), filter([ST_Intersects(tt1.ge, ST_GeomFromText('POINT(15 20)', 4236))])
access([tt1.__pk_increment], [tt1.ge], [tt1.id]), partitions(p0)
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([tt1.__cellid_24], [tt1.__mbr_24], [tt1.__pk_increment]), range(1240640185631322861,MIN,MIN ; 1240640185631322861,MAX,MAX), (1240640185631322860,
MIN,MIN ; 1240640185631322860,MAX,MAX), (1240640185631322864,MIN,MIN ; 1240640185631322864,MAX,MAX), (1240640185631322816,MIN,MIN ; 1240640185631322816,
MAX,MAX), (1240640185631322880,MIN,MIN ; 1240640185631322880,MAX,MAX), (1240640185631323136,MIN,MIN ; 1240640185631323136,MAX,MAX), (1240640185631322112,
MIN,MIN ; 1240640185631322112,MAX,MAX), (1240640185631326208,MIN,MIN ; 1240640185631326208,MAX,MAX), (1240640185631309824,MIN,MIN ; 1240640185631309824,
MAX,MAX), (1240640185631506432,MIN,MIN ; 1240640185631506432,MAX,MAX), (1240640185632292864,MIN,MIN ; 1240640185632292864,MAX,MAX), (1240640185633341440,
MIN,MIN ; 1240640185633341440,MAX,MAX), (1240640185637535744,MIN,MIN ; 1240640185637535744,MAX,MAX), (1240640185587204096,MIN,MIN ; 1240640185587204096,
MAX,MAX), (1240640185520095232,MIN,MIN ; 1240640185520095232,MAX,MAX), (1240640184714788864,MIN,MIN ; 1240640184714788864,MAX,MAX), (1240640185788530688,
MIN,MIN ; 1240640185788530688,MAX,MAX), (1240640181493563392,MIN,MIN ; 1240640181493563392,MAX,MAX), (1240640198673432576,MIN,MIN ; 1240640198673432576,
MAX,MAX), (1240640267392909312,MIN,MIN ; 1240640267392909312,MAX,MAX), (1240639442759188480,MIN,MIN ; 1240639442759188480,MAX,MAX), (1240640542270816256,
MIN,MIN ; 1240640542270816256,MAX,MAX), (1240653736410349568,MIN,MIN ; 1240653736410349568,MAX,MAX), (1240671328596393984,MIN,MIN ; 1240671328596393984,
MAX,MAX), (1240460222363860992,MIN,MIN ; 1240460222363860992,MAX,MAX), (1239615797433729024,MIN,MIN ; 1239615797433729024,MAX,MAX), (1238489897526886400,
MIN,MIN ; 1238489897526886400,MAX,MAX), (1242993497154256896,MIN,MIN ; 1242993497154256896,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([tt1.__cellid_24], [tt1.__mbr_24], [tt1.__pk_increment]), range(1240640185631322860,MIN,MIN ; 1240640185631322860,MAX,MAX), (1240640185631322864,
MIN,MIN ; 1240640185631322864,MAX,MAX), (1240640185631322816,MIN,MIN ; 1240640185631322816,MAX,MAX), (1240640185631322880,MIN,MIN ; 1240640185631322880,
MAX,MAX), (1240640185631323136,MIN,MIN ; 1240640185631323136,MAX,MAX), (1240640185631322112,MIN,MIN ; 1240640185631322112,MAX,MAX), (1240640185631326208,
MIN,MIN ; 1240640185631326208,MAX,MAX), (1240640185631309824,MIN,MIN ; 1240640185631309824,MAX,MAX), (1240640185631506432,MIN,MIN ; 1240640185631506432,
MAX,MAX), (1240640185632292864,MIN,MIN ; 1240640185632292864,MAX,MAX), (1240640185633341440,MIN,MIN ; 1240640185633341440,MAX,MAX), (1240640185637535744,
MIN,MIN ; 1240640185637535744,MAX,MAX), (1240640185587204096,MIN,MIN ; 1240640185587204096,MAX,MAX), (1240640185520095232,MIN,MIN ; 1240640185520095232,
MAX,MAX), (1240640184714788864,MIN,MIN ; 1240640184714788864,MAX,MAX), (1240640185788530688,MIN,MIN ; 1240640185788530688,MAX,MAX), (1240640181493563392,
MIN,MIN ; 1240640181493563392,MAX,MAX), (1240640198673432576,MIN,MIN ; 1240640198673432576,MAX,MAX), (1240640267392909312,MIN,MIN ; 1240640267392909312,
MAX,MAX), (1240639442759188480,MIN,MIN ; 1240639442759188480,MAX,MAX), (1240640542270816256,MIN,MIN ; 1240640542270816256,MAX,MAX), (1240653736410349568,
MIN,MIN ; 1240653736410349568,MAX,MAX), (1240671328596393984,MIN,MIN ; 1240671328596393984,MAX,MAX), (1240460222363860992,MIN,MIN ; 1240460222363860992,
MAX,MAX), (1239615797433729024,MIN,MIN ; 1239615797433729024,MAX,MAX), (1238489897526886400,MIN,MIN ; 1238489897526886400,MAX,MAX), (1242993497154256896,
MIN,MIN ; 1242993497154256896,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1240640185631322861,MIN,MIN ; 1240640185631322861,MAX,MAX)
drop table tt1;
create table t1 (a geometry not null, spatial index(a)) row_format=dynamic;
INSERT IGNORE INTO t1 VALUES (NULL);

View File

@ -244,3 +244,12 @@ Outputs & filters:
is_index_back=false, is_global_index=false, filter_before_indexback[false],
range_key([t1.__pk_increment]), range(MIN ; MAX)always true
drop table t1;
drop table if exists spatial_index_dml;
CREATE TABLE spatial_index_dml (i1 int, i2 int, g GEOMETRY NOT NULL SRID 4326, PRIMARY KEY (i1));
INSERT INTO spatial_index_dml VALUES (1, 2, ST_GEOMFROMTEXT('POINT(0 0)', 4326));
CREATE INDEX idx ON spatial_index_dml (g);
alter table spatial_index_dml drop column i2;
select i1, st_astext(g) from spatial_index_dml;
i1 st_astext(g)
1 POINT(0 0)
drop table spatial_index_dml;

View File

@ -25,19 +25,19 @@ Outputs & filters:
3 - output([partition_t1.g]), filter([st_intersects(partition_t1.g, st_geomfromtext('point(1 1)'))])
access([partition_t1.c1], [partition_t1.g]), partitions(p[0-1])
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([partition_t1.__cellid_17], [partition_t1.__mbr_17], [partition_t1.c1]), range(1152921504606846977,MIN,MIN ; 1152921504606846977,MAX,MAX),
(1152921504606846980,MIN,MIN ; 1152921504606846980,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN
; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX),
(1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN
; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX),
(1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN
; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX),
(1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN
; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX),
(1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN
; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX),
(1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN
; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([partition_t1.__cellid_17], [partition_t1.__mbr_17], [partition_t1.c1]), range(1152921504606846980,MIN,MIN ; 1152921504606846980,MAX,MAX),
(1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN
; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX),
(1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN
; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX),
(1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN
; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX),
(1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN
; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX),
(1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN
; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX),
(1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN
; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846977,MAX,MAX)
select /*+index(partition_t1 idx)*/ st_astext(g) from partition_t1 where st_intersects(g, st_geomfromtext('point(1 1)'));
st_astext(g)
POINT(1 1)
@ -76,19 +76,19 @@ Outputs & filters:
3 - output([t1.g]), filter([st_intersects(t1.g, st_geomfromtext('point(1 1)'))])
access([t1.c1], [t1.g]), partitions(p[0-1])
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([t1.__cellid_17], [t1.__mbr_17], [t1.c1]), range(1152921504606846977,MIN,MIN ; 1152921504606846977,MAX,MAX), (1152921504606846980,MIN,MIN
; 1152921504606846980,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX),
(1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN
; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX),
(1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN
; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX),
(1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN
; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX),
(1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN
; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX),
(1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN
; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX),
(1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([t1.__cellid_17], [t1.__mbr_17], [t1.c1]), range(1152921504606846980,MIN,MIN ; 1152921504606846980,MAX,MAX), (1152921504606846992,MIN,MIN
; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX),
(1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN
; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX),
(1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN
; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX),
(1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN
; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX),
(1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN
; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX),
(1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN
; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX),
(1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846977,MAX,MAX)
select /*+index(t1 idx)*/ st_astext(g) from t1 where st_intersects(g, st_geomfromtext('point(1 1)'));
st_astext(g)
POINT(1 1)
@ -198,19 +198,19 @@ Outputs & filters:
5 - output(nil), filter([st_intersects(geo_maxpt_coords_100y.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0))])
access([geo_maxpt_coords_100y.__pk_increment], [geo_maxpt_coords_100y.geo_pwkt]), partitions(p[0-255])
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([geo_maxpt_coords_100y.__cellid_18], [geo_maxpt_coords_100y.__mbr_18], [geo_maxpt_coords_100y.__pk_increment]), range(1152921504606846977,
MIN,MIN ; 1152921504606846983,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,
MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,
MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,
MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,
MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,
MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,
MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,
MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,
MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,
MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,
MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([geo_maxpt_coords_100y.__cellid_18], [geo_maxpt_coords_100y.__mbr_18], [geo_maxpt_coords_100y.__pk_increment]), range(1152921504606846992,
MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,
MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,
MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,
MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,
MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,
MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,
MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,
MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,
MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,
MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,
MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846983,MAX,MAX)
explain select /*+ parallel(1) */ count(*) from geo_maxpt_coords_100y where st_intersects(geo_maxpt_coords_100y.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0));
Query Plan
========================================================================================
@ -237,30 +237,30 @@ Outputs & filters:
5 - output(nil), filter([st_intersects(geo_maxpt_coords_100y.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0))])
access([geo_maxpt_coords_100y.__pk_increment], [geo_maxpt_coords_100y.geo_pwkt]), partitions(p[0-255])
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([geo_maxpt_coords_100y.__cellid_18], [geo_maxpt_coords_100y.__mbr_18], [geo_maxpt_coords_100y.__pk_increment]), range(1152921504606846977,
MIN,MIN ; 1152921504606846983,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,
MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,
MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,
MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,
MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,
MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,
MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,
MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,
MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,
MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,
MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([geo_maxpt_coords_100y.__cellid_18], [geo_maxpt_coords_100y.__mbr_18], [geo_maxpt_coords_100y.__pk_increment]), range(1152921504606846992,
MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,
MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,
MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,
MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,
MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,
MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,
MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,
MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,
MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,
MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,
MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846983,MAX,MAX)
explain select /*+ parallel(3) */ count(*) from geo_maxpt_coords_100y where st_intersects(geo_maxpt_coords_100y.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0));
Query Plan
========================================================================================
|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|
----------------------------------------------------------------------------------------
|0 |SCALAR GROUP BY | |1 |32285 |
|1 |└─PX COORDINATOR | |1 |32285 |
|2 | └─EXCHANGE OUT DISTR |:EX10000 |1 |32285 |
|3 | └─MERGE GROUP BY | |1 |32285 |
|4 | └─PX PARTITION ITERATOR| |1 |32285 |
|5 | └─TABLE FULL SCAN |geo_maxpt_coords_100y(geo_pwkt)|1 |32285 |
|0 |SCALAR GROUP BY | |1 |10762 |
|1 |└─PX COORDINATOR | |1 |10762 |
|2 | └─EXCHANGE OUT DISTR |:EX10000 |1 |10762 |
|3 | └─MERGE GROUP BY | |1 |10762 |
|4 | └─PX PARTITION ITERATOR| |1 |10762 |
|5 | └─TABLE FULL SCAN |geo_maxpt_coords_100y(geo_pwkt)|1 |10762 |
========================================================================================
Outputs & filters:
-------------------------------------
@ -268,7 +268,7 @@ Outputs & filters:
group(nil), agg_func([T_FUN_COUNT_SUM(T_FUN_COUNT(*))])
1 - output([T_FUN_COUNT(*)]), filter(nil)
2 - output([T_FUN_COUNT(*)]), filter(nil)
dop=1
dop=3
3 - output([T_FUN_COUNT(*)]), filter(nil)
group(nil), agg_func([T_FUN_COUNT(*)])
4 - output(nil), filter(nil)
@ -276,19 +276,19 @@ Outputs & filters:
5 - output(nil), filter([st_intersects(geo_maxpt_coords_100y.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0))])
access([geo_maxpt_coords_100y.__pk_increment], [geo_maxpt_coords_100y.geo_pwkt]), partitions(p[0-255])
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([geo_maxpt_coords_100y.__cellid_18], [geo_maxpt_coords_100y.__mbr_18], [geo_maxpt_coords_100y.__pk_increment]), range(1152921504606846977,
MIN,MIN ; 1152921504606846983,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,
MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,
MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,
MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,
MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,
MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,
MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,
MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,
MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,
MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,
MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([geo_maxpt_coords_100y.__cellid_18], [geo_maxpt_coords_100y.__mbr_18], [geo_maxpt_coords_100y.__pk_increment]), range(1152921504606846992,
MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,
MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,
MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,
MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,
MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,
MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,
MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,
MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,
MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,
MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,
MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846983,MAX,MAX)
explain select count(*) from geo_maxpt_coords_100y_2 where st_intersects(geo_maxpt_coords_100y_2.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0));
Query Plan
==============================================================================
@ -304,19 +304,19 @@ Outputs & filters:
1 - output(nil), filter([st_intersects(geo_maxpt_coords_100y_2.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0))])
access([geo_maxpt_coords_100y_2.__pk_increment], [geo_maxpt_coords_100y_2.geo_pwkt]), partitions(p0)
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([geo_maxpt_coords_100y_2.__cellid_18], [geo_maxpt_coords_100y_2.__mbr_18], [geo_maxpt_coords_100y_2.__pk_increment]), range(1152921504606846977,
MIN,MIN ; 1152921504606846983,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,
MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,
MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,
MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,
MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,
MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,
MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,
MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,
MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,
MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,
MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([geo_maxpt_coords_100y_2.__cellid_18], [geo_maxpt_coords_100y_2.__mbr_18], [geo_maxpt_coords_100y_2.__pk_increment]), range(1152921504606846992,
MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,
MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,
MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,
MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,
MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,
MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,
MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,
MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,
MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,
MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,
MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846983,MAX,MAX)
explain select /*+ parallel(1) */ count(*) from geo_maxpt_coords_100y_2 where st_intersects(geo_maxpt_coords_100y_2.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0));
Query Plan
==============================================================================
@ -332,19 +332,19 @@ Outputs & filters:
1 - output(nil), filter([st_intersects(geo_maxpt_coords_100y_2.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0))])
access([geo_maxpt_coords_100y_2.__pk_increment], [geo_maxpt_coords_100y_2.geo_pwkt]), partitions(p0)
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([geo_maxpt_coords_100y_2.__cellid_18], [geo_maxpt_coords_100y_2.__mbr_18], [geo_maxpt_coords_100y_2.__pk_increment]), range(1152921504606846977,
MIN,MIN ; 1152921504606846983,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,
MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,
MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,
MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,
MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,
MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,
MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,
MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,
MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,
MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,
MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([geo_maxpt_coords_100y_2.__cellid_18], [geo_maxpt_coords_100y_2.__mbr_18], [geo_maxpt_coords_100y_2.__pk_increment]), range(1152921504606846992,
MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,
MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,
MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,
MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,
MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,
MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,
MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,
MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,
MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,
MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,
MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846983,MAX,MAX)
explain select /*+ parallel(3) */ count(*) from geo_maxpt_coords_100y_2 where st_intersects(geo_maxpt_coords_100y_2.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0));
Query Plan
==============================================================================
@ -360,16 +360,16 @@ Outputs & filters:
1 - output(nil), filter([st_intersects(geo_maxpt_coords_100y_2.geo_pwkt, st_geomfromtext('polygon((0 0,5 0,5 5,0 5,0 0))', 0))])
access([geo_maxpt_coords_100y_2.__pk_increment], [geo_maxpt_coords_100y_2.geo_pwkt]), partitions(p0)
is_index_back=true, is_global_index=false, filter_before_indexback[false],
range_key([geo_maxpt_coords_100y_2.__cellid_18], [geo_maxpt_coords_100y_2.__mbr_18], [geo_maxpt_coords_100y_2.__pk_increment]), range(1152921504606846977,
MIN,MIN ; 1152921504606846983,MAX,MAX), (1152921504606846992,MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,
MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,
MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,
MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,
MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,
MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,
MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,
MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,
MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,
MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,
MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,
MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX)
range_key([geo_maxpt_coords_100y_2.__cellid_18], [geo_maxpt_coords_100y_2.__mbr_18], [geo_maxpt_coords_100y_2.__pk_increment]), range(1152921504606846992,
MIN,MIN ; 1152921504606846992,MAX,MAX), (1152921504606847040,MIN,MIN ; 1152921504606847040,MAX,MAX), (1152921504606847232,MIN,MIN ; 1152921504606847232,
MAX,MAX), (1152921504606848000,MIN,MIN ; 1152921504606848000,MAX,MAX), (1152921504606851072,MIN,MIN ; 1152921504606851072,MAX,MAX), (1152921504606863360,
MIN,MIN ; 1152921504606863360,MAX,MAX), (1152921504606912512,MIN,MIN ; 1152921504606912512,MAX,MAX), (1152921504607109120,MIN,MIN ; 1152921504607109120,
MAX,MAX), (1152921504607895552,MIN,MIN ; 1152921504607895552,MAX,MAX), (1152921504611041280,MIN,MIN ; 1152921504611041280,MAX,MAX), (1152921504623624192,
MIN,MIN ; 1152921504623624192,MAX,MAX), (1152921504673955840,MIN,MIN ; 1152921504673955840,MAX,MAX), (1152921504875282432,MIN,MIN ; 1152921504875282432,
MAX,MAX), (1152921505680588800,MIN,MIN ; 1152921505680588800,MAX,MAX), (1152921508901814272,MIN,MIN ; 1152921508901814272,MAX,MAX), (1152921521786716160,
MIN,MIN ; 1152921521786716160,MAX,MAX), (1152921573326323712,MIN,MIN ; 1152921573326323712,MAX,MAX), (1152921779484753920,MIN,MIN ; 1152921779484753920,
MAX,MAX), (1152922604118474752,MIN,MIN ; 1152922604118474752,MAX,MAX), (1152925902653358080,MIN,MIN ; 1152925902653358080,MAX,MAX), (1152939096792891392,
MIN,MIN ; 1152939096792891392,MAX,MAX), (1152991873351024640,MIN,MIN ; 1152991873351024640,MAX,MAX), (1153202979583557632,MIN,MIN ; 1153202979583557632,
MAX,MAX), (1154047404513689600,MIN,MIN ; 1154047404513689600,MAX,MAX), (1157425104234217472,MIN,MIN ; 1157425104234217472,MAX,MAX), (1170935903116328960,
MIN,MIN ; 1170935903116328960,MAX,MAX), (1224979098644774912,MIN,MIN ; 1224979098644774912,MAX,MAX), (1441151880758558720,MIN,MIN ; 1441151880758558720,
MAX,MAX), (1152921504606846976,MIN,MIN ; 1152921504606846976,MAX,MAX), (1152921504606846977,MIN,MIN ; 1152921504606846983,MAX,MAX)

View File

@ -60,14 +60,14 @@ SET @pt_lat_minus_91 = x'E6100000010100000000000000000000000000000000C056C0';
SET @pt_lat_plus_91 = x'E6100000010100000000000000000000000000000000C05640';
SET @pt_long_minus_181 = x'E610000001010000000000000000A066C00000000000000000';
SET @pt_long_plus_181 = x'E610000001010000000000000000A066400000000000000000';
SELECT _st_covers(@pt_lat_minus_91, @pt);
ERROR 22S03: A parameter of function _st_covers contains a geometry with latitude -91.000000, which is out of range. It must be within [-90.000000, 90.000000].
SELECT _st_covers(@pt_lat_plus_91, @pt);
ERROR 22S03: A parameter of function _st_covers contains a geometry with latitude 91.000000, which is out of range. It must be within [-90.000000, 90.000000].
SELECT _st_covers(@pt_long_minus_181, @pt);
ERROR 22S02: A parameter of function _st_covers contains a geometry with longitude -181.000000, which is out of range. It must be within (-180.000000, 180.000000].
SELECT _st_covers(@pt_long_plus_181, @pt);
ERROR 22S02: A parameter of function _st_covers contains a geometry with longitude 181.000000, which is out of range. It must be within (-180.000000, 180.000000].
SELECT _st_covers(cast(@pt_lat_minus_91 as point), @pt);
ERROR 22S03: A parameter of function cast_as_point contains a geometry with latitude -91.000000, which is out of range. It must be within [-90.000000, 90.000000].
SELECT _st_covers(cast(@pt_lat_plus_91 as point), @pt);
ERROR 22S03: A parameter of function cast_as_point contains a geometry with latitude 91.000000, which is out of range. It must be within [-90.000000, 90.000000].
SELECT _st_covers(cast(@pt_long_minus_181 as point), @pt);
ERROR 22S02: A parameter of function cast_as_point contains a geometry with longitude -181.000000, which is out of range. It must be within (-180.000000, 180.000000].
SELECT _st_covers(cast(@pt_long_plus_181 as point), @pt);
ERROR 22S02: A parameter of function cast_as_point contains a geometry with longitude 181.000000, which is out of range. It must be within (-180.000000, 180.000000].
drop table if exists gis_geometrycollection, gis_geometrycollection_2;
#####################################################################################
# _st_covers(g1,g2)
@ -1932,12 +1932,12 @@ GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) POINT(1 1) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) LINESTRING(1 1,2 2) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) POLYGON((0 0,1 0,1 1,0 1,0 0)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOINT((1 1),(2 2)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTILINESTRING((1 1,2 2),(3 3,4 4)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(POINT(1 1)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))) 1
@ -1948,17 +1948,17 @@ GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0))
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) POINT(1 1) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) LINESTRING(1 1,2 2) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) POLYGON((0 0,1 0,1 1,0 1,0 0)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOINT((1 1),(2 2)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTILINESTRING((1 1,2 2),(3 3,4 4)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(POINT(1 1)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))) 1
@ -1969,7 +1969,7 @@ GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0))
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6)))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) 0
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) 1
GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(1 1,2 2),POLYGON((0 0,1 0,1 1,0 1,0 0)),POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4)),MULTIPOINT((1 1),(2 2)),MULTILINESTRING((1 1,2 2),(3 3,4 4)),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5))),MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))),GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((0 0,1 0,1 1,0 1,0 0))),GEOMETRYCOLLECTION(POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,6 4,6 6,4 6,4 4))),GEOMETRYCOLLECTION(MULTIPOINT((1 1),(2 2))),GEOMETRYCOLLECTION(MULTILINESTRING((1 1,2 2),(3 3,4 4))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5)))),GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)),((5 5,10 5,10 10,5 10,5 5),(6 6,7 6,7 7,6 7,6 6))))) GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4)))) 1
GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4)))) POINT(1 1) 1
GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 1)),GEOMETRYCOLLECTION(LINESTRING(1 1,2 2)),GEOMETRYCOLLECTION(POLYGON((1 1,10 1,10 10,1 10,1 1),(4 4,6 4,6 6,4 6,4 4)))) LINESTRING(1 1,2 2) 1

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