mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
7b50447aa6
MDEV-9408 CREATE TABLE SELECT MAX(int_column) creates different columns for table vs view There were three almost identical pieces of the code: - Field *Item_func::tmp_table_field(); - Field *Item_sum::create_tmp_field(); - Field *create_tmp_field_from_item(); with a difference in very small details (hence the bugs): Only Item_func::tmp_table_field() was correct, the other two were not. Removing the two incorrect pieces of the redundant code. Joining these three functions/methods into a single virtual method Item::create_tmp_field(). Additionally, moving Item::make_string_field() and Item::tmp_table_field_from_field_type() from the public into the protected section of the class declaration, as they are now not needed outside of Item.
627 lines
17 KiB
C++
627 lines
17 KiB
C++
#ifndef ITEM_GEOFUNC_INCLUDED
|
|
#define ITEM_GEOFUNC_INCLUDED
|
|
|
|
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
|
|
Copyright (C) 2011, 2015 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-1301, USA */
|
|
|
|
|
|
/* This file defines all spatial functions */
|
|
|
|
#ifdef HAVE_SPATIAL
|
|
|
|
#ifdef USE_PRAGMA_INTERFACE
|
|
#pragma interface /* gcc class implementation */
|
|
#endif
|
|
|
|
#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) {}
|
|
void fix_length_and_dec();
|
|
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
|
|
Field *create_field_for_create_select(THD *thd, TABLE *table);
|
|
};
|
|
|
|
class Item_func_geometry_from_text: public Item_geometry_func
|
|
{
|
|
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 *);
|
|
};
|
|
|
|
class Item_func_geometry_from_wkb: public Item_geometry_func
|
|
{
|
|
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 *);
|
|
};
|
|
|
|
class Item_func_as_wkt: public Item_str_ascii_func
|
|
{
|
|
public:
|
|
Item_func_as_wkt(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
|
|
const char *func_name() const { return "st_astext"; }
|
|
String *val_str_ascii(String *);
|
|
void fix_length_and_dec();
|
|
};
|
|
|
|
class Item_func_as_wkb: public Item_geometry_func
|
|
{
|
|
public:
|
|
Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
|
|
const char *func_name() const { return "st_aswkb"; }
|
|
String *val_str(String *);
|
|
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
|
};
|
|
|
|
class Item_func_geometry_type: public Item_str_ascii_func
|
|
{
|
|
public:
|
|
Item_func_geometry_type(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
|
|
String *val_str_ascii(String *);
|
|
const char *func_name() const { return "st_geometrytype"; }
|
|
void fix_length_and_dec()
|
|
{
|
|
// "GeometryCollection" is the longest
|
|
fix_length_and_charset(20, default_charset());
|
|
maybe_null= 1;
|
|
};
|
|
};
|
|
|
|
|
|
// #define HEAVY_CONVEX_HULL
|
|
class Item_func_convexhull: public Item_geometry_func
|
|
{
|
|
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(thd, a),
|
|
res_heap(8192, sizeof(ch_node))
|
|
{}
|
|
const char *func_name() const { return "st_convexhull"; }
|
|
String *val_str(String *);
|
|
};
|
|
|
|
|
|
class Item_func_centroid: public Item_geometry_func
|
|
{
|
|
public:
|
|
Item_func_centroid(THD *thd, Item *a): Item_geometry_func(thd, a) {}
|
|
const char *func_name() const { return "st_centroid"; }
|
|
String *val_str(String *);
|
|
Field::geometry_type get_geometry_type() const;
|
|
};
|
|
|
|
class Item_func_envelope: public Item_geometry_func
|
|
{
|
|
public:
|
|
Item_func_envelope(THD *thd, Item *a): Item_geometry_func(thd, a) {}
|
|
const char *func_name() const { return "st_envelope"; }
|
|
String *val_str(String *);
|
|
Field::geometry_type get_geometry_type() const;
|
|
};
|
|
|
|
|
|
class Item_func_boundary: public Item_geometry_func
|
|
{
|
|
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(thd, a) {}
|
|
const char *func_name() const { return "st_boundary"; }
|
|
String *val_str(String *);
|
|
};
|
|
|
|
|
|
class Item_func_point: public Item_geometry_func
|
|
{
|
|
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 *);
|
|
Field::geometry_type get_geometry_type() const;
|
|
};
|
|
|
|
class Item_func_spatial_decomp: public Item_geometry_func
|
|
{
|
|
enum Functype decomp_func;
|
|
public:
|
|
Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
|
|
Item_geometry_func(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 *);
|
|
};
|
|
|
|
class Item_func_spatial_decomp_n: public Item_geometry_func
|
|
{
|
|
enum Functype decomp_func_n;
|
|
public:
|
|
Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft):
|
|
Item_geometry_func(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 *);
|
|
};
|
|
|
|
class Item_func_spatial_collection: public Item_geometry_func
|
|
{
|
|
String tmp_value;
|
|
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 *);
|
|
void fix_length_and_dec()
|
|
{
|
|
Item_geometry_func::fix_length_and_dec();
|
|
for (unsigned int i= 0; i < arg_count; ++i)
|
|
{
|
|
if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
|
|
{
|
|
String str;
|
|
args[i]->print(&str, QT_ORDINARY);
|
|
str.append('\0');
|
|
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
|
|
str.ptr());
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *func_name() const { return "st_multipoint"; }
|
|
};
|
|
|
|
|
|
/*
|
|
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);
|
|
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)
|
|
{
|
|
maybe_null= true;
|
|
}
|
|
enum Functype functype() const { return spatial_rel; }
|
|
enum Functype rev_functype() const { 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);
|
|
}
|
|
};
|
|
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
class Item_func_spatial_relate: public Item_bool_func
|
|
{
|
|
Gcalc_heap collector;
|
|
Gcalc_scan_iterator scan_it;
|
|
Gcalc_function func;
|
|
String tmp_value1, tmp_value2, tmp_matrix;
|
|
public:
|
|
Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
|
|
Item_bool_func(thd, a, b, matrix)
|
|
{ }
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_relate"; }
|
|
};
|
|
|
|
|
|
/*
|
|
Spatial operations
|
|
*/
|
|
|
|
class Item_func_spatial_operation: public Item_geometry_func
|
|
{
|
|
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);
|
|
}
|
|
};
|
|
|
|
|
|
class Item_func_buffer: public Item_geometry_func
|
|
{
|
|
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;
|
|
String tmp_value;
|
|
|
|
public:
|
|
Item_func_buffer(THD *thd, Item *obj, Item *distance):
|
|
Item_geometry_func(thd, obj, distance) {}
|
|
const char *func_name() const { return "st_buffer"; }
|
|
String *val_str(String *);
|
|
};
|
|
|
|
|
|
class Item_func_isempty: public Item_bool_func
|
|
{
|
|
public:
|
|
Item_func_isempty(THD *thd, Item *a): Item_bool_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_isempty"; }
|
|
void fix_length_and_dec() { maybe_null= 1; }
|
|
};
|
|
|
|
class Item_func_issimple: public Item_int_func
|
|
{
|
|
Gcalc_heap collector;
|
|
Gcalc_function func;
|
|
Gcalc_scan_iterator scan_it;
|
|
String tmp;
|
|
public:
|
|
Item_func_issimple(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_issimple"; }
|
|
void fix_length_and_dec() { decimals=0; max_length=2; }
|
|
uint decimal_precision() const { return 1; }
|
|
};
|
|
|
|
class Item_func_isclosed: public Item_int_func
|
|
{
|
|
public:
|
|
Item_func_isclosed(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_isclosed"; }
|
|
void fix_length_and_dec() { decimals=0; max_length=2; }
|
|
uint decimal_precision() const { return 1; }
|
|
};
|
|
|
|
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"; }
|
|
};
|
|
|
|
class Item_func_dimension: public Item_int_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_dimension(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_dimension"; }
|
|
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
|
};
|
|
|
|
class Item_func_x: public Item_real_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_x(THD *thd, Item *a): Item_real_func(thd, a) {}
|
|
double val_real();
|
|
const char *func_name() const { return "st_x"; }
|
|
void fix_length_and_dec()
|
|
{
|
|
Item_real_func::fix_length_and_dec();
|
|
maybe_null= 1;
|
|
}
|
|
};
|
|
|
|
|
|
class Item_func_y: public Item_real_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_y(THD *thd, Item *a): Item_real_func(thd, a) {}
|
|
double val_real();
|
|
const char *func_name() const { return "st_y"; }
|
|
void fix_length_and_dec()
|
|
{
|
|
Item_real_func::fix_length_and_dec();
|
|
maybe_null= 1;
|
|
}
|
|
};
|
|
|
|
|
|
class Item_func_numgeometries: public Item_int_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_numgeometries(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_numgeometries"; }
|
|
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
|
};
|
|
|
|
|
|
class Item_func_numinteriorring: public Item_int_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_numinteriorring(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_numinteriorrings"; }
|
|
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
|
};
|
|
|
|
|
|
class Item_func_numpoints: public Item_int_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_numpoints(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "st_numpoints"; }
|
|
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
|
};
|
|
|
|
|
|
class Item_func_area: public Item_real_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_area(THD *thd, Item *a): Item_real_func(thd, a) {}
|
|
double val_real();
|
|
const char *func_name() const { return "st_area"; }
|
|
void fix_length_and_dec()
|
|
{
|
|
Item_real_func::fix_length_and_dec();
|
|
maybe_null= 1;
|
|
}
|
|
};
|
|
|
|
|
|
class Item_func_glength: public Item_real_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_glength(THD *thd, Item *a): Item_real_func(thd, a) {}
|
|
double val_real();
|
|
const char *func_name() const { return "st_length"; }
|
|
void fix_length_and_dec()
|
|
{
|
|
Item_real_func::fix_length_and_dec();
|
|
maybe_null= 1;
|
|
}
|
|
};
|
|
|
|
|
|
class Item_func_srid: public Item_int_func
|
|
{
|
|
String value;
|
|
public:
|
|
Item_func_srid(THD *thd, Item *a): Item_int_func(thd, a) {}
|
|
longlong val_int();
|
|
const char *func_name() const { return "srid"; }
|
|
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
|
};
|
|
|
|
|
|
class Item_func_distance: public Item_real_func
|
|
{
|
|
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(thd, a, b) {}
|
|
double val_real();
|
|
const char *func_name() const { return "st_distance"; }
|
|
};
|
|
|
|
|
|
class Item_func_pointonsurface: public Item_geometry_func
|
|
{
|
|
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(thd, a) {}
|
|
const char *func_name() const { return "st_pointonsurface"; }
|
|
String *val_str(String *);
|
|
Field::geometry_type get_geometry_type() const;
|
|
};
|
|
|
|
|
|
#ifndef DBUG_OFF
|
|
class Item_func_gis_debug: public Item_int_func
|
|
{
|
|
public:
|
|
Item_func_gis_debug(THD *thd, Item *a): Item_int_func(thd, a)
|
|
{ null_value= false; }
|
|
const char *func_name() const { return "st_gis_debug"; }
|
|
longlong val_int();
|
|
};
|
|
#endif
|
|
|
|
|
|
#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
|
|
|
|
#else /*HAVE_SPATIAL*/
|
|
|
|
#define GEOM_NEW(thd, obj_constructor) NULL
|
|
|
|
#endif /*HAVE_SPATIAL*/
|
|
#endif /* ITEM_GEOFUNC_INCLUDED */
|