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