item_geofunc.cc 16.2 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2003-2006 MySQL AB
2 3 4

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
6 7 8 9 10 11 12 13 14 15 16 17 18

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* This file defines all spatial functions */

19
#ifdef USE_PRAGMA_IMPLEMENTATION
20 21 22 23
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
unknown's avatar
SCRUM  
unknown committed
24
#ifdef HAVE_SPATIAL
25 26
#include <m_ctype.h>

27 28
Field *Item_geometry_func::tmp_table_field(TABLE *t_arg)
{
unknown's avatar
unknown committed
29 30
  Field *result;
  if ((result= new Field_geom(max_length, maybe_null, name, t_arg->s,
31
                              get_geometry_type())))
unknown's avatar
unknown committed
32 33
    result->init(t_arg);
  return result;
34 35
}

36 37 38 39 40
void Item_geometry_func::fix_length_and_dec()
{
  collation.set(&my_charset_bin);
  decimals=0;
  max_length=MAX_BLOB_WIDTH;
41
  maybe_null= 1;
42 43
}

unknown's avatar
unknown committed
44

45 46
String *Item_func_geometry_from_text::val_str(String *str)
{
47
  DBUG_ASSERT(fixed == 1);
48
  Geometry_buffer buffer;
49 50
  String arg_val;
  String *wkt= args[0]->val_str(&arg_val);
unknown's avatar
unknown committed
51 52 53 54 55

  if ((null_value= args[0]->null_value))
    return 0;

  Gis_read_stream trs(wkt->charset(), wkt->ptr(), wkt->length());
unknown's avatar
unknown committed
56
  uint32 srid= 0;
57 58

  if ((arg_count == 2) && !args[1]->null_value)
59
    srid= (uint32)args[1]->val_int();
60

61
  str->set_charset(&my_charset_bin);
62 63 64 65
  if (str->reserve(SRID_SIZE, 512))
    return 0;
  str->length(0);
  str->q_append(srid);
unknown's avatar
unknown committed
66 67
  if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
    return 0;
68 69 70 71 72 73
  return str;
}


String *Item_func_geometry_from_wkb::val_str(String *str)
{
74
  DBUG_ASSERT(fixed == 1);
75 76
  String arg_val;
  String *wkb= args[0]->val_str(&arg_val);
77
  Geometry_buffer buffer;
unknown's avatar
unknown committed
78
  uint32 srid= 0;
79 80

  if ((arg_count == 2) && !args[1]->null_value)
81
    srid= (uint32)args[1]->val_int();
82

83
  str->set_charset(&my_charset_bin);
84 85 86 87
  if (str->reserve(SRID_SIZE, 512))
    return 0;
  str->length(0);
  str->q_append(srid);
88 89
  if ((null_value= 
       (args[0]->null_value ||
90
        !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length(), str))))
91 92 93 94 95
    return 0;
  return str;
}


