1 #ifndef ITEM_GEOFUNC_INCLUDED
2 #define ITEM_GEOFUNC_INCLUDED
3 
4 /* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
5    Copyright (C) 2011, 2021, MariaDB
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; version 2 of the License.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA */
19 
20 
21 /* This file defines all spatial functions */
22 
23 #ifdef HAVE_SPATIAL
24 
25 #ifdef USE_PRAGMA_INTERFACE
26 #pragma interface			/* gcc class implementation */
27 #endif
28 
29 #include "gcalc_slicescan.h"
30 #include "gcalc_tools.h"
31 
32 class Item_geometry_func: public Item_str_func
33 {
34 public:
Item_geometry_func(THD * thd)35   Item_geometry_func(THD *thd): Item_str_func(thd) {}
Item_geometry_func(THD * thd,Item * a)36   Item_geometry_func(THD *thd, Item *a): Item_str_func(thd, a) {}
Item_geometry_func(THD * thd,Item * a,Item * b)37   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)38   Item_geometry_func(THD *thd, Item *a, Item *b, Item *c):
39     Item_str_func(thd, a, b, c) {}
Item_geometry_func(THD * thd,List<Item> & list)40   Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
41   bool fix_length_and_dec();
type_handler()42   const Type_handler *type_handler() const { return &type_handler_geometry; }
43 };
44 
45 
46 /*
47   Functions returning REAL measurements of a single GEOMETRY argument
48 */
49 class Item_real_func_args_geometry: public Item_real_func
50 {
51 protected:
52   String value;
check_arguments()53   bool check_arguments() const
54   {
55     DBUG_ASSERT(arg_count == 1);
56     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
57   }
58 public:
Item_real_func_args_geometry(THD * thd,Item * a)59   Item_real_func_args_geometry(THD *thd, Item *a)
60    :Item_real_func(thd, a) {}
61 };
62 
63 
64 /*
65   Functions returning INT measurements of a single GEOMETRY argument
66 */
67 class Item_long_func_args_geometry: public Item_long_func
68 {
check_arguments()69   bool check_arguments() const
70   {
71     DBUG_ASSERT(arg_count == 1);
72     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
73   }
74 protected:
75   String value;
76 public:
Item_long_func_args_geometry(THD * thd,Item * a)77   Item_long_func_args_geometry(THD *thd, Item *a)
78    :Item_long_func(thd, a) {}
79 };
80 
81 
82 /*
83   Functions returning BOOL measurements of a single GEOMETRY argument
84 */
85 class Item_bool_func_args_geometry: public Item_bool_func
86 {
87 protected:
88   String value;
check_arguments()89   bool check_arguments() const
90   {
91     DBUG_ASSERT(arg_count == 1);
92     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
93   }
94 public:
Item_bool_func_args_geometry(THD * thd,Item * a)95   Item_bool_func_args_geometry(THD *thd, Item *a)
96    :Item_bool_func(thd, a) {}
97 };
98 
99 
100 /*
101   Functions returning ASCII string measurements of a single GEOMETRY argument
102 */
103 class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
104 {
105 protected:
check_arguments()106   bool check_arguments() const
107   {
108     DBUG_ASSERT(arg_count >= 1);
109     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
110   }
111 public:
Item_str_ascii_func_args_geometry(THD * thd,Item * a)112   Item_str_ascii_func_args_geometry(THD *thd, Item *a)
113    :Item_str_ascii_func(thd, a) {}
Item_str_ascii_func_args_geometry(THD * thd,Item * a,Item * b)114   Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
115    :Item_str_ascii_func(thd, a, b) {}
Item_str_ascii_func_args_geometry(THD * thd,Item * a,Item * b,Item * c)116   Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c)
117    :Item_str_ascii_func(thd, a, b, c) {}
118 };
119 
120 
121 /*
122   Functions returning binary string measurements of a single GEOMETRY argument
123 */
124 class Item_binary_func_args_geometry: public Item_str_func
125 {
126 protected:
check_arguments()127   bool check_arguments() const
128   {
129     DBUG_ASSERT(arg_count >= 1);
130     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
131   }
132 public:
Item_binary_func_args_geometry(THD * thd,Item * a)133   Item_binary_func_args_geometry(THD *thd, Item *a)
134    :Item_str_func(thd, a) {}
135 };
136 
137 
138 /*
139   Functions returning GEOMETRY measurements of a single GEOEMETRY argument
140 */
141 class Item_geometry_func_args_geometry: public Item_geometry_func
142 {
143 protected:
check_arguments()144   bool check_arguments() const
145   {
146     DBUG_ASSERT(arg_count >= 1);
147     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
148   }
149 public:
Item_geometry_func_args_geometry(THD * thd,Item * a)150   Item_geometry_func_args_geometry(THD *thd, Item *a)
151    :Item_geometry_func(thd, a) {}
Item_geometry_func_args_geometry(THD * thd,Item * a,Item * b)152   Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b)
153    :Item_geometry_func(thd, a, b) {}
154 };
155 
156 
157 /*
158   Functions returning REAL result relationships between two GEOMETRY arguments
159 */
160 class Item_real_func_args_geometry_geometry: public Item_real_func
161 {
162 protected:
check_arguments()163   bool check_arguments() const
164   {
165     DBUG_ASSERT(arg_count >= 2);
166     return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
167   }
168 public:
Item_real_func_args_geometry_geometry(THD * thd,Item * a,Item * b)169   Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
170    :Item_real_func(thd, a, b) {}
171 };
172 
173 
174 /*
175   Functions returning BOOL result relationships between two GEOMETRY arguments
176 */
177 class Item_bool_func_args_geometry_geometry: public Item_bool_func
178 {
179 protected:
180   String value;
check_arguments()181   bool check_arguments() const
182   {
183     DBUG_ASSERT(arg_count >= 2);
184     return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
185   }
186 public:
Item_bool_func_args_geometry_geometry(THD * thd,Item * a,Item * b,Item * c)187   Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
188    :Item_bool_func(thd, a, b, c) {}
189 };
190 
191 
192 class Item_func_geometry_from_text: public Item_geometry_func
193 {
check_arguments()194   bool check_arguments() const
195   {
196     return args[0]->check_type_general_purpose_string(func_name()) ||
197            check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
198   }
199 public:
Item_func_geometry_from_text(THD * thd,Item * a)200   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)201   Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
202     Item_geometry_func(thd, a, srid) {}
func_name()203   const char *func_name() const { return "st_geometryfromtext"; }
204   String *val_str(String *);
get_copy(THD * thd)205   Item *get_copy(THD *thd)
206   { return get_item_copy<Item_func_geometry_from_text>(thd, this); }
207 };
208 
209 class Item_func_geometry_from_wkb: public Item_geometry_func
210 {
check_arguments()211   bool check_arguments() const
212   {
213     return args[0]->check_type_or_binary(func_name(), &type_handler_geometry) ||
214            check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
215   }
216 public:
Item_func_geometry_from_wkb(THD * thd,Item * a)217   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)218   Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid):
219     Item_geometry_func(thd, a, srid) {}
func_name()220   const char *func_name() const { return "st_geometryfromwkb"; }
221   String *val_str(String *);
get_copy(THD * thd)222   Item *get_copy(THD *thd)
223   { return get_item_copy<Item_func_geometry_from_wkb>(thd, this); }
224 };
225 
226 
227 class Item_func_geometry_from_json: public Item_geometry_func
228 {
229   String tmp_js;
check_arguments()230   bool check_arguments() const
231   {
232     // TODO: check with Alexey, for better args[1] and args[2] type control
233     return args[0]->check_type_general_purpose_string(func_name()) ||
234            check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
235   }
236 public:
Item_func_geometry_from_json(THD * thd,Item * js)237   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)238   Item_func_geometry_from_json(THD *thd, Item *js, Item *opt):
239     Item_geometry_func(thd, js, opt) {}
Item_func_geometry_from_json(THD * thd,Item * js,Item * opt,Item * srid)240   Item_func_geometry_from_json(THD *thd, Item *js, Item *opt, Item *srid):
241     Item_geometry_func(thd, js, opt, srid) {}
func_name()242   const char *func_name() const { return "st_geomfromgeojson"; }
243   String *val_str(String *);
get_copy(THD * thd)244   Item *get_copy(THD *thd)
245   { return get_item_copy<Item_func_geometry_from_json>(thd, this); }
246 };
247 
248 
249 class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
250 {
251 public:
Item_func_as_wkt(THD * thd,Item * a)252   Item_func_as_wkt(THD *thd, Item *a)
253    :Item_str_ascii_func_args_geometry(thd, a) {}
func_name()254   const char *func_name() const { return "st_astext"; }
255   String *val_str_ascii(String *);
256   bool fix_length_and_dec();
get_copy(THD * thd)257   Item *get_copy(THD *thd)
258   { return get_item_copy<Item_func_as_wkt>(thd, this); }
259 };
260 
261 class Item_func_as_wkb: public Item_binary_func_args_geometry
262 {
263 public:
Item_func_as_wkb(THD * thd,Item * a)264   Item_func_as_wkb(THD *thd, Item *a)
265    :Item_binary_func_args_geometry(thd, a) {}
func_name()266   const char *func_name() const { return "st_aswkb"; }
267   String *val_str(String *);
type_handler()268   const Type_handler *type_handler() const { return &type_handler_long_blob; }
fix_length_and_dec()269   bool fix_length_and_dec()
270   {
271     collation.set(&my_charset_bin);
272     decimals=0;
273     max_length= (uint32) UINT_MAX32;
274     maybe_null= 1;
275     return FALSE;
276   }
get_copy(THD * thd)277   Item *get_copy(THD *thd)
278   { return get_item_copy<Item_func_as_wkb>(thd, this); }
279 };
280 
281 
282 class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
283 {
check_arguments()284   bool check_arguments() const
285   {
286     // TODO: check with Alexey, for better args[1] and args[2] type control
287     return Item_str_ascii_func_args_geometry::check_arguments() ||
288            check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
289   }
290 public:
Item_func_as_geojson(THD * thd,Item * js)291   Item_func_as_geojson(THD *thd, Item *js)
292    :Item_str_ascii_func_args_geometry(thd, js) {}
Item_func_as_geojson(THD * thd,Item * js,Item * max_dec_digits)293   Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
294    :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)295   Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
296    :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
func_name()297   const char *func_name() const { return "st_asgeojson"; }
298   bool fix_length_and_dec();
299   String *val_str_ascii(String *);
get_copy(THD * thd)300   Item *get_copy(THD *thd)
301   { return get_item_copy<Item_func_as_geojson>(thd, this); }
302 };
303 
304 
305 class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
306 {
307 public:
Item_func_geometry_type(THD * thd,Item * a)308   Item_func_geometry_type(THD *thd, Item *a)
309    :Item_str_ascii_func_args_geometry(thd, a) {}
310   String *val_str_ascii(String *);
func_name()311   const char *func_name() const { return "st_geometrytype"; }
fix_length_and_dec()312   bool fix_length_and_dec()
313   {
314     // "GeometryCollection" is the longest
315     fix_length_and_charset(20, default_charset());
316     maybe_null= 1;
317     return FALSE;
318   };
get_copy(THD * thd)319   Item *get_copy(THD *thd)
320   { return get_item_copy<Item_func_geometry_type>(thd, this); }
321 };
322 
323 
324 // #define HEAVY_CONVEX_HULL
325 class Item_func_convexhull: public Item_geometry_func_args_geometry
326 {
327   class ch_node: public Gcalc_dyn_list::Item
328   {
329   public:
330     const Gcalc_heap::Info *pi;
331     ch_node *prev;
332     Gcalc_dyn_list::Item *next;
get_next()333     ch_node *get_next() { return (ch_node *) next; }
334   };
335 
336   Gcalc_heap collector;
337   Gcalc_function func;
338   Gcalc_dyn_list res_heap;
339 
340   Gcalc_result_receiver res_receiver;
341   String tmp_value;
342 #ifdef HEAVY_CONVEX_HULL
343   Gcalc_scan_iterator scan_it;
344 #endif /*HEAVY_CONVEX_HULL*/
new_ch_node()345   ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
346   int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
347 public:
Item_func_convexhull(THD * thd,Item * a)348   Item_func_convexhull(THD *thd, Item *a)
349    :Item_geometry_func_args_geometry(thd, a),
350     res_heap(8192, sizeof(ch_node))
351     {}
func_name()352   const char *func_name() const { return "st_convexhull"; }
353   String *val_str(String *);
get_copy(THD * thd)354   Item *get_copy(THD *thd)
355   { return get_item_copy<Item_func_convexhull>(thd, this); }
356 };
357 
358 
359 class Item_func_centroid: public Item_geometry_func_args_geometry
360 {
361 public:
Item_func_centroid(THD * thd,Item * a)362   Item_func_centroid(THD *thd, Item *a)
363    :Item_geometry_func_args_geometry(thd, a) {}
func_name()364   const char *func_name() const { return "st_centroid"; }
365   String *val_str(String *);
366   Field::geometry_type get_geometry_type() const;
get_copy(THD * thd)367   Item *get_copy(THD *thd)
368   { return get_item_copy<Item_func_centroid>(thd, this); }
369 };
370 
371 class Item_func_envelope: public Item_geometry_func_args_geometry
372 {
373 public:
Item_func_envelope(THD * thd,Item * a)374   Item_func_envelope(THD *thd, Item *a)
375    :Item_geometry_func_args_geometry(thd, a) {}
func_name()376   const char *func_name() const { return "st_envelope"; }
377   String *val_str(String *);
378   Field::geometry_type get_geometry_type() const;
get_copy(THD * thd)379   Item *get_copy(THD *thd)
380   { return get_item_copy<Item_func_envelope>(thd, this); }
381 };
382 
383 
384 class Item_func_boundary: public Item_geometry_func_args_geometry
385 {
386   class Transporter : public Gcalc_shape_transporter
387   {
388     Gcalc_result_receiver *m_receiver;
389     uint n_points;
390     Gcalc_function::shape_type current_type;
391     double last_x, last_y;
392   public:
Transporter(Gcalc_result_receiver * receiver)393     Transporter(Gcalc_result_receiver *receiver) :
394       Gcalc_shape_transporter(NULL), m_receiver(receiver)
395     {}
396     int single_point(double x, double y);
397     int start_line();
398     int complete_line();
399     int start_poly();
400     int complete_poly();
401     int start_ring();
402     int complete_ring();
403     int add_point(double x, double y);
404 
405     int start_collection(int n_objects);
406   };
407   Gcalc_result_receiver res_receiver;
408 public:
Item_func_boundary(THD * thd,Item * a)409   Item_func_boundary(THD *thd, Item *a)
410    :Item_geometry_func_args_geometry(thd, a) {}
func_name()411   const char *func_name() const { return "st_boundary"; }
412   String *val_str(String *);
get_copy(THD * thd)413   Item *get_copy(THD *thd)
414   { return get_item_copy<Item_func_boundary>(thd, this); }
415 };
416 
417 
418 class Item_func_point: public Item_geometry_func
419 {
check_arguments()420   bool check_arguments() const
421   { return check_argument_types_can_return_real(0, 2); }
422 public:
Item_func_point(THD * thd,Item * a,Item * b)423   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)424   Item_func_point(THD *thd, Item *a, Item *b, Item *srid):
425     Item_geometry_func(thd, a, b, srid) {}
func_name()426   const char *func_name() const { return "point"; }
427   String *val_str(String *);
428   Field::geometry_type get_geometry_type() const;
get_copy(THD * thd)429   Item *get_copy(THD *thd)
430   { return get_item_copy<Item_func_point>(thd, this); }
431 };
432 
433 class Item_func_spatial_decomp: public Item_geometry_func_args_geometry
434 {
435   enum Functype decomp_func;
436 public:
Item_func_spatial_decomp(THD * thd,Item * a,Item_func::Functype ft)437   Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
438     Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; }
func_name()439   const char *func_name() const
440   {
441     switch (decomp_func)
442     {
443       case SP_STARTPOINT:
444         return "st_startpoint";
445       case SP_ENDPOINT:
446         return "st_endpoint";
447       case SP_EXTERIORRING:
448         return "st_exteriorring";
449       default:
450 	DBUG_ASSERT(0);  // Should never happened
451         return "spatial_decomp_unknown";
452     }
453   }
454   String *val_str(String *);
get_copy(THD * thd)455   Item *get_copy(THD *thd)
456   { return get_item_copy<Item_func_spatial_decomp>(thd, this); }
457 };
458 
459 class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry
460 {
461   enum Functype decomp_func_n;
check_arguments()462   bool check_arguments() const
463   {
464     return Item_geometry_func_args_geometry::check_arguments() ||
465            args[1]->check_type_can_return_int(func_name());
466   }
467 public:
Item_func_spatial_decomp_n(THD * thd,Item * a,Item * b,Item_func::Functype ft)468   Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft)
469    :Item_geometry_func_args_geometry(thd, a, b),
470     decomp_func_n(ft)
471   { }
func_name()472   const char *func_name() const
473   {
474     switch (decomp_func_n)
475     {
476       case SP_POINTN:
477         return "st_pointn";
478       case SP_GEOMETRYN:
479         return "st_geometryn";
480       case SP_INTERIORRINGN:
481         return "st_interiorringn";
482       default:
483 	DBUG_ASSERT(0);  // Should never happened
484         return "spatial_decomp_n_unknown";
485     }
486   }
487   String *val_str(String *);
get_copy(THD * thd)488   Item *get_copy(THD *thd)
489   { return get_item_copy<Item_func_spatial_decomp_n>(thd, this); }
490 };
491 
492 class Item_func_spatial_collection: public Item_geometry_func
493 {
check_arguments()494   bool check_arguments() const
495   {
496     return check_argument_types_or_binary(&type_handler_geometry, 0, arg_count);
497   }
498   enum Geometry::wkbType coll_type;
499   enum Geometry::wkbType item_type;
500 public:
Item_func_spatial_collection(THD * thd,List<Item> & list,enum Geometry::wkbType ct,enum Geometry::wkbType it)501   Item_func_spatial_collection(THD *thd,
502      List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it):
503   Item_geometry_func(thd, list)
504   {
505     coll_type=ct;
506     item_type=it;
507   }
508   String *val_str(String *);
fix_length_and_dec()509   bool fix_length_and_dec()
510   {
511     if (Item_geometry_func::fix_length_and_dec())
512       return TRUE;
513     for (unsigned int i= 0; i < arg_count; ++i)
514     {
515       if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
516       {
517         String str;
518         args[i]->print(&str, QT_NO_DATA_EXPANSION);
519         str.append('\0');
520         my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
521                  str.ptr());
522         return TRUE;
523       }
524     }
525     return FALSE;
526   }
527 
func_name()528   const char *func_name() const { return "geometrycollection"; }
get_copy(THD * thd)529   Item *get_copy(THD *thd)
530   { return get_item_copy<Item_func_spatial_collection>(thd, this); }
531 };
532 
533 
534 /*
535   Spatial relations
536 */
537 
538 class Item_func_spatial_rel: public Item_bool_func2_with_rev
539 {
540 protected:
541   enum Functype spatial_rel;
542   String tmp_value1, tmp_value2;
543   SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
544                        KEY_PART *key_part,
545                        Item_func::Functype type, Item *value);
check_arguments()546   bool check_arguments() const
547   {
548     DBUG_ASSERT(arg_count >= 2);
549     return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
550   }
551 public:
Item_func_spatial_rel(THD * thd,Item * a,Item * b,enum Functype sp_rel)552   Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
553     Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel)
554   {
555     maybe_null= true;
556   }
functype()557   enum Functype functype() const { return spatial_rel; }
rev_functype()558   enum Functype rev_functype() const
559   {
560     switch (spatial_rel)
561     {
562       case SP_CONTAINS_FUNC:
563         return SP_WITHIN_FUNC;
564       case SP_WITHIN_FUNC:
565         return SP_CONTAINS_FUNC;
566       default:
567         return spatial_rel;
568     }
569   }
is_null()570   bool is_null() { (void) val_int(); return null_value; }
add_key_fields(JOIN * join,KEY_FIELD ** key_fields,uint * and_level,table_map usable_tables,SARGABLE_PARAM ** sargables)571   void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
572                       uint *and_level, table_map usable_tables,
573                       SARGABLE_PARAM **sargables)
574   {
575     return add_key_fields_optimize_op(join, key_fields, and_level,
576                                       usable_tables, sargables, false);
577   }
need_parentheses_in_default()578   bool need_parentheses_in_default() { return false; }
build_clone(THD * thd)579   Item *build_clone(THD *thd) { return 0; }
580 };
581 
582 
583 class Item_func_spatial_mbr_rel: public Item_func_spatial_rel
584 {
585 public:
Item_func_spatial_mbr_rel(THD * thd,Item * a,Item * b,enum Functype sp_rel)586   Item_func_spatial_mbr_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
587     Item_func_spatial_rel(thd, a, b, sp_rel)
588   { }
589   longlong val_int();
590   const char *func_name() const;
get_copy(THD * thd)591   Item *get_copy(THD *thd)
592   { return get_item_copy<Item_func_spatial_mbr_rel>(thd, this); }
593 };
594 
595 
596 class Item_func_spatial_precise_rel: public Item_func_spatial_rel
597 {
598   Gcalc_heap collector;
599   Gcalc_scan_iterator scan_it;
600   Gcalc_function func;
601 public:
Item_func_spatial_precise_rel(THD * thd,Item * a,Item * b,enum Functype sp_rel)602   Item_func_spatial_precise_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
603     Item_func_spatial_rel(thd, a, b, sp_rel), collector()
604   { }
605   longlong val_int();
606   const char *func_name() const;
get_copy(THD * thd)607   Item *get_copy(THD *thd)
608   { return get_item_copy<Item_func_spatial_precise_rel>(thd, this); }
609 };
610 
611 
612 class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry
613 {
614   Gcalc_heap collector;
615   Gcalc_scan_iterator scan_it;
616   Gcalc_function func;
617   String tmp_value1, tmp_value2, tmp_matrix;
check_arguments()618   bool check_arguments() const
619   {
620     return Item_bool_func_args_geometry_geometry::check_arguments() ||
621            args[2]->check_type_general_purpose_string(func_name());
622   }
623 public:
Item_func_spatial_relate(THD * thd,Item * a,Item * b,Item * matrix)624   Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
625     Item_bool_func_args_geometry_geometry(thd, a, b, matrix)
626   { }
627   longlong val_int();
func_name()628   const char *func_name() const { return "st_relate"; }
need_parentheses_in_default()629   bool need_parentheses_in_default() { return false; }
get_copy(THD * thd)630   Item *get_copy(THD *thd)
631   { return get_item_copy<Item_func_spatial_relate>(thd, this); }
632 };
633 
634 
635 /*
636   Spatial operations
637 */
638 
639 class Item_func_spatial_operation: public Item_geometry_func
640 {
check_arguments()641   bool check_arguments() const
642   {
643     DBUG_ASSERT(arg_count >= 2);
644     return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
645   }
646 public:
647   Gcalc_function::op_type spatial_op;
648   Gcalc_heap collector;
649   Gcalc_function func;
650 
651   Gcalc_result_receiver res_receiver;
652   Gcalc_operation_reducer operation;
653   String tmp_value1,tmp_value2;
654 public:
Item_func_spatial_operation(THD * thd,Item * a,Item * b,Gcalc_function::op_type sp_op)655   Item_func_spatial_operation(THD *thd, Item *a,Item *b,
656                               Gcalc_function::op_type sp_op):
657     Item_geometry_func(thd, a, b), spatial_op(sp_op)
658   {}
659   virtual ~Item_func_spatial_operation();
660   String *val_str(String *);
661   const char *func_name() const;
print(String * str,enum_query_type query_type)662   virtual inline void print(String *str, enum_query_type query_type)
663   {
664     Item_func::print(str, query_type);
665   }
get_copy(THD * thd)666   Item *get_copy(THD *thd)
667   { return get_item_copy<Item_func_spatial_operation>(thd, this); }
668 };
669 
670 
671 class Item_func_buffer: public Item_geometry_func_args_geometry
672 {
check_arguments()673   bool check_arguments() const
674   {
675     return Item_geometry_func_args_geometry::check_arguments() ||
676            args[1]->check_type_can_return_real(func_name());
677   }
678 protected:
679   class Transporter : public Gcalc_operation_transporter
680   {
681     int m_npoints;
682     double m_d;
683     double x1,y1,x2,y2;
684     double x00,y00,x01,y01;
685     int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2);
686     int add_last_edge_buffer();
687     int add_point_buffer(double x, double y);
688     int complete();
689     int m_nshapes;
690     Gcalc_function::op_type buffer_op;
691     int last_shape_pos;
692     bool skip_line;
693 
694   public:
Transporter(Gcalc_function * fn,Gcalc_heap * heap,double d)695     Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) :
696       Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d),
697       m_nshapes(0), buffer_op((d > 0.0) ? Gcalc_function::op_union :
698                                           Gcalc_function::op_difference),
699       skip_line(FALSE)
700     {}
701     int single_point(double x, double y);
702     int start_line();
703     int complete_line();
704     int start_poly();
705     int complete_poly();
706     int start_ring();
707     int complete_ring();
708     int add_point(double x, double y);
709 
710     int start_collection(int n_objects);
711   };
712   Gcalc_heap collector;
713   Gcalc_function func;
714 
715   Gcalc_result_receiver res_receiver;
716   Gcalc_operation_reducer operation;
717 
718 public:
Item_func_buffer(THD * thd,Item * obj,Item * distance)719   Item_func_buffer(THD *thd, Item *obj, Item *distance)
720    :Item_geometry_func_args_geometry(thd, obj, distance) {}
func_name()721   const char *func_name() const { return "st_buffer"; }
722   String *val_str(String *);
get_copy(THD * thd)723   Item *get_copy(THD *thd)
724   { return get_item_copy<Item_func_buffer>(thd, this); }
725 };
726 
727 
728 class Item_func_isempty: public Item_bool_func_args_geometry
729 {
730 public:
Item_func_isempty(THD * thd,Item * a)731   Item_func_isempty(THD *thd, Item *a)
732    :Item_bool_func_args_geometry(thd, a) {}
733   longlong val_int();
func_name()734   const char *func_name() const { return "st_isempty"; }
fix_length_and_dec()735   bool fix_length_and_dec() { maybe_null= 1; return FALSE; }
need_parentheses_in_default()736   bool need_parentheses_in_default() { return false; }
get_copy(THD * thd)737   Item *get_copy(THD *thd)
738   { return get_item_copy<Item_func_isempty>(thd, this); }
739 };
740 
741 class Item_func_issimple: public Item_long_func_args_geometry
742 {
743   Gcalc_heap collector;
744   Gcalc_function func;
745   Gcalc_scan_iterator scan_it;
746   String tmp;
747 public:
Item_func_issimple(THD * thd,Item * a)748   Item_func_issimple(THD *thd, Item *a)
749    :Item_long_func_args_geometry(thd, a) {}
750   longlong val_int();
func_name()751   const char *func_name() const { return "st_issimple"; }
fix_length_and_dec()752   bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
decimal_precision()753   uint decimal_precision() const { return 1; }
get_copy(THD * thd)754   Item *get_copy(THD *thd)
755   { return get_item_copy<Item_func_issimple>(thd, this); }
756 };
757 
758 class Item_func_isclosed: public Item_long_func_args_geometry
759 {
760 public:
Item_func_isclosed(THD * thd,Item * a)761   Item_func_isclosed(THD *thd, Item *a)
762    :Item_long_func_args_geometry(thd, a) {}
763   longlong val_int();
func_name()764   const char *func_name() const { return "st_isclosed"; }
fix_length_and_dec()765   bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
decimal_precision()766   uint decimal_precision() const { return 1; }
get_copy(THD * thd)767   Item *get_copy(THD *thd)
768   { return get_item_copy<Item_func_isclosed>(thd, this); }
769 };
770 
771 class Item_func_isring: public Item_func_issimple
772 {
773 public:
Item_func_isring(THD * thd,Item * a)774   Item_func_isring(THD *thd, Item *a): Item_func_issimple(thd, a) {}
775   longlong val_int();
func_name()776   const char *func_name() const { return "st_isring"; }
get_copy(THD * thd)777   Item *get_copy(THD *thd)
778   { return get_item_copy<Item_func_isring>(thd, this); }
779 };
780 
781 class Item_func_dimension: public Item_long_func_args_geometry
782 {
783 public:
Item_func_dimension(THD * thd,Item * a)784   Item_func_dimension(THD *thd, Item *a)
785    :Item_long_func_args_geometry(thd, a) {}
786   longlong val_int();
func_name()787   const char *func_name() const { return "st_dimension"; }
fix_length_and_dec()788   bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
get_copy(THD * thd)789   Item *get_copy(THD *thd)
790   { return get_item_copy<Item_func_dimension>(thd, this); }
791 };
792 
793 
794 class Item_func_x: public Item_real_func_args_geometry
795 {
796 public:
Item_func_x(THD * thd,Item * a)797   Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
798   double val_real();
func_name()799   const char *func_name() const { return "st_x"; }
fix_length_and_dec()800   bool fix_length_and_dec()
801   {
802     if (Item_real_func::fix_length_and_dec())
803       return TRUE;
804     maybe_null= 1;
805     return FALSE;
806   }
get_copy(THD * thd)807   Item *get_copy(THD *thd)
808   { return get_item_copy<Item_func_x>(thd, this); }
809 };
810 
811 
812 class Item_func_y: public Item_real_func_args_geometry
813 {
814 public:
Item_func_y(THD * thd,Item * a)815   Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
816   double val_real();
func_name()817   const char *func_name() const { return "st_y"; }
fix_length_and_dec()818   bool fix_length_and_dec()
819   {
820     if (Item_real_func::fix_length_and_dec())
821       return TRUE;
822     maybe_null= 1;
823     return FALSE;
824   }
get_copy(THD * thd)825   Item *get_copy(THD *thd)
826   { return get_item_copy<Item_func_y>(thd, this); }
827 };
828 
829 
830 class Item_func_numgeometries: public Item_long_func_args_geometry
831 {
832 public:
Item_func_numgeometries(THD * thd,Item * a)833   Item_func_numgeometries(THD *thd, Item *a)
834    :Item_long_func_args_geometry(thd, a) {}
835   longlong val_int();
func_name()836   const char *func_name() const { return "st_numgeometries"; }
fix_length_and_dec()837   bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
get_copy(THD * thd)838   Item *get_copy(THD *thd)
839   { return get_item_copy<Item_func_numgeometries>(thd, this); }
840 };
841 
842 
843 class Item_func_numinteriorring: public Item_long_func_args_geometry
844 {
845 public:
Item_func_numinteriorring(THD * thd,Item * a)846   Item_func_numinteriorring(THD *thd, Item *a)
847    :Item_long_func_args_geometry(thd, a) {}
848   longlong val_int();
func_name()849   const char *func_name() const { return "st_numinteriorrings"; }
fix_length_and_dec()850   bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
get_copy(THD * thd)851   Item *get_copy(THD *thd)
852   { return get_item_copy<Item_func_numinteriorring>(thd, this); }
853 };
854 
855 
856 class Item_func_numpoints: public Item_long_func_args_geometry
857 {
858 public:
Item_func_numpoints(THD * thd,Item * a)859   Item_func_numpoints(THD *thd, Item *a)
860    :Item_long_func_args_geometry(thd, a) {}
861   longlong val_int();
func_name()862   const char *func_name() const { return "st_numpoints"; }
fix_length_and_dec()863   bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
get_copy(THD * thd)864   Item *get_copy(THD *thd)
865   { return get_item_copy<Item_func_numpoints>(thd, this); }
866 };
867 
868 
869 class Item_func_area: public Item_real_func_args_geometry
870 {
871 public:
Item_func_area(THD * thd,Item * a)872   Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
873   double val_real();
func_name()874   const char *func_name() const { return "st_area"; }
fix_length_and_dec()875   bool fix_length_and_dec()
876   {
877     if (Item_real_func::fix_length_and_dec())
878       return TRUE;
879     maybe_null= 1;
880     return FALSE;
881   }
get_copy(THD * thd)882   Item *get_copy(THD *thd)
883   { return get_item_copy<Item_func_area>(thd, this); }
884 };
885 
886 
887 class Item_func_glength: public Item_real_func_args_geometry
888 {
889   String value;
890 public:
Item_func_glength(THD * thd,Item * a)891   Item_func_glength(THD *thd, Item *a)
892    :Item_real_func_args_geometry(thd, a) {}
893   double val_real();
func_name()894   const char *func_name() const { return "st_length"; }
fix_length_and_dec()895   bool fix_length_and_dec()
896   {
897     if (Item_real_func::fix_length_and_dec())
898       return TRUE;
899     maybe_null= 1;
900     return FALSE;
901   }
get_copy(THD * thd)902   Item *get_copy(THD *thd)
903   { return get_item_copy<Item_func_glength>(thd, this); }
904 };
905 
906 
907 class Item_func_srid: public Item_long_func_args_geometry
908 {
909 public:
Item_func_srid(THD * thd,Item * a)910   Item_func_srid(THD *thd, Item *a)
911    :Item_long_func_args_geometry(thd, a) {}
912   longlong val_int();
func_name()913   const char *func_name() const { return "srid"; }
fix_length_and_dec()914   bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
get_copy(THD * thd)915   Item *get_copy(THD *thd)
916   { return get_item_copy<Item_func_srid>(thd, this); }
917 };
918 
919 
920 class Item_func_distance: public Item_real_func_args_geometry_geometry
921 {
922   String tmp_value1;
923   String tmp_value2;
924   Gcalc_heap collector;
925   Gcalc_function func;
926   Gcalc_scan_iterator scan_it;
927 public:
Item_func_distance(THD * thd,Item * a,Item * b)928   Item_func_distance(THD *thd, Item *a, Item *b)
929    :Item_real_func_args_geometry_geometry(thd, a, b) {}
930   double val_real();
func_name()931   const char *func_name() const { return "st_distance"; }
get_copy(THD * thd)932   Item *get_copy(THD *thd)
933   { return get_item_copy<Item_func_distance>(thd, this); }
934 };
935 
936 
937 class Item_func_sphere_distance: public Item_real_func
938 {
939   double spherical_distance_points(Geometry *g1, Geometry *g2,
940                                    const double sphere_r);
941 public:
Item_func_sphere_distance(THD * thd,List<Item> & list)942   Item_func_sphere_distance(THD *thd, List<Item> &list):
943     Item_real_func(thd, list) {}
944   double val_real();
func_name()945   const char *func_name() const { return "st_distance_sphere"; }
get_copy(THD * thd)946   Item *get_copy(THD *thd)
947   { return get_item_copy<Item_func_sphere_distance>(thd, this); }
948 };
949 
950 
951 class Item_func_pointonsurface: public Item_geometry_func_args_geometry
952 {
953   String tmp_value;
954   Gcalc_heap collector;
955   Gcalc_function func;
956   Gcalc_scan_iterator scan_it;
957 public:
Item_func_pointonsurface(THD * thd,Item * a)958   Item_func_pointonsurface(THD *thd, Item *a)
959    :Item_geometry_func_args_geometry(thd, a) {}
func_name()960   const char *func_name() const { return "st_pointonsurface"; }
961   String *val_str(String *);
962   Field::geometry_type get_geometry_type() const;
get_copy(THD * thd)963   Item *get_copy(THD *thd)
964   { return get_item_copy<Item_func_pointonsurface>(thd, this); }
965 };
966 
967 
968 #ifndef DBUG_OFF
969 class Item_func_gis_debug: public Item_long_func
970 {
971   public:
Item_func_gis_debug(THD * thd,Item * a)972     Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
973     { null_value= false; }
fix_length_and_dec()974     bool fix_length_and_dec() { fix_char_length(10); return FALSE; }
func_name()975     const char *func_name() const  { return "st_gis_debug"; }
976     longlong val_int();
check_vcol_func_processor(void * arg)977     bool check_vcol_func_processor(void *arg)
978     {
979       return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
980     }
get_copy(THD * thd)981     Item *get_copy(THD *thd)
982     { return get_item_copy<Item_func_gis_debug>(thd, this); }
983 };
984 #endif
985 
986 
987 #define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
988 
989 #else /*HAVE_SPATIAL*/
990 
991 #define GEOM_NEW(thd, obj_constructor) NULL
992 
993 #endif /*HAVE_SPATIAL*/
994 #endif /* ITEM_GEOFUNC_INCLUDED */
995