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