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, 2016, 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-1301, 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
32class Item_geometry_func: public Item_str_func
33{
34public:
35 Item_geometry_func(THD *thd): Item_str_func(thd) {}
36 Item_geometry_func(THD *thd, Item *a): Item_str_func(thd, a) {}
37 Item_geometry_func(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
38 Item_geometry_func(THD *thd, Item *a, Item *b, Item *c):
39 Item_str_func(thd, a, b, c) {}
40 Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
41 void fix_length_and_dec();
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*/
49class Item_real_func_args_geometry: public Item_real_func
50{
51protected:
52 String value;
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 }
58public:
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*/
67class Item_long_func_args_geometry: public Item_long_func
68{
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 }
74protected:
75 String value;
76public:
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*/
85class Item_bool_func_args_geometry: public Item_bool_func
86{
87protected:
88 String value;
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 }
94public:
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*/
103class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
104{
105protected:
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 }
111public:
112 Item_str_ascii_func_args_geometry(THD *thd, Item *a)
113 :Item_str_ascii_func(thd, a) {}
114 Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
115 :Item_str_ascii_func(thd, a, b) {}
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*/
124class Item_binary_func_args_geometry: public Item_str_func
125{
126protected:
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 }
132public:
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*/
141class Item_geometry_func_args_geometry: public Item_geometry_func
142{
143protected:
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 }
149public:
150 Item_geometry_func_args_geometry(THD *thd, Item *a)
151 :Item_geometry_func(thd, a) {}
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*/
160class Item_real_func_args_geometry_geometry: public Item_real_func
161{
162protected:
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 }
168public:
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*/
177class Item_bool_func_args_geometry_geometry: public Item_bool_func
178{
179protected:
180 String value;
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 }
186public:
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
192class Item_func_geometry_from_text: public Item_geometry_func
193{
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 }
199public:
200 Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {}
201 Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
202 Item_geometry_func(thd, a, srid) {}
203 const char *func_name() const { return "st_geometryfromtext"; }
204 String *val_str(String *);
205 Item *get_copy(THD *thd)
206 { return get_item_copy<Item_func_geometry_from_text>(thd, this); }
207};
208
209class Item_func_geometry_from_wkb: public Item_geometry_func
210{
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 }
216public:
217 Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
218 Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid):
219 Item_geometry_func(thd, a, srid) {}
220 const char *func_name() const { return "st_geometryfromwkb"; }
221 String *val_str(String *);
222 Item *get_copy(THD *thd)
223 { return get_item_copy<Item_func_geometry_from_wkb>(thd, this); }
224};
225
226
227class Item_func_geometry_from_json: public Item_geometry_func
228{
229 String tmp_js;
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 }
236public:
237 Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {}
238 Item_func_geometry_from_json(THD *thd, Item *js, Item *opt):
239 Item_geometry_func(thd, js, opt) {}
240 Item_func_geometry_from_json(THD *thd, Item *js, Item *opt, Item *srid):
241 Item_geometry_func(thd, js, opt, srid) {}
242 const char *func_name() const { return "st_geomfromgeojson"; }
243 String *val_str(String *);
244 Item *get_copy(THD *thd)
245 { return get_item_copy<Item_func_geometry_from_json>(thd, this); }
246};
247
248
249class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
250{
251public:
252 Item_func_as_wkt(THD *thd, Item *a)
253 :Item_str_ascii_func_args_geometry(thd, a) {}
254 const char *func_name() const { return "st_astext"; }
255 String *val_str_ascii(String *);
256 void fix_length_and_dec();
257 Item *get_copy(THD *thd)
258 { return get_item_copy<Item_func_as_wkt>(thd, this); }
259};
260
261class Item_func_as_wkb: public Item_binary_func_args_geometry
262{
263public:
264 Item_func_as_wkb(THD *thd, Item *a)
265 :Item_binary_func_args_geometry(thd, a) {}
266 const char *func_name() const { return "st_aswkb"; }
267 String *val_str(String *);
268 const Type_handler *type_handler() const { return &type_handler_long_blob; }
269 void 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 }
276 Item *get_copy(THD *thd)
277 { return get_item_copy<Item_func_as_wkb>(thd, this); }
278};
279
280
281class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
282{
283 bool check_arguments() const
284 {
285 // TODO: check with Alexey, for better args[1] and args[2] type control
286 return Item_str_ascii_func_args_geometry::check_arguments() ||
287 check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
288 }
289public:
290 Item_func_as_geojson(THD *thd, Item *js)
291 :Item_str_ascii_func_args_geometry(thd, js) {}
292 Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
293 :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {}
294 Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
295 :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
296 const char *func_name() const { return "st_asgeojson"; }
297 void fix_length_and_dec();
298 String *val_str_ascii(String *);
299 Item *get_copy(THD *thd)
300 { return get_item_copy<Item_func_as_geojson>(thd, this); }
301};
302
303
304class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
305{
306public:
307 Item_func_geometry_type(THD *thd, Item *a)
308 :Item_str_ascii_func_args_geometry(thd, a) {}
309 String *val_str_ascii(String *);
310 const char *func_name() const { return "st_geometrytype"; }
311 void fix_length_and_dec()
312 {
313 // "GeometryCollection" is the longest
314 fix_length_and_charset(20, default_charset());
315 maybe_null= 1;
316 };
317 Item *get_copy(THD *thd)
318 { return get_item_copy<Item_func_geometry_type>(thd, this); }
319};
320
321
322// #define HEAVY_CONVEX_HULL
323class Item_func_convexhull: public Item_geometry_func_args_geometry
324{
325 class ch_node: public Gcalc_dyn_list::Item
326 {
327 public:
328 const Gcalc_heap::Info *pi;
329 ch_node *prev;
330 Gcalc_dyn_list::Item *next;
331 ch_node *get_next() { return (ch_node *) next; }
332 };
333
334 Gcalc_heap collector;
335 Gcalc_function func;
336 Gcalc_dyn_list res_heap;
337
338 Gcalc_result_receiver res_receiver;
339 String tmp_value;
340#ifdef HEAVY_CONVEX_HULL
341 Gcalc_scan_iterator scan_it;
342#endif /*HEAVY_CONVEX_HULL*/
343 ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
344 int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
345public:
346 Item_func_convexhull(THD *thd, Item *a)
347 :Item_geometry_func_args_geometry(thd, a),
348 res_heap(8192, sizeof(ch_node))
349 {}
350 const char *func_name() const { return "st_convexhull"; }
351 String *val_str(String *);
352 Item *get_copy(THD *thd)
353 { return get_item_copy<Item_func_convexhull>(thd, this); }
354};
355
356
357class Item_func_centroid: public Item_geometry_func_args_geometry
358{
359public:
360 Item_func_centroid(THD *thd, Item *a)
361 :Item_geometry_func_args_geometry(thd, a) {}
362 const char *func_name() const { return "st_centroid"; }
363 String *val_str(String *);
364 Field::geometry_type get_geometry_type() const;
365 Item *get_copy(THD *thd)
366 { return get_item_copy<Item_func_centroid>(thd, this); }
367};
368
369class Item_func_envelope: public Item_geometry_func_args_geometry
370{
371public:
372 Item_func_envelope(THD *thd, Item *a)
373 :Item_geometry_func_args_geometry(thd, a) {}
374 const char *func_name() const { return "st_envelope"; }
375 String *val_str(String *);
376 Field::geometry_type get_geometry_type() const;
377 Item *get_copy(THD *thd)
378 { return get_item_copy<Item_func_envelope>(thd, this); }
379};
380
381
382class Item_func_boundary: public Item_geometry_func_args_geometry
383{
384 class Transporter : public Gcalc_shape_transporter
385 {
386 Gcalc_result_receiver *m_receiver;
387 uint n_points;
388 Gcalc_function::shape_type current_type;
389 double last_x, last_y;
390 public:
391 Transporter(Gcalc_result_receiver *receiver) :
392 Gcalc_shape_transporter(NULL), m_receiver(receiver)
393 {}
394 int single_point(double x, double y);
395 int start_line();
396 int complete_line();
397 int start_poly();
398 int complete_poly();
399 int start_ring();
400 int complete_ring();
401 int add_point(double x, double y);
402
403 int start_collection(int n_objects);
404 };
405 Gcalc_result_receiver res_receiver;
406public:
407 Item_func_boundary(THD *thd, Item *a)
408 :Item_geometry_func_args_geometry(thd, a) {}
409 const char *func_name() const { return "st_boundary"; }
410 String *val_str(String *);
411 Item *get_copy(THD *thd)
412 { return get_item_copy<Item_func_boundary>(thd, this); }
413};
414
415
416class Item_func_point: public Item_geometry_func
417{
418 bool check_arguments() const
419 { return check_argument_types_can_return_real(0, 2); }
420public:
421 Item_func_point(THD *thd, Item *a, Item *b): Item_geometry_func(thd, a, b) {}
422 Item_func_point(THD *thd, Item *a, Item *b, Item *srid):
423 Item_geometry_func(thd, a, b, srid) {}
424 const char *func_name() const { return "point"; }
425 String *val_str(String *);
426 Field::geometry_type get_geometry_type() const;
427 Item *get_copy(THD *thd)
428 { return get_item_copy<Item_func_point>(thd, this); }
429};
430
431class Item_func_spatial_decomp: public Item_geometry_func_args_geometry
432{
433 enum Functype decomp_func;
434public:
435 Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
436 Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; }
437 const char *func_name() const
438 {
439 switch (decomp_func)
440 {
441 case SP_STARTPOINT:
442 return "st_startpoint";
443 case SP_ENDPOINT:
444 return "st_endpoint";
445 case SP_EXTERIORRING:
446 return "st_exteriorring";
447 default:
448 DBUG_ASSERT(0); // Should never happened
449 return "spatial_decomp_unknown";
450 }
451 }
452 String *val_str(String *);
453 Item *get_copy(THD *thd)
454 { return get_item_copy<Item_func_spatial_decomp>(thd, this); }
455};
456
457class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry
458{
459 enum Functype decomp_func_n;
460 bool check_arguments() const
461 {
462 return Item_geometry_func_args_geometry::check_arguments() ||
463 args[1]->check_type_can_return_int(func_name());
464 }
465public:
466 Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft)
467 :Item_geometry_func_args_geometry(thd, a, b),
468 decomp_func_n(ft)
469 { }
470 const char *func_name() const
471 {
472 switch (decomp_func_n)
473 {
474 case SP_POINTN:
475 return "st_pointn";
476 case SP_GEOMETRYN:
477 return "st_geometryn";
478 case SP_INTERIORRINGN:
479 return "st_interiorringn";
480 default:
481 DBUG_ASSERT(0); // Should never happened
482 return "spatial_decomp_n_unknown";
483 }
484 }
485 String *val_str(String *);
486 Item *get_copy(THD *thd)
487 { return get_item_copy<Item_func_spatial_decomp_n>(thd, this); }
488};
489
490class Item_func_spatial_collection: public Item_geometry_func
491{
492 bool check_arguments() const
493 {
494 return check_argument_types_or_binary(&type_handler_geometry, 0, arg_count);
495 }
496 enum Geometry::wkbType coll_type;
497 enum Geometry::wkbType item_type;
498public:
499 Item_func_spatial_collection(THD *thd,
500 List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it):
501 Item_geometry_func(thd, list)
502 {
503 coll_type=ct;
504 item_type=it;
505 }
506 String *val_str(String *);
507 void fix_length_and_dec()
508 {
509 Item_geometry_func::fix_length_and_dec();
510 for (unsigned int i= 0; i < arg_count; ++i)
511 {
512 if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
513 {
514 String str;
515 args[i]->print(&str, QT_NO_DATA_EXPANSION);
516 str.append('\0');
517 my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
518 str.ptr());
519 }
520 }
521 }
522
523 const char *func_name() const { return "geometrycollection"; }
524 Item *get_copy(THD *thd)
525 { return get_item_copy<Item_func_spatial_collection>(thd, this); }
526};
527
528
529/*
530 Spatial relations
531*/
532
533class Item_func_spatial_rel: public Item_bool_func2_with_rev
534{
535protected:
536 enum Functype spatial_rel;
537 String tmp_value1, tmp_value2;
538 SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
539 KEY_PART *key_part,
540 Item_func::Functype type, Item *value);
541 bool check_arguments() const
542 {
543 DBUG_ASSERT(arg_count >= 2);
544 return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
545 }
546public:
547 Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
548 Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel)
549 {
550 maybe_null= true;
551 }
552 enum Functype functype() const { return spatial_rel; }
553 enum Functype rev_functype() const
554 {
555 switch (spatial_rel)
556 {
557 case SP_CONTAINS_FUNC:
558 return SP_WITHIN_FUNC;
559 case SP_WITHIN_FUNC:
560 return SP_CONTAINS_FUNC;
561 default:
562 return spatial_rel;
563 }
564 }
565 bool is_null() { (void) val_int(); return null_value; }
566 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
567 uint *and_level, table_map usable_tables,
568 SARGABLE_PARAM **sargables)
569 {
570 return add_key_fields_optimize_op(join, key_fields, and_level,
571 usable_tables, sargables, false);
572 }
573 bool need_parentheses_in_default() { return false; }
574 Item *build_clone(THD *thd) { return 0; }
575};
576
577
578class Item_func_spatial_mbr_rel: public Item_func_spatial_rel
579{
580public:
581 Item_func_spatial_mbr_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
582 Item_func_spatial_rel(thd, a, b, sp_rel)
583 { }
584 longlong val_int();
585 const char *func_name() const;
586 Item *get_copy(THD *thd)
587 { return get_item_copy<Item_func_spatial_mbr_rel>(thd, this); }
588};
589
590
591class Item_func_spatial_precise_rel: public Item_func_spatial_rel
592{
593 Gcalc_heap collector;
594 Gcalc_scan_iterator scan_it;
595 Gcalc_function func;
596public:
597 Item_func_spatial_precise_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
598 Item_func_spatial_rel(thd, a, b, sp_rel), collector()
599 { }
600 longlong val_int();
601 const char *func_name() const;
602 Item *get_copy(THD *thd)
603 { return get_item_copy<Item_func_spatial_precise_rel>(thd, this); }
604};
605
606
607class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry
608{
609 Gcalc_heap collector;
610 Gcalc_scan_iterator scan_it;
611 Gcalc_function func;
612 String tmp_value1, tmp_value2, tmp_matrix;
613 bool check_arguments() const
614 {
615 return Item_bool_func_args_geometry_geometry::check_arguments() ||
616 args[2]->check_type_general_purpose_string(func_name());
617 }
618public:
619 Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
620 Item_bool_func_args_geometry_geometry(thd, a, b, matrix)
621 { }
622 longlong val_int();
623 const char *func_name() const { return "st_relate"; }
624 bool need_parentheses_in_default() { return false; }
625 Item *get_copy(THD *thd)
626 { return get_item_copy<Item_func_spatial_relate>(thd, this); }
627};
628
629
630/*
631 Spatial operations
632*/
633
634class Item_func_spatial_operation: public Item_geometry_func
635{
636 bool check_arguments() const
637 {
638 DBUG_ASSERT(arg_count >= 2);
639 return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
640 }
641public:
642 Gcalc_function::op_type spatial_op;
643 Gcalc_heap collector;
644 Gcalc_function func;
645
646 Gcalc_result_receiver res_receiver;
647 Gcalc_operation_reducer operation;
648 String tmp_value1,tmp_value2;
649public:
650 Item_func_spatial_operation(THD *thd, Item *a,Item *b,
651 Gcalc_function::op_type sp_op):
652 Item_geometry_func(thd, a, b), spatial_op(sp_op)
653 {}
654 virtual ~Item_func_spatial_operation();
655 String *val_str(String *);
656 const char *func_name() const;
657 virtual inline void print(String *str, enum_query_type query_type)
658 {
659 Item_func::print(str, query_type);
660 }
661 Item *get_copy(THD *thd)
662 { return get_item_copy<Item_func_spatial_operation>(thd, this); }
663};
664
665
666class Item_func_buffer: public Item_geometry_func_args_geometry
667{
668 bool check_arguments() const
669 {
670 return Item_geometry_func_args_geometry::check_arguments() ||
671 args[1]->check_type_can_return_real(func_name());
672 }
673protected:
674 class Transporter : public Gcalc_operation_transporter
675 {
676 int m_npoints;
677 double m_d;
678 double x1,y1,x2,y2;
679 double x00,y00,x01,y01;
680 int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2);
681 int add_last_edge_buffer();
682 int add_point_buffer(double x, double y);
683 int complete();
684 int m_nshapes;
685 Gcalc_function::op_type buffer_op;
686 int last_shape_pos;
687 bool skip_line;
688
689 public:
690 Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) :
691 Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d),
692 m_nshapes(0), buffer_op((d > 0.0) ? Gcalc_function::op_union :
693 Gcalc_function::op_difference),
694 skip_line(FALSE)
695 {}
696 int single_point(double x, double y);
697 int start_line();
698 int complete_line();
699 int start_poly();
700 int complete_poly();
701 int start_ring();
702 int complete_ring();
703 int add_point(double x, double y);
704
705 int start_collection(int n_objects);
706 };
707 Gcalc_heap collector;
708 Gcalc_function func;
709
710 Gcalc_result_receiver res_receiver;
711 Gcalc_operation_reducer operation;
712
713public:
714 Item_func_buffer(THD *thd, Item *obj, Item *distance)
715 :Item_geometry_func_args_geometry(thd, obj, distance) {}
716 const char *func_name() const { return "st_buffer"; }
717 String *val_str(String *);
718 Item *get_copy(THD *thd)
719 { return get_item_copy<Item_func_buffer>(thd, this); }
720};
721
722
723class Item_func_isempty: public Item_bool_func_args_geometry
724{
725public:
726 Item_func_isempty(THD *thd, Item *a)
727 :Item_bool_func_args_geometry(thd, a) {}
728 longlong val_int();
729 const char *func_name() const { return "st_isempty"; }
730 void fix_length_and_dec() { maybe_null= 1; }
731 bool need_parentheses_in_default() { return false; }
732 Item *get_copy(THD *thd)
733 { return get_item_copy<Item_func_isempty>(thd, this); }
734};
735
736class Item_func_issimple: public Item_long_func_args_geometry
737{
738 Gcalc_heap collector;
739 Gcalc_function func;
740 Gcalc_scan_iterator scan_it;
741 String tmp;
742public:
743 Item_func_issimple(THD *thd, Item *a)
744 :Item_long_func_args_geometry(thd, a) {}
745 longlong val_int();
746 const char *func_name() const { return "st_issimple"; }
747 void fix_length_and_dec() { decimals=0; max_length=2; }
748 uint decimal_precision() const { return 1; }
749 Item *get_copy(THD *thd)
750 { return get_item_copy<Item_func_issimple>(thd, this); }
751};
752
753class Item_func_isclosed: public Item_long_func_args_geometry
754{
755public:
756 Item_func_isclosed(THD *thd, Item *a)
757 :Item_long_func_args_geometry(thd, a) {}
758 longlong val_int();
759 const char *func_name() const { return "st_isclosed"; }
760 void fix_length_and_dec() { decimals=0; max_length=2; }
761 uint decimal_precision() const { return 1; }
762 Item *get_copy(THD *thd)
763 { return get_item_copy<Item_func_isclosed>(thd, this); }
764};
765
766class Item_func_isring: public Item_func_issimple
767{
768public:
769 Item_func_isring(THD *thd, Item *a): Item_func_issimple(thd, a) {}
770 longlong val_int();
771 const char *func_name() const { return "st_isring"; }
772 Item *get_copy(THD *thd)
773 { return get_item_copy<Item_func_isring>(thd, this); }
774};
775
776class Item_func_dimension: public Item_long_func_args_geometry
777{
778public:
779 Item_func_dimension(THD *thd, Item *a)
780 :Item_long_func_args_geometry(thd, a) {}
781 longlong val_int();
782 const char *func_name() const { return "st_dimension"; }
783 void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
784 Item *get_copy(THD *thd)
785 { return get_item_copy<Item_func_dimension>(thd, this); }
786};
787
788
789class Item_func_x: public Item_real_func_args_geometry
790{
791public:
792 Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
793 double val_real();
794 const char *func_name() const { return "st_x"; }
795 void fix_length_and_dec()
796 {
797 Item_real_func::fix_length_and_dec();
798 maybe_null= 1;
799 }
800 Item *get_copy(THD *thd)
801 { return get_item_copy<Item_func_x>(thd, this); }
802};
803
804
805class Item_func_y: public Item_real_func_args_geometry
806{
807public:
808 Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
809 double val_real();
810 const char *func_name() const { return "st_y"; }
811 void fix_length_and_dec()
812 {
813 Item_real_func::fix_length_and_dec();
814 maybe_null= 1;
815 }
816 Item *get_copy(THD *thd)
817 { return get_item_copy<Item_func_y>(thd, this); }
818};
819
820
821class Item_func_numgeometries: public Item_long_func_args_geometry
822{
823public:
824 Item_func_numgeometries(THD *thd, Item *a)
825 :Item_long_func_args_geometry(thd, a) {}
826 longlong val_int();
827 const char *func_name() const { return "st_numgeometries"; }
828 void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
829 Item *get_copy(THD *thd)
830 { return get_item_copy<Item_func_numgeometries>(thd, this); }
831};
832
833
834class Item_func_numinteriorring: public Item_long_func_args_geometry
835{
836public:
837 Item_func_numinteriorring(THD *thd, Item *a)
838 :Item_long_func_args_geometry(thd, a) {}
839 longlong val_int();
840 const char *func_name() const { return "st_numinteriorrings"; }
841 void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
842 Item *get_copy(THD *thd)
843 { return get_item_copy<Item_func_numinteriorring>(thd, this); }
844};
845
846
847class Item_func_numpoints: public Item_long_func_args_geometry
848{
849public:
850 Item_func_numpoints(THD *thd, Item *a)
851 :Item_long_func_args_geometry(thd, a) {}
852 longlong val_int();
853 const char *func_name() const { return "st_numpoints"; }
854 void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
855 Item *get_copy(THD *thd)
856 { return get_item_copy<Item_func_numpoints>(thd, this); }
857};
858
859
860class Item_func_area: public Item_real_func_args_geometry
861{
862public:
863 Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
864 double val_real();
865 const char *func_name() const { return "st_area"; }
866 void fix_length_and_dec()
867 {
868 Item_real_func::fix_length_and_dec();
869 maybe_null= 1;
870 }
871 Item *get_copy(THD *thd)
872 { return get_item_copy<Item_func_area>(thd, this); }
873};
874
875
876class Item_func_glength: public Item_real_func_args_geometry
877{
878 String value;
879public:
880 Item_func_glength(THD *thd, Item *a)
881 :Item_real_func_args_geometry(thd, a) {}
882 double val_real();
883 const char *func_name() const { return "st_length"; }
884 void fix_length_and_dec()
885 {
886 Item_real_func::fix_length_and_dec();
887 maybe_null= 1;
888 }
889 Item *get_copy(THD *thd)
890 { return get_item_copy<Item_func_glength>(thd, this); }
891};
892
893
894class Item_func_srid: public Item_long_func_args_geometry
895{
896public:
897 Item_func_srid(THD *thd, Item *a)
898 :Item_long_func_args_geometry(thd, a) {}
899 longlong val_int();
900 const char *func_name() const { return "srid"; }
901 void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
902 Item *get_copy(THD *thd)
903 { return get_item_copy<Item_func_srid>(thd, this); }
904};
905
906
907class Item_func_distance: public Item_real_func_args_geometry_geometry
908{
909 String tmp_value1;
910 String tmp_value2;
911 Gcalc_heap collector;
912 Gcalc_function func;
913 Gcalc_scan_iterator scan_it;
914public:
915 Item_func_distance(THD *thd, Item *a, Item *b)
916 :Item_real_func_args_geometry_geometry(thd, a, b) {}
917 double val_real();
918 const char *func_name() const { return "st_distance"; }
919 Item *get_copy(THD *thd)
920 { return get_item_copy<Item_func_distance>(thd, this); }
921};
922
923
924class Item_func_pointonsurface: public Item_geometry_func_args_geometry
925{
926 String tmp_value;
927 Gcalc_heap collector;
928 Gcalc_function func;
929 Gcalc_scan_iterator scan_it;
930public:
931 Item_func_pointonsurface(THD *thd, Item *a)
932 :Item_geometry_func_args_geometry(thd, a) {}
933 const char *func_name() const { return "st_pointonsurface"; }
934 String *val_str(String *);
935 Field::geometry_type get_geometry_type() const;
936 Item *get_copy(THD *thd)
937 { return get_item_copy<Item_func_pointonsurface>(thd, this); }
938};
939
940
941#ifndef DBUG_OFF
942class Item_func_gis_debug: public Item_long_func
943{
944 public:
945 Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
946 { null_value= false; }
947 void fix_length_and_dec() { fix_char_length(10); }
948 const char *func_name() const { return "st_gis_debug"; }
949 longlong val_int();
950 bool check_vcol_func_processor(void *arg)
951 {
952 return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
953 }
954 Item *get_copy(THD *thd)
955 { return get_item_copy<Item_func_gis_debug>(thd, this); }
956};
957#endif
958
959
960#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
961
962#else /*HAVE_SPATIAL*/
963
964#define GEOM_NEW(thd, obj_constructor) NULL
965
966#endif /*HAVE_SPATIAL*/
967#endif /* ITEM_GEOFUNC_INCLUDED */
968