Files
oceanbase/src/sql/engine/expr/ob_geo_expr_utils.h
wu-xingying c770941bf6 gis bugfix
2024-07-01 15:18:45 +00:00

251 lines
11 KiB
C++

/**
* 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 ob_geo_expr_utils.
*/
#ifndef OCEANBASE_SQL_OB_GEO_EXPR_UTILS_H_
#define OCEANBASE_SQL_OB_GEO_EXPR_UTILS_H_
#include "lib/allocator/ob_allocator.h"
#include "lib/string/ob_string.h"
#include "lib/geo/ob_geo.h"
#include "lib/geo/ob_geo_utils.h"
#include "lib/geo/ob_geo_common.h"
#include "sql/engine/expr/ob_expr.h" // for ObExpr
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/ob_exec_context.h"
#include "share/ob_i_sql_expression.h" // for ObExprCtx
#include "observer/omt/ob_tenant_srs.h"
#include "sql/engine/expr/ob_expr_lob_utils.h"
namespace oceanbase
{
namespace common
{
class ObCachedGeom;
}
namespace sql
{
struct ObGeoUnit
{
const char *name;
double factor;
};
const ObGeoUnit OB_GEO_UNITS[] = {
// order by unit s, asc
{ "British chain (Benoit 1895 A)", 20.1167824 },
{ "British chain (Benoit 1895 B)", 20.116782494375872 },
{ "British chain (Sears 1922 truncated)", 20.116756 },
{ "British chain (Sears 1922)", 20.116765121552632 },
{ "British foot (1865)", 0.30480083333333335 },
{ "British foot (1936)", 0.3048007491 },
{ "British foot (Benoit 1895 A)", 0.3047997333333333 },
{ "British foot (Benoit 1895 B)", 0.30479973476327077 },
{ "British foot (Sears 1922 truncated)", 0.30479933333333337 },
{ "British foot (Sears 1922)", 0.3047994715386762 },
{ "British link (Benoit 1895 A)", 0.201167824 },
{ "British link (Benoit 1895 B)", 0.2011678249437587 },
{ "British link (Sears 1922 truncated)", 0.20116756 },
{ "British link (Sears 1922)", 0.2011676512155263 },
{ "British yard (Benoit 1895 A)", 0.9143992 },
{ "British yard (Benoit 1895 B)", 0.9143992042898124 },
{ "British yard (Sears 1922 truncated)", 0.914398 },
{ "British yard (Sears 1922)", 0.9143984146160288 },
{ "centimetre", 0.01 },
{ "chain", 20.1168 },
{ "Clarke's chain", 20.1166195164 },
{ "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 },
{ "Gold Coast foot", 0.3047997101815088 },
{ "Indian foot", 0.30479951024814694 },
{ "Indian foot (1937)", 0.30479841 },
{ "Indian foot (1962)", 0.3047996 },
{ "Indian foot (1975)", 0.3047995 },
{ "Indian yard", 0.9143985307444408 },
{ "Indian yard (1937)", 0.91439523 },
{ "Indian yard (1962)", 0.9143988 },
{ "Indian yard (1975)", 0.9143985 },
{ "kilometre", 1000 },
{ "km", 1000 },
{ "link", 0.201168 },
{ "metre", 1 },
{ "millimetre", 0.001 },
{ "nautical mile", 1852 },
{ "Statute mile", 1609.344 },
{ "US survey chain", 20.11684023368047 },
{ "US survey foot", 0.30480060960121924 },
{ "US survey link", 0.2011684023368047 },
{ "US survey mile", 1609.3472186944375 },
{ "yard", 0.9144 }
};
class ObGeoConstParamCache;
enum class ObGeoAxisOrder
{
LONG_LAT = 0,
LAT_LONG = 1,
SRID_DEFINED = 2,
INVALID = 3,
};
class ObGeoExprUtils
{
public:
ObGeoExprUtils();
virtual ~ObGeoExprUtils() = default;
static int get_srs_item(uint64_t tenant_id,
omt::ObSrsCacheGuard &srs_guard,
const uint32_t srid,
const common::ObSrsItem *&srs);
static int get_srs_item(ObEvalCtx &ctx,
omt::ObSrsCacheGuard &srs_guard,
const common::ObString &wkb,
const common::ObSrsItem *&srs,
bool use_little_bo = false,
const char *func_name = NULL);
static int build_geometry(common::ObIAllocator &allocator,
const common::ObString &wkb,
common::ObGeometry *&geo,
const common::ObSrsItem *srs,
const char *func_name,
uint8_t build_flag = ObGeoBuildFlag::GEO_DEFAULT);
static int construct_geometry(common::ObIAllocator &allocator,
const common::ObString &wkb,
omt::ObSrsCacheGuard &srs_guard,
const common::ObSrsItem *&srs,
common::ObGeometry *&geo,
const char *func_name,
bool has_srid = true);
static int check_coordinate_range(const common::ObSrsItem *srs,
common::ObGeometry *geo,
const char *func_name,
const bool is_param = false,
const bool is_normalized = false);
static int parse_axis_order(const common::ObString option_str,
const char *func_name,
ObGeoAxisOrder &axis_order);
static int check_need_reverse(ObGeoAxisOrder axis_order,
bool &need_reverse);
static int correct_coordinate_range(const common::ObSrsItem *srs_item,
common::ObGeometry *geo,
const char *func_name);
static int check_empty(common::ObGeometry *geo,
bool &is_empty);
static int parse_srid(const common::ObString &srid_str,
uint32_t &srid);
static int get_box_bestsrid(common::ObGeogBox *geo_box1,
common::ObGeogBox *geo_box2,
int32 &bestsrid);
static int normalize_wkb(const common::ObSrsItem *srs,
common::ObString &wkb,
common::ObArenaAllocator &allocator,
common::ObGeometry *&geo);
static int normalize_wkb(common::ObString &proj4text,
common::ObGeometry *geo); // for st_transform
static int denormalize_wkb(common::ObString &proj4text,
common::ObGeometry *geo); // for st_transform
static int geo_to_wkb(common::ObGeometry &geo,
const ObExpr &expr,
ObEvalCtx &ctx,
const common::ObSrsItem *srs_item,
common::ObString &res_wkb,
uint32_t srs_id = 0);
static int geo_to_wkb(common::ObGeometry &geo,
common::ObExprCtx &expr_ctx,
const common::ObSrsItem *srs_item,
common::ObString &res_wkb,
uint32_t srs_id = 0);
static int geo_to_2d_wkb(common::ObGeometry &geo,
const ObExpr &expr,
ObEvalCtx &ctx,
const common::ObSrsItem *srs_item,
common::ObString &res_wkb,
uint32_t srs_id = 0);
static int geo_to_3d_wkb(common::ObGeometry &geo,
const ObExpr &expr,
ObEvalCtx &ctx,
const common::ObSrsItem *srs_item,
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,
bool is_geo1_cached = false, bool is_geo2_cached = false);
static int pack_geo_res(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res, const ObString &str);
static int reverse_coordinate(ObGeometry *geo, const char *func_name);
static int length_unit_conversion(const ObString &unit_str, const ObSrsItem *srs, double in_num, double &out_num);
static int get_input_geometry(ObIAllocator &allocator, ObDatum *gis_datum, ObEvalCtx &ctx, ObExpr *gis_arg,
omt::ObSrsCacheGuard &srs_guard, const char *func_name,
const ObSrsItem *&srs, ObGeometry *&geo);
static int make_valid_polygon_inner(
ObCartesianPolygon &poly, ObIAllocator &allocator, ObGeometry *&valid_poly);
static int union_polygons(
ObIAllocator &allocator, const ObGeometry &poly, ObGeometry *&polygons_union);
static int make_valid_polygon(ObGeometry *poly, ObIAllocator &allocator, ObGeometry *&valid_poly);
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
} // oceanbase
#endif // OCEANBASE_SQL_OB_GEO_EXPR_UTILS_H_