1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00
Files
mariadb/sql/item_geofunc.h
Michael Widenius 3105c9e7a5 Change bitfields in Item to an uint16
The reason for the change is that neither clang or gcc can do efficient
code when several bit fields are change at the same time or when copying
one or more bits between identical bit fields.
Updated bits explicitely with & and | is MUCH more efficient than what
current compilers can do.
2021-05-19 22:27:28 +02:00

1124 lines
33 KiB
C++

#ifndef ITEM_GEOFUNC_INCLUDED
#define ITEM_GEOFUNC_INCLUDED
/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
Copyright (C) 2011, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/* This file defines all spatial functions */
#ifdef HAVE_SPATIAL
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
#include "sql_type_geom.h"
#include "item.h"
#include "gstream.h"
#include "spatial.h"
#include "gcalc_slicescan.h"
#include "gcalc_tools.h"
class Item_geometry_func: public Item_str_func
{
public:
Item_geometry_func(THD *thd): Item_str_func(thd) {}
Item_geometry_func(THD *thd, Item *a): Item_str_func(thd, a) {}
Item_geometry_func(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
Item_geometry_func(THD *thd, Item *a, Item *b, Item *c):
Item_str_func(thd, a, b, c) {}
Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
bool fix_length_and_dec();
const Type_handler *type_handler() const { return &type_handler_geometry; }
};
/*
Functions returning REAL measurements of a single GEOMETRY argument
*/
class Item_real_func_args_geometry: public Item_real_func
{
protected:
String value;
bool check_arguments() const
{
DBUG_ASSERT(arg_count == 1);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_real_func_args_geometry(THD *thd, Item *a)
:Item_real_func(thd, a) {}
};
/*
Functions returning INT measurements of a single GEOMETRY argument
*/
class Item_long_func_args_geometry: public Item_long_func
{
bool check_arguments() const
{
DBUG_ASSERT(arg_count == 1);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
protected:
String value;
public:
Item_long_func_args_geometry(THD *thd, Item *a)
:Item_long_func(thd, a) {}
};
/*
Functions returning BOOL measurements of a single GEOMETRY argument
*/
class Item_bool_func_args_geometry: public Item_bool_func
{
protected:
String value;
bool check_arguments() const
{
DBUG_ASSERT(arg_count == 1);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_bool_func_args_geometry(THD *thd, Item *a)
:Item_bool_func(thd, a) {}
};
/*
Functions returning ASCII string measurements of a single GEOMETRY argument
*/
class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
{
protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 1);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_str_ascii_func_args_geometry(THD *thd, Item *a)
:Item_str_ascii_func(thd, a) {}
Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
:Item_str_ascii_func(thd, a, b) {}
Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c)
:Item_str_ascii_func(thd, a, b, c) {}
};
/*
Functions returning binary string measurements of a single GEOMETRY argument
*/
class Item_binary_func_args_geometry: public Item_str_func
{
protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 1);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_binary_func_args_geometry(THD *thd, Item *a)
:Item_str_func(thd, a) {}
};
/*
Functions returning GEOMETRY measurements of a single GEOEMETRY argument
*/
class Item_geometry_func_args_geometry: public Item_geometry_func
{
protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 1);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_geometry_func_args_geometry(THD *thd, Item *a)
:Item_geometry_func(thd, a) {}
Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b)
:Item_geometry_func(thd, a, b) {}
};
/*
Functions returning REAL result relationships between two GEOMETRY arguments
*/
class Item_real_func_args_geometry_geometry: public Item_real_func
{
protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
:Item_real_func(thd, a, b) {}
};
/*
Functions returning BOOL result relationships between two GEOMETRY arguments
*/
class Item_bool_func_args_geometry_geometry: public Item_bool_func
{
protected:
String value;
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
:Item_bool_func(thd, a, b, c) {}
};
class Item_func_geometry_from_text: public Item_geometry_func
{
bool check_arguments() const
{
return args[0]->check_type_general_purpose_string(func_name()) ||
check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
}
public:
Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
Item_geometry_func(thd, a, srid) {}
const char *func_name() const { return "st_geometryfromtext"; }
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_geometry_from_text>(thd, this); }
};
class Item_func_geometry_from_wkb: public Item_geometry_func
{
bool check_arguments() const
{
return
Type_handler_geometry::check_type_geom_or_binary(func_name(), args[0]) ||
check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
}
public:
Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid):
Item_geometry_func(thd, a, srid) {}
const char *func_name() const { return "st_geometryfromwkb"; }
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_geometry_from_wkb>(thd, this); }
};
class Item_func_geometry_from_json: public Item_geometry_func
{
String tmp_js;
bool check_arguments() const
{
// TODO: check with Alexey, for better args[1] and args[2] type control
return args[0]->check_type_general_purpose_string(func_name()) ||
check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
}
public:
Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {}
Item_func_geometry_from_json(THD *thd, Item *js, Item *opt):
Item_geometry_func(thd, js, opt) {}
Item_func_geometry_from_json(THD *thd, Item *js, Item *opt, Item *srid):
Item_geometry_func(thd, js, opt, srid) {}
const char *func_name() const { return "st_geomfromgeojson"; }
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_geometry_from_json>(thd, this); }
};
class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
{
public:
Item_func_as_wkt(THD *thd, Item *a)
:Item_str_ascii_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_astext"; }
String *val_str_ascii(String *);
bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_as_wkt>(thd, this); }
};
class Item_func_as_wkb: public Item_binary_func_args_geometry
{
public:
Item_func_as_wkb(THD *thd, Item *a)
:Item_binary_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
const Type_handler *type_handler() const { return &type_handler_long_blob; }
bool fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
max_length= (uint32) UINT_MAX32;
flags|= ITEM_FLAG_MAYBE_NULL;
return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_as_wkb>(thd, this); }
};
class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
{
bool check_arguments() const
{
// TODO: check with Alexey, for better args[1] and args[2] type control
return Item_str_ascii_func_args_geometry::check_arguments() ||
check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
}
public:
Item_func_as_geojson(THD *thd, Item *js)
:Item_str_ascii_func_args_geometry(thd, js) {}
Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
:Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {}
Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
:Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
const char *func_name() const { return "st_asgeojson"; }
bool fix_length_and_dec();
String *val_str_ascii(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_as_geojson>(thd, this); }
};
class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
{
public:
Item_func_geometry_type(THD *thd, Item *a)
:Item_str_ascii_func_args_geometry(thd, a) {}
String *val_str_ascii(String *);
const char *func_name() const { return "st_geometrytype"; }
bool fix_length_and_dec()
{
// "GeometryCollection" is the longest
fix_length_and_charset(20, default_charset());
flags|= ITEM_FLAG_MAYBE_NULL;
return FALSE;
};
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_geometry_type>(thd, this); }
};
// #define HEAVY_CONVEX_HULL
class Item_func_convexhull: public Item_geometry_func_args_geometry
{
class ch_node: public Gcalc_dyn_list::Item
{
public:
const Gcalc_heap::Info *pi;
ch_node *prev;
Gcalc_dyn_list::Item *next;
ch_node *get_next() { return (ch_node *) next; }
};
Gcalc_heap collector;
Gcalc_function func;
Gcalc_dyn_list res_heap;
Gcalc_result_receiver res_receiver;
String tmp_value;
#ifdef HEAVY_CONVEX_HULL
Gcalc_scan_iterator scan_it;
#endif /*HEAVY_CONVEX_HULL*/
ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
public:
Item_func_convexhull(THD *thd, Item *a)
:Item_geometry_func_args_geometry(thd, a),
res_heap(8192, sizeof(ch_node))
{}
const char *func_name() const { return "st_convexhull"; }
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_convexhull>(thd, this); }
};
class Item_func_centroid: public Item_geometry_func_args_geometry
{
public:
Item_func_centroid(THD *thd, Item *a)
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_centroid"; }
String *val_str(String *);
const Type_handler *type_handler() const
{
return &type_handler_point;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_centroid>(thd, this); }
};
class Item_func_envelope: public Item_geometry_func_args_geometry
{
public:
Item_func_envelope(THD *thd, Item *a)
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_envelope"; }
String *val_str(String *);
const Type_handler *type_handler() const
{
return &type_handler_polygon;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_envelope>(thd, this); }
};
class Item_func_boundary: public Item_geometry_func_args_geometry
{
class Transporter : public Gcalc_shape_transporter
{
Gcalc_result_receiver *m_receiver;
uint n_points;
Gcalc_function::shape_type current_type;
double last_x, last_y;
public:
Transporter(Gcalc_result_receiver *receiver) :
Gcalc_shape_transporter(NULL), m_receiver(receiver)
{}
int single_point(double x, double y);
int start_line();
int complete_line();
int start_poly();
int complete_poly();
int start_ring();
int complete_ring();
int add_point(double x, double y);
int start_collection(int n_objects);
};
Gcalc_result_receiver res_receiver;
public:
Item_func_boundary(THD *thd, Item *a)
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_boundary"; }
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_boundary>(thd, this); }
};
class Item_func_point: public Item_geometry_func
{
bool check_arguments() const
{ return check_argument_types_can_return_real(0, 2); }
public:
Item_func_point(THD *thd, Item *a, Item *b): Item_geometry_func(thd, a, b) {}
Item_func_point(THD *thd, Item *a, Item *b, Item *srid):
Item_geometry_func(thd, a, b, srid) {}
const char *func_name() const { return "point"; }
String *val_str(String *);
const Type_handler *type_handler() const
{
return &type_handler_point;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_point>(thd, this); }
};
class Item_func_spatial_decomp: public Item_geometry_func_args_geometry
{
enum Functype decomp_func;
public:
Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; }
const char *func_name() const
{
switch (decomp_func)
{
case SP_STARTPOINT:
return "st_startpoint";
case SP_ENDPOINT:
return "st_endpoint";
case SP_EXTERIORRING:
return "st_exteriorring";
default:
DBUG_ASSERT(0); // Should never happened
return "spatial_decomp_unknown";
}
}
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_decomp>(thd, this); }
};
class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry
{
enum Functype decomp_func_n;
bool check_arguments() const
{
return Item_geometry_func_args_geometry::check_arguments() ||
args[1]->check_type_can_return_int(func_name());
}
public:
Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft)
:Item_geometry_func_args_geometry(thd, a, b),
decomp_func_n(ft)
{ }
const char *func_name() const
{
switch (decomp_func_n)
{
case SP_POINTN:
return "st_pointn";
case SP_GEOMETRYN:
return "st_geometryn";
case SP_INTERIORRINGN:
return "st_interiorringn";
default:
DBUG_ASSERT(0); // Should never happened
return "spatial_decomp_n_unknown";
}
}
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_decomp_n>(thd, this); }
};
class Item_func_spatial_collection: public Item_geometry_func
{
bool check_arguments() const
{
return Type_handler_geometry::check_types_geom_or_binary(func_name(), args,
0, arg_count);
}
enum Geometry::wkbType coll_type;
enum Geometry::wkbType item_type;
public:
Item_func_spatial_collection(THD *thd,
List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it):
Item_geometry_func(thd, list)
{
coll_type=ct;
item_type=it;
}
String *val_str(String *);
bool fix_length_and_dec()
{
if (Item_geometry_func::fix_length_and_dec())
return TRUE;
for (unsigned int i= 0; i < arg_count; ++i)
{
if (args[i]->is_fixed() && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
{
String str;
args[i]->print(&str, QT_NO_DATA_EXPANSION);
str.append('\0');
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
str.ptr());
return TRUE;
}
}
return FALSE;
}
};
class Item_func_geometrycollection: public Item_func_spatial_collection
{
public:
Item_func_geometrycollection(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_geometrycollection,
Geometry::wkb_point)
{ }
const Type_handler *type_handler() const
{
return &type_handler_geometrycollection;
}
const char *func_name() const { return "geometrycollection"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_geometrycollection>(thd, this); }
};
class Item_func_linestring: public Item_func_spatial_collection
{
public:
Item_func_linestring(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_linestring,
Geometry::wkb_point)
{ }
const Type_handler *type_handler() const { return &type_handler_linestring; }
const char *func_name() const { return "linestring"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_linestring>(thd, this); }
};
class Item_func_polygon: public Item_func_spatial_collection
{
public:
Item_func_polygon(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_polygon,
Geometry::wkb_linestring)
{ }
const Type_handler *type_handler() const { return &type_handler_polygon; }
const char *func_name() const { return "polygon"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_polygon>(thd, this); }
};
class Item_func_multilinestring: public Item_func_spatial_collection
{
public:
Item_func_multilinestring(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_multilinestring,
Geometry::wkb_linestring)
{ }
const Type_handler *type_handler() const
{
return &type_handler_multilinestring;
}
const char *func_name() const { return "multilinestring"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_multilinestring>(thd, this); }
};
class Item_func_multipoint: public Item_func_spatial_collection
{
public:
Item_func_multipoint(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_multipoint,
Geometry::wkb_point)
{ }
const Type_handler *type_handler() const
{
return &type_handler_multipoint;
}
const char *func_name() const { return "multipoint"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_multipoint>(thd, this); }
};
class Item_func_multipolygon: public Item_func_spatial_collection
{
public:
Item_func_multipolygon(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_multipolygon,
Geometry::wkb_polygon)
{ }
const Type_handler *type_handler() const
{
return &type_handler_multipolygon;
}
const char *func_name() const { return "multipolygon"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_multipolygon>(thd, this); }
};
/*
Spatial relations
*/
class Item_func_spatial_rel: public Item_bool_func2_with_rev
{
protected:
enum Functype spatial_rel;
String tmp_value1, tmp_value2;
SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
KEY_PART *key_part,
Item_func::Functype type, Item *value);
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel)
{
flags|= ITEM_FLAG_MAYBE_NULL;
}
enum Functype functype() const { return spatial_rel; }
enum Functype rev_functype() const
{
switch (spatial_rel)
{
case SP_CONTAINS_FUNC:
return SP_WITHIN_FUNC;
case SP_WITHIN_FUNC:
return SP_CONTAINS_FUNC;
default:
return spatial_rel;
}
}
bool is_null() { (void) val_int(); return null_value; }
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
uint *and_level, table_map usable_tables,
SARGABLE_PARAM **sargables)
{
return add_key_fields_optimize_op(join, key_fields, and_level,
usable_tables, sargables, false);
}
bool need_parentheses_in_default() { return false; }
Item *build_clone(THD *thd) { return 0; }
};
class Item_func_spatial_mbr_rel: public Item_func_spatial_rel
{
public:
Item_func_spatial_mbr_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
Item_func_spatial_rel(thd, a, b, sp_rel)
{ }
longlong val_int();
const char *func_name() const;
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_mbr_rel>(thd, this); }
};
class Item_func_spatial_precise_rel: public Item_func_spatial_rel
{
Gcalc_heap collector;
Gcalc_scan_iterator scan_it;
Gcalc_function func;
public:
Item_func_spatial_precise_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
Item_func_spatial_rel(thd, a, b, sp_rel), collector()
{ }
longlong val_int();
const char *func_name() const;
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_precise_rel>(thd, this); }
};
class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry
{
Gcalc_heap collector;
Gcalc_scan_iterator scan_it;
Gcalc_function func;
String tmp_value1, tmp_value2, tmp_matrix;
bool check_arguments() const
{
return Item_bool_func_args_geometry_geometry::check_arguments() ||
args[2]->check_type_general_purpose_string(func_name());
}
public:
Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
Item_bool_func_args_geometry_geometry(thd, a, b, matrix)
{ }
longlong val_int();
const char *func_name() const { return "st_relate"; }
bool need_parentheses_in_default() { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_relate>(thd, this); }
};
/*
Spatial operations
*/
class Item_func_spatial_operation: public Item_geometry_func
{
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Gcalc_function::op_type spatial_op;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_result_receiver res_receiver;
Gcalc_operation_reducer operation;
String tmp_value1,tmp_value2;
public:
Item_func_spatial_operation(THD *thd, Item *a,Item *b,
Gcalc_function::op_type sp_op):
Item_geometry_func(thd, a, b), spatial_op(sp_op)
{}
virtual ~Item_func_spatial_operation();
String *val_str(String *);
const char *func_name() const;
virtual inline void print(String *str, enum_query_type query_type)
{
Item_func::print(str, query_type);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_operation>(thd, this); }
};
class Item_func_buffer: public Item_geometry_func_args_geometry
{
bool check_arguments() const
{
return Item_geometry_func_args_geometry::check_arguments() ||
args[1]->check_type_can_return_real(func_name());
}
protected:
class Transporter : public Gcalc_operation_transporter
{
int m_npoints;
double m_d;
double x1,y1,x2,y2;
double x00,y00,x01,y01;
int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2);
int add_last_edge_buffer();
int add_point_buffer(double x, double y);
int complete();
int m_nshapes;
Gcalc_function::op_type buffer_op;
int last_shape_pos;
bool skip_line;
public:
Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) :
Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d),
m_nshapes(0), buffer_op((d > 0.0) ? Gcalc_function::op_union :
Gcalc_function::op_difference),
skip_line(FALSE)
{}
int single_point(double x, double y);
int start_line();
int complete_line();
int start_poly();
int complete_poly();
int start_ring();
int complete_ring();
int add_point(double x, double y);
int start_collection(int n_objects);
};
Gcalc_heap collector;
Gcalc_function func;
Gcalc_result_receiver res_receiver;
Gcalc_operation_reducer operation;
public:
Item_func_buffer(THD *thd, Item *obj, Item *distance)
:Item_geometry_func_args_geometry(thd, obj, distance) {}
const char *func_name() const { return "st_buffer"; }
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_buffer>(thd, this); }
};
class Item_func_isempty: public Item_bool_func_args_geometry
{
public:
Item_func_isempty(THD *thd, Item *a)
:Item_bool_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isempty"; }
bool fix_length_and_dec() { flags|= ITEM_FLAG_MAYBE_NULL; return FALSE; }
bool need_parentheses_in_default() { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isempty>(thd, this); }
};
class Item_func_issimple: public Item_long_func_args_geometry
{
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
String tmp;
public:
Item_func_issimple(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_issimple"; }
bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
decimal_digits_t decimal_precision() const override { return 1; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_issimple>(thd, this); }
};
class Item_func_isclosed: public Item_long_func_args_geometry
{
public:
Item_func_isclosed(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isclosed"; }
bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
decimal_digits_t decimal_precision() const override { return 1; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isclosed>(thd, this); }
};
class Item_func_isring: public Item_func_issimple
{
public:
Item_func_isring(THD *thd, Item *a): Item_func_issimple(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isring"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isring>(thd, this); }
};
class Item_func_dimension: public Item_long_func_args_geometry
{
public:
Item_func_dimension(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_dimension"; }
bool fix_length_and_dec() { max_length= 10; flags|= ITEM_FLAG_MAYBE_NULL; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_dimension>(thd, this); }
};
class Item_func_x: public Item_real_func_args_geometry
{
public:
Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_x"; }
bool fix_length_and_dec()
{
if (Item_real_func::fix_length_and_dec())
return TRUE;
flags|= ITEM_FLAG_MAYBE_NULL;
return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_x>(thd, this); }
};
class Item_func_y: public Item_real_func_args_geometry
{
public:
Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_y"; }
bool fix_length_and_dec()
{
if (Item_real_func::fix_length_and_dec())
return TRUE;
flags|= ITEM_FLAG_MAYBE_NULL;
return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_y>(thd, this); }
};
class Item_func_numgeometries: public Item_long_func_args_geometry
{
public:
Item_func_numgeometries(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numgeometries"; }
bool fix_length_and_dec() { max_length= 10; flags|= ITEM_FLAG_MAYBE_NULL; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_numgeometries>(thd, this); }
};
class Item_func_numinteriorring: public Item_long_func_args_geometry
{
public:
Item_func_numinteriorring(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numinteriorrings"; }
bool fix_length_and_dec() { max_length= 10; flags|= ITEM_FLAG_MAYBE_NULL; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_numinteriorring>(thd, this); }
};
class Item_func_numpoints: public Item_long_func_args_geometry
{
public:
Item_func_numpoints(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numpoints"; }
bool fix_length_and_dec() { max_length= 10; flags|= ITEM_FLAG_MAYBE_NULL; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_numpoints>(thd, this); }
};
class Item_func_area: public Item_real_func_args_geometry
{
public:
Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_area"; }
bool fix_length_and_dec()
{
if (Item_real_func::fix_length_and_dec())
return TRUE;
flags|= ITEM_FLAG_MAYBE_NULL;
return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_area>(thd, this); }
};
class Item_func_glength: public Item_real_func_args_geometry
{
String value;
public:
Item_func_glength(THD *thd, Item *a)
:Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_length"; }
bool fix_length_and_dec()
{
if (Item_real_func::fix_length_and_dec())
return TRUE;
flags|= ITEM_FLAG_MAYBE_NULL;
return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_glength>(thd, this); }
};
class Item_func_srid: public Item_long_func_args_geometry
{
public:
Item_func_srid(THD *thd, Item *a)
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "srid"; }
bool fix_length_and_dec() { max_length= 10; flags|= ITEM_FLAG_MAYBE_NULL; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_srid>(thd, this); }
};
class Item_func_distance: public Item_real_func_args_geometry_geometry
{
String tmp_value1;
String tmp_value2;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
Item_func_distance(THD *thd, Item *a, Item *b)
:Item_real_func_args_geometry_geometry(thd, a, b) {}
double val_real();
const char *func_name() const { return "st_distance"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_distance>(thd, this); }
};
class Item_func_sphere_distance: public Item_real_func
{
double spherical_distance_points(Geometry *g1, Geometry *g2,
const double sphere_r);
public:
Item_func_sphere_distance(THD *thd, List<Item> &list):
Item_real_func(thd, list) {}
double val_real();
const char *func_name() const { return "st_distance_sphere"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_sphere_distance>(thd, this); }
};
class Item_func_pointonsurface: public Item_geometry_func_args_geometry
{
String tmp_value;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
Item_func_pointonsurface(THD *thd, Item *a)
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_pointonsurface"; }
String *val_str(String *);
const Type_handler *type_handler() const
{
return &type_handler_point;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_pointonsurface>(thd, this); }
};
#ifndef DBUG_OFF
class Item_func_gis_debug: public Item_long_func
{
public:
Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
{ null_value= false; }
bool fix_length_and_dec() { fix_char_length(10); return FALSE; }
const char *func_name() const { return "st_gis_debug"; }
longlong val_int();
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_gis_debug>(thd, this); }
};
#endif
#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
#define GEOM_TYPE(x) (x)
#else /*HAVE_SPATIAL*/
#define GEOM_NEW(thd, obj_constructor) NULL
#define GEOM_TYPE(x) NULL
#endif /*HAVE_SPATIAL*/
#endif /* ITEM_GEOFUNC_INCLUDED */