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