96
String *Item_func_as_wkt::val_str(String *str)
97
{
98
  DBUG_ASSERT(fixed == 1);
99 100
  String arg_val;
  String *swkb= args[0]->val_str(&arg_val);
101 102
  Geometry_buffer buffer;
  Geometry *geom= NULL;
unknown's avatar
unknown committed
103
  const char *dummy;
104

105 106
  if ((null_value=
       (args[0]->null_value ||
107
	!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
108 109 110
    return 0;

  str->length(0);
111
  if ((null_value= geom->as_wkt(str, &dummy)))
112 113 114 115 116
    return 0;

  return str;
}

unknown's avatar
unknown committed
117

118
void Item_func_as_wkt::fix_length_and_dec()
119 120
{
  max_length=MAX_BLOB_WIDTH;
121
  maybe_null= 1;
122 123
}

unknown's avatar
unknown committed
124

125 126
String *Item_func_as_wkb::val_str(String *str)
{
127
  DBUG_ASSERT(fixed == 1);
128 129
  String arg_val;
  String *swkb= args[0]->val_str(&arg_val);
130
  Geometry_buffer buffer;
131

132 133
  if ((null_value=
       (args[0]->null_value ||
134
	!(Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
135 136 137 138 139 140 141
    return 0;

  str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
	    &my_charset_bin);
  return str;
}

unknown's avatar
unknown committed
142

143 144
String *Item_func_geometry_type::val_str(String *str)
{
145
  DBUG_ASSERT(fixed == 1);
146
  String *swkb= args[0]->val_str(str);
147 148
  Geometry_buffer buffer;
  Geometry *geom= NULL;
149

150 151
  if ((null_value=
       (args[0]->null_value ||
152
	!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
153
    return 0;
unknown's avatar
unknown committed
154
  /* String will not move */
155 156 157
  str->copy(geom->get_class_info()->m_name.str,
	    geom->get_class_info()->m_name.length,
	    default_charset());
158 159 160 161
  return str;
}


162
Field::geometry_type Item_func_envelope::get_geometry_type() const
163
{
164
  return Field::GEOM_POLYGON;
165 166 167
}


168 169
String *Item_func_envelope::val_str(String *str)
{
170
  DBUG_ASSERT(fixed == 1);
171 172
  String arg_val;
  String *swkb= args[0]->val_str(&arg_val);
173 174
  Geometry_buffer buffer;
  Geometry *geom= NULL;
unknown's avatar
unknown committed
175
  uint32 srid;
176
  
177 178
  if ((null_value=
       args[0]->null_value ||
179
       !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
180 181
    return 0;
  
unknown's avatar
unknown committed
182
  srid= uint4korr(swkb->ptr());
183
  str->set_charset(&my_charset_bin);
184 185 186 187
  str->length(0);
  if (str->reserve(SRID_SIZE, 512))
    return 0;
  str->q_append(srid);
188
  return (null_value= geom->envelope(str)) ? 0 : str;
189 190 191
}


192
Field::geometry_type Item_func_centroid::get_geometry_type() const
193
{
194
  return Field::GEOM_POINT;
195 196 197
}


198 199
String *Item_func_centroid::val_str(String *str)
{
200
  DBUG_ASSERT(fixed == 1);
201 202
  String arg_val;
  String *swkb= args[0]->val_str(&arg_val);
203 204
  Geometry_buffer buffer;
  Geometry *geom= NULL;
unknown's avatar
unknown committed
205
  uint32 srid;
206 207

  if ((null_value= args[0]->null_value ||
208
       !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
209 210
    return 0;

211
  str->set_charset(&my_charset_bin);
212 213 214
  if (str->reserve(SRID_SIZE, 512))
    return 0;
  str->length(0);
unknown's avatar
unknown committed
215
  srid= uint4korr(swkb->ptr());
216 217
  str->q_append(srid);

218
  return (null_value= test(geom->centroid(str))) ? 0 : str;
219 220 221 222 223 224 225 226 227
}


/*
  Spatial decomposition functions
*/

String *Item_func_spatial_decomp::val_str(String *str)
{
228
  DBUG_ASSERT(fixed == 1);
229 230
  String arg_val;
  String *swkb= args[0]->val_str(&arg_val);
231 232
  Geometry_buffer buffer;
  Geometry *geom= NULL;
unknown's avatar
unknown committed
233
  uint32 srid;
234

235 236
  if ((null_value=
       (args[0]->null_value ||
237
	!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
238 239
    return 0;

unknown's avatar
unknown committed
240
  srid= uint4korr(swkb->ptr());
241
  str->set_charset(&my_charset_bin);
242
  if (str->reserve(SRID_SIZE, 512))
unknown's avatar
unknown committed
243
    goto err;
244 245
  str->length(0);
  str->q_append(srid);
unknown's avatar
unknown committed
246
  switch (decomp_func) {
247
    case SP_STARTPOINT:
248
      if (geom->start_point(str))
unknown's avatar
unknown committed
249
        goto err;
250 251 252
      break;

    case SP_ENDPOINT:
253
      if (geom->end_point(str))
unknown's avatar
unknown committed
254
        goto err;
255 256 257
      break;

    case SP_EXTERIORRING:
258
      if (geom->exterior_ring(str))
unknown's avatar
unknown committed
259
        goto err;
260 261 262
      break;

    default:
unknown's avatar
unknown committed
263
      goto err;
264
  }
unknown's avatar
unknown committed
265
  return str;
266

unknown's avatar
unknown committed
267 268 269
err:
  null_value= 1;
  return 0;
270 271 272 273 274
}


String *Item_func_spatial_decomp_n::val_str(String *str)
{
275
  DBUG_ASSERT(fixed == 1);
276 277 278
  String arg_val;
  String *swkb= args[0]->val_str(&arg_val);
  long n= (long) args[1]->val_int();
279 280
  Geometry_buffer buffer;
  Geometry *geom= NULL;
unknown's avatar
unknown committed
281
  uint32 srid;
282

283 284
  if ((null_value=
       (args[0]->null_value || args[1]->null_value ||
285
	!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
286 287
    return 0;

288
  str->set_charset(&my_charset_bin);
289
  if (str->reserve(SRID_SIZE, 512))
unknown's avatar
unknown committed
290 291
    goto err;
  srid= uint4korr(swkb->ptr());
292 293
  str->length(0);
  str->q_append(srid);
unknown's avatar
unknown committed
294
  switch (decomp_func_n)
295 296
  {
    case SP_POINTN:
297
      if (geom->point_n(n,str))
unknown's avatar
unknown committed
298
        goto err;
299 300 301
      break;

    case SP_GEOMETRYN:
302
      if (geom->geometry_n(n,str))
unknown's avatar
unknown committed
303
        goto err;
304 305 306
      break;

    case SP_INTERIORRINGN:
307
      if (geom->interior_ring_n(n,str))
unknown's avatar
unknown committed
308
        goto err;
309 310 311
      break;

    default:
unknown's avatar
unknown committed
312
      goto err;
313
  }
unknown's avatar
unknown committed
314
  return str;
315

unknown's avatar
unknown committed
316 317 318
err:
  null_value=1;
  return 0;
319 320 321 322
}


/*
unknown's avatar
unknown committed
323
  Functions to concatenate various spatial objects
324 325 326 327
*/


/*
unknown's avatar
unknown committed
328
*  Concatenate doubles into Point
329 330 331
*/


332
Field::geometry_type Item_func_point::get_geometry_type() const
333
{
334
  return Field::GEOM_POINT;
335 336 337
}


338 339
String *Item_func_point::val_str(String *str)
{
340
  DBUG_ASSERT(fixed == 1);
341 342
  double x= args[0]->val_real();
  double y= args[1]->val_real();
343

unknown's avatar
unknown committed
344 345 346
  if ((null_value= (args[0]->null_value ||
		    args[1]->null_value ||
		    str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
347 348
    return 0;

349
  str->set_charset(&my_charset_bin);
350
  str->length(0);
351 352
  str->q_append((char)Geometry::wkb_ndr);
  str->q_append((uint32)Geometry::wkb_point);
353 354 355 356 357 358 359
  str->q_append(x);
  str->q_append(y);
  return str;
}


/*
unknown's avatar
unknown committed
360
  Concatenates various items into various collections
361 362 363 364 365 366 367 368 369 370
  with checkings for valid wkb type of items.
  For example, MultiPoint can be a collection of Points only.
  coll_type contains wkb type of target collection.
  item_type contains a valid wkb type of items.
  In the case when coll_type is wkbGeometryCollection,
  we do not check wkb type of items, any is valid.
*/

String *Item_func_spatial_collection::val_str(String *str)
{
371
  DBUG_ASSERT(fixed == 1);
372 373 374
  String arg_value;
  uint i;

375
  str->set_charset(&my_charset_bin);
376 377
  str->length(0);
  if (str->reserve(1 + 4 + 4, 512))
unknown's avatar
unknown committed
378
    goto err;
379

380
  str->q_append((char) Geometry::wkb_ndr);
381 382 383 384 385 386
  str->q_append((uint32) coll_type);
  str->q_append((uint32) arg_count);

  for (i= 0; i < arg_count; ++i)
  {
    String *res= args[i]->val_str(&arg_value);
387 388
    uint32 len;
    if (args[i]->null_value || ((len= res->length()) < WKB_HEADER_SIZE))
unknown's avatar
unknown committed
389
      goto err;
390

391
    if (coll_type == Geometry::wkb_geometrycollection)
392 393
    {
      /*
unknown's avatar
unknown committed
394 395
	In the case of GeometryCollection we don't need any checkings
	for item types, so just copy them into target collection
396
      */
397
      if (str->append(res->ptr(), len, (uint32) 512))
unknown's avatar
unknown committed
398
        goto err;
399 400 401 402 403 404 405
    }
    else
    {
      enum Geometry::wkbType wkb_type;
      const char *data= res->ptr() + 1;

      /*
unknown's avatar
unknown committed
406
	In the case of named collection we must check that items
unknown's avatar
unknown committed
407
	are of specific type, let's do this checking now
408 409 410 411 412 413
      */

      wkb_type= (Geometry::wkbType) uint4korr(data);
      data+= 4;
      len-= 5;
      if (wkb_type != item_type)
unknown's avatar
unknown committed
414
        goto err;
415 416

      switch (coll_type) {
417 418 419
      case Geometry::wkb_multipoint:
      case Geometry::wkb_multilinestring:
      case Geometry::wkb_multipolygon:
unknown's avatar
unknown committed
420 421 422
	if (len < WKB_HEADER_SIZE ||
	    str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
	  goto err;
423 424
	break;

425
      case Geometry::wkb_linestring:
unknown's avatar
unknown committed
426 427
	if (str->append(data, POINT_DATA_SIZE, 512))
	  goto err;
428
	break;
429
      case Geometry::wkb_polygon:
430 431 432
      {
	uint32 n_points;
	double x1, y1, x2, y2;
unknown's avatar
unknown committed
433
	const char *org_data= data;
434 435

	if (len < 4 + 2 * POINT_DATA_SIZE)
unknown's avatar
unknown committed
436
	  goto err;
437 438 439 440

	n_points= uint4korr(data);
	data+= 4;
	float8get(x1, data);
unknown's avatar
unknown committed
441
	data+= SIZEOF_STORED_DOUBLE;
442
	float8get(y1, data);
unknown's avatar
unknown committed
443
	data+= SIZEOF_STORED_DOUBLE;
444 445 446 447

	data+= (n_points - 2) * POINT_DATA_SIZE;

	float8get(x2, data);
unknown's avatar
unknown committed
448
	float8get(y2, data + SIZEOF_STORED_DOUBLE);
449

unknown's avatar
unknown committed
450 451 452
	if ((x1 != x2) || (y1 != y2) ||
	    str->append(org_data, len, 512))
	  goto err;
453 454 455 456
      }
      break;

      default:
unknown's avatar
unknown committed
457
	goto err;
458 459 460 461
      }
    }
  }
  if (str->length() > current_thd->variables.max_allowed_packet)
462 463 464
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
465 466
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
unknown's avatar
unknown committed
467
    goto err;
468
  }
469 470

  null_value = 0;
unknown's avatar
unknown committed
471
  return str;
472

unknown's avatar
unknown committed
473 474 475
err:
  null_value= 1;
  return 0;
476 477
}

unknown's avatar
unknown committed
478

479 480 481 482 483 484
/*
  Functions for spatial relations
*/

longlong Item_func_spatial_rel::val_int()
{
485
  DBUG_ASSERT(fixed == 1);
486 487
  String *res1= args[0]->val_str(&tmp_value1);
  String *res2= args[1]->val_str(&tmp_value2);
488 489
  Geometry_buffer buffer1, buffer2;
  Geometry *g1, *g2;
490
  MBR mbr1, mbr2;
unknown's avatar
unknown committed
491
  const char *dummy;
492

493 494 495
  if ((null_value=
       (args[0]->null_value ||
	args[1]->null_value ||
496 497
	!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
	!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
498 499
	g1->get_mbr(&mbr1, &dummy) ||
	g2->get_mbr(&mbr2, &dummy))))
500 501
   return 0;

unknown's avatar
unknown committed
502
  switch (spatial_rel) {
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
    case SP_CONTAINS_FUNC:
      return mbr1.contains(&mbr2);
    case SP_WITHIN_FUNC:
      return mbr1.within(&mbr2);
    case SP_EQUALS_FUNC:
      return mbr1.equals(&mbr2);
    case SP_DISJOINT_FUNC:
      return mbr1.disjoint(&mbr2);
    case SP_INTERSECTS_FUNC:
      return mbr1.intersects(&mbr2);
    case SP_TOUCHES_FUNC:
      return mbr1.touches(&mbr2);
    case SP_OVERLAPS_FUNC:
      return mbr1.overlaps(&mbr2);
    case SP_CROSSES_FUNC:
      return 0;
    default:
      break;
  }

  null_value=1;
  return 0;
}

unknown's avatar
unknown committed
527

528 529
longlong Item_func_isempty::val_int()
{
530
  DBUG_ASSERT(fixed == 1);
531 532 533 534 535 536 537
  String tmp;
  String *swkb= args[0]->val_str(&tmp);
  Geometry_buffer buffer;
  
  null_value= args[0]->null_value ||
              !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
  return null_value ? 1 : 0;
538 539
}

unknown's avatar
unknown committed
540

541 542
longlong Item_func_issimple::val_int()
{
543
  DBUG_ASSERT(fixed == 1);
544
  String tmp;
545 546 547 548 549
  String *swkb= args[0]->val_str(&tmp);
  Geometry_buffer buffer;
  
  null_value= args[0]->null_value ||
              !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
550 551 552 553
  /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
  return 0;
}

unknown's avatar
unknown committed
554

555 556
longlong Item_func_isclosed::val_int()
{
557
  DBUG_ASSERT(fixed == 1);
558 559
  String tmp;
  String *swkb= args[0]->val_str(&tmp);
560 561
  Geometry_buffer buffer;
  Geometry *geom;
unknown's avatar
unknown committed
562
  int isclosed= 0;				// In case of error
563 564 565

  null_value= (!swkb || 
	       args[0]->null_value ||
566
	       !(geom=
567
		 Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
568
	       geom->is_closed(&isclosed));
569 570 571 572 573 574 575 576

  return (longlong) isclosed;
}

/*
  Numerical functions
*/

unknown's avatar
unknown committed
577

578 579
longlong Item_func_dimension::val_int()
{
580
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
581
  uint32 dim= 0;				// In case of error
582
  String *swkb= args[0]->val_str(&value);
583 584
  Geometry_buffer buffer;
  Geometry *geom;
unknown's avatar
unknown committed
585
  const char *dummy;
586 587 588

  null_value= (!swkb || 
	       args[0]->null_value ||
589
	       !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
590
	       geom->dimension(&dim, &dummy));
591 592 593
  return (longlong) dim;
}

unknown's avatar
unknown committed
594

595 596
longlong Item_func_numinteriorring::val_int()
{
597
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
598
  uint32 num= 0;				// In case of error
599
  String *swkb= args[0]->val_str(&value);
600 601
  Geometry_buffer buffer;
  Geometry *geom;
602 603

  null_value= (!swkb || 
604 605
	       !(geom= Geometry::construct(&buffer,
                                           swkb->ptr(), swkb->length())) ||
606
	       geom->num_interior_ring(&num));
607 608 609
  return (longlong) num;
}

unknown's avatar
unknown committed
610

611 612
longlong Item_func_numgeometries::val_int()
{
613
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
614
  uint32 num= 0;				// In case of errors
615
  String *swkb= args[0]->val_str(&value);
616 617
  Geometry_buffer buffer;
  Geometry *geom;
618 619

  null_value= (!swkb ||
620 621
	       !(geom= Geometry::construct(&buffer,
                                           swkb->ptr(), swkb->length())) ||
622
	       geom->num_geometries(&num));
623 624 625
  return (longlong) num;
}

unknown's avatar
unknown committed
626

627 628
longlong Item_func_numpoints::val_int()
{
629
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
630
  uint32 num= 0;				// In case of errors
631
  String *swkb= args[0]->val_str(&value);
632 633
  Geometry_buffer buffer;
  Geometry *geom;
634 635 636

  null_value= (!swkb ||
	       args[0]->null_value ||
637 638
	       !(geom= Geometry::construct(&buffer,
                                           swkb->ptr(), swkb->length())) ||
639
	       geom->num_points(&num));
640 641 642
  return (longlong) num;
}

unknown's avatar
unknown committed
643

644
double Item_func_x::val_real()
645
{
646
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
647
  double res= 0.0;				// In case of errors
648
  String *swkb= args[0]->val_str(&value);
649 650
  Geometry_buffer buffer;
  Geometry *geom;
651 652

  null_value= (!swkb ||
653 654
	       !(geom= Geometry::construct(&buffer,
                                           swkb->ptr(), swkb->length())) ||
655
	       geom->get_x(&res));
656 657 658
  return res;
}

unknown's avatar
unknown committed
659

660
double Item_func_y::val_real()
661
{
662
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
663
  double res= 0;				// In case of errors
664
  String *swkb= args[0]->val_str(&value);
665 666
  Geometry_buffer buffer;
  Geometry *geom;
667 668

  null_value= (!swkb ||
669 670
	       !(geom= Geometry::construct(&buffer,
                                           swkb->ptr(), swkb->length())) ||
671
	       geom->get_y(&res));
672 673 674
  return res;
}

unknown's avatar
unknown committed
675

676
double Item_func_area::val_real()
677
{
678
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
679
  double res= 0;				// In case of errors
680
  String *swkb= args[0]->val_str(&value);
681 682
  Geometry_buffer buffer;
  Geometry *geom;
unknown's avatar
unknown committed
683
  const char *dummy;
684 685

  null_value= (!swkb ||
686 687
	       !(geom= Geometry::construct(&buffer,
                                           swkb->ptr(), swkb->length())) ||
688
	       geom->area(&res, &dummy));
689 690 691
  return res;
}

692
double Item_func_glength::val_real()
693
{
694
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
695
  double res= 0;				// In case of errors
696
  String *swkb= args[0]->val_str(&value);
697 698
  Geometry_buffer buffer;
  Geometry *geom;
699 700

  null_value= (!swkb || 
701
	       !(geom= Geometry::construct(&buffer,
702 703 704
                                           swkb->ptr(),
                                           swkb->length())) ||
	       geom->geom_length(&res));
705 706 707 708 709
  return res;
}

longlong Item_func_srid::val_int()
{
710
  DBUG_ASSERT(fixed == 1);
711
  String *swkb= args[0]->val_str(&value);
712
  Geometry_buffer buffer;
713
  
unknown's avatar
unknown committed
714
  null_value= (!swkb || 
715 716
	       !Geometry::construct(&buffer,
                                    swkb->ptr(), swkb->length()));
unknown's avatar
unknown committed
717 718 719 720
  if (null_value)
    return 0;

  return (longlong) (uint4korr(swkb->ptr()));
721
}
unknown's avatar
unknown committed
722 723

#endif /*HAVE_SPATIAL*/