item_geofunc.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* This file defines all spatial functions */
  14. #ifdef USE_PRAGMA_IMPLEMENTATION
  15. #pragma implementation // gcc: Class implementation
  16. #endif
  17. #include "mysql_priv.h"
  18. #ifdef HAVE_SPATIAL
  19. #include <m_ctype.h>
  20. void Item_geometry_func::fix_length_and_dec()
  21. {
  22.   collation.set(&my_charset_bin);
  23.   decimals=0;
  24.   max_length=MAX_BLOB_WIDTH;
  25. }
  26. String *Item_func_geometry_from_text::val_str(String *str)
  27. {
  28.   DBUG_ASSERT(fixed == 1);
  29.   Geometry_buffer buffer;
  30.   String arg_val;
  31.   String *wkt= args[0]->val_str(&arg_val);
  32.   if ((null_value= args[0]->null_value))
  33.     return 0;
  34.   Gis_read_stream trs(wkt->charset(), wkt->ptr(), wkt->length());
  35.   uint32 srid= 0;
  36.   if ((arg_count == 2) && !args[1]->null_value)
  37.     srid= (uint32)args[1]->val_int();
  38.   str->set_charset(&my_charset_bin);
  39.   if (str->reserve(SRID_SIZE, 512))
  40.     return 0;
  41.   str->length(0);
  42.   str->q_append(srid);
  43.   if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
  44.     return 0;
  45.   return str;
  46. }
  47. String *Item_func_geometry_from_wkb::val_str(String *str)
  48. {
  49.   DBUG_ASSERT(fixed == 1);
  50.   String arg_val;
  51.   String *wkb= args[0]->val_str(&arg_val);
  52.   Geometry_buffer buffer;
  53.   uint32 srid= 0;
  54.   if ((arg_count == 2) && !args[1]->null_value)
  55.     srid= (uint32)args[1]->val_int();
  56.   str->set_charset(&my_charset_bin);
  57.   if (str->reserve(SRID_SIZE, 512))
  58.     return 0;
  59.   str->length(0);
  60.   str->q_append(srid);
  61.   if ((null_value= 
  62.        (args[0]->null_value ||
  63.         !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length(), str))))
  64.     return 0;
  65.   return str;
  66. }
  67. String *Item_func_as_wkt::val_str(String *str)
  68. {
  69.   DBUG_ASSERT(fixed == 1);
  70.   String arg_val;
  71.   String *swkb= args[0]->val_str(&arg_val);
  72.   Geometry_buffer buffer;
  73.   Geometry *geom= NULL;
  74.   const char *dummy;
  75.   if ((null_value=
  76.        (args[0]->null_value ||
  77. !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
  78.     return 0;
  79.   str->length(0);
  80.   if ((null_value= geom->as_wkt(str, &dummy)))
  81.     return 0;
  82.   return str;
  83. }
  84. void Item_func_as_wkt::fix_length_and_dec()
  85. {
  86.   max_length=MAX_BLOB_WIDTH;
  87. }
  88. String *Item_func_as_wkb::val_str(String *str)
  89. {
  90.   DBUG_ASSERT(fixed == 1);
  91.   String arg_val;
  92.   String *swkb= args[0]->val_str(&arg_val);
  93.   Geometry_buffer buffer;
  94.   if ((null_value=
  95.        (args[0]->null_value ||
  96. !(Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
  97.     return 0;
  98.   str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
  99.     &my_charset_bin);
  100.   return str;
  101. }
  102. String *Item_func_geometry_type::val_str(String *str)
  103. {
  104.   DBUG_ASSERT(fixed == 1);
  105.   String *swkb= args[0]->val_str(str);
  106.   Geometry_buffer buffer;
  107.   Geometry *geom= NULL;
  108.   if ((null_value=
  109.        (args[0]->null_value ||
  110. !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
  111.     return 0;
  112.   /* String will not move */
  113.   str->copy(geom->get_class_info()->m_name.str,
  114.     geom->get_class_info()->m_name.length,
  115.     default_charset());
  116.   return str;
  117. }
  118. String *Item_func_envelope::val_str(String *str)
  119. {
  120.   DBUG_ASSERT(fixed == 1);
  121.   String arg_val;
  122.   String *swkb= args[0]->val_str(&arg_val);
  123.   Geometry_buffer buffer;
  124.   Geometry *geom= NULL;
  125.   uint32 srid;
  126.   
  127.   if ((null_value=
  128.        args[0]->null_value ||
  129.        !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
  130.     return 0;
  131.   
  132.   srid= uint4korr(swkb->ptr());
  133.   str->set_charset(&my_charset_bin);
  134.   str->length(0);
  135.   if (str->reserve(SRID_SIZE, 512))
  136.     return 0;
  137.   str->q_append(srid);
  138.   return (null_value= geom->envelope(str)) ? 0 : str;
  139. }
  140. String *Item_func_centroid::val_str(String *str)
  141. {
  142.   DBUG_ASSERT(fixed == 1);
  143.   String arg_val;
  144.   String *swkb= args[0]->val_str(&arg_val);
  145.   Geometry_buffer buffer;
  146.   Geometry *geom= NULL;
  147.   uint32 srid;
  148.   if ((null_value= args[0]->null_value ||
  149.        !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
  150.     return 0;
  151.   str->set_charset(&my_charset_bin);
  152.   if (str->reserve(SRID_SIZE, 512))
  153.     return 0;
  154.   str->length(0);
  155.   srid= uint4korr(swkb->ptr());
  156.   str->q_append(srid);
  157.   return (null_value= test(geom->centroid(str))) ? 0 : str;
  158. }
  159. /*
  160.   Spatial decomposition functions
  161. */
  162. String *Item_func_spatial_decomp::val_str(String *str)
  163. {
  164.   DBUG_ASSERT(fixed == 1);
  165.   String arg_val;
  166.   String *swkb= args[0]->val_str(&arg_val);
  167.   Geometry_buffer buffer;
  168.   Geometry *geom= NULL;
  169.   uint32 srid;
  170.   if ((null_value=
  171.        (args[0]->null_value ||
  172. !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
  173.     return 0;
  174.   srid= uint4korr(swkb->ptr());
  175.   str->set_charset(&my_charset_bin);
  176.   if (str->reserve(SRID_SIZE, 512))
  177.     goto err;
  178.   str->length(0);
  179.   str->q_append(srid);
  180.   switch (decomp_func) {
  181.     case SP_STARTPOINT:
  182.       if (geom->start_point(str))
  183.         goto err;
  184.       break;
  185.     case SP_ENDPOINT:
  186.       if (geom->end_point(str))
  187.         goto err;
  188.       break;
  189.     case SP_EXTERIORRING:
  190.       if (geom->exterior_ring(str))
  191.         goto err;
  192.       break;
  193.     default:
  194.       goto err;
  195.   }
  196.   return str;
  197. err:
  198.   null_value= 1;
  199.   return 0;
  200. }
  201. String *Item_func_spatial_decomp_n::val_str(String *str)
  202. {
  203.   DBUG_ASSERT(fixed == 1);
  204.   String arg_val;
  205.   String *swkb= args[0]->val_str(&arg_val);
  206.   long n= (long) args[1]->val_int();
  207.   Geometry_buffer buffer;
  208.   Geometry *geom= NULL;
  209.   uint32 srid;
  210.   if ((null_value=
  211.        (args[0]->null_value || args[1]->null_value ||
  212. !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
  213.     return 0;
  214.   str->set_charset(&my_charset_bin);
  215.   if (str->reserve(SRID_SIZE, 512))
  216.     goto err;
  217.   srid= uint4korr(swkb->ptr());
  218.   str->length(0);
  219.   str->q_append(srid);
  220.   switch (decomp_func_n)
  221.   {
  222.     case SP_POINTN:
  223.       if (geom->point_n(n,str))
  224.         goto err;
  225.       break;
  226.     case SP_GEOMETRYN:
  227.       if (geom->geometry_n(n,str))
  228.         goto err;
  229.       break;
  230.     case SP_INTERIORRINGN:
  231.       if (geom->interior_ring_n(n,str))
  232.         goto err;
  233.       break;
  234.     default:
  235.       goto err;
  236.   }
  237.   return str;
  238. err:
  239.   null_value=1;
  240.   return 0;
  241. }
  242. /*
  243.   Functions to concatenate various spatial objects
  244. */
  245. /*
  246. *  Concatenate doubles into Point
  247. */
  248. String *Item_func_point::val_str(String *str)
  249. {
  250.   DBUG_ASSERT(fixed == 1);
  251.   double x= args[0]->val();
  252.   double y= args[1]->val();
  253.   if ((null_value= (args[0]->null_value ||
  254.     args[1]->null_value ||
  255.     str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
  256.     return 0;
  257.   str->set_charset(&my_charset_bin);
  258.   str->length(0);
  259.   str->q_append((char)Geometry::wkb_ndr);
  260.   str->q_append((uint32)Geometry::wkb_point);
  261.   str->q_append(x);
  262.   str->q_append(y);
  263.   return str;
  264. }
  265. /*
  266.   Concatenates various items into various collections
  267.   with checkings for valid wkb type of items.
  268.   For example, MultiPoint can be a collection of Points only.
  269.   coll_type contains wkb type of target collection.
  270.   item_type contains a valid wkb type of items.
  271.   In the case when coll_type is wkbGeometryCollection,
  272.   we do not check wkb type of items, any is valid.
  273. */
  274. String *Item_func_spatial_collection::val_str(String *str)
  275. {
  276.   DBUG_ASSERT(fixed == 1);
  277.   String arg_value;
  278.   uint i;
  279.   str->set_charset(&my_charset_bin);
  280.   str->length(0);
  281.   if (str->reserve(1 + 4 + 4, 512))
  282.     goto err;
  283.   str->q_append((char) Geometry::wkb_ndr);
  284.   str->q_append((uint32) coll_type);
  285.   str->q_append((uint32) arg_count);
  286.   for (i= 0; i < arg_count; ++i)
  287.   {
  288.     String *res= args[i]->val_str(&arg_value);
  289.     if (args[i]->null_value)
  290.       goto err;
  291.     if (coll_type == Geometry::wkb_geometrycollection)
  292.     {
  293.       /*
  294. In the case of GeometryCollection we don't need any checkings
  295. for item types, so just copy them into target collection
  296.       */
  297.       if (str->append(res->ptr(), res->length(), (uint32) 512))
  298.         goto err;
  299.     }
  300.     else
  301.     {
  302.       enum Geometry::wkbType wkb_type;
  303.       uint32 len=res->length();
  304.       const char *data= res->ptr() + 1;
  305.       /*
  306. In the case of named collection we must check that items
  307. are of specific type, let's do this checking now
  308.       */
  309.       if (len < 5)
  310.         goto err;
  311.       wkb_type= (Geometry::wkbType) uint4korr(data);
  312.       data+= 4;
  313.       len-= 5;
  314.       if (wkb_type != item_type)
  315.         goto err;
  316.       switch (coll_type) {
  317.       case Geometry::wkb_multipoint:
  318.       case Geometry::wkb_multilinestring:
  319.       case Geometry::wkb_multipolygon:
  320. if (len < WKB_HEADER_SIZE ||
  321.     str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
  322.   goto err;
  323. break;
  324.       case Geometry::wkb_linestring:
  325. if (str->append(data, POINT_DATA_SIZE, 512))
  326.   goto err;
  327. break;
  328.       case Geometry::wkb_polygon:
  329.       {
  330. uint32 n_points;
  331. double x1, y1, x2, y2;
  332. const char *org_data= data;
  333. if (len < 4 + 2 * POINT_DATA_SIZE)
  334.   goto err;
  335. n_points= uint4korr(data);
  336. data+= 4;
  337. float8get(x1, data);
  338. data+= SIZEOF_STORED_DOUBLE;
  339. float8get(y1, data);
  340. data+= SIZEOF_STORED_DOUBLE;
  341. data+= (n_points - 2) * POINT_DATA_SIZE;
  342. float8get(x2, data);
  343. float8get(y2, data + SIZEOF_STORED_DOUBLE);
  344. if ((x1 != x2) || (y1 != y2) ||
  345.     str->append(org_data, len, 512))
  346.   goto err;
  347.       }
  348.       break;
  349.       default:
  350. goto err;
  351.       }
  352.     }
  353.   }
  354.   if (str->length() > current_thd->variables.max_allowed_packet)
  355.   {
  356.     push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
  357. ER_WARN_ALLOWED_PACKET_OVERFLOWED,
  358. ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
  359. func_name(), current_thd->variables.max_allowed_packet);
  360.     goto err;
  361.   }
  362.   null_value = 0;
  363.   return str;
  364. err:
  365.   null_value= 1;
  366.   return 0;
  367. }
  368. /*
  369.   Functions for spatial relations
  370. */
  371. longlong Item_func_spatial_rel::val_int()
  372. {
  373.   DBUG_ASSERT(fixed == 1);
  374.   String *res1= args[0]->val_str(&tmp_value1);
  375.   String *res2= args[1]->val_str(&tmp_value2);
  376.   Geometry_buffer buffer1, buffer2;
  377.   Geometry *g1, *g2;
  378.   MBR mbr1, mbr2;
  379.   const char *dummy;
  380.   if ((null_value=
  381.        (args[0]->null_value ||
  382. args[1]->null_value ||
  383. !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
  384. !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
  385. g1->get_mbr(&mbr1, &dummy) ||
  386. g2->get_mbr(&mbr2, &dummy))))
  387.    return 0;
  388.   switch (spatial_rel) {
  389.     case SP_CONTAINS_FUNC:
  390.       return mbr1.contains(&mbr2);
  391.     case SP_WITHIN_FUNC:
  392.       return mbr1.within(&mbr2);
  393.     case SP_EQUALS_FUNC:
  394.       return mbr1.equals(&mbr2);
  395.     case SP_DISJOINT_FUNC:
  396.       return mbr1.disjoint(&mbr2);
  397.     case SP_INTERSECTS_FUNC:
  398.       return mbr1.intersects(&mbr2);
  399.     case SP_TOUCHES_FUNC:
  400.       return mbr1.touches(&mbr2);
  401.     case SP_OVERLAPS_FUNC:
  402.       return mbr1.overlaps(&mbr2);
  403.     case SP_CROSSES_FUNC:
  404.       return 0;
  405.     default:
  406.       break;
  407.   }
  408.   null_value=1;
  409.   return 0;
  410. }
  411. longlong Item_func_isempty::val_int()
  412. {
  413.   DBUG_ASSERT(fixed == 1);
  414.   String tmp; 
  415.   null_value=0;
  416.   return args[0]->null_value ? 1 : 0;
  417. }
  418. longlong Item_func_issimple::val_int()
  419. {
  420.   DBUG_ASSERT(fixed == 1);
  421.   String tmp;
  422.   String *wkb=args[0]->val_str(&tmp);
  423.   if ((null_value= (!wkb || args[0]->null_value)))
  424.     return 0;
  425.   /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
  426.   return 0;
  427. }
  428. longlong Item_func_isclosed::val_int()
  429. {
  430.   DBUG_ASSERT(fixed == 1);
  431.   String tmp;
  432.   String *swkb= args[0]->val_str(&tmp);
  433.   Geometry_buffer buffer;
  434.   Geometry *geom;
  435.   int isclosed= 0; // In case of error
  436.   null_value= (!swkb || 
  437.        args[0]->null_value ||
  438.        !(geom=
  439.  Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
  440.        geom->is_closed(&isclosed));
  441.   return (longlong) isclosed;
  442. }
  443. /*
  444.   Numerical functions
  445. */
  446. longlong Item_func_dimension::val_int()
  447. {
  448.   DBUG_ASSERT(fixed == 1);
  449.   uint32 dim= 0; // In case of error
  450.   String *swkb= args[0]->val_str(&value);
  451.   Geometry_buffer buffer;
  452.   Geometry *geom;
  453.   const char *dummy;
  454.   null_value= (!swkb || 
  455.        args[0]->null_value ||
  456.        !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
  457.        geom->dimension(&dim, &dummy));
  458.   return (longlong) dim;
  459. }
  460. longlong Item_func_numinteriorring::val_int()
  461. {
  462.   DBUG_ASSERT(fixed == 1);
  463.   uint32 num= 0; // In case of error
  464.   String *swkb= args[0]->val_str(&value);
  465.   Geometry_buffer buffer;
  466.   Geometry *geom;
  467.   null_value= (!swkb || 
  468.        !(geom= Geometry::construct(&buffer,
  469.                                            swkb->ptr(), swkb->length())) ||
  470.        geom->num_interior_ring(&num));
  471.   return (longlong) num;
  472. }
  473. longlong Item_func_numgeometries::val_int()
  474. {
  475.   DBUG_ASSERT(fixed == 1);
  476.   uint32 num= 0; // In case of errors
  477.   String *swkb= args[0]->val_str(&value);
  478.   Geometry_buffer buffer;
  479.   Geometry *geom;
  480.   null_value= (!swkb ||
  481.        !(geom= Geometry::construct(&buffer,
  482.                                            swkb->ptr(), swkb->length())) ||
  483.        geom->num_geometries(&num));
  484.   return (longlong) num;
  485. }
  486. longlong Item_func_numpoints::val_int()
  487. {
  488.   DBUG_ASSERT(fixed == 1);
  489.   uint32 num= 0; // In case of errors
  490.   String *swkb= args[0]->val_str(&value);
  491.   Geometry_buffer buffer;
  492.   Geometry *geom;
  493.   null_value= (!swkb ||
  494.        args[0]->null_value ||
  495.        !(geom= Geometry::construct(&buffer,
  496.                                            swkb->ptr(), swkb->length())) ||
  497.        geom->num_points(&num));
  498.   return (longlong) num;
  499. }
  500. double Item_func_x::val()
  501. {
  502.   DBUG_ASSERT(fixed == 1);
  503.   double res= 0.0; // In case of errors
  504.   String *swkb= args[0]->val_str(&value);
  505.   Geometry_buffer buffer;
  506.   Geometry *geom;
  507.   null_value= (!swkb ||
  508.        !(geom= Geometry::construct(&buffer,
  509.                                            swkb->ptr(), swkb->length())) ||
  510.        geom->get_x(&res));
  511.   return res;
  512. }
  513. double Item_func_y::val()
  514. {
  515.   DBUG_ASSERT(fixed == 1);
  516.   double res= 0; // In case of errors
  517.   String *swkb= args[0]->val_str(&value);
  518.   Geometry_buffer buffer;
  519.   Geometry *geom;
  520.   null_value= (!swkb ||
  521.        !(geom= Geometry::construct(&buffer,
  522.                                            swkb->ptr(), swkb->length())) ||
  523.        geom->get_y(&res));
  524.   return res;
  525. }
  526. double Item_func_area::val()
  527. {
  528.   DBUG_ASSERT(fixed == 1);
  529.   double res= 0; // In case of errors
  530.   String *swkb= args[0]->val_str(&value);
  531.   Geometry_buffer buffer;
  532.   Geometry *geom;
  533.   const char *dummy;
  534.   null_value= (!swkb ||
  535.        !(geom= Geometry::construct(&buffer,
  536.                                            swkb->ptr(), swkb->length())) ||
  537.        geom->area(&res, &dummy));
  538.   return res;
  539. }
  540. double Item_func_glength::val()
  541. {
  542.   DBUG_ASSERT(fixed == 1);
  543.   double res= 0; // In case of errors
  544.   String *swkb= args[0]->val_str(&value);
  545.   Geometry_buffer buffer;
  546.   Geometry *geom;
  547.   null_value= (!swkb || 
  548.        !(geom= Geometry::construct(&buffer,
  549.                                            swkb->ptr(), swkb->length())) ||
  550.        geom->length(&res));
  551.   return res;
  552. }
  553. longlong Item_func_srid::val_int()
  554. {
  555.   DBUG_ASSERT(fixed == 1);
  556.   String *swkb= args[0]->val_str(&value);
  557.   Geometry_buffer buffer;
  558.   
  559.   null_value= (!swkb || 
  560.        !Geometry::construct(&buffer,
  561.                                     swkb->ptr(), swkb->length()));
  562.   if (null_value)
  563.     return 0;
  564.   return (longlong) (uint4korr(swkb->ptr()));
  565. }
  566. #endif /*HAVE_SPATIAL*/