1 /* Copyright (c) 2003, 2016, Oracle and/or its affiliates.
2 Copyright (c) 2011, 2021, MariaDB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
16
17
18 /**
19 @file
20
21 @brief
22 This file defines all spatial functions
23 */
24
25 #ifdef USE_PRAGMA_IMPLEMENTATION
26 #pragma implementation // gcc: Class implementation
27 #endif
28
29 #include "mariadb.h"
30 #include "sql_priv.h"
31 /*
32 It is necessary to include set_var.h instead of item.h because there
33 are dependencies on include order for set_var.h and item.h. This
34 will be resolved later.
35 */
36 #include "sql_class.h" // THD, set_var.h: THD
37 #include "set_var.h"
38 #ifdef HAVE_SPATIAL
39 #include <m_ctype.h>
40 #include "opt_range.h"
41 #include "item_geofunc.h"
42 #include "item_create.h"
43
44
fix_length_and_dec()45 bool Item_geometry_func::fix_length_and_dec()
46 {
47 collation.set(&my_charset_bin);
48 decimals=0;
49 max_length= (uint32) UINT_MAX32;
50 maybe_null= 1;
51 return FALSE;
52 }
53
54
val_str(String * str)55 String *Item_func_geometry_from_text::val_str(String *str)
56 {
57 DBUG_ASSERT(fixed == 1);
58 Geometry_buffer buffer;
59 String arg_val;
60 String *wkt= args[0]->val_str_ascii(&arg_val);
61
62 if ((null_value= args[0]->null_value))
63 return 0;
64
65 Gis_read_stream trs(wkt->charset(), wkt->ptr(), wkt->length());
66 uint32 srid= 0;
67
68 if ((arg_count == 2) && !args[1]->null_value)
69 srid= (uint32)args[1]->val_int();
70
71 str->set_charset(&my_charset_bin);
72 str->length(0);
73 if (str->reserve(SRID_SIZE, 512))
74 return 0;
75 str->q_append(srid);
76 if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
77 return 0;
78 return str;
79 }
80
81
val_str(String * str)82 String *Item_func_geometry_from_wkb::val_str(String *str)
83 {
84 DBUG_ASSERT(fixed == 1);
85 String arg_val;
86 String *wkb;
87 Geometry_buffer buffer;
88 uint32 srid= 0;
89
90 if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY)
91 {
92 String *str_ret= args[0]->val_str(str);
93 null_value= args[0]->null_value;
94 return str_ret;
95 }
96
97 wkb= args[0]->val_str(&arg_val);
98
99 if ((arg_count == 2) && !args[1]->null_value)
100 srid= (uint32)args[1]->val_int();
101
102 str->set_charset(&my_charset_bin);
103 if (str->reserve(SRID_SIZE, 512))
104 {
105 null_value= TRUE; /* purecov: inspected */
106 return 0; /* purecov: inspected */
107 }
108 str->length(0);
109 str->q_append(srid);
110 if ((null_value=
111 (args[0]->null_value ||
112 !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length(), str))))
113 return 0;
114 return str;
115 }
116
117
118 void report_json_error_ex(String *js, json_engine_t *je,
119 const char *fname, int n_param,
120 Sql_condition::enum_warning_level lv);
121
val_str(String * str)122 String *Item_func_geometry_from_json::val_str(String *str)
123 {
124 DBUG_ASSERT(fixed == 1);
125 Geometry_buffer buffer;
126 String *js= args[0]->val_str_ascii(&tmp_js);
127 uint32 srid= 0;
128 longlong options= 0;
129 json_engine_t je;
130
131 if ((null_value= args[0]->null_value))
132 return 0;
133
134 if (arg_count > 1 && !args[1]->null_value)
135 {
136 options= args[1]->val_int();
137 if (options > 4 || options < 1)
138 {
139 String *sv= args[1]->val_str(&tmp_js);
140 my_error(ER_WRONG_VALUE_FOR_TYPE, MYF(0),
141 "option", sv->c_ptr_safe(), "ST_GeomFromGeoJSON");
142 null_value= 1;
143 return 0;
144 }
145 }
146
147 if ((arg_count == 3) && !args[2]->null_value)
148 srid= (uint32)args[2]->val_int();
149
150 str->set_charset(&my_charset_bin);
151 if (str->reserve(SRID_SIZE, 512))
152 return 0;
153 str->length(0);
154 str->q_append(srid);
155
156 json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
157 (const uchar *) js->end());
158
159 if ((null_value= !Geometry::create_from_json(&buffer, &je, options==1, str)))
160 {
161 int code= 0;
162
163 switch (je.s.error)
164 {
165 case Geometry::GEOJ_INCORRECT_GEOJSON:
166 code= ER_GEOJSON_INCORRECT;
167 break;
168 case Geometry::GEOJ_TOO_FEW_POINTS:
169 code= ER_GEOJSON_TOO_FEW_POINTS;
170 break;
171 case Geometry::GEOJ_EMPTY_COORDINATES:
172 code= ER_GEOJSON_EMPTY_COORDINATES;
173 break;
174 case Geometry::GEOJ_POLYGON_NOT_CLOSED:
175 code= ER_GEOJSON_NOT_CLOSED;
176 break;
177 case Geometry::GEOJ_DIMENSION_NOT_SUPPORTED:
178 my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_GeomFromGeoJSON");
179 break;
180 default:
181 report_json_error_ex(js, &je, func_name(), 0, Sql_condition::WARN_LEVEL_WARN);
182 return NULL;
183 }
184
185 if (code)
186 {
187 THD *thd= current_thd;
188 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, code,
189 ER_THD(thd, code));
190 }
191 return 0;
192 }
193 return str;
194 }
195
196
val_str_ascii(String * str)197 String *Item_func_as_wkt::val_str_ascii(String *str)
198 {
199 DBUG_ASSERT(fixed == 1);
200 String arg_val;
201 String *swkb= args[0]->val_str(&arg_val);
202 Geometry_buffer buffer;
203 Geometry *geom= NULL;
204 const char *dummy;
205
206 if ((null_value=
207 (args[0]->null_value ||
208 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
209 return 0;
210
211 str->length(0);
212 str->set_charset(&my_charset_latin1);
213 if ((null_value= geom->as_wkt(str, &dummy)))
214 return 0;
215
216 return str;
217 }
218
219
fix_length_and_dec()220 bool Item_func_as_wkt::fix_length_and_dec()
221 {
222 collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
223 max_length= (uint32) UINT_MAX32;
224 maybe_null= 1;
225 return FALSE;
226 }
227
228
val_str(String * str)229 String *Item_func_as_wkb::val_str(String *str)
230 {
231 DBUG_ASSERT(fixed == 1);
232 String arg_val;
233 String *swkb= args[0]->val_str(&arg_val);
234 Geometry_buffer buffer;
235
236 if ((null_value=
237 (args[0]->null_value ||
238 !(Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
239 return 0;
240
241 str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
242 &my_charset_bin);
243 return str;
244 }
245
246
fix_length_and_dec()247 bool Item_func_as_geojson::fix_length_and_dec()
248 {
249 collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
250 max_length=MAX_BLOB_WIDTH;
251 maybe_null= 1;
252 return FALSE;
253 }
254
255
val_str_ascii(String * str)256 String *Item_func_as_geojson::val_str_ascii(String *str)
257 {
258 DBUG_ASSERT(fixed == 1);
259 String arg_val;
260 String *swkb= args[0]->val_str(&arg_val);
261 uint max_dec= FLOATING_POINT_DECIMALS;
262 longlong options= 0;
263 Geometry_buffer buffer;
264 Geometry *geom= NULL;
265 const char *dummy;
266
267 if ((null_value=
268 (args[0]->null_value ||
269 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
270 return 0;
271
272 if (arg_count > 1)
273 {
274 max_dec= (uint) args[1]->val_int();
275 if (args[1]->null_value)
276 max_dec= FLOATING_POINT_DECIMALS;
277 if (arg_count > 2)
278 {
279 options= args[2]->val_int();
280 if (args[2]->null_value)
281 options= 0;
282 }
283 }
284
285 str->length(0);
286 str->set_charset(&my_charset_latin1);
287
288 if (str->reserve(1, 512))
289 return 0;
290
291 str->qs_append('{');
292
293 if (options & 1)
294 {
295 if (geom->bbox_as_json(str) || str->append(", ", 2))
296 goto error;
297 }
298
299 if ((geom->as_json(str, max_dec, &dummy) || str->append("}", 1)))
300 goto error;
301
302 return str;
303
304 error:
305 null_value= 1;
306 return 0;
307 }
308
309
val_str_ascii(String * str)310 String *Item_func_geometry_type::val_str_ascii(String *str)
311 {
312 DBUG_ASSERT(fixed == 1);
313 String *swkb= args[0]->val_str(str);
314 Geometry_buffer buffer;
315 Geometry *geom= NULL;
316
317 if ((null_value=
318 (args[0]->null_value ||
319 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
320 return 0;
321 /* String will not move */
322 str->copy(geom->get_class_info()->m_name.str,
323 geom->get_class_info()->m_name.length,
324 &my_charset_latin1);
325 return str;
326 }
327
328
val_str(String * str)329 String *Item_func_envelope::val_str(String *str)
330 {
331 DBUG_ASSERT(fixed == 1);
332 String arg_val;
333 String *swkb= args[0]->val_str(&arg_val);
334 Geometry_buffer buffer;
335 Geometry *geom= NULL;
336 uint32 srid;
337
338 if ((null_value=
339 args[0]->null_value ||
340 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
341 return 0;
342
343 srid= uint4korr(swkb->ptr());
344 str->set_charset(&my_charset_bin);
345 str->length(0);
346 if (str->reserve(SRID_SIZE, 512))
347 return 0;
348 str->q_append(srid);
349 return (null_value= geom->envelope(str)) ? 0 : str;
350 }
351
352
single_point(double x,double y)353 int Item_func_boundary::Transporter::single_point(double x, double y)
354 {
355 return 0;
356 }
357
358
start_line()359 int Item_func_boundary::Transporter::start_line()
360 {
361 n_points= 0;
362 current_type= Gcalc_function::shape_line;
363 return 0;
364 }
365
366
complete_line()367 int Item_func_boundary::Transporter::complete_line()
368 {
369 current_type= (Gcalc_function::shape_type) 0;
370 if (n_points > 1)
371 return m_receiver->single_point(last_x, last_y);
372 return 0;
373 }
374
375
start_poly()376 int Item_func_boundary::Transporter::start_poly()
377 {
378 current_type= Gcalc_function::shape_polygon;
379 return 0;
380 }
381
382
complete_poly()383 int Item_func_boundary::Transporter::complete_poly()
384 {
385 current_type= (Gcalc_function::shape_type) 0;
386 return 0;
387 }
388
389
start_ring()390 int Item_func_boundary::Transporter::start_ring()
391 {
392 n_points= 0;
393 return m_receiver->start_shape(Gcalc_function::shape_line);
394 }
395
396
complete_ring()397 int Item_func_boundary::Transporter::complete_ring()
398 {
399 if (n_points > 1)
400 {
401 m_receiver->add_point(last_x, last_y);
402 }
403 m_receiver->complete_shape();
404 return 0;
405 }
406
407
add_point(double x,double y)408 int Item_func_boundary::Transporter::add_point(double x, double y)
409 {
410 ++n_points;
411 if (current_type== Gcalc_function::shape_polygon)
412 {
413 /* Polygon's ring case */
414 if (n_points == 1)
415 {
416 last_x= x;
417 last_y= y;
418 }
419 return m_receiver->add_point(x, y);
420 }
421
422 if (current_type== Gcalc_function::shape_line)
423 {
424 /* Line's case */
425 last_x= x;
426 last_y= y;
427 if (n_points == 1)
428 return m_receiver->single_point(x, y);
429 }
430 return 0;
431 }
432
433
start_collection(int n_objects)434 int Item_func_boundary::Transporter::start_collection(int n_objects)
435 {
436 return 0;
437 }
438
439
val_str(String * str_value)440 String *Item_func_boundary::val_str(String *str_value)
441 {
442 DBUG_ENTER("Item_func_boundary::val_str");
443 DBUG_ASSERT(fixed == 1);
444 String arg_val;
445 String *swkb= args[0]->val_str(&arg_val);
446
447 if ((null_value= args[0]->null_value))
448 DBUG_RETURN(0);
449
450 Geometry_buffer buffer;
451 uint32 srid= 0;
452 Transporter trn(&res_receiver);
453
454 Geometry *g= Geometry::construct(&buffer, swkb->ptr(), swkb->length());
455 if (!g)
456 DBUG_RETURN(0);
457
458 if (g->store_shapes(&trn))
459 goto mem_error;
460
461 str_value->set_charset(&my_charset_bin);
462 if (str_value->reserve(SRID_SIZE, 512))
463 goto mem_error;
464 str_value->length(0);
465 str_value->q_append(srid);
466
467 if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
468 goto mem_error;
469
470 res_receiver.reset();
471 DBUG_RETURN(str_value);
472
473 mem_error:
474 null_value= 1;
475 DBUG_RETURN(0);
476 }
477
478
val_str(String * str)479 String *Item_func_centroid::val_str(String *str)
480 {
481 DBUG_ASSERT(fixed == 1);
482 String arg_val;
483 String *swkb= args[0]->val_str(&arg_val);
484 Geometry_buffer buffer;
485 Geometry *geom= NULL;
486 uint32 srid;
487
488 if ((null_value= args[0]->null_value ||
489 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
490 return 0;
491
492 str->set_charset(&my_charset_bin);
493 if (str->reserve(SRID_SIZE, 512))
494 return 0;
495 str->length(0);
496 srid= uint4korr(swkb->ptr());
497 str->q_append(srid);
498
499 return (null_value= MY_TEST(geom->centroid(str))) ? 0 : str;
500 }
501
502
add_node_to_line(ch_node ** p_cur,int dir,const Gcalc_heap::Info * pi)503 int Item_func_convexhull::add_node_to_line(ch_node **p_cur, int dir,
504 const Gcalc_heap::Info *pi)
505 {
506 ch_node *new_node;
507 ch_node *cur= *p_cur;
508
509 while (cur->prev)
510 {
511 int v_sign= Gcalc_scan_iterator::point::cmp_dx_dy(
512 cur->prev->pi, cur->pi, cur->pi, pi);
513 if (v_sign*dir <0)
514 break;
515 new_node= cur;
516 cur= cur->prev;
517 res_heap.free_item(new_node);
518 }
519 if (!(new_node= new_ch_node()))
520 return 1;
521 cur->next= new_node;
522 new_node->prev= cur;
523 new_node->pi= pi;
524 *p_cur= new_node;
525 return 0;
526 }
527
528
529 #ifndef HEAVY_CONVEX_HULL
val_str(String * str_value)530 String *Item_func_convexhull::val_str(String *str_value)
531 {
532 Geometry_buffer buffer;
533 Geometry *geom= NULL;
534 MBR mbr;
535 const char *c_end;
536 Gcalc_operation_transporter trn(&func, &collector);
537 uint32 srid= 0;
538 ch_node *left_first, *left_cur, *right_first, *right_cur;
539 Gcalc_heap::Info *cur_pi;
540
541 DBUG_ENTER("Item_func_convexhull::val_str");
542 DBUG_ASSERT(fixed == 1);
543 String *swkb= args[0]->val_str(&tmp_value);
544
545 if ((null_value=
546 args[0]->null_value ||
547 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
548 DBUG_RETURN(0);
549
550 geom->get_mbr(&mbr, &c_end);
551 collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
552 if ((null_value= geom->store_shapes(&trn)))
553 {
554 str_value= 0;
555 goto mem_error;
556 }
557
558 collector.prepare_operation();
559 if (!(cur_pi= collector.get_first()))
560 goto build_result; /* An EMPTY GEOMETRY */
561
562 if (!cur_pi->get_next())
563 {
564 /* Single point. */
565 if (res_receiver.single_point(cur_pi->node.shape.x, cur_pi->node.shape.y))
566 goto mem_error;
567 goto build_result;
568 }
569
570 left_cur= left_first= new_ch_node();
571 right_cur= right_first= new_ch_node();
572 right_first->prev= left_first->prev= 0;
573 right_first->pi= left_first->pi= cur_pi;
574
575 while ((cur_pi= cur_pi->get_next()))
576 {
577 /* Handle left part of the hull, then the right part. */
578 if (add_node_to_line(&left_cur, 1, cur_pi))
579 goto mem_error;
580 if (add_node_to_line(&right_cur, -1, cur_pi))
581 goto mem_error;
582 }
583
584 left_cur->next= 0;
585 if (left_first->get_next()->get_next() == NULL &&
586 right_cur->prev->prev == NULL)
587 {
588 /* We only have 2 nodes in the result, so we create a polyline. */
589 if (res_receiver.start_shape(Gcalc_function::shape_line) ||
590 res_receiver.add_point(left_first->pi->node.shape.x, left_first->pi->node.shape.y) ||
591 res_receiver.add_point(left_cur->pi->node.shape.x, left_cur->pi->node.shape.y) ||
592 res_receiver.complete_shape())
593
594 goto mem_error;
595
596 goto build_result;
597 }
598
599 if (res_receiver.start_shape(Gcalc_function::shape_polygon))
600 goto mem_error;
601
602 while (left_first)
603 {
604 if (res_receiver.add_point(left_first->pi->node.shape.x, left_first->pi->node.shape.y))
605 goto mem_error;
606 left_first= left_first->get_next();
607 }
608
609 /* Skip last point in the right part as it coincides */
610 /* with the last one in the left. */
611 right_cur= right_cur->prev;
612 while (right_cur->prev)
613 {
614 if (res_receiver.add_point(right_cur->pi->node.shape.x, right_cur->pi->node.shape.y))
615 goto mem_error;
616 right_cur= right_cur->prev;
617 }
618 res_receiver.complete_shape();
619
620 build_result:
621 str_value->set_charset(&my_charset_bin);
622 if (str_value->reserve(SRID_SIZE, 512))
623 goto mem_error;
624 str_value->length(0);
625 str_value->q_append(srid);
626
627 if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
628 goto mem_error;
629
630 mem_error:
631 collector.reset();
632 func.reset();
633 res_receiver.reset();
634 res_heap.reset();
635 DBUG_RETURN(str_value);
636 }
637
638 #else /*HEAVY_CONVEX_HULL*/
val_str(String * str_value)639 String *Item_func_convexhull::val_str(String *str_value)
640 {
641 Geometry_buffer buffer;
642 Geometry *geom= NULL;
643 MBR mbr;
644 const char *c_end;
645 Gcalc_operation_transporter trn(&func, &collector);
646 const Gcalc_scan_iterator::event_point *ev;
647 uint32 srid= 0;
648 ch_node *left_first, *left_cur, *right_first, *right_cur;
649
650 DBUG_ENTER("Item_func_convexhull::val_str");
651 DBUG_ASSERT(fixed == 1);
652 String *swkb= args[0]->val_str(&tmp_value);
653
654 if ((null_value=
655 args[0]->null_value ||
656 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
657 DBUG_RETURN(0);
658
659 geom->get_mbr(&mbr, &c_end);
660 collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
661 if ((null_value= geom->store_shapes(&trn)))
662 {
663 str_value= 0;
664 goto mem_error;
665 }
666
667 collector.prepare_operation();
668 scan_it.init(&collector);
669 scan_it.killed= (int *) &(current_thd->killed);
670
671 if (!scan_it.more_points())
672 goto build_result; /* An EMPTY GEOMETRY */
673
674 if (scan_it.step())
675 goto mem_error;
676
677 if (!scan_it.more_points())
678 {
679 /* Single point. */
680 if (res_receiver.single_point(scan_it.get_events()->pi->x,
681 scan_it.get_events()->pi->y))
682 goto mem_error;
683 goto build_result;
684 }
685
686 left_cur= left_first= new_ch_node();
687 right_cur= right_first= new_ch_node();
688 right_first->prev= left_first->prev= 0;
689 right_first->pi= left_first->pi= scan_it.get_events()->pi;
690
691 while (scan_it.more_points())
692 {
693 if (scan_it.step())
694 goto mem_error;
695 ev= scan_it.get_events();
696
697 /* Skip the intersections-only events. */
698 while (ev->event == scev_intersection)
699 {
700 ev= ev->get_next();
701 if (!ev)
702 goto skip_point;
703 }
704
705 {
706 Gcalc_point_iterator pit(&scan_it);
707 if (!pit.point() || scan_it.get_event_position() == pit.point())
708 {
709 /* Handle left part of the hull. */
710 if (add_node_to_line(&left_cur, 1, ev->pi))
711 goto mem_error;
712 }
713 if (pit.point())
714 {
715 /* Check the rightmost point */
716 for(; pit.point()->c_get_next(); ++pit)
717 ;
718 }
719 if (!pit.point() || pit.point()->event ||
720 scan_it.get_event_position() == pit.point()->c_get_next())
721 {
722 /* Handle right part of the hull. */
723 if (add_node_to_line(&right_cur, -1, ev->pi))
724 goto mem_error;
725 }
726 }
727 skip_point:;
728 }
729
730 left_cur->next= 0;
731 if (left_first->get_next()->get_next() == NULL &&
732 right_cur->prev->prev == NULL)
733 {
734 /* We only have 2 nodes in the result, so we create a polyline. */
735 if (res_receiver.start_shape(Gcalc_function::shape_line) ||
736 res_receiver.add_point(left_first->pi->x, left_first->pi->y) ||
737 res_receiver.add_point(left_cur->pi->x, left_cur->pi->y) ||
738 res_receiver.complete_shape())
739
740 goto mem_error;
741
742 goto build_result;
743 }
744
745 if (res_receiver.start_shape(Gcalc_function::shape_polygon))
746 goto mem_error;
747
748 while (left_first)
749 {
750 if (res_receiver.add_point(left_first->pi->x, left_first->pi->y))
751 goto mem_error;
752 left_first= left_first->get_next();
753 }
754
755 /* Skip last point in the right part as it coincides */
756 /* with the last one in the left. */
757 right_cur= right_cur->prev;
758 while (right_cur->prev)
759 {
760 if (res_receiver.add_point(right_cur->pi->x, right_cur->pi->y))
761 goto mem_error;
762 right_cur= right_cur->prev;
763 }
764 res_receiver.complete_shape();
765
766 build_result:
767 str_value->set_charset(&my_charset_bin);
768 if (str_value->reserve(SRID_SIZE, 512))
769 goto mem_error;
770 str_value->length(0);
771 str_value->q_append(srid);
772
773 if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
774 goto mem_error;
775
776 mem_error:
777 collector.reset();
778 func.reset();
779 res_receiver.reset();
780 res_heap.reset();
781 DBUG_RETURN(str_value);
782 }
783 #endif /*HEAVY_CONVEX_HULL*/
784
785
786 /*
787 Spatial decomposition functions
788 */
789
val_str(String * str)790 String *Item_func_spatial_decomp::val_str(String *str)
791 {
792 DBUG_ASSERT(fixed == 1);
793 String arg_val;
794 String *swkb= args[0]->val_str(&arg_val);
795 Geometry_buffer buffer;
796 Geometry *geom= NULL;
797 uint32 srid;
798
799 if ((null_value=
800 (args[0]->null_value ||
801 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
802 return 0;
803
804 srid= uint4korr(swkb->ptr());
805 str->set_charset(&my_charset_bin);
806 if (str->reserve(SRID_SIZE, 512))
807 goto err;
808 str->length(0);
809 str->q_append(srid);
810 switch (decomp_func) {
811 case SP_STARTPOINT:
812 if (geom->start_point(str))
813 goto err;
814 break;
815
816 case SP_ENDPOINT:
817 if (geom->end_point(str))
818 goto err;
819 break;
820
821 case SP_EXTERIORRING:
822 if (geom->exterior_ring(str))
823 goto err;
824 break;
825
826 default:
827 goto err;
828 }
829 return str;
830
831 err:
832 null_value= 1;
833 return 0;
834 }
835
836
val_str(String * str)837 String *Item_func_spatial_decomp_n::val_str(String *str)
838 {
839 DBUG_ASSERT(fixed == 1);
840 String arg_val;
841 String *swkb= args[0]->val_str(&arg_val);
842 long n= (long) args[1]->val_int();
843 Geometry_buffer buffer;
844 Geometry *geom= NULL;
845 uint32 srid;
846
847 if ((null_value=
848 (args[0]->null_value || args[1]->null_value ||
849 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
850 return 0;
851
852 str->set_charset(&my_charset_bin);
853 if (str->reserve(SRID_SIZE, 512))
854 goto err;
855 srid= uint4korr(swkb->ptr());
856 str->length(0);
857 str->q_append(srid);
858 switch (decomp_func_n)
859 {
860 case SP_POINTN:
861 if (geom->point_n(n,str))
862 goto err;
863 break;
864
865 case SP_GEOMETRYN:
866 if (geom->geometry_n(n,str))
867 goto err;
868 break;
869
870 case SP_INTERIORRINGN:
871 if (geom->interior_ring_n(n,str))
872 goto err;
873 break;
874
875 default:
876 goto err;
877 }
878 return str;
879
880 err:
881 null_value=1;
882 return 0;
883 }
884
885
886 /*
887 Functions to concatenate various spatial objects
888 */
889
890
891 /*
892 * Concatenate doubles into Point
893 */
894
895
val_str(String * str)896 String *Item_func_point::val_str(String *str)
897 {
898 DBUG_ASSERT(fixed == 1);
899 double x= args[0]->val_real();
900 double y= args[1]->val_real();
901 uint32 srid= 0;
902
903 if ((null_value= (args[0]->null_value ||
904 args[1]->null_value ||
905 str->alloc(4/*SRID*/ + 1 + 4 + SIZEOF_STORED_DOUBLE * 2))))
906 return 0;
907
908 str->set_charset(&my_charset_bin);
909 str->length(0);
910 str->q_append(srid);
911 str->q_append((char)Geometry::wkb_ndr);
912 str->q_append((uint32)Geometry::wkb_point);
913 str->q_append(x);
914 str->q_append(y);
915 return str;
916 }
917
918
919 /**
920 Concatenates various items into various collections
921 with checkings for valid wkb type of items.
922 For example, MultiPoint can be a collection of Points only.
923 coll_type contains wkb type of target collection.
924 item_type contains a valid wkb type of items.
925 In the case when coll_type is wkbGeometryCollection,
926 we do not check wkb type of items, any is valid.
927 */
928
val_str(String * str)929 String *Item_func_spatial_collection::val_str(String *str)
930 {
931 DBUG_ASSERT(fixed == 1);
932 String arg_value;
933 uint i;
934 uint32 srid= 0;
935
936 str->set_charset(&my_charset_bin);
937 str->length(0);
938 if (str->reserve(4/*SRID*/ + 1 + 4 + 4, 512))
939 goto err;
940
941 str->q_append(srid);
942 str->q_append((char) Geometry::wkb_ndr);
943 str->q_append((uint32) coll_type);
944 str->q_append((uint32) arg_count);
945
946 for (i= 0; i < arg_count; ++i)
947 {
948 String *res= args[i]->val_str(&arg_value);
949 uint32 len;
950 if (args[i]->null_value || ((len= res->length()) < WKB_HEADER_SIZE))
951 goto err;
952
953 if (coll_type == Geometry::wkb_geometrycollection)
954 {
955 /*
956 In the case of GeometryCollection we don't need any checkings
957 for item types, so just copy them into target collection
958 */
959 if (str->append(res->ptr() + 4/*SRID*/, len - 4/*SRID*/, (uint32) 512))
960 goto err;
961 }
962 else
963 {
964 enum Geometry::wkbType wkb_type;
965 const uint data_offset= 4/*SRID*/ + 1;
966 if (res->length() < data_offset + sizeof(uint32))
967 goto err;
968 const char *data= res->ptr() + data_offset;
969
970 /*
971 In the case of named collection we must check that items
972 are of specific type, let's do this checking now
973 */
974
975 wkb_type= (Geometry::wkbType) uint4korr(data);
976 data+= 4;
977 len-= 5 + 4/*SRID*/;
978 if (wkb_type != item_type)
979 goto err;
980
981 switch (coll_type) {
982 case Geometry::wkb_multipoint:
983 case Geometry::wkb_multilinestring:
984 case Geometry::wkb_multipolygon:
985 if (len < WKB_HEADER_SIZE ||
986 str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
987 goto err;
988 break;
989
990 case Geometry::wkb_linestring:
991 if (len < POINT_DATA_SIZE || str->append(data, POINT_DATA_SIZE, 512))
992 goto err;
993 break;
994 case Geometry::wkb_polygon:
995 {
996 uint32 n_points;
997 double x1, y1, x2, y2;
998 const char *org_data= data;
999
1000 if (len < 4)
1001 goto err;
1002
1003 n_points= uint4korr(data);
1004 data+= 4;
1005
1006 if (n_points < 2 || len < 4 + n_points * POINT_DATA_SIZE)
1007 goto err;
1008
1009 float8get(x1, data);
1010 data+= SIZEOF_STORED_DOUBLE;
1011 float8get(y1, data);
1012 data+= SIZEOF_STORED_DOUBLE;
1013
1014 data+= (n_points - 2) * POINT_DATA_SIZE;
1015
1016 float8get(x2, data);
1017 float8get(y2, data + SIZEOF_STORED_DOUBLE);
1018
1019 if ((x1 != x2) || (y1 != y2) ||
1020 str->append(org_data, len, 512))
1021 goto err;
1022 }
1023 break;
1024
1025 default:
1026 goto err;
1027 }
1028 }
1029 }
1030 if (str->length() > current_thd->variables.max_allowed_packet)
1031 {
1032 THD *thd= current_thd;
1033 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1034 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
1035 ER_THD(thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED),
1036 func_name(), thd->variables.max_allowed_packet);
1037 goto err;
1038 }
1039
1040 null_value = 0;
1041 return str;
1042
1043 err:
1044 null_value= 1;
1045 return 0;
1046 }
1047
1048
1049 /*
1050 Functions for spatial relations
1051 */
1052
1053 static SEL_ARG sel_arg_impossible(SEL_ARG::IMPOSSIBLE);
1054
1055 SEL_ARG *
get_mm_leaf(RANGE_OPT_PARAM * param,Field * field,KEY_PART * key_part,Item_func::Functype type,Item * value)1056 Item_func_spatial_rel::get_mm_leaf(RANGE_OPT_PARAM *param,
1057 Field *field, KEY_PART *key_part,
1058 Item_func::Functype type, Item *value)
1059 {
1060 DBUG_ENTER("Item_func_spatial_rel::get_mm_leaf");
1061 if (key_part->image_type != Field::itMBR)
1062 DBUG_RETURN(0);
1063 if (value->cmp_type() != STRING_RESULT)
1064 DBUG_RETURN(&sel_arg_impossible);
1065
1066 if (param->using_real_indexes &&
1067 !field->optimize_range(param->real_keynr[key_part->key],
1068 key_part->part))
1069 DBUG_RETURN(0);
1070
1071 Field_geom *field_geom= dynamic_cast<Field_geom*>(field);
1072 DBUG_ASSERT(field_geom);
1073 const Type_handler_geometry *sav_geom_type= field_geom->type_handler_geom();
1074 // We have to be able to store all sorts of spatial features here
1075 field_geom->set_type_handler(&type_handler_geometry);
1076 bool rc= value->save_in_field_no_warnings(field, 1);
1077 field_geom->set_type_handler(sav_geom_type);
1078
1079 if (rc)
1080 DBUG_RETURN(&sel_arg_impossible); // Bad GEOMETRY value
1081
1082 DBUG_ASSERT(!field->real_maybe_null()); // SPATIAL keys do not support NULL
1083
1084 uchar *str= (uchar*) alloc_root(param->mem_root, key_part->store_length + 1);
1085 if (!str)
1086 DBUG_RETURN(0); // out of memory
1087 field->get_key_image(str, key_part->length, key_part->image_type);
1088 SEL_ARG *tree;
1089 if (!(tree= new (param->mem_root) SEL_ARG(field, str, str)))
1090 DBUG_RETURN(0); // out of memory
1091
1092 switch (type) {
1093 case SP_EQUALS_FUNC:
1094 tree->min_flag= GEOM_FLAG | HA_READ_MBR_EQUAL;// NEAR_MIN;//512;
1095 tree->max_flag= NO_MAX_RANGE;
1096 break;
1097 case SP_DISJOINT_FUNC:
1098 tree->min_flag= GEOM_FLAG | HA_READ_MBR_DISJOINT;// NEAR_MIN;//512;
1099 tree->max_flag= NO_MAX_RANGE;
1100 break;
1101 case SP_INTERSECTS_FUNC:
1102 tree->min_flag= GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
1103 tree->max_flag= NO_MAX_RANGE;
1104 break;
1105 case SP_TOUCHES_FUNC:
1106 tree->min_flag= GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
1107 tree->max_flag= NO_MAX_RANGE;
1108 break;
1109 case SP_CROSSES_FUNC:
1110 tree->min_flag= GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
1111 tree->max_flag= NO_MAX_RANGE;
1112 break;
1113 case SP_WITHIN_FUNC:
1114 tree->min_flag= GEOM_FLAG | HA_READ_MBR_CONTAIN;// NEAR_MIN;//512;
1115 tree->max_flag= NO_MAX_RANGE;
1116 break;
1117 case SP_CONTAINS_FUNC:
1118 tree->min_flag= GEOM_FLAG | HA_READ_MBR_WITHIN;// NEAR_MIN;//512;
1119 tree->max_flag= NO_MAX_RANGE;
1120 break;
1121 case SP_OVERLAPS_FUNC:
1122 tree->min_flag= GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
1123 tree->max_flag= NO_MAX_RANGE;
1124 break;
1125 default:
1126 DBUG_ASSERT(0);
1127 break;
1128 }
1129 DBUG_RETURN(tree);
1130 }
1131
1132
func_name() const1133 const char *Item_func_spatial_mbr_rel::func_name() const
1134 {
1135 switch (spatial_rel) {
1136 case SP_CONTAINS_FUNC:
1137 return "mbrcontains";
1138 case SP_WITHIN_FUNC:
1139 return "mbrwithin";
1140 case SP_EQUALS_FUNC:
1141 return "mbrequals";
1142 case SP_DISJOINT_FUNC:
1143 return "mbrdisjoint";
1144 case SP_INTERSECTS_FUNC:
1145 return "mbrintersects";
1146 case SP_TOUCHES_FUNC:
1147 return "mbrtouches";
1148 case SP_CROSSES_FUNC:
1149 return "mbrcrosses";
1150 case SP_OVERLAPS_FUNC:
1151 return "mbroverlaps";
1152 default:
1153 DBUG_ASSERT(0); // Should never happened
1154 return "mbrsp_unknown";
1155 }
1156 }
1157
1158
val_int()1159 longlong Item_func_spatial_mbr_rel::val_int()
1160 {
1161 DBUG_ASSERT(fixed == 1);
1162 String *res1= args[0]->val_str(&tmp_value1);
1163 String *res2= args[1]->val_str(&tmp_value2);
1164 Geometry_buffer buffer1, buffer2;
1165 Geometry *g1, *g2;
1166 MBR mbr1, mbr2;
1167 const char *dummy;
1168
1169 if ((null_value=
1170 (args[0]->null_value ||
1171 args[1]->null_value ||
1172 !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
1173 !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
1174 g1->get_mbr(&mbr1, &dummy) || !mbr1.valid() ||
1175 g2->get_mbr(&mbr2, &dummy) || !mbr2.valid())))
1176 return 0;
1177
1178 switch (spatial_rel) {
1179 case SP_CONTAINS_FUNC:
1180 return mbr1.contains(&mbr2);
1181 case SP_WITHIN_FUNC:
1182 return mbr1.within(&mbr2);
1183 case SP_EQUALS_FUNC:
1184 return mbr1.equals(&mbr2);
1185 case SP_DISJOINT_FUNC:
1186 return mbr1.disjoint(&mbr2);
1187 case SP_INTERSECTS_FUNC:
1188 return mbr1.intersects(&mbr2);
1189 case SP_TOUCHES_FUNC:
1190 return mbr1.touches(&mbr2);
1191 case SP_OVERLAPS_FUNC:
1192 return mbr1.overlaps(&mbr2);
1193 case SP_CROSSES_FUNC:
1194 return 0;
1195 default:
1196 break;
1197 }
1198
1199 null_value=1;
1200 return 0;
1201 }
1202
1203
func_name() const1204 const char *Item_func_spatial_precise_rel::func_name() const
1205 {
1206 switch (spatial_rel) {
1207 case SP_CONTAINS_FUNC:
1208 return "st_contains";
1209 case SP_WITHIN_FUNC:
1210 return "st_within";
1211 case SP_EQUALS_FUNC:
1212 return "st_equals";
1213 case SP_DISJOINT_FUNC:
1214 return "st_disjoint";
1215 case SP_INTERSECTS_FUNC:
1216 return "st_intersects";
1217 case SP_TOUCHES_FUNC:
1218 return "st_touches";
1219 case SP_CROSSES_FUNC:
1220 return "st_crosses";
1221 case SP_OVERLAPS_FUNC:
1222 return "st_overlaps";
1223 default:
1224 DBUG_ASSERT(0); // Should never happened
1225 return "sp_unknown";
1226 }
1227 }
1228
1229
count_edge_t(const Gcalc_heap::Info * ea,const Gcalc_heap::Info * eb,const Gcalc_heap::Info * v,double & ex,double & ey,double & vx,double & vy,double & e_sqrlen)1230 static double count_edge_t(const Gcalc_heap::Info *ea,
1231 const Gcalc_heap::Info *eb,
1232 const Gcalc_heap::Info *v,
1233 double &ex, double &ey, double &vx, double &vy,
1234 double &e_sqrlen)
1235 {
1236 ex= eb->node.shape.x - ea->node.shape.x;
1237 ey= eb->node.shape.y - ea->node.shape.y;
1238 vx= v->node.shape.x - ea->node.shape.x;
1239 vy= v->node.shape.y - ea->node.shape.y;
1240 e_sqrlen= ex * ex + ey * ey;
1241 return (ex * vx + ey * vy) / e_sqrlen;
1242 }
1243
1244
distance_to_line(double ex,double ey,double vx,double vy,double e_sqrlen)1245 static double distance_to_line(double ex, double ey, double vx, double vy,
1246 double e_sqrlen)
1247 {
1248 return fabs(vx * ey - vy * ex) / sqrt(e_sqrlen);
1249 }
1250
1251
distance_points(const Gcalc_heap::Info * a,const Gcalc_heap::Info * b)1252 static double distance_points(const Gcalc_heap::Info *a,
1253 const Gcalc_heap::Info *b)
1254 {
1255 double x= a->node.shape.x - b->node.shape.x;
1256 double y= a->node.shape.y - b->node.shape.y;
1257 return sqrt(x * x + y * y);
1258 }
1259
1260
op_matrix(int n)1261 static Gcalc_function::op_type op_matrix(int n)
1262 {
1263 switch (n)
1264 {
1265 case 0:
1266 return Gcalc_function::op_internals;
1267 case 1:
1268 return Gcalc_function::op_border;
1269 case 2:
1270 return (Gcalc_function::op_type)
1271 ((int) Gcalc_function::op_not | (int) Gcalc_function::op_union);
1272 };
1273 GCALC_DBUG_ASSERT(FALSE);
1274 return Gcalc_function::op_any;
1275 }
1276
1277
setup_relate_func(Geometry * g1,Geometry * g2,Gcalc_operation_transporter * trn,Gcalc_function * func,const char * mask)1278 static int setup_relate_func(Geometry *g1, Geometry *g2,
1279 Gcalc_operation_transporter *trn, Gcalc_function *func,
1280 const char *mask)
1281 {
1282 int do_store_shapes=1;
1283 uint UNINIT_VAR(shape_a), UNINIT_VAR(shape_b);
1284 uint n_operands= 0;
1285 int last_shape_pos;
1286
1287 last_shape_pos= func->get_next_expression_pos();
1288 if (func->reserve_op_buffer(1))
1289 return 1;
1290 func->add_operation(Gcalc_function::op_intersection, 0);
1291 for (int nc=0; nc<9; nc++)
1292 {
1293 uint cur_op;
1294
1295 cur_op= Gcalc_function::op_intersection;
1296 switch (mask[nc])
1297 {
1298 case '*':
1299 continue;
1300 case 'T':
1301 case '0':
1302 case '1':
1303 case '2':
1304 cur_op|= Gcalc_function::v_find_t;
1305 break;
1306 case 'F':
1307 cur_op|= (Gcalc_function::op_not | Gcalc_function::v_find_f);
1308 break;
1309 default:
1310 return 1;
1311 };
1312 ++n_operands;
1313 if (func->reserve_op_buffer(3))
1314 return 1;
1315 func->add_operation(cur_op, 2);
1316
1317 func->add_operation(op_matrix(nc/3), 1);
1318 if (do_store_shapes)
1319 {
1320 shape_a= func->get_next_expression_pos();
1321 if (g1->store_shapes(trn))
1322 return 1;
1323 }
1324 else
1325 func->repeat_expression(shape_a);
1326 if (func->reserve_op_buffer(1))
1327 return 1;
1328 func->add_operation(op_matrix(nc%3), 1);
1329 if (do_store_shapes)
1330 {
1331 shape_b= func->get_next_expression_pos();
1332 if (g2->store_shapes(trn))
1333 return 1;
1334 do_store_shapes= 0;
1335 }
1336 else
1337 func->repeat_expression(shape_b);
1338 }
1339
1340 func->add_operands_to_op(last_shape_pos, n_operands);
1341 return 0;
1342 }
1343
1344
1345 #define GIS_ZERO 0.00000000001
1346
1347 class Geometry_ptr_with_buffer_and_mbr
1348 {
1349 public:
1350 Geometry *geom;
1351 Geometry_buffer buffer;
1352 MBR mbr;
construct(Item * item,String * tmp_value)1353 bool construct(Item *item, String *tmp_value)
1354 {
1355 const char *c_end;
1356 String *res= item->val_str(tmp_value);
1357 return
1358 item->null_value ||
1359 !(geom= Geometry::construct(&buffer, res->ptr(), res->length())) ||
1360 geom->get_mbr(&mbr, &c_end) || !mbr.valid();
1361 }
store_shapes(Gcalc_shape_transporter * trn) const1362 int store_shapes(Gcalc_shape_transporter *trn) const
1363 { return geom->store_shapes(trn); }
1364 };
1365
1366
val_int()1367 longlong Item_func_spatial_relate::val_int()
1368 {
1369 DBUG_ENTER("Item_func_spatial_relate::val_int");
1370 DBUG_ASSERT(fixed == 1);
1371 Geometry_ptr_with_buffer_and_mbr g1, g2;
1372 int result= 0;
1373
1374 if ((null_value= (g1.construct(args[0], &tmp_value1) ||
1375 g2.construct(args[1], &tmp_value2) ||
1376 func.reserve_op_buffer(1))))
1377 DBUG_RETURN(0);
1378
1379 MBR umbr(g1.mbr, g2.mbr);
1380 collector.set_extent(umbr.xmin, umbr.xmax, umbr.ymin, umbr.ymax);
1381 g1.mbr.buffer(1e-5);
1382 Gcalc_operation_transporter trn(&func, &collector);
1383
1384 String *matrix= args[2]->val_str(&tmp_matrix);
1385 if ((null_value= args[2]->null_value || matrix->length() != 9 ||
1386 setup_relate_func(g1.geom, g2.geom,
1387 &trn, &func, matrix->ptr())))
1388 goto exit;
1389
1390 collector.prepare_operation();
1391 scan_it.init(&collector);
1392 scan_it.killed= (int *) &(current_thd->killed);
1393 if (!func.alloc_states())
1394 result= func.check_function(scan_it);
1395
1396 exit:
1397 collector.reset();
1398 func.reset();
1399 scan_it.reset();
1400 DBUG_RETURN(result);
1401 }
1402
1403
val_int()1404 longlong Item_func_spatial_precise_rel::val_int()
1405 {
1406 DBUG_ENTER("Item_func_spatial_precise_rel::val_int");
1407 DBUG_ASSERT(fixed == 1);
1408 Geometry_ptr_with_buffer_and_mbr g1, g2;
1409 int result= 0;
1410 uint shape_a, shape_b;
1411
1412 if ((null_value= (g1.construct(args[0], &tmp_value1) ||
1413 g2.construct(args[1], &tmp_value2) ||
1414 func.reserve_op_buffer(1))))
1415 DBUG_RETURN(0);
1416
1417 Gcalc_operation_transporter trn(&func, &collector);
1418
1419 MBR umbr(g1.mbr, g2.mbr);
1420 collector.set_extent(umbr.xmin, umbr.xmax, umbr.ymin, umbr.ymax);
1421
1422 g1.mbr.buffer(1e-5);
1423
1424 switch (spatial_rel) {
1425 case SP_CONTAINS_FUNC:
1426 if (!g1.mbr.contains(&g2.mbr))
1427 goto exit;
1428 func.add_operation(Gcalc_function::v_find_f |
1429 Gcalc_function::op_not |
1430 Gcalc_function::op_difference, 2);
1431 /* Mind the g2 goes first. */
1432 null_value= g2.store_shapes(&trn) || g1.store_shapes(&trn);
1433 break;
1434 case SP_WITHIN_FUNC:
1435 g2.mbr.buffer(2e-5);
1436 if (!g1.mbr.within(&g2.mbr))
1437 goto exit;
1438 func.add_operation(Gcalc_function::v_find_f |
1439 Gcalc_function::op_not |
1440 Gcalc_function::op_difference, 2);
1441 null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
1442 break;
1443 case SP_EQUALS_FUNC:
1444 if (!g1.mbr.contains(&g2.mbr))
1445 goto exit;
1446 func.add_operation(Gcalc_function::v_find_f |
1447 Gcalc_function::op_not |
1448 Gcalc_function::op_symdifference, 2);
1449 null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
1450 break;
1451 case SP_DISJOINT_FUNC:
1452 func.add_operation(Gcalc_function::v_find_f |
1453 Gcalc_function::op_not |
1454 Gcalc_function::op_intersection, 2);
1455 null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
1456 break;
1457 case SP_INTERSECTS_FUNC:
1458 if (!g1.mbr.intersects(&g2.mbr))
1459 goto exit;
1460 func.add_operation(Gcalc_function::v_find_t |
1461 Gcalc_function::op_intersection, 2);
1462 null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
1463 break;
1464 case SP_OVERLAPS_FUNC:
1465 case SP_CROSSES_FUNC:
1466 func.add_operation(Gcalc_function::op_intersection, 2);
1467 if (func.reserve_op_buffer(3))
1468 break;
1469 func.add_operation(Gcalc_function::v_find_t |
1470 Gcalc_function::op_intersection, 2);
1471 shape_a= func.get_next_expression_pos();
1472 if ((null_value= g1.store_shapes(&trn)))
1473 break;
1474 shape_b= func.get_next_expression_pos();
1475 if ((null_value= g2.store_shapes(&trn)))
1476 break;
1477 if (func.reserve_op_buffer(7))
1478 break;
1479 func.add_operation(Gcalc_function::op_intersection, 2);
1480 func.add_operation(Gcalc_function::v_find_t |
1481 Gcalc_function::op_difference, 2);
1482 func.repeat_expression(shape_a);
1483 func.repeat_expression(shape_b);
1484 func.add_operation(Gcalc_function::v_find_t |
1485 Gcalc_function::op_difference, 2);
1486 func.repeat_expression(shape_b);
1487 func.repeat_expression(shape_a);
1488 break;
1489 case SP_TOUCHES_FUNC:
1490 if (func.reserve_op_buffer(5))
1491 break;
1492 func.add_operation(Gcalc_function::op_intersection, 2);
1493 func.add_operation(Gcalc_function::v_find_f |
1494 Gcalc_function::op_not |
1495 Gcalc_function::op_intersection, 2);
1496 func.add_operation(Gcalc_function::op_internals, 1);
1497 shape_a= func.get_next_expression_pos();
1498 if ((null_value= g1.store_shapes(&trn)) ||
1499 func.reserve_op_buffer(1))
1500 break;
1501 func.add_operation(Gcalc_function::op_internals, 1);
1502 shape_b= func.get_next_expression_pos();
1503 if ((null_value= g2.store_shapes(&trn)) ||
1504 func.reserve_op_buffer(1))
1505 break;
1506 func.add_operation(Gcalc_function::v_find_t |
1507 Gcalc_function::op_intersection, 2);
1508 func.repeat_expression(shape_a);
1509 func.repeat_expression(shape_b);
1510 break;
1511 default:
1512 DBUG_ASSERT(FALSE);
1513 break;
1514 }
1515
1516 if (null_value)
1517 goto exit;
1518
1519 collector.prepare_operation();
1520 scan_it.init(&collector);
1521 scan_it.killed= (int *) &(current_thd->killed);
1522
1523 if (func.alloc_states())
1524 goto exit;
1525
1526 result= func.check_function(scan_it);
1527
1528 exit:
1529 collector.reset();
1530 func.reset();
1531 scan_it.reset();
1532 DBUG_RETURN(result);
1533 }
1534
1535
~Item_func_spatial_operation()1536 Item_func_spatial_operation::~Item_func_spatial_operation()
1537 {
1538 }
1539
1540
val_str(String * str_value)1541 String *Item_func_spatial_operation::val_str(String *str_value)
1542 {
1543 DBUG_ENTER("Item_func_spatial_operation::val_str");
1544 DBUG_ASSERT(fixed == 1);
1545 Geometry_ptr_with_buffer_and_mbr g1, g2;
1546 uint32 srid= 0;
1547 Gcalc_operation_transporter trn(&func, &collector);
1548
1549 if (func.reserve_op_buffer(1))
1550 DBUG_RETURN(0);
1551 func.add_operation(spatial_op, 2);
1552
1553 if ((null_value= (g1.construct(args[0], &tmp_value1) ||
1554 g2.construct(args[1], &tmp_value2))))
1555 {
1556 str_value= 0;
1557 goto exit;
1558 }
1559
1560 g1.mbr.add_mbr(&g2.mbr);
1561 collector.set_extent(g1.mbr.xmin, g1.mbr.xmax, g1.mbr.ymin, g1.mbr.ymax);
1562
1563 if ((null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn)))
1564 {
1565 str_value= 0;
1566 goto exit;
1567 }
1568
1569 collector.prepare_operation();
1570 if (func.alloc_states())
1571 goto exit;
1572
1573 operation.init(&func);
1574
1575 if (operation.count_all(&collector) ||
1576 operation.get_result(&res_receiver))
1577 goto exit;
1578
1579
1580 str_value->set_charset(&my_charset_bin);
1581 if (str_value->reserve(SRID_SIZE, 512))
1582 goto exit;
1583 str_value->length(0);
1584 str_value->q_append(srid);
1585
1586 if (!Geometry::create_from_opresult(&g1.buffer, str_value, res_receiver))
1587 goto exit;
1588
1589 exit:
1590 collector.reset();
1591 func.reset();
1592 res_receiver.reset();
1593 DBUG_RETURN(str_value);
1594 }
1595
1596
func_name() const1597 const char *Item_func_spatial_operation::func_name() const
1598 {
1599 switch (spatial_op) {
1600 case Gcalc_function::op_intersection:
1601 return "st_intersection";
1602 case Gcalc_function::op_difference:
1603 return "st_difference";
1604 case Gcalc_function::op_union:
1605 return "st_union";
1606 case Gcalc_function::op_symdifference:
1607 return "st_symdifference";
1608 default:
1609 DBUG_ASSERT(0); // Should never happen
1610 return "sp_unknown";
1611 }
1612 }
1613
1614
1615 static const int SINUSES_CALCULATED= 32;
1616 static double n_sinus[SINUSES_CALCULATED+1]=
1617 {
1618 0,
1619 0.04906767432741802,
1620 0.0980171403295606,
1621 0.1467304744553618,
1622 0.1950903220161283,
1623 0.2429801799032639,
1624 0.2902846772544623,
1625 0.3368898533922201,
1626 0.3826834323650898,
1627 0.4275550934302821,
1628 0.4713967368259976,
1629 0.5141027441932217,
1630 0.5555702330196022,
1631 0.5956993044924334,
1632 0.6343932841636455,
1633 0.6715589548470183,
1634 0.7071067811865475,
1635 0.7409511253549591,
1636 0.773010453362737,
1637 0.8032075314806448,
1638 0.8314696123025452,
1639 0.8577286100002721,
1640 0.8819212643483549,
1641 0.9039892931234433,
1642 0.9238795325112867,
1643 0.9415440651830208,
1644 0.9569403357322089,
1645 0.970031253194544,
1646 0.9807852804032304,
1647 0.989176509964781,
1648 0.9951847266721968,
1649 0.9987954562051724,
1650 1
1651 };
1652
1653
get_n_sincos(int n,double * sinus,double * cosinus)1654 static void get_n_sincos(int n, double *sinus, double *cosinus)
1655 {
1656 DBUG_ASSERT(n > 0 && n < SINUSES_CALCULATED*2+1);
1657 if (n < (SINUSES_CALCULATED + 1))
1658 {
1659 *sinus= n_sinus[n];
1660 *cosinus= n_sinus[SINUSES_CALCULATED - n];
1661 }
1662 else
1663 {
1664 n-= SINUSES_CALCULATED;
1665 *sinus= n_sinus[SINUSES_CALCULATED - n];
1666 *cosinus= -n_sinus[n];
1667 }
1668 }
1669
1670
fill_half_circle(Gcalc_shape_transporter * trn,double x,double y,double ax,double ay)1671 static int fill_half_circle(Gcalc_shape_transporter *trn, double x, double y,
1672 double ax, double ay)
1673 {
1674 double n_sin, n_cos;
1675 double x_n, y_n;
1676 for (int n = 1; n < (SINUSES_CALCULATED * 2 - 1); n++)
1677 {
1678 get_n_sincos(n, &n_sin, &n_cos);
1679 x_n= ax * n_cos - ay * n_sin;
1680 y_n= ax * n_sin + ay * n_cos;
1681 if (trn->add_point(x_n + x, y_n + y))
1682 return 1;
1683 }
1684 return 0;
1685 }
1686
1687
fill_gap(Gcalc_shape_transporter * trn,double x,double y,double ax,double ay,double bx,double by,double d,bool * empty_gap)1688 static int fill_gap(Gcalc_shape_transporter *trn,
1689 double x, double y,
1690 double ax, double ay, double bx, double by, double d,
1691 bool *empty_gap)
1692 {
1693 double ab= ax * bx + ay * by;
1694 double cosab= ab / (d * d) + GIS_ZERO;
1695 double n_sin, n_cos;
1696 double x_n, y_n;
1697 int n=1;
1698
1699 *empty_gap= true;
1700 for (;;)
1701 {
1702 get_n_sincos(n++, &n_sin, &n_cos);
1703 if (n_cos <= cosab)
1704 break;
1705 *empty_gap= false;
1706 x_n= ax * n_cos - ay * n_sin;
1707 y_n= ax * n_sin + ay * n_cos;
1708 if (trn->add_point(x_n + x, y_n + y))
1709 return 1;
1710 }
1711 return 0;
1712 }
1713
1714
1715 /*
1716 Calculates the vector (p2,p1) and
1717 negatively orthogonal to it with the length of d.
1718 The result is (ex,ey) - the vector, (px,py) - the orthogonal.
1719 */
1720
calculate_perpendicular(double x1,double y1,double x2,double y2,double d,double * ex,double * ey,double * px,double * py)1721 static void calculate_perpendicular(
1722 double x1, double y1, double x2, double y2, double d,
1723 double *ex, double *ey,
1724 double *px, double *py)
1725 {
1726 double q;
1727 *ex= x1 - x2;
1728 *ey= y1 - y2;
1729 q= d / sqrt((*ex) * (*ex) + (*ey) * (*ey));
1730 *px= (*ey) * q;
1731 *py= -(*ex) * q;
1732 }
1733
1734
single_point(double x,double y)1735 int Item_func_buffer::Transporter::single_point(double x, double y)
1736 {
1737 if (buffer_op == Gcalc_function::op_difference)
1738 {
1739 if (m_fn->reserve_op_buffer(1))
1740 return 1;
1741 m_fn->add_operation(Gcalc_function::op_false, 0);
1742 return 0;
1743 }
1744
1745 m_nshapes= 0;
1746 return add_point_buffer(x, y);
1747 }
1748
1749
add_edge_buffer(double x3,double y3,bool round_p1,bool round_p2)1750 int Item_func_buffer::Transporter::add_edge_buffer(
1751 double x3, double y3, bool round_p1, bool round_p2)
1752 {
1753 Gcalc_operation_transporter trn(m_fn, m_heap);
1754 double e1_x, e1_y, e2_x, e2_y, p1_x, p1_y, p2_x, p2_y;
1755 double e1e2;
1756 double sin1, cos1;
1757 double x_n, y_n;
1758 bool empty_gap1, empty_gap2;
1759
1760 ++m_nshapes;
1761 if (trn.start_simple_poly())
1762 return 1;
1763
1764 calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
1765 calculate_perpendicular(x3, y3, x2, y2, m_d, &e2_x, &e2_y, &p2_x, &p2_y);
1766
1767 e1e2= e1_x * e2_y - e2_x * e1_y;
1768 sin1= n_sinus[1];
1769 cos1= n_sinus[31];
1770 if (e1e2 < 0)
1771 {
1772 empty_gap2= false;
1773 x_n= x2 + p2_x * cos1 - p2_y * sin1;
1774 y_n= y2 + p2_y * cos1 + p2_x * sin1;
1775 if (fill_gap(&trn, x2, y2, -p1_x,-p1_y, p2_x,p2_y, m_d, &empty_gap1) ||
1776 trn.add_point(x2 + p2_x, y2 + p2_y) ||
1777 trn.add_point(x_n, y_n))
1778 return 1;
1779 }
1780 else
1781 {
1782 x_n= x2 - p2_x * cos1 - p2_y * sin1;
1783 y_n= y2 - p2_y * cos1 + p2_x * sin1;
1784 if (trn.add_point(x_n, y_n) ||
1785 trn.add_point(x2 - p2_x, y2 - p2_y) ||
1786 fill_gap(&trn, x2, y2, -p2_x, -p2_y, p1_x, p1_y, m_d, &empty_gap2))
1787 return 1;
1788 empty_gap1= false;
1789 }
1790 if ((!empty_gap2 && trn.add_point(x2 + p1_x, y2 + p1_y)) ||
1791 trn.add_point(x1 + p1_x, y1 + p1_y))
1792 return 1;
1793
1794 if (round_p1 && fill_half_circle(&trn, x1, y1, p1_x, p1_y))
1795 return 1;
1796
1797 if (trn.add_point(x1 - p1_x, y1 - p1_y) ||
1798 (!empty_gap1 && trn.add_point(x2 - p1_x, y2 - p1_y)))
1799 return 1;
1800 return trn.complete_simple_poly();
1801 }
1802
1803
add_last_edge_buffer()1804 int Item_func_buffer::Transporter::add_last_edge_buffer()
1805 {
1806 Gcalc_operation_transporter trn(m_fn, m_heap);
1807 double e1_x, e1_y, p1_x, p1_y;
1808
1809 ++m_nshapes;
1810 if (trn.start_simple_poly())
1811 return 1;
1812
1813 calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
1814
1815 if (trn.add_point(x1 + p1_x, y1 + p1_y) ||
1816 trn.add_point(x1 - p1_x, y1 - p1_y) ||
1817 trn.add_point(x2 - p1_x, y2 - p1_y) ||
1818 fill_half_circle(&trn, x2, y2, -p1_x, -p1_y) ||
1819 trn.add_point(x2 + p1_x, y2 + p1_y))
1820 return 1;
1821 return trn.complete_simple_poly();
1822 }
1823
1824
add_point_buffer(double x,double y)1825 int Item_func_buffer::Transporter::add_point_buffer(double x, double y)
1826 {
1827 Gcalc_operation_transporter trn(m_fn, m_heap);
1828
1829 m_nshapes++;
1830 if (trn.start_simple_poly())
1831 return 1;
1832 if (trn.add_point(x - m_d, y) ||
1833 fill_half_circle(&trn, x, y, -m_d, 0.0) ||
1834 trn.add_point(x + m_d, y) ||
1835 fill_half_circle(&trn, x, y, m_d, 0.0))
1836 return 1;
1837 return trn.complete_simple_poly();
1838 }
1839
1840
start_line()1841 int Item_func_buffer::Transporter::start_line()
1842 {
1843 if (buffer_op == Gcalc_function::op_difference)
1844 {
1845 if (m_fn->reserve_op_buffer(1))
1846 return 1;
1847 m_fn->add_operation(Gcalc_function::op_false, 0);
1848 skip_line= TRUE;
1849 return 0;
1850 }
1851
1852 m_nshapes= 0;
1853
1854 if (m_fn->reserve_op_buffer(2))
1855 return 1;
1856 last_shape_pos= m_fn->get_next_expression_pos();
1857 m_fn->add_operation(buffer_op, 0);
1858 m_npoints= 0;
1859 int_start_line();
1860 return 0;
1861 }
1862
1863
start_poly()1864 int Item_func_buffer::Transporter::start_poly()
1865 {
1866 m_nshapes= 1;
1867
1868 if (m_fn->reserve_op_buffer(2))
1869 return 1;
1870 last_shape_pos= m_fn->get_next_expression_pos();
1871 m_fn->add_operation(buffer_op, 0);
1872 return Gcalc_operation_transporter::start_poly();
1873 }
1874
1875
complete_poly()1876 int Item_func_buffer::Transporter::complete_poly()
1877 {
1878 if (Gcalc_operation_transporter::complete_poly())
1879 return 1;
1880 m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
1881 return 0;
1882 }
1883
1884
start_ring()1885 int Item_func_buffer::Transporter::start_ring()
1886 {
1887 m_npoints= 0;
1888 return Gcalc_operation_transporter::start_ring();
1889 }
1890
1891
start_collection(int n_objects)1892 int Item_func_buffer::Transporter::start_collection(int n_objects)
1893 {
1894 if (m_fn->reserve_op_buffer(1))
1895 return 1;
1896 m_fn->add_operation(Gcalc_function::op_union, n_objects);
1897 return 0;
1898 }
1899
1900
add_point(double x,double y)1901 int Item_func_buffer::Transporter::add_point(double x, double y)
1902 {
1903 if (skip_line)
1904 return 0;
1905
1906 if (m_npoints && x == x2 && y == y2)
1907 return 0;
1908
1909 ++m_npoints;
1910
1911 if (m_npoints == 1)
1912 {
1913 x00= x;
1914 y00= y;
1915 }
1916 else if (m_npoints == 2)
1917 {
1918 x01= x;
1919 y01= y;
1920 }
1921 else if (add_edge_buffer(x, y, (m_npoints == 3) && line_started(), false))
1922 return 1;
1923
1924 x1= x2;
1925 y1= y2;
1926 x2= x;
1927 y2= y;
1928
1929 return line_started() ? 0 : Gcalc_operation_transporter::add_point(x, y);
1930 }
1931
1932
complete()1933 int Item_func_buffer::Transporter::complete()
1934 {
1935 if (m_npoints)
1936 {
1937 if (m_npoints == 1)
1938 {
1939 if (add_point_buffer(x2, y2))
1940 return 1;
1941 }
1942 else if (m_npoints == 2)
1943 {
1944 if (add_edge_buffer(x1, y1, true, true))
1945 return 1;
1946 }
1947 else if (line_started())
1948 {
1949 if (add_last_edge_buffer())
1950 return 1;
1951 }
1952 else
1953 {
1954 if (x2 != x00 || y2 != y00)
1955 {
1956 if (add_edge_buffer(x00, y00, false, false))
1957 return 1;
1958 x1= x2;
1959 y1= y2;
1960 x2= x00;
1961 y2= y00;
1962 }
1963 if (add_edge_buffer(x01, y01, false, false))
1964 return 1;
1965 }
1966 }
1967
1968 return 0;
1969 }
1970
1971
complete_line()1972 int Item_func_buffer::Transporter::complete_line()
1973 {
1974 if (!skip_line)
1975 {
1976 if (complete())
1977 return 1;
1978 int_complete_line();
1979 m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
1980 }
1981 skip_line= FALSE;
1982 return 0;
1983 }
1984
1985
complete_ring()1986 int Item_func_buffer::Transporter::complete_ring()
1987 {
1988 return complete() ||
1989 Gcalc_operation_transporter::complete_ring();
1990 }
1991
1992
val_str(String * str_value)1993 String *Item_func_buffer::val_str(String *str_value)
1994 {
1995 DBUG_ENTER("Item_func_buffer::val_str");
1996 DBUG_ASSERT(fixed == 1);
1997 String *obj= args[0]->val_str(str_value);
1998 double dist= args[1]->val_real();
1999 Geometry_buffer buffer;
2000 Geometry *g;
2001 uint32 srid= 0;
2002 String *str_result= NULL;
2003 Transporter trn(&func, &collector, dist);
2004 MBR mbr;
2005 const char *c_end;
2006
2007 null_value= 1;
2008 if (args[0]->null_value || args[1]->null_value ||
2009 !(g= Geometry::construct(&buffer, obj->ptr(), obj->length())) ||
2010 g->get_mbr(&mbr, &c_end))
2011 goto mem_error;
2012
2013 if (dist > 0.0)
2014 mbr.buffer(dist);
2015 else
2016 {
2017 /* This happens when dist is too far negative. */
2018 if (mbr.xmax + dist < mbr.xmin || mbr.ymax + dist < mbr.ymin)
2019 goto return_empty_result;
2020 }
2021
2022 collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
2023 /*
2024 If the distance given is 0, the Buffer function is in fact NOOP,
2025 so it's natural just to return the argument1.
2026 Besides, internal calculations here can't handle zero distance anyway.
2027 */
2028 if (fabs(dist) < GIS_ZERO)
2029 {
2030 null_value= 0;
2031 str_result= obj;
2032 goto mem_error;
2033 }
2034
2035 if (g->store_shapes(&trn))
2036 goto mem_error;
2037
2038 collector.prepare_operation();
2039 if (func.alloc_states())
2040 goto mem_error;
2041 operation.init(&func);
2042 operation.killed= (int *) &(current_thd->killed);
2043
2044 if (operation.count_all(&collector) ||
2045 operation.get_result(&res_receiver))
2046 goto mem_error;
2047
2048
2049 return_empty_result:
2050 str_value->set_charset(&my_charset_bin);
2051 if (str_value->reserve(SRID_SIZE, 512))
2052 goto mem_error;
2053 str_value->length(0);
2054 str_value->q_append(srid);
2055
2056 if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
2057 goto mem_error;
2058
2059 null_value= 0;
2060 str_result= str_value;
2061 mem_error:
2062 collector.reset();
2063 func.reset();
2064 res_receiver.reset();
2065 DBUG_RETURN(str_result);
2066 }
2067
2068
val_int()2069 longlong Item_func_isempty::val_int()
2070 {
2071 DBUG_ASSERT(fixed == 1);
2072 String tmp;
2073 String *swkb= args[0]->val_str(&tmp);
2074 Geometry_buffer buffer;
2075
2076 null_value= args[0]->null_value ||
2077 !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
2078 return null_value ? 1 : 0;
2079 }
2080
2081
val_int()2082 longlong Item_func_issimple::val_int()
2083 {
2084 String *swkb= args[0]->val_str(&tmp);
2085 Geometry_buffer buffer;
2086 Gcalc_operation_transporter trn(&func, &collector);
2087 Geometry *g;
2088 int result= 1;
2089 MBR mbr;
2090 const char *c_end;
2091
2092 DBUG_ENTER("Item_func_issimple::val_int");
2093 DBUG_ASSERT(fixed == 1);
2094
2095 null_value= 0;
2096 if ((args[0]->null_value ||
2097 !(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
2098 g->get_mbr(&mbr, &c_end)))
2099 {
2100 /* We got NULL as an argument. Have to return -1 */
2101 DBUG_RETURN(-1);
2102 }
2103
2104 collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
2105
2106 if (g->get_class_info()->m_type_id == Geometry::wkb_point)
2107 DBUG_RETURN(1);
2108
2109 if (g->store_shapes(&trn))
2110 goto mem_error;
2111
2112 collector.prepare_operation();
2113 scan_it.init(&collector);
2114
2115 while (scan_it.more_points())
2116 {
2117 const Gcalc_scan_iterator::event_point *ev, *next_ev;
2118
2119 if (scan_it.step())
2120 goto mem_error;
2121
2122 ev= scan_it.get_events();
2123 if (ev->simple_event())
2124 continue;
2125
2126 next_ev= ev->get_next();
2127 if ((ev->event & (scev_thread | scev_single_point)) && !next_ev)
2128 continue;
2129
2130 if ((ev->event == scev_two_threads) && !next_ev->get_next())
2131 continue;
2132
2133 /* If the first and last points of a curve coincide - that is */
2134 /* an exception to the rule and the line is considered as simple. */
2135 if ((next_ev && !next_ev->get_next()) &&
2136 (ev->event & (scev_thread | scev_end)) &&
2137 (next_ev->event & (scev_thread | scev_end)))
2138 continue;
2139
2140 result= 0;
2141 break;
2142 }
2143
2144 collector.reset();
2145 func.reset();
2146 scan_it.reset();
2147 DBUG_RETURN(result);
2148 mem_error:
2149 null_value= 1;
2150 DBUG_RETURN(0);
2151 }
2152
2153
val_int()2154 longlong Item_func_isclosed::val_int()
2155 {
2156 DBUG_ASSERT(fixed == 1);
2157 String tmp;
2158 String *swkb= args[0]->val_str(&tmp);
2159 Geometry_buffer buffer;
2160 Geometry *geom;
2161 int isclosed= 0; // In case of error
2162
2163 null_value= 0;
2164 if (!swkb ||
2165 args[0]->null_value ||
2166 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
2167 geom->is_closed(&isclosed))
2168 {
2169 /* IsClosed(NULL) should return -1 */
2170 return -1;
2171 }
2172
2173 return (longlong) isclosed;
2174 }
2175
2176
val_int()2177 longlong Item_func_isring::val_int()
2178 {
2179 /* It's actually a combination of two functions - IsClosed and IsSimple */
2180 DBUG_ASSERT(fixed == 1);
2181 String tmp;
2182 String *swkb= args[0]->val_str(&tmp);
2183 Geometry_buffer buffer;
2184 Geometry *geom;
2185 int isclosed= 0; // In case of error
2186
2187 null_value= 0;
2188 if (!swkb ||
2189 args[0]->null_value ||
2190 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
2191 geom->is_closed(&isclosed))
2192 {
2193 /* IsRing(NULL) should return -1 */
2194 return -1;
2195 }
2196
2197 if (!isclosed)
2198 return 0;
2199
2200 return Item_func_issimple::val_int();
2201 }
2202
2203
2204 /*
2205 Numerical functions
2206 */
2207
2208
val_int()2209 longlong Item_func_dimension::val_int()
2210 {
2211 DBUG_ASSERT(fixed == 1);
2212 uint32 dim= 0; // In case of error
2213 String *swkb= args[0]->val_str(&value);
2214 Geometry_buffer buffer;
2215 Geometry *geom;
2216 const char *dummy;
2217
2218 null_value= (!swkb ||
2219 args[0]->null_value ||
2220 !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
2221 geom->dimension(&dim, &dummy));
2222 return (longlong) dim;
2223 }
2224
2225
val_int()2226 longlong Item_func_numinteriorring::val_int()
2227 {
2228 DBUG_ASSERT(fixed == 1);
2229 uint32 num= 0; // In case of error
2230 String *swkb= args[0]->val_str(&value);
2231 Geometry_buffer buffer;
2232 Geometry *geom;
2233
2234 null_value= (!swkb ||
2235 !(geom= Geometry::construct(&buffer,
2236 swkb->ptr(), swkb->length())) ||
2237 geom->num_interior_ring(&num));
2238 return (longlong) num;
2239 }
2240
2241
val_int()2242 longlong Item_func_numgeometries::val_int()
2243 {
2244 DBUG_ASSERT(fixed == 1);
2245 uint32 num= 0; // In case of errors
2246 String *swkb= args[0]->val_str(&value);
2247 Geometry_buffer buffer;
2248 Geometry *geom;
2249
2250 null_value= (!swkb ||
2251 !(geom= Geometry::construct(&buffer,
2252 swkb->ptr(), swkb->length())) ||
2253 geom->num_geometries(&num));
2254 return (longlong) num;
2255 }
2256
2257
val_int()2258 longlong Item_func_numpoints::val_int()
2259 {
2260 DBUG_ASSERT(fixed == 1);
2261 uint32 num= 0; // In case of errors
2262 String *swkb= args[0]->val_str(&value);
2263 Geometry_buffer buffer;
2264 Geometry *geom;
2265
2266 null_value= (!swkb ||
2267 args[0]->null_value ||
2268 !(geom= Geometry::construct(&buffer,
2269 swkb->ptr(), swkb->length())) ||
2270 geom->num_points(&num));
2271 return (longlong) num;
2272 }
2273
2274
val_real()2275 double Item_func_x::val_real()
2276 {
2277 DBUG_ASSERT(fixed == 1);
2278 double res= 0.0; // In case of errors
2279 String *swkb= args[0]->val_str(&value);
2280 Geometry_buffer buffer;
2281 Geometry *geom;
2282
2283 null_value= (!swkb ||
2284 !(geom= Geometry::construct(&buffer,
2285 swkb->ptr(), swkb->length())) ||
2286 geom->get_x(&res));
2287 return res;
2288 }
2289
2290
val_real()2291 double Item_func_y::val_real()
2292 {
2293 DBUG_ASSERT(fixed == 1);
2294 double res= 0; // In case of errors
2295 String *swkb= args[0]->val_str(&value);
2296 Geometry_buffer buffer;
2297 Geometry *geom;
2298
2299 null_value= (!swkb ||
2300 !(geom= Geometry::construct(&buffer,
2301 swkb->ptr(), swkb->length())) ||
2302 geom->get_y(&res));
2303 return res;
2304 }
2305
2306
val_real()2307 double Item_func_area::val_real()
2308 {
2309 DBUG_ASSERT(fixed == 1);
2310 double res= 0; // In case of errors
2311 String *swkb= args[0]->val_str(&value);
2312 Geometry_buffer buffer;
2313 Geometry *geom;
2314 const char *dummy;
2315
2316 null_value= (!swkb ||
2317 !(geom= Geometry::construct(&buffer,
2318 swkb->ptr(), swkb->length())) ||
2319 geom->area(&res, &dummy));
2320 return res;
2321 }
2322
val_real()2323 double Item_func_glength::val_real()
2324 {
2325 DBUG_ASSERT(fixed == 1);
2326 double res= 0; // In case of errors
2327 String *swkb= args[0]->val_str(&value);
2328 Geometry_buffer buffer;
2329 Geometry *geom;
2330 const char *end;
2331
2332 null_value= (!swkb ||
2333 !(geom= Geometry::construct(&buffer,
2334 swkb->ptr(),
2335 swkb->length())) ||
2336 geom->geom_length(&res, &end));
2337 return res;
2338 }
2339
val_int()2340 longlong Item_func_srid::val_int()
2341 {
2342 DBUG_ASSERT(fixed == 1);
2343 String *swkb= args[0]->val_str(&value);
2344 Geometry_buffer buffer;
2345
2346 null_value= (!swkb ||
2347 !Geometry::construct(&buffer,
2348 swkb->ptr(), swkb->length()));
2349 if (null_value)
2350 return 0;
2351
2352 return (longlong) (uint4korr(swkb->ptr()));
2353 }
2354
2355
val_real()2356 double Item_func_distance::val_real()
2357 {
2358 bool cur_point_edge;
2359 const Gcalc_scan_iterator::point *evpos;
2360 const Gcalc_heap::Info *cur_point, *dist_point;
2361 const Gcalc_scan_iterator::event_point *ev;
2362 double t, distance, cur_distance;
2363 double x1, x2, y1, y2;
2364 double ex, ey, vx, vy, e_sqrlen;
2365 uint obj2_si;
2366 Gcalc_operation_transporter trn(&func, &collector);
2367
2368 DBUG_ENTER("Item_func_distance::val_real");
2369 DBUG_ASSERT(fixed == 1);
2370 String *res1= args[0]->val_str(&tmp_value1);
2371 String *res2= args[1]->val_str(&tmp_value2);
2372 Geometry_buffer buffer1, buffer2;
2373 Geometry *g1, *g2;
2374 MBR mbr1, mbr2;
2375 const char *c_end;
2376
2377 if (args[0]->null_value || args[1]->null_value)
2378 goto mem_error;
2379 g1= Geometry::construct(&buffer1, res1->ptr(), res1->length());
2380 if (!g1)
2381 goto mem_error;
2382 g2= Geometry::construct(&buffer2, res2->ptr(), res2->length());
2383 if (!g2)
2384 goto mem_error;
2385 if (g1->get_mbr(&mbr1, &c_end) || g2->get_mbr(&mbr2, &c_end))
2386 goto mem_error;
2387
2388 mbr1.add_mbr(&mbr2);
2389 collector.set_extent(mbr1.xmin, mbr1.xmax, mbr1.ymin, mbr1.ymax);
2390
2391 if ((g1->get_class_info()->m_type_id == Geometry::wkb_point) &&
2392 (g2->get_class_info()->m_type_id == Geometry::wkb_point))
2393 {
2394 if (((Gis_point *) g1)->get_xy(&x1, &y1) ||
2395 ((Gis_point *) g2)->get_xy(&x2, &y2))
2396 goto mem_error;
2397 ex= x2 - x1;
2398 ey= y2 - y1;
2399 DBUG_RETURN(sqrt(ex * ex + ey * ey));
2400 }
2401
2402 if (func.reserve_op_buffer(1))
2403 goto mem_error;
2404 func.add_operation(Gcalc_function::op_intersection, 2);
2405
2406 if (g1->store_shapes(&trn))
2407 goto mem_error;
2408 obj2_si= func.get_nshapes();
2409 if (g2->store_shapes(&trn) || func.alloc_states())
2410 goto mem_error;
2411
2412 if (obj2_si == 0 || func.get_nshapes() == obj2_si)
2413 {
2414 distance= 0.0;
2415 null_value= 1;
2416 goto exit;
2417 }
2418
2419
2420 collector.prepare_operation();
2421 scan_it.init(&collector);
2422
2423 distance= DBL_MAX;
2424 while (scan_it.more_points())
2425 {
2426 if (scan_it.step())
2427 goto mem_error;
2428 evpos= scan_it.get_event_position();
2429 ev= scan_it.get_events();
2430
2431 if (ev->simple_event())
2432 {
2433 cur_point= ev->pi;
2434 goto count_distance;
2435 }
2436 /*
2437 handling intersection we only need to check if it's the intersecion
2438 of objects 1 and 2. In this case distance is 0
2439 */
2440 cur_point= NULL;
2441
2442 /*
2443 having these events we need to check for possible intersection
2444 of objects
2445 scev_thread | scev_two_threads | scev_single_point
2446 */
2447 func.clear_i_states();
2448 for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit)
2449 {
2450 gcalc_shape_info si= pit.point()->get_shape();
2451 if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
2452 func.invert_i_state(si);
2453 }
2454
2455 func.clear_b_states();
2456 for (; ev; ev= ev->get_next())
2457 {
2458 if (ev->event != scev_intersection)
2459 cur_point= ev->pi;
2460 func.set_b_state(ev->get_shape());
2461 if (func.count())
2462 {
2463 /* Point of one object is inside the other - intersection found */
2464 distance= 0;
2465 goto exit;
2466 }
2467 }
2468
2469 if (!cur_point)
2470 continue;
2471
2472 count_distance:
2473 if (cur_point->node.shape.shape >= obj2_si)
2474 continue;
2475 cur_point_edge= !cur_point->is_bottom();
2476
2477 for (dist_point= collector.get_first(); dist_point; dist_point= dist_point->get_next())
2478 {
2479 /* We only check vertices of object 2 */
2480 if (dist_point->type != Gcalc_heap::nt_shape_node ||
2481 dist_point->node.shape.shape < obj2_si)
2482 continue;
2483
2484 /* if we have an edge to check */
2485 if (dist_point->node.shape.left)
2486 {
2487 t= count_edge_t(dist_point, dist_point->node.shape.left, cur_point,
2488 ex, ey, vx, vy, e_sqrlen);
2489 if ((t>0.0) && (t<1.0))
2490 {
2491 cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
2492 if (distance > cur_distance)
2493 distance= cur_distance;
2494 }
2495 }
2496 if (cur_point_edge)
2497 {
2498 t= count_edge_t(cur_point, cur_point->node.shape.left, dist_point,
2499 ex, ey, vx, vy, e_sqrlen);
2500 if ((t>0.0) && (t<1.0))
2501 {
2502 cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
2503 if (distance > cur_distance)
2504 distance= cur_distance;
2505 }
2506 }
2507 cur_distance= distance_points(cur_point, dist_point);
2508 if (distance > cur_distance)
2509 distance= cur_distance;
2510 }
2511 }
2512 exit:
2513 collector.reset();
2514 func.reset();
2515 scan_it.reset();
2516 DBUG_RETURN(distance);
2517 mem_error:
2518 null_value= 1;
2519 DBUG_RETURN(0);
2520 }
2521
2522
val_real()2523 double Item_func_sphere_distance::val_real()
2524 {
2525 /* To test null_value of item, first get well-known bytes as a backups */
2526 String bak1, bak2;
2527 String *arg1= args[0]->val_str(&bak1);
2528 String *arg2= args[1]->val_str(&bak2);
2529 double distance= 0.0;
2530 double sphere_radius= 6370986.0; // Default radius equals Earth radius
2531
2532 null_value= (args[0]->null_value || args[1]->null_value);
2533 if (null_value)
2534 {
2535 return 0;
2536 }
2537
2538 if (arg_count == 3)
2539 {
2540 sphere_radius= args[2]->val_real();
2541 // Radius cannot be Null
2542 if (args[2]->null_value)
2543 {
2544 null_value= true;
2545 return 0;
2546 }
2547 if (sphere_radius <= 0)
2548 {
2549 my_error(ER_INTERNAL_ERROR, MYF(0), "Radius must be greater than zero.");
2550 return 1;
2551 }
2552 }
2553 Geometry_buffer buffer1, buffer2;
2554 Geometry *g1, *g2;
2555 if (!(g1= Geometry::construct(&buffer1, arg1->ptr(), arg1->length())) ||
2556 !(g2= Geometry::construct(&buffer2, arg2->ptr(), arg2->length())))
2557 {
2558 my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_Distance_Sphere");
2559 goto handle_errors;
2560 }
2561 // Method allowed for points and multipoints
2562 if (!(g1->get_class_info()->m_type_id == Geometry::wkb_point ||
2563 g1->get_class_info()->m_type_id == Geometry::wkb_multipoint) ||
2564 !(g2->get_class_info()->m_type_id == Geometry::wkb_point ||
2565 g2->get_class_info()->m_type_id == Geometry::wkb_multipoint))
2566 {
2567 // Generate error message in case different geometry is used?
2568 my_error(ER_INTERNAL_ERROR, MYF(0), func_name());
2569 return 0;
2570 }
2571 distance= spherical_distance_points(g1, g2, sphere_radius);
2572 if (distance < 0)
2573 {
2574 my_error(ER_INTERNAL_ERROR, MYF(0), "Returned distance cannot be negative.");
2575 return 1;
2576 }
2577 return distance;
2578
2579 handle_errors:
2580 return 0;
2581 }
2582
2583
spherical_distance_points(Geometry * g1,Geometry * g2,const double r)2584 double Item_func_sphere_distance::spherical_distance_points(Geometry *g1,
2585 Geometry *g2,
2586 const double r)
2587 {
2588 double res= 0.0;
2589 // Length for the single point (25 Bytes)
2590 uint32 len= SRID_SIZE + POINT_DATA_SIZE + WKB_HEADER_SIZE;
2591 int error= 0;
2592
2593 switch (g2->get_class_info()->m_type_id)
2594 {
2595 case Geometry::wkb_point:
2596 // Optimization for point-point case
2597 if (g1->get_class_info()->m_type_id == Geometry::wkb_point)
2598 {
2599 res= static_cast<Gis_point *>(g2)->calculate_haversine(g1, r, &error);
2600 }
2601 else
2602 {
2603 // Optimization for single point in Multipoint
2604 if (g1->get_data_size() == len)
2605 {
2606 res= static_cast<Gis_point *>(g2)->calculate_haversine(g1, r, &error);
2607 }
2608 else
2609 {
2610 // There are multipoints in g1
2611 // g1 is MultiPoint and calculate MP.sphericaldistance from g2 Point
2612 if (g1->get_data_size() != GET_SIZE_ERROR)
2613 static_cast<Gis_point *>(g2)->spherical_distance_multipoints(
2614 (Gis_multi_point *)g1, r, &res, &error);
2615 }
2616 }
2617 break;
2618
2619 case Geometry::wkb_multipoint:
2620 // Optimization for point-point case
2621 if (g1->get_class_info()->m_type_id == Geometry::wkb_point)
2622 {
2623 // Optimization for single point in Multipoint g2
2624 if (g2->get_data_size() == len)
2625 {
2626 res= static_cast<Gis_point *>(g1)->calculate_haversine(g2, r, &error);
2627 }
2628 else
2629 {
2630 if (g2->get_data_size() != GET_SIZE_ERROR)
2631 // g1 is a point (casted to multi_point) and g2 multipoint
2632 static_cast<Gis_point *>(g1)->spherical_distance_multipoints(
2633 (Gis_multi_point *)g2, r, &res, &error);
2634 }
2635 }
2636 else
2637 {
2638 // Multipoints in g1 and g2 - no optimization
2639 static_cast<Gis_multi_point *>(g1)->spherical_distance_multipoints(
2640 (Gis_multi_point *)g2, r, &res, &error);
2641 }
2642 break;
2643
2644 default:
2645 DBUG_ASSERT(0);
2646 break;
2647 }
2648
2649 if (res < 0)
2650 goto handle_error;
2651
2652 handle_error:
2653 if (error > 0)
2654 my_error(ER_STD_OUT_OF_RANGE_ERROR, MYF(0),
2655 "Longitude should be [-180,180]", "ST_Distance_Sphere");
2656 else if(error < 0)
2657 my_error(ER_STD_OUT_OF_RANGE_ERROR, MYF(0),
2658 "Latitude should be [-90,90]", "ST_Distance_Sphere");
2659 return res;
2660 }
2661
2662
val_str(String * str)2663 String *Item_func_pointonsurface::val_str(String *str)
2664 {
2665 Gcalc_operation_transporter trn(&func, &collector);
2666
2667 DBUG_ENTER("Item_func_pointonsurface::val_str");
2668 DBUG_ASSERT(fixed == 1);
2669 String *res= args[0]->val_str(&tmp_value);
2670 Geometry_buffer buffer;
2671 Geometry *g;
2672 MBR mbr;
2673 const char *c_end;
2674 double UNINIT_VAR(px), UNINIT_VAR(py), x0, UNINIT_VAR(y0);
2675 String *result= 0;
2676 const Gcalc_scan_iterator::point *pprev= NULL;
2677 uint32 srid;
2678
2679 null_value= 1;
2680 if ((args[0]->null_value ||
2681 !(g= Geometry::construct(&buffer, res->ptr(), res->length())) ||
2682 g->get_mbr(&mbr, &c_end)))
2683 goto mem_error;
2684
2685 collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
2686
2687 if (g->store_shapes(&trn))
2688 goto mem_error;
2689
2690 collector.prepare_operation();
2691 scan_it.init(&collector);
2692
2693 while (scan_it.more_points())
2694 {
2695 if (scan_it.step())
2696 goto mem_error;
2697
2698 if (scan_it.get_h() > GIS_ZERO)
2699 {
2700 y0= scan_it.get_y();
2701 break;
2702 }
2703 }
2704
2705 if (!scan_it.more_points())
2706 {
2707 goto exit;
2708 }
2709
2710 if (scan_it.step())
2711 goto mem_error;
2712
2713 for (Gcalc_point_iterator pit(&scan_it); pit.point(); ++pit)
2714 {
2715 if (pprev == NULL)
2716 {
2717 pprev= pit.point();
2718 continue;
2719 }
2720 x0= scan_it.get_sp_x(pprev);
2721 px= scan_it.get_sp_x(pit.point());
2722 if (px - x0 > GIS_ZERO)
2723 {
2724 if (scan_it.get_h() > GIS_ZERO)
2725 {
2726 px= (px + x0) / 2.0;
2727 py= scan_it.get_y();
2728 }
2729 else
2730 {
2731 px= (px + x0) / 2.0;
2732 py= (y0 + scan_it.get_y()) / 2.0;
2733 }
2734 null_value= 0;
2735 break;
2736 }
2737 pprev= NULL;
2738 }
2739
2740 if (null_value)
2741 goto exit;
2742
2743 str->set_charset(&my_charset_bin);
2744 if (str->reserve(SRID_SIZE, 512))
2745 goto mem_error;
2746
2747 str->length(0);
2748 srid= uint4korr(res->ptr());
2749 str->q_append(srid);
2750
2751 if (Geometry::create_point(str, px, py))
2752 goto mem_error;
2753
2754 result= str;
2755
2756 exit:
2757 collector.reset();
2758 func.reset();
2759 scan_it.reset();
2760 DBUG_RETURN(result);
2761
2762 mem_error:
2763 collector.reset();
2764 func.reset();
2765 scan_it.reset();
2766 null_value= 1;
2767 DBUG_RETURN(0);
2768 }
2769
2770
2771 #ifndef DBUG_OFF
val_int()2772 longlong Item_func_gis_debug::val_int()
2773 {
2774 /* For now this is just a stub. TODO: implement the internal GIS debuggign */
2775 return 0;
2776 }
2777 #endif
2778
2779
2780 /**********************************************************************/
2781
2782
2783 class Create_func_area : public Create_func_arg1
2784 {
2785 public:
create_1_arg(THD * thd,Item * arg1)2786 Item *create_1_arg(THD *thd, Item *arg1) override
2787 {
2788 return new (thd->mem_root) Item_func_area(thd, arg1);
2789 }
2790
2791 static Create_func_area s_singleton;
2792
2793 protected:
Create_func_area()2794 Create_func_area() {}
~Create_func_area()2795 virtual ~Create_func_area() {}
2796 };
2797
2798
2799 class Create_func_as_wkb : public Create_func_arg1
2800 {
2801 public:
create_1_arg(THD * thd,Item * arg1)2802 Item *create_1_arg(THD *thd, Item *arg1) override
2803 {
2804 return new (thd->mem_root) Item_func_as_wkb(thd, arg1);
2805 }
2806
2807 static Create_func_as_wkb s_singleton;
2808
2809 protected:
Create_func_as_wkb()2810 Create_func_as_wkb() {}
~Create_func_as_wkb()2811 virtual ~Create_func_as_wkb() {}
2812 };
2813
2814
2815 class Create_func_as_wkt : public Create_func_arg1
2816 {
2817 public:
create_1_arg(THD * thd,Item * arg1)2818 Item *create_1_arg(THD *thd, Item *arg1) override
2819 {
2820 return new (thd->mem_root) Item_func_as_wkt(thd, arg1);
2821 }
2822
2823 static Create_func_as_wkt s_singleton;
2824
2825 protected:
Create_func_as_wkt()2826 Create_func_as_wkt() {}
~Create_func_as_wkt()2827 virtual ~Create_func_as_wkt() {}
2828 };
2829
2830
2831
2832 class Create_func_centroid : public Create_func_arg1
2833 {
2834 public:
create_1_arg(THD * thd,Item * arg1)2835 Item *create_1_arg(THD *thd, Item *arg1) override
2836 {
2837 return new (thd->mem_root) Item_func_centroid(thd, arg1);
2838 }
2839
2840 static Create_func_centroid s_singleton;
2841
2842 protected:
Create_func_centroid()2843 Create_func_centroid() {}
~Create_func_centroid()2844 virtual ~Create_func_centroid() {}
2845 };
2846
2847
2848 class Create_func_convexhull : public Create_func_arg1
2849 {
2850 public:
create_1_arg(THD * thd,Item * arg1)2851 Item *create_1_arg(THD *thd, Item *arg1) override
2852 {
2853 return new (thd->mem_root) Item_func_convexhull(thd, arg1);
2854 }
2855
2856 static Create_func_convexhull s_singleton;
2857
2858 protected:
Create_func_convexhull()2859 Create_func_convexhull() {}
~Create_func_convexhull()2860 virtual ~Create_func_convexhull() {}
2861 };
2862
2863
2864 class Create_func_pointonsurface : public Create_func_arg1
2865 {
2866 public:
create_1_arg(THD * thd,Item * arg1)2867 Item *create_1_arg(THD *thd, Item *arg1) override
2868 {
2869 return new (thd->mem_root) Item_func_pointonsurface(thd, arg1);
2870 }
2871
2872 static Create_func_pointonsurface s_singleton;
2873
2874 protected:
Create_func_pointonsurface()2875 Create_func_pointonsurface() {}
~Create_func_pointonsurface()2876 virtual ~Create_func_pointonsurface() {}
2877 };
2878
2879
2880 class Create_func_mbr_contains : public Create_func_arg2
2881 {
2882 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)2883 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
2884 {
2885 return new (thd->mem_root) Item_func_spatial_mbr_rel(thd, arg1, arg2,
2886 Item_func::SP_CONTAINS_FUNC);
2887 }
2888
2889 static Create_func_mbr_contains s_singleton;
2890
2891 protected:
Create_func_mbr_contains()2892 Create_func_mbr_contains() {}
~Create_func_mbr_contains()2893 virtual ~Create_func_mbr_contains() {}
2894 };
2895
2896
2897 class Create_func_contains : public Create_func_arg2
2898 {
2899 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)2900 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
2901 {
2902 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
2903 Item_func::SP_CONTAINS_FUNC);
2904 }
2905 static Create_func_contains s_singleton;
2906
2907 protected:
Create_func_contains()2908 Create_func_contains() {}
~Create_func_contains()2909 virtual ~Create_func_contains() {}
2910 };
2911
2912
2913 class Create_func_crosses : public Create_func_arg2
2914 {
2915 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)2916 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
2917 {
2918 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
2919 Item_func::SP_CROSSES_FUNC);
2920 }
2921 static Create_func_crosses s_singleton;
2922
2923 protected:
Create_func_crosses()2924 Create_func_crosses() {}
~Create_func_crosses()2925 virtual ~Create_func_crosses() {}
2926 };
2927
2928
2929 class Create_func_dimension : public Create_func_arg1
2930 {
2931 public:
create_1_arg(THD * thd,Item * arg1)2932 Item *create_1_arg(THD *thd, Item *arg1) override
2933 {
2934 return new (thd->mem_root) Item_func_dimension(thd, arg1);
2935 }
2936
2937 static Create_func_dimension s_singleton;
2938
2939 protected:
Create_func_dimension()2940 Create_func_dimension() {}
~Create_func_dimension()2941 virtual ~Create_func_dimension() {}
2942 };
2943
2944
2945 class Create_func_mbr_disjoint : public Create_func_arg2
2946 {
2947 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)2948 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
2949 {
2950 return new (thd->mem_root) Item_func_spatial_mbr_rel(thd, arg1, arg2,
2951 Item_func::SP_DISJOINT_FUNC);
2952 }
2953
2954 static Create_func_mbr_disjoint s_singleton;
2955
2956 protected:
Create_func_mbr_disjoint()2957 Create_func_mbr_disjoint() {}
~Create_func_mbr_disjoint()2958 virtual ~Create_func_mbr_disjoint() {}
2959 };
2960
2961
2962 class Create_func_disjoint : public Create_func_arg2
2963 {
2964 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)2965 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
2966 {
2967 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
2968 Item_func::SP_DISJOINT_FUNC);
2969 }
2970 static Create_func_disjoint s_singleton;
2971
2972 protected:
Create_func_disjoint()2973 Create_func_disjoint() {}
~Create_func_disjoint()2974 virtual ~Create_func_disjoint() {}
2975 };
2976
2977
2978 class Create_func_distance : public Create_func_arg2
2979 {
2980 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)2981 Item* create_2_arg(THD *thd, Item *arg1, Item *arg2) override
2982 {
2983 return new (thd->mem_root) Item_func_distance(thd, arg1, arg2);
2984 }
2985
2986 static Create_func_distance s_singleton;
2987
2988 protected:
Create_func_distance()2989 Create_func_distance() {}
~Create_func_distance()2990 virtual ~Create_func_distance() {}
2991 };
2992
2993
2994 class Create_func_distance_sphere: public Create_native_func
2995 {
2996 public:
2997 Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
2998 override;
2999 static Create_func_distance_sphere s_singleton;
3000
3001 protected:
Create_func_distance_sphere()3002 Create_func_distance_sphere() {}
~Create_func_distance_sphere()3003 virtual ~Create_func_distance_sphere() {}
3004 };
3005
3006
3007 Item*
create_native(THD * thd,LEX_CSTRING * name,List<Item> * item_list)3008 Create_func_distance_sphere::create_native(THD *thd, LEX_CSTRING *name,
3009 List<Item> *item_list)
3010 {
3011 int arg_count= 0;
3012
3013 if (item_list != NULL)
3014 arg_count= item_list->elements;
3015
3016 if (arg_count < 2)
3017 {
3018 my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
3019 return NULL;
3020 }
3021 return new (thd->mem_root) Item_func_sphere_distance(thd, *item_list);
3022 }
3023
3024
3025 class Create_func_endpoint : public Create_func_arg1
3026 {
3027 public:
create_1_arg(THD * thd,Item * arg1)3028 Item *create_1_arg(THD *thd, Item *arg1) override
3029 {
3030 return new (thd->mem_root) Item_func_spatial_decomp(thd, arg1,
3031 Item_func::SP_ENDPOINT);
3032 }
3033
3034 static Create_func_endpoint s_singleton;
3035
3036 protected:
Create_func_endpoint()3037 Create_func_endpoint() {}
~Create_func_endpoint()3038 virtual ~Create_func_endpoint() {}
3039 };
3040
3041
3042 class Create_func_envelope : public Create_func_arg1
3043 {
3044 public:
create_1_arg(THD * thd,Item * arg1)3045 Item *create_1_arg(THD *thd, Item *arg1) override
3046 {
3047 return new (thd->mem_root) Item_func_envelope(thd, arg1);
3048 }
3049
3050 static Create_func_envelope s_singleton;
3051
3052 protected:
Create_func_envelope()3053 Create_func_envelope() {}
~Create_func_envelope()3054 virtual ~Create_func_envelope() {}
3055 };
3056
3057 class Create_func_boundary : public Create_func_arg1
3058 {
3059 public:
create_1_arg(THD * thd,Item * arg1)3060 Item *create_1_arg(THD *thd, Item *arg1) override
3061 {
3062 return new (thd->mem_root) Item_func_boundary(thd, arg1);
3063 }
3064
3065 static Create_func_boundary s_singleton;
3066
3067 protected:
Create_func_boundary()3068 Create_func_boundary() {}
~Create_func_boundary()3069 virtual ~Create_func_boundary() {}
3070 };
3071
3072
3073 class Create_func_mbr_equals : public Create_func_arg2
3074 {
3075 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3076 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3077 {
3078 return new (thd->mem_root) Item_func_spatial_mbr_rel(thd, arg1, arg2,
3079 Item_func::SP_EQUALS_FUNC);
3080 }
3081
3082 static Create_func_mbr_equals s_singleton;
3083
3084 protected:
Create_func_mbr_equals()3085 Create_func_mbr_equals() {}
~Create_func_mbr_equals()3086 virtual ~Create_func_mbr_equals() {}
3087 };
3088
3089
3090 class Create_func_equals : public Create_func_arg2
3091 {
3092 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3093 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3094 {
3095 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
3096 Item_func::SP_EQUALS_FUNC);
3097 }
3098
3099 static Create_func_equals s_singleton;
3100
3101 protected:
Create_func_equals()3102 Create_func_equals() {}
~Create_func_equals()3103 virtual ~Create_func_equals() {}
3104 };
3105
3106
3107 class Create_func_exteriorring : public Create_func_arg1
3108 {
3109 public:
create_1_arg(THD * thd,Item * arg1)3110 Item *create_1_arg(THD *thd, Item *arg1) override
3111 {
3112 return new (thd->mem_root) Item_func_spatial_decomp(thd, arg1,
3113 Item_func::SP_EXTERIORRING);
3114 }
3115
3116 static Create_func_exteriorring s_singleton;
3117
3118 protected:
Create_func_exteriorring()3119 Create_func_exteriorring() {}
~Create_func_exteriorring()3120 virtual ~Create_func_exteriorring() {}
3121 };
3122
3123
3124
3125 class Create_func_geometry_from_text : public Create_native_func
3126 {
3127 public:
3128 Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
3129
3130 static Create_func_geometry_from_text s_singleton;
3131
3132 protected:
Create_func_geometry_from_text()3133 Create_func_geometry_from_text() {}
~Create_func_geometry_from_text()3134 virtual ~Create_func_geometry_from_text() {}
3135 };
3136
3137
3138 Item*
create_native(THD * thd,LEX_CSTRING * name,List<Item> * item_list)3139 Create_func_geometry_from_text::create_native(THD *thd, LEX_CSTRING *name,
3140 List<Item> *item_list)
3141 {
3142 Item *func= NULL;
3143 int arg_count= 0;
3144
3145 if (item_list != NULL)
3146 arg_count= item_list->elements;
3147
3148 switch (arg_count) {
3149 case 1:
3150 {
3151 Item *param_1= item_list->pop();
3152 func= new (thd->mem_root) Item_func_geometry_from_text(thd, param_1);
3153 thd->lex->uncacheable(UNCACHEABLE_RAND);
3154 break;
3155 }
3156 case 2:
3157 {
3158 Item *param_1= item_list->pop();
3159 Item *param_2= item_list->pop();
3160 func= new (thd->mem_root) Item_func_geometry_from_text(thd, param_1, param_2);
3161 break;
3162 }
3163 default:
3164 {
3165 my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
3166 break;
3167 }
3168 }
3169
3170 return func;
3171 }
3172
3173
3174 class Create_func_geometry_from_wkb : public Create_native_func
3175 {
3176 public:
3177 Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
3178
3179 static Create_func_geometry_from_wkb s_singleton;
3180
3181 protected:
Create_func_geometry_from_wkb()3182 Create_func_geometry_from_wkb() {}
~Create_func_geometry_from_wkb()3183 virtual ~Create_func_geometry_from_wkb() {}
3184 };
3185
3186
3187 Item*
create_native(THD * thd,LEX_CSTRING * name,List<Item> * item_list)3188 Create_func_geometry_from_wkb::create_native(THD *thd, LEX_CSTRING *name,
3189 List<Item> *item_list)
3190 {
3191 Item *func= NULL;
3192 int arg_count= 0;
3193
3194 if (item_list != NULL)
3195 arg_count= item_list->elements;
3196
3197 switch (arg_count) {
3198 case 1:
3199 {
3200 Item *param_1= item_list->pop();
3201 func= new (thd->mem_root) Item_func_geometry_from_wkb(thd, param_1);
3202 thd->lex->uncacheable(UNCACHEABLE_RAND);
3203 break;
3204 }
3205 case 2:
3206 {
3207 Item *param_1= item_list->pop();
3208 Item *param_2= item_list->pop();
3209 func= new (thd->mem_root) Item_func_geometry_from_wkb(thd, param_1, param_2);
3210 break;
3211 }
3212 default:
3213 {
3214 my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
3215 break;
3216 }
3217 }
3218
3219 return func;
3220 }
3221
3222
3223 class Create_func_geometry_from_json : public Create_native_func
3224 {
3225 public:
3226 Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
3227
3228 static Create_func_geometry_from_json s_singleton;
3229
3230 protected:
Create_func_geometry_from_json()3231 Create_func_geometry_from_json() {}
~Create_func_geometry_from_json()3232 virtual ~Create_func_geometry_from_json() {}
3233 };
3234
3235
3236 Item*
create_native(THD * thd,LEX_CSTRING * name,List<Item> * item_list)3237 Create_func_geometry_from_json::create_native(THD *thd, LEX_CSTRING *name,
3238 List<Item> *item_list)
3239 {
3240 Item *func= NULL;
3241 int arg_count= 0;
3242
3243 if (item_list != NULL)
3244 arg_count= item_list->elements;
3245
3246 switch (arg_count) {
3247 case 1:
3248 {
3249 Item *json= item_list->pop();
3250 func= new (thd->mem_root) Item_func_geometry_from_json(thd, json);
3251 thd->lex->uncacheable(UNCACHEABLE_RAND);
3252 break;
3253 }
3254 case 2:
3255 {
3256 Item *json= item_list->pop();
3257 Item *options= item_list->pop();
3258 func= new (thd->mem_root) Item_func_geometry_from_json(thd, json, options);
3259 break;
3260 }
3261 case 3:
3262 {
3263 Item *json= item_list->pop();
3264 Item *options= item_list->pop();
3265 Item *srid= item_list->pop();
3266 func= new (thd->mem_root) Item_func_geometry_from_json(thd, json, options,
3267 srid);
3268 break;
3269 }
3270 default:
3271 {
3272 my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
3273 break;
3274 }
3275 }
3276
3277 return func;
3278 }
3279
3280
3281 class Create_func_as_geojson : public Create_native_func
3282 {
3283 public:
3284 Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
3285
3286 static Create_func_as_geojson s_singleton;
3287
3288 protected:
Create_func_as_geojson()3289 Create_func_as_geojson() {}
~Create_func_as_geojson()3290 virtual ~Create_func_as_geojson() {}
3291 };
3292
3293
3294 Item*
create_native(THD * thd,LEX_CSTRING * name,List<Item> * item_list)3295 Create_func_as_geojson::create_native(THD *thd, LEX_CSTRING *name,
3296 List<Item> *item_list)
3297 {
3298 Item *func= NULL;
3299 int arg_count= 0;
3300
3301 if (item_list != NULL)
3302 arg_count= item_list->elements;
3303
3304 switch (arg_count) {
3305 case 1:
3306 {
3307 Item *geom= item_list->pop();
3308 func= new (thd->mem_root) Item_func_as_geojson(thd, geom);
3309 thd->lex->uncacheable(UNCACHEABLE_RAND);
3310 break;
3311 }
3312 case 2:
3313 {
3314 Item *geom= item_list->pop();
3315 Item *max_dec= item_list->pop();
3316 func= new (thd->mem_root) Item_func_as_geojson(thd, geom, max_dec);
3317 break;
3318 }
3319 case 3:
3320 {
3321 Item *geom= item_list->pop();
3322 Item *max_dec= item_list->pop();
3323 Item *options= item_list->pop();
3324 func= new (thd->mem_root) Item_func_as_geojson(thd, geom, max_dec, options);
3325 break;
3326 }
3327 default:
3328 {
3329 my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
3330 break;
3331 }
3332 }
3333
3334 return func;
3335 }
3336
3337
3338 class Create_func_geometry_type : public Create_func_arg1
3339 {
3340 public:
create_1_arg(THD * thd,Item * arg1)3341 Item *create_1_arg(THD *thd, Item *arg1) override
3342 {
3343 return new (thd->mem_root) Item_func_geometry_type(thd, arg1);
3344 }
3345
3346 static Create_func_geometry_type s_singleton;
3347
3348 protected:
Create_func_geometry_type()3349 Create_func_geometry_type() {}
~Create_func_geometry_type()3350 virtual ~Create_func_geometry_type() {}
3351 };
3352
3353
3354 class Create_func_geometryn : public Create_func_arg2
3355 {
3356 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3357 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3358 {
3359 return new (thd->mem_root) Item_func_spatial_decomp_n(thd, arg1, arg2,
3360 Item_func::SP_GEOMETRYN);
3361 }
3362
3363 static Create_func_geometryn s_singleton;
3364
3365 protected:
Create_func_geometryn()3366 Create_func_geometryn() {}
~Create_func_geometryn()3367 virtual ~Create_func_geometryn() {}
3368 };
3369
3370
3371 #if !defined(DBUG_OFF)
3372 class Create_func_gis_debug : public Create_func_arg1
3373 {
3374 public:
create_1_arg(THD * thd,Item * arg1)3375 Item *create_1_arg(THD *thd, Item *arg1) override
3376 {
3377 return new (thd->mem_root) Item_func_gis_debug(thd, arg1);
3378 }
3379
3380 static Create_func_gis_debug s_singleton;
3381
3382 protected:
Create_func_gis_debug()3383 Create_func_gis_debug() {}
~Create_func_gis_debug()3384 virtual ~Create_func_gis_debug() {}
3385 };
3386 #endif
3387
3388
3389 class Create_func_glength : public Create_func_arg1
3390 {
3391 public:
create_1_arg(THD * thd,Item * arg1)3392 Item *create_1_arg(THD *thd, Item *arg1) override
3393 {
3394 return new (thd->mem_root) Item_func_glength(thd, arg1);
3395 }
3396
3397 static Create_func_glength s_singleton;
3398
3399 protected:
Create_func_glength()3400 Create_func_glength() {}
~Create_func_glength()3401 virtual ~Create_func_glength() {}
3402 };
3403
3404
3405 class Create_func_interiorringn : public Create_func_arg2
3406 {
3407 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3408 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3409 {
3410 return new (thd->mem_root) Item_func_spatial_decomp_n(thd, arg1, arg2,
3411 Item_func::SP_INTERIORRINGN);
3412 }
3413
3414 static Create_func_interiorringn s_singleton;
3415
3416 protected:
Create_func_interiorringn()3417 Create_func_interiorringn() {}
~Create_func_interiorringn()3418 virtual ~Create_func_interiorringn() {}
3419 };
3420
3421
3422 class Create_func_relate : public Create_func_arg3
3423 {
3424 public:
create_3_arg(THD * thd,Item * arg1,Item * arg2,Item * arg3)3425 Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) override
3426 {
3427 return new (thd->mem_root) Item_func_spatial_relate(thd, arg1, arg2, arg3);
3428 }
3429
3430 static Create_func_relate s_singleton;
3431
3432 protected:
Create_func_relate()3433 Create_func_relate() {}
~Create_func_relate()3434 virtual ~Create_func_relate() {}
3435 };
3436
3437
3438 class Create_func_mbr_intersects : public Create_func_arg2
3439 {
3440 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3441 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3442 {
3443 return new (thd->mem_root) Item_func_spatial_mbr_rel(thd, arg1, arg2,
3444 Item_func::SP_INTERSECTS_FUNC);
3445 }
3446
3447 static Create_func_mbr_intersects s_singleton;
3448
3449 protected:
Create_func_mbr_intersects()3450 Create_func_mbr_intersects() {}
~Create_func_mbr_intersects()3451 virtual ~Create_func_mbr_intersects() {}
3452 };
3453
3454
3455 class Create_func_intersects : public Create_func_arg2
3456 {
3457 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3458 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3459 {
3460 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
3461 Item_func::SP_INTERSECTS_FUNC);
3462 }
3463
3464 static Create_func_intersects s_singleton;
3465
3466 protected:
Create_func_intersects()3467 Create_func_intersects() {}
~Create_func_intersects()3468 virtual ~Create_func_intersects() {}
3469 };
3470
3471
3472 class Create_func_intersection : public Create_func_arg2
3473 {
3474 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3475 Item* create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3476 {
3477 return new (thd->mem_root) Item_func_spatial_operation(thd, arg1, arg2,
3478 Gcalc_function::op_intersection);
3479 }
3480
3481 static Create_func_intersection s_singleton;
3482
3483 protected:
Create_func_intersection()3484 Create_func_intersection() {}
~Create_func_intersection()3485 virtual ~Create_func_intersection() {}
3486 };
3487
3488
3489 class Create_func_difference : public Create_func_arg2
3490 {
3491 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3492 Item* create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3493 {
3494 return new (thd->mem_root) Item_func_spatial_operation(thd, arg1, arg2,
3495 Gcalc_function::op_difference);
3496 }
3497
3498 static Create_func_difference s_singleton;
3499
3500 protected:
Create_func_difference()3501 Create_func_difference() {}
~Create_func_difference()3502 virtual ~Create_func_difference() {}
3503 };
3504
3505
3506 class Create_func_union : public Create_func_arg2
3507 {
3508 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3509 Item* create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3510 {
3511 return new (thd->mem_root) Item_func_spatial_operation(thd, arg1, arg2,
3512 Gcalc_function::op_union);
3513 }
3514
3515 static Create_func_union s_singleton;
3516
3517 protected:
Create_func_union()3518 Create_func_union() {}
~Create_func_union()3519 virtual ~Create_func_union() {}
3520 };
3521
3522
3523 class Create_func_symdifference : public Create_func_arg2
3524 {
3525 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3526 Item* create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3527 {
3528 return new (thd->mem_root) Item_func_spatial_operation(thd, arg1, arg2,
3529 Gcalc_function::op_symdifference);
3530 }
3531
3532 static Create_func_symdifference s_singleton;
3533
3534 protected:
Create_func_symdifference()3535 Create_func_symdifference() {}
~Create_func_symdifference()3536 virtual ~Create_func_symdifference() {}
3537 };
3538
3539
3540 class Create_func_buffer : public Create_func_arg2
3541 {
3542 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3543 Item* create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3544 {
3545 return new (thd->mem_root) Item_func_buffer(thd, arg1, arg2);
3546 }
3547
3548 static Create_func_buffer s_singleton;
3549
3550 protected:
Create_func_buffer()3551 Create_func_buffer() {}
~Create_func_buffer()3552 virtual ~Create_func_buffer() {}
3553 };
3554
3555
3556 class Create_func_isclosed : public Create_func_arg1
3557 {
3558 public:
create_1_arg(THD * thd,Item * arg1)3559 Item *create_1_arg(THD *thd, Item *arg1) override
3560 {
3561 return new (thd->mem_root) Item_func_isclosed(thd, arg1);
3562 }
3563
3564 static Create_func_isclosed s_singleton;
3565
3566 protected:
Create_func_isclosed()3567 Create_func_isclosed() {}
~Create_func_isclosed()3568 virtual ~Create_func_isclosed() {}
3569 };
3570
3571
3572 class Create_func_isring : public Create_func_arg1
3573 {
3574 public:
create_1_arg(THD * thd,Item * arg1)3575 Item *create_1_arg(THD *thd, Item *arg1) override
3576 {
3577 return new (thd->mem_root) Item_func_isring(thd, arg1);
3578 }
3579
3580 static Create_func_isring s_singleton;
3581
3582 protected:
Create_func_isring()3583 Create_func_isring() {}
~Create_func_isring()3584 virtual ~Create_func_isring() {}
3585 };
3586
3587
3588 class Create_func_isempty : public Create_func_arg1
3589 {
3590 public:
create_1_arg(THD * thd,Item * arg1)3591 Item *create_1_arg(THD *thd, Item *arg1) override
3592 {
3593 return new (thd->mem_root) Item_func_isempty(thd, arg1);
3594 }
3595
3596 static Create_func_isempty s_singleton;
3597
3598 protected:
Create_func_isempty()3599 Create_func_isempty() {}
~Create_func_isempty()3600 virtual ~Create_func_isempty() {}
3601 };
3602
3603
3604 class Create_func_issimple : public Create_func_arg1
3605 {
3606 public:
create_1_arg(THD * thd,Item * arg1)3607 Item *create_1_arg(THD *thd, Item *arg1) override
3608 {
3609 return new (thd->mem_root) Item_func_issimple(thd, arg1);
3610 }
3611
3612 static Create_func_issimple s_singleton;
3613
3614 protected:
Create_func_issimple()3615 Create_func_issimple() {}
~Create_func_issimple()3616 virtual ~Create_func_issimple() {}
3617 };
3618
3619
3620
3621 class Create_func_numgeometries : public Create_func_arg1
3622 {
3623 public:
create_1_arg(THD * thd,Item * arg1)3624 Item *create_1_arg(THD *thd, Item *arg1) override
3625 {
3626 return new (thd->mem_root) Item_func_numgeometries(thd, arg1);
3627 }
3628
3629 static Create_func_numgeometries s_singleton;
3630
3631 protected:
Create_func_numgeometries()3632 Create_func_numgeometries() {}
~Create_func_numgeometries()3633 virtual ~Create_func_numgeometries() {}
3634 };
3635
3636
3637 class Create_func_numinteriorring : public Create_func_arg1
3638 {
3639 public:
create_1_arg(THD * thd,Item * arg1)3640 Item *create_1_arg(THD *thd, Item *arg1) override
3641 {
3642 return new (thd->mem_root) Item_func_numinteriorring(thd, arg1);
3643 }
3644
3645 static Create_func_numinteriorring s_singleton;
3646
3647 protected:
Create_func_numinteriorring()3648 Create_func_numinteriorring() {}
~Create_func_numinteriorring()3649 virtual ~Create_func_numinteriorring() {}
3650 };
3651
3652
3653 class Create_func_numpoints : public Create_func_arg1
3654 {
3655 public:
create_1_arg(THD * thd,Item * arg1)3656 Item *create_1_arg(THD *thd, Item *arg1) override
3657 {
3658 return new (thd->mem_root) Item_func_numpoints(thd, arg1);
3659 }
3660
3661 static Create_func_numpoints s_singleton;
3662
3663 protected:
Create_func_numpoints()3664 Create_func_numpoints() {}
~Create_func_numpoints()3665 virtual ~Create_func_numpoints() {}
3666 };
3667
3668
3669 class Create_func_mbr_overlaps : public Create_func_arg2
3670 {
3671 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3672 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3673 {
3674 return new (thd->mem_root) Item_func_spatial_mbr_rel(thd, arg1, arg2,
3675 Item_func::SP_OVERLAPS_FUNC);
3676 }
3677
3678 static Create_func_mbr_overlaps s_singleton;
3679
3680 protected:
Create_func_mbr_overlaps()3681 Create_func_mbr_overlaps() {}
~Create_func_mbr_overlaps()3682 virtual ~Create_func_mbr_overlaps() {}
3683 };
3684
3685
3686 class Create_func_overlaps : public Create_func_arg2
3687 {
3688 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3689 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3690 {
3691 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
3692 Item_func::SP_OVERLAPS_FUNC);
3693 }
3694
3695 static Create_func_overlaps s_singleton;
3696
3697 protected:
Create_func_overlaps()3698 Create_func_overlaps() {}
~Create_func_overlaps()3699 virtual ~Create_func_overlaps() {}
3700 };
3701
3702
3703
3704
3705
3706 class Create_func_pointn : public Create_func_arg2
3707 {
3708 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3709 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3710 {
3711 return new (thd->mem_root) Item_func_spatial_decomp_n(thd, arg1, arg2,
3712 Item_func::SP_POINTN);
3713 }
3714 static Create_func_pointn s_singleton;
3715
3716 protected:
Create_func_pointn()3717 Create_func_pointn() {}
~Create_func_pointn()3718 virtual ~Create_func_pointn() {}
3719 };
3720
3721
3722
3723
3724 class Create_func_srid : public Create_func_arg1
3725 {
3726 public:
create_1_arg(THD * thd,Item * arg1)3727 Item *create_1_arg(THD *thd, Item *arg1) override
3728 {
3729 return new (thd->mem_root) Item_func_srid(thd, arg1);
3730 }
3731
3732 static Create_func_srid s_singleton;
3733
3734 protected:
Create_func_srid()3735 Create_func_srid() {}
~Create_func_srid()3736 virtual ~Create_func_srid() {}
3737 };
3738
3739
3740 class Create_func_startpoint : public Create_func_arg1
3741 {
3742 public:
create_1_arg(THD * thd,Item * arg1)3743 Item *create_1_arg(THD *thd, Item *arg1) override
3744 {
3745 return new (thd->mem_root) Item_func_spatial_decomp(thd, arg1,
3746 Item_func::SP_STARTPOINT);
3747 }
3748
3749 static Create_func_startpoint s_singleton;
3750
3751 protected:
Create_func_startpoint()3752 Create_func_startpoint() {}
~Create_func_startpoint()3753 virtual ~Create_func_startpoint() {}
3754 };
3755
3756
3757
3758 class Create_func_touches : public Create_func_arg2
3759 {
3760 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3761 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3762 {
3763 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
3764 Item_func::SP_TOUCHES_FUNC);
3765 }
3766
3767 static Create_func_touches s_singleton;
3768
3769 protected:
Create_func_touches()3770 Create_func_touches() {}
~Create_func_touches()3771 virtual ~Create_func_touches() {}
3772 };
3773
3774
3775 class Create_func_mbr_within : public Create_func_arg2
3776 {
3777 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3778 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3779 {
3780 return new (thd->mem_root) Item_func_spatial_mbr_rel(thd, arg1, arg2,
3781 Item_func::SP_WITHIN_FUNC);
3782 }
3783
3784 static Create_func_mbr_within s_singleton;
3785
3786 protected:
Create_func_mbr_within()3787 Create_func_mbr_within() {}
~Create_func_mbr_within()3788 virtual ~Create_func_mbr_within() {}
3789 };
3790
3791
3792 class Create_func_within : public Create_func_arg2
3793 {
3794 public:
create_2_arg(THD * thd,Item * arg1,Item * arg2)3795 Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) override
3796 {
3797 return new (thd->mem_root) Item_func_spatial_precise_rel(thd, arg1, arg2,
3798 Item_func::SP_WITHIN_FUNC);
3799 }
3800
3801 static Create_func_within s_singleton;
3802
3803 protected:
Create_func_within()3804 Create_func_within() {}
~Create_func_within()3805 virtual ~Create_func_within() {}
3806 };
3807
3808
3809 class Create_func_x : public Create_func_arg1
3810 {
3811 public:
create_1_arg(THD * thd,Item * arg1)3812 Item *create_1_arg(THD *thd, Item *arg1) override
3813 {
3814 return new (thd->mem_root) Item_func_x(thd, arg1);
3815 }
3816
3817 static Create_func_x s_singleton;
3818
3819 protected:
Create_func_x()3820 Create_func_x() {}
~Create_func_x()3821 virtual ~Create_func_x() {}
3822 };
3823
3824
3825 class Create_func_y : public Create_func_arg1
3826 {
3827 public:
create_1_arg(THD * thd,Item * arg1)3828 Item *create_1_arg(THD *thd, Item *arg1) override
3829 {
3830 return new (thd->mem_root) Item_func_y(thd, arg1);
3831 }
3832
3833 static Create_func_y s_singleton;
3834
3835 protected:
Create_func_y()3836 Create_func_y() {}
~Create_func_y()3837 virtual ~Create_func_y() {}
3838 };
3839
3840
3841 /*****************************************************************/
3842
3843
3844
3845
3846
3847
3848
3849 /*************************************************************************/
3850
3851 #if !defined(DBUG_OFF)
3852 Create_func_gis_debug Create_func_gis_debug::s_singleton;
3853 #endif
3854
3855 Create_func_area Create_func_area::s_singleton;
3856 Create_func_as_geojson Create_func_as_geojson::s_singleton;
3857 Create_func_as_wkb Create_func_as_wkb::s_singleton;
3858 Create_func_as_wkt Create_func_as_wkt::s_singleton;
3859 Create_func_boundary Create_func_boundary::s_singleton;
3860 Create_func_buffer Create_func_buffer::s_singleton;
3861 Create_func_centroid Create_func_centroid::s_singleton;
3862 Create_func_contains Create_func_contains::s_singleton;
3863 Create_func_convexhull Create_func_convexhull::s_singleton;
3864 Create_func_crosses Create_func_crosses::s_singleton;
3865 Create_func_difference Create_func_difference::s_singleton;
3866 Create_func_dimension Create_func_dimension::s_singleton;
3867 Create_func_disjoint Create_func_disjoint::s_singleton;
3868 Create_func_distance Create_func_distance::s_singleton;
3869 Create_func_distance_sphere Create_func_distance_sphere::s_singleton;
3870 Create_func_endpoint Create_func_endpoint::s_singleton;
3871 Create_func_envelope Create_func_envelope::s_singleton;
3872 Create_func_equals Create_func_equals::s_singleton;
3873 Create_func_exteriorring Create_func_exteriorring::s_singleton;
3874 Create_func_geometry_from_json Create_func_geometry_from_json::s_singleton;
3875 Create_func_geometry_from_text Create_func_geometry_from_text::s_singleton;
3876 Create_func_geometry_from_wkb Create_func_geometry_from_wkb::s_singleton;
3877 Create_func_geometryn Create_func_geometryn::s_singleton;
3878 Create_func_geometry_type Create_func_geometry_type::s_singleton;
3879 Create_func_glength Create_func_glength::s_singleton;
3880 Create_func_interiorringn Create_func_interiorringn::s_singleton;
3881 Create_func_intersection Create_func_intersection::s_singleton;
3882 Create_func_intersects Create_func_intersects::s_singleton;
3883 Create_func_isclosed Create_func_isclosed::s_singleton;
3884 Create_func_isempty Create_func_isempty::s_singleton;
3885 Create_func_isring Create_func_isring::s_singleton;
3886 Create_func_issimple Create_func_issimple::s_singleton;
3887 Create_func_mbr_contains Create_func_mbr_contains::s_singleton;
3888 Create_func_mbr_disjoint Create_func_mbr_disjoint::s_singleton;
3889 Create_func_mbr_equals Create_func_mbr_equals::s_singleton;
3890 Create_func_mbr_intersects Create_func_mbr_intersects::s_singleton;
3891 Create_func_mbr_overlaps Create_func_mbr_overlaps::s_singleton;
3892 Create_func_mbr_within Create_func_mbr_within::s_singleton;
3893 Create_func_numgeometries Create_func_numgeometries::s_singleton;
3894 Create_func_numinteriorring Create_func_numinteriorring::s_singleton;
3895 Create_func_numpoints Create_func_numpoints::s_singleton;
3896 Create_func_overlaps Create_func_overlaps::s_singleton;
3897 Create_func_pointn Create_func_pointn::s_singleton;
3898 Create_func_pointonsurface Create_func_pointonsurface::s_singleton;
3899 Create_func_relate Create_func_relate::s_singleton;
3900 Create_func_srid Create_func_srid::s_singleton;
3901 Create_func_startpoint Create_func_startpoint::s_singleton;
3902 Create_func_symdifference Create_func_symdifference::s_singleton;
3903 Create_func_touches Create_func_touches::s_singleton;
3904 Create_func_union Create_func_union::s_singleton;
3905 Create_func_within Create_func_within::s_singleton;
3906 Create_func_x Create_func_x::s_singleton;
3907 Create_func_y Create_func_y::s_singleton;
3908
3909 /*************************************************************************/
3910
3911
3912 #define GEOM_BUILDER(F) & F::s_singleton
3913
3914
3915 static Native_func_registry func_array_geom[] =
3916 {
3917 #ifndef DBUG_OFF
3918 { { STRING_WITH_LEN("ST_GIS_DEBUG") }, GEOM_BUILDER(Create_func_gis_debug)},
3919 #endif
3920 { { STRING_WITH_LEN("AREA") }, GEOM_BUILDER(Create_func_area)},
3921 { { STRING_WITH_LEN("ASBINARY") }, GEOM_BUILDER(Create_func_as_wkb)},
3922 { { STRING_WITH_LEN("ASTEXT") }, GEOM_BUILDER(Create_func_as_wkt)},
3923 { { STRING_WITH_LEN("ASWKB") }, GEOM_BUILDER(Create_func_as_wkb)},
3924 { { STRING_WITH_LEN("ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)},
3925 { { STRING_WITH_LEN("BOUNDARY") }, GEOM_BUILDER(Create_func_boundary)},
3926 { { STRING_WITH_LEN("BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
3927 { { STRING_WITH_LEN("CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
3928 { { STRING_WITH_LEN("CONTAINS") }, GEOM_BUILDER(Create_func_contains)},
3929 { { STRING_WITH_LEN("CONVEXHULL") }, GEOM_BUILDER(Create_func_convexhull)},
3930 { { STRING_WITH_LEN("CROSSES") }, GEOM_BUILDER(Create_func_crosses)},
3931 { { STRING_WITH_LEN("DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
3932 { { STRING_WITH_LEN("DISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
3933 { { STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
3934 { { STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
3935 { { STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_equals)},
3936 { { STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
3937 { { STRING_WITH_LEN("GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3938 { { STRING_WITH_LEN("GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3939 { { STRING_WITH_LEN("GEOMETRYCOLLECTIONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3940 { { STRING_WITH_LEN("GEOMETRYCOLLECTIONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3941 { { STRING_WITH_LEN("GEOMETRYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3942 { { STRING_WITH_LEN("GEOMETRYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3943 { { STRING_WITH_LEN("GEOMETRYN") }, GEOM_BUILDER(Create_func_geometryn)},
3944 { { STRING_WITH_LEN("GEOMETRYTYPE") }, GEOM_BUILDER(Create_func_geometry_type)},
3945 { { STRING_WITH_LEN("GEOMFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3946 { { STRING_WITH_LEN("GEOMFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3947 { { STRING_WITH_LEN("GLENGTH") }, GEOM_BUILDER(Create_func_glength)},
3948 { { STRING_WITH_LEN("INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
3949 { { STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
3950 { { STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
3951 { { STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
3952 { { STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)},
3953 { { STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
3954 { { STRING_WITH_LEN("LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3955 { { STRING_WITH_LEN("LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3956 { { STRING_WITH_LEN("LINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3957 { { STRING_WITH_LEN("LINESTRINGFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3958 { { STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_mbr_contains)},
3959 { { STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
3960 { { STRING_WITH_LEN("MBREQUAL") }, GEOM_BUILDER(Create_func_mbr_equals)},
3961 { { STRING_WITH_LEN("MBREQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)},
3962 { { STRING_WITH_LEN("MBRINTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
3963 { { STRING_WITH_LEN("MBROVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
3964 { { STRING_WITH_LEN("MBRTOUCHES") }, GEOM_BUILDER(Create_func_touches)},
3965 { { STRING_WITH_LEN("MBRWITHIN") }, GEOM_BUILDER(Create_func_mbr_within)},
3966 { { STRING_WITH_LEN("MLINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3967 { { STRING_WITH_LEN("MLINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3968 { { STRING_WITH_LEN("MPOINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3969 { { STRING_WITH_LEN("MPOINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3970 { { STRING_WITH_LEN("MPOLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3971 { { STRING_WITH_LEN("MPOLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3972 { { STRING_WITH_LEN("MULTILINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3973 { { STRING_WITH_LEN("MULTILINESTRINGFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3974 { { STRING_WITH_LEN("MULTIPOINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3975 { { STRING_WITH_LEN("MULTIPOINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3976 { { STRING_WITH_LEN("MULTIPOLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3977 { { STRING_WITH_LEN("MULTIPOLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3978 { { STRING_WITH_LEN("NUMGEOMETRIES") }, GEOM_BUILDER(Create_func_numgeometries)},
3979 { { STRING_WITH_LEN("NUMINTERIORRINGS") }, GEOM_BUILDER(Create_func_numinteriorring)},
3980 { { STRING_WITH_LEN("NUMPOINTS") }, GEOM_BUILDER(Create_func_numpoints)},
3981 { { STRING_WITH_LEN("OVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
3982 { { STRING_WITH_LEN("POINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3983 { { STRING_WITH_LEN("POINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3984 { { STRING_WITH_LEN("POINTN") }, GEOM_BUILDER(Create_func_pointn)},
3985 { { STRING_WITH_LEN("POINTONSURFACE") }, GEOM_BUILDER(Create_func_pointonsurface)},
3986 { { STRING_WITH_LEN("POLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3987 { { STRING_WITH_LEN("POLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3988 { { STRING_WITH_LEN("POLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
3989 { { STRING_WITH_LEN("POLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
3990 { { STRING_WITH_LEN("SRID") }, GEOM_BUILDER(Create_func_srid)},
3991 { { STRING_WITH_LEN("ST_AREA") }, GEOM_BUILDER(Create_func_area)},
3992 { { STRING_WITH_LEN("STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
3993 { { STRING_WITH_LEN("ST_ASBINARY") }, GEOM_BUILDER(Create_func_as_wkb)},
3994 { { STRING_WITH_LEN("ST_ASGEOJSON") }, GEOM_BUILDER(Create_func_as_geojson)},
3995 { { STRING_WITH_LEN("ST_ASTEXT") }, GEOM_BUILDER(Create_func_as_wkt)},
3996 { { STRING_WITH_LEN("ST_ASWKB") }, GEOM_BUILDER(Create_func_as_wkb)},
3997 { { STRING_WITH_LEN("ST_ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)},
3998 { { STRING_WITH_LEN("ST_BOUNDARY") }, GEOM_BUILDER(Create_func_boundary)},
3999 { { STRING_WITH_LEN("ST_BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
4000 { { STRING_WITH_LEN("ST_CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
4001 { { STRING_WITH_LEN("ST_CONTAINS") }, GEOM_BUILDER(Create_func_contains)},
4002 { { STRING_WITH_LEN("ST_CONVEXHULL") }, GEOM_BUILDER(Create_func_convexhull)},
4003 { { STRING_WITH_LEN("ST_CROSSES") }, GEOM_BUILDER(Create_func_crosses)},
4004 { { STRING_WITH_LEN("ST_DIFFERENCE") }, GEOM_BUILDER(Create_func_difference)},
4005 { { STRING_WITH_LEN("ST_DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
4006 { { STRING_WITH_LEN("ST_DISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
4007 { { STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)},
4008 { { STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
4009 { { STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
4010 { { STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
4011 { { STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
4012 { { STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
4013 { { STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4014 { { STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4015 { { STRING_WITH_LEN("ST_GEOMETRYCOLLECTIONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4016 { { STRING_WITH_LEN("ST_GEOMETRYCOLLECTIONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4017 { { STRING_WITH_LEN("ST_GEOMETRYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4018 { { STRING_WITH_LEN("ST_GEOMETRYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4019 { { STRING_WITH_LEN("ST_GEOMETRYN") }, GEOM_BUILDER(Create_func_geometryn)},
4020 { { STRING_WITH_LEN("ST_GEOMETRYTYPE") }, GEOM_BUILDER(Create_func_geometry_type)},
4021 { { STRING_WITH_LEN("ST_GEOMFROMGEOJSON") }, GEOM_BUILDER(Create_func_geometry_from_json)},
4022 { { STRING_WITH_LEN("ST_GEOMFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4023 { { STRING_WITH_LEN("ST_GEOMFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4024 { { STRING_WITH_LEN("ST_INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
4025 { { STRING_WITH_LEN("ST_INTERSECTION") }, GEOM_BUILDER(Create_func_intersection)},
4026 { { STRING_WITH_LEN("ST_INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
4027 { { STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
4028 { { STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
4029 { { STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)},
4030 { { STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
4031 { { STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
4032 { { STRING_WITH_LEN("ST_LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4033 { { STRING_WITH_LEN("ST_LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4034 { { STRING_WITH_LEN("ST_LINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4035 { { STRING_WITH_LEN("ST_LINESTRINGFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4036 { { STRING_WITH_LEN("ST_MLINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4037 { { STRING_WITH_LEN("ST_MLINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4038 { { STRING_WITH_LEN("ST_MPOINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4039 { { STRING_WITH_LEN("ST_MPOINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4040 { { STRING_WITH_LEN("ST_MPOLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4041 { { STRING_WITH_LEN("ST_MPOLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4042 { { STRING_WITH_LEN("ST_MULTILINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4043 { { STRING_WITH_LEN("ST_MULTILINESTRINGFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4044 { { STRING_WITH_LEN("ST_MULTIPOINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4045 { { STRING_WITH_LEN("ST_MULTIPOINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4046 { { STRING_WITH_LEN("ST_MULTIPOLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4047 { { STRING_WITH_LEN("ST_MULTIPOLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4048 { { STRING_WITH_LEN("ST_NUMGEOMETRIES") }, GEOM_BUILDER(Create_func_numgeometries)},
4049 { { STRING_WITH_LEN("ST_NUMINTERIORRINGS") }, GEOM_BUILDER(Create_func_numinteriorring)},
4050 { { STRING_WITH_LEN("ST_NUMPOINTS") }, GEOM_BUILDER(Create_func_numpoints)},
4051 { { STRING_WITH_LEN("ST_OVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
4052 { { STRING_WITH_LEN("ST_POINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4053 { { STRING_WITH_LEN("ST_POINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4054 { { STRING_WITH_LEN("ST_POINTN") }, GEOM_BUILDER(Create_func_pointn)},
4055 { { STRING_WITH_LEN("ST_POINTONSURFACE") }, GEOM_BUILDER(Create_func_pointonsurface)},
4056 { { STRING_WITH_LEN("ST_POLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4057 { { STRING_WITH_LEN("ST_POLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4058 { { STRING_WITH_LEN("ST_POLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
4059 { { STRING_WITH_LEN("ST_POLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
4060 { { STRING_WITH_LEN("ST_RELATE") }, GEOM_BUILDER(Create_func_relate)},
4061 { { STRING_WITH_LEN("ST_SRID") }, GEOM_BUILDER(Create_func_srid)},
4062 { { STRING_WITH_LEN("ST_STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
4063 { { STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)},
4064 { { STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
4065 { { STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)},
4066 { { STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)},
4067 { { STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
4068 { { STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
4069 { { STRING_WITH_LEN("ST_DISTANCE_SPHERE") }, GEOM_BUILDER(Create_func_distance_sphere)},
4070 { { STRING_WITH_LEN("TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
4071 { { STRING_WITH_LEN("WITHIN") }, GEOM_BUILDER(Create_func_within)},
4072 { { STRING_WITH_LEN("X") }, GEOM_BUILDER(Create_func_x)},
4073 { { STRING_WITH_LEN("Y") }, GEOM_BUILDER(Create_func_y)},
4074 };
4075
4076
4077 Native_func_registry_array
4078 native_func_registry_array_geom(func_array_geom,
4079 array_elements(func_array_geom));
4080
4081 #endif /*HAVE_SPATIAL*/
4082