2016-06-14 13:55:28 +02:00
|
|
|
/* Copyright (c) 2003, 2016, Oracle and/or its affiliates.
|
|
|
|
Copyright (c) 2011, 2016, MariaDB
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
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
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
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
|
2019-05-11 20:29:06 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
@file
|
|
|
|
|
|
|
|
@brief
|
|
|
|
This file defines all spatial functions
|
|
|
|
*/
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2005-05-26 12:09:14 +02:00
|
|
|
#ifdef USE_PRAGMA_IMPLEMENTATION
|
2003-05-30 12:22:34 +02:00
|
|
|
#pragma implementation // gcc: Class implementation
|
|
|
|
#endif
|
|
|
|
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "sql_priv.h"
|
|
|
|
/*
|
|
|
|
It is necessary to include set_var.h instead of item.h because there
|
|
|
|
are dependencies on include order for set_var.h and item.h. This
|
|
|
|
will be resolved later.
|
|
|
|
*/
|
|
|
|
#include "sql_class.h" // THD, set_var.h: THD
|
|
|
|
#include "set_var.h"
|
2004-01-23 16:54:22 +01:00
|
|
|
#ifdef HAVE_SPATIAL
|
2003-05-30 12:22:34 +02:00
|
|
|
#include <m_ctype.h>
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
|
2006-07-04 09:56:53 +02:00
|
|
|
Field *Item_geometry_func::tmp_table_field(TABLE *t_arg)
|
|
|
|
{
|
2006-08-18 19:29:35 +02:00
|
|
|
Field *result;
|
|
|
|
if ((result= new Field_geom(max_length, maybe_null, name, t_arg->s,
|
2007-10-12 12:33:26 +02:00
|
|
|
get_geometry_type())))
|
2006-08-18 19:29:35 +02:00
|
|
|
result->init(t_arg);
|
|
|
|
return result;
|
2006-07-04 09:56:53 +02:00
|
|
|
}
|
|
|
|
|
2004-09-22 19:36:53 +02:00
|
|
|
void Item_geometry_func::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
collation.set(&my_charset_bin);
|
|
|
|
decimals=0;
|
2010-07-23 22:13:36 +02:00
|
|
|
max_length= (uint32) 4294967295U;
|
2013-09-25 14:30:13 +02:00
|
|
|
maybe_null= 1;
|
2004-09-22 19:36:53 +02:00
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
String *Item_func_geometry_from_text::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
String *wkt= args[0]->val_str_ascii(&arg_val);
|
2004-03-15 13:32:53 +01:00
|
|
|
|
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Gis_read_stream trs(wkt->charset(), wkt->ptr(), wkt->length());
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 srid= 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
if ((arg_count == 2) && !args[1]->null_value)
|
2003-06-04 05:59:32 +02:00
|
|
|
srid= (uint32)args[1]->val_int();
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
if (str->reserve(SRID_SIZE, 512))
|
|
|
|
return 0;
|
|
|
|
str->length(0);
|
|
|
|
str->q_append(srid);
|
2007-03-02 12:09:44 +01:00
|
|
|
if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
|
|
|
|
return 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_geometry_from_wkb::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
2009-04-28 11:47:26 +02:00
|
|
|
String *wkb;
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 srid= 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2009-04-28 11:47:26 +02:00
|
|
|
if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY)
|
|
|
|
{
|
2009-10-21 10:43:45 +02:00
|
|
|
String *str_ret= args[0]->val_str(str);
|
|
|
|
null_value= args[0]->null_value;
|
|
|
|
return str_ret;
|
2009-04-28 11:47:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
wkb= args[0]->val_str(&arg_val);
|
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
if ((arg_count == 2) && !args[1]->null_value)
|
2003-06-04 05:59:32 +02:00
|
|
|
srid= (uint32)args[1]->val_int();
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
if (str->reserve(SRID_SIZE, 512))
|
2009-10-21 10:43:45 +02:00
|
|
|
{
|
|
|
|
null_value= TRUE; /* purecov: inspected */
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
}
|
2003-05-30 12:22:34 +02:00
|
|
|
str->length(0);
|
|
|
|
str->q_append(srid);
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
2009-04-28 11:47:26 +02:00
|
|
|
(args[0]->null_value ||
|
|
|
|
!Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length(), str))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
String *Item_func_as_wkt::val_str_ascii(String *str)
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
|
|
|
String *swkb= args[0]->val_str(&arg_val);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom= NULL;
|
2004-03-04 07:50:37 +01:00
|
|
|
const char *dummy;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
str->length(0);
|
2012-08-09 18:25:47 +02:00
|
|
|
str->set_charset(&my_charset_latin1);
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value= geom->as_wkt(str, &dummy)))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-06-20 11:53:37 +02:00
|
|
|
void Item_func_as_wkt::fix_length_and_dec()
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
2003-05-30 12:22:34 +02:00
|
|
|
max_length=MAX_BLOB_WIDTH;
|
2013-09-25 14:30:13 +02:00
|
|
|
maybe_null= 1;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
String *Item_func_as_wkb::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
|
|
|
String *swkb= args[0]->val_str(&arg_val);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
|
|
|
|
&my_charset_bin);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
String *Item_func_geometry_type::val_str_ascii(String *str)
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(str);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom= NULL;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
2004-03-04 07:50:37 +01:00
|
|
|
/* String will not move */
|
2004-10-22 17:32:02 +02:00
|
|
|
str->copy(geom->get_class_info()->m_name.str,
|
|
|
|
geom->get_class_info()->m_name.length,
|
2012-08-09 18:25:47 +02:00
|
|
|
&my_charset_latin1);
|
2003-05-30 12:22:34 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-04 09:01:28 +02:00
|
|
|
Field::geometry_type Item_func_envelope::get_geometry_type() const
|
2006-07-04 09:56:53 +02:00
|
|
|
{
|
2007-10-04 09:01:28 +02:00
|
|
|
return Field::GEOM_POLYGON;
|
2006-07-04 09:56:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
String *Item_func_envelope::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
|
|
|
String *swkb= args[0]->val_str(&arg_val);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom= NULL;
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 srid;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
srid= uint4korr(swkb->ptr());
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
str->length(0);
|
|
|
|
if (str->reserve(SRID_SIZE, 512))
|
|
|
|
return 0;
|
|
|
|
str->q_append(srid);
|
2004-03-12 09:04:00 +01:00
|
|
|
return (null_value= geom->envelope(str)) ? 0 : str;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-04 09:01:28 +02:00
|
|
|
Field::geometry_type Item_func_centroid::get_geometry_type() const
|
2006-07-04 09:56:53 +02:00
|
|
|
{
|
2007-10-04 09:01:28 +02:00
|
|
|
return Field::GEOM_POINT;
|
2006-07-04 09:56:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
String *Item_func_centroid::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
|
|
|
String *swkb= args[0]->val_str(&arg_val);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom= NULL;
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 srid;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
if ((null_value= args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
if (str->reserve(SRID_SIZE, 512))
|
|
|
|
return 0;
|
|
|
|
str->length(0);
|
2004-03-04 07:50:37 +01:00
|
|
|
srid= uint4korr(swkb->ptr());
|
2003-05-30 12:22:34 +02:00
|
|
|
str->q_append(srid);
|
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
return (null_value= test(geom->centroid(str))) ? 0 : str;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Spatial decomposition functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
String *Item_func_spatial_decomp::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
|
|
|
String *swkb= args[0]->val_str(&arg_val);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom= NULL;
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 srid;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
srid= uint4korr(swkb->ptr());
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
if (str->reserve(SRID_SIZE, 512))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
str->length(0);
|
|
|
|
str->q_append(srid);
|
2004-03-04 07:50:37 +01:00
|
|
|
switch (decomp_func) {
|
2003-05-30 12:22:34 +02:00
|
|
|
case SP_STARTPOINT:
|
2004-03-12 09:04:00 +01:00
|
|
|
if (geom->start_point(str))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SP_ENDPOINT:
|
2004-03-12 09:04:00 +01:00
|
|
|
if (geom->end_point(str))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SP_EXTERIORRING:
|
2004-03-12 09:04:00 +01:00
|
|
|
if (geom->exterior_ring(str))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
2004-03-04 07:50:37 +01:00
|
|
|
return str;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
err:
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_spatial_decomp_n::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_val;
|
|
|
|
String *swkb= args[0]->val_str(&arg_val);
|
|
|
|
long n= (long) args[1]->val_int();
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom= NULL;
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 srid;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value || args[1]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
if (str->reserve(SRID_SIZE, 512))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
|
|
|
srid= uint4korr(swkb->ptr());
|
2003-05-30 12:22:34 +02:00
|
|
|
str->length(0);
|
|
|
|
str->q_append(srid);
|
2004-03-04 07:50:37 +01:00
|
|
|
switch (decomp_func_n)
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
|
|
|
case SP_POINTN:
|
2004-03-12 09:04:00 +01:00
|
|
|
if (geom->point_n(n,str))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SP_GEOMETRYN:
|
2004-03-12 09:04:00 +01:00
|
|
|
if (geom->geometry_n(n,str))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SP_INTERIORRINGN:
|
2004-03-12 09:04:00 +01:00
|
|
|
if (geom->interior_ring_n(n,str))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
2004-03-04 07:50:37 +01:00
|
|
|
return str;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
err:
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2004-07-02 23:22:46 +02:00
|
|
|
Functions to concatenate various spatial objects
|
2003-05-30 12:22:34 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2004-07-02 23:22:46 +02:00
|
|
|
* Concatenate doubles into Point
|
2003-05-30 12:22:34 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2007-10-04 09:01:28 +02:00
|
|
|
Field::geometry_type Item_func_point::get_geometry_type() const
|
2006-07-04 09:56:53 +02:00
|
|
|
{
|
2007-10-04 09:01:28 +02:00
|
|
|
return Field::GEOM_POINT;
|
2006-07-04 09:56:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
String *Item_func_point::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double x= args[0]->val_real();
|
|
|
|
double y= args[1]->val_real();
|
2009-04-28 11:47:26 +02:00
|
|
|
uint32 srid= 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
if ((null_value= (args[0]->null_value ||
|
2011-05-04 20:20:17 +02:00
|
|
|
args[1]->null_value ||
|
|
|
|
str->realloc(4/*SRID*/ + 1 + 4 + SIZEOF_STORED_DOUBLE * 2))))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
str->length(0);
|
2009-04-28 11:47:26 +02:00
|
|
|
str->q_append(srid);
|
2004-03-12 09:04:00 +01:00
|
|
|
str->q_append((char)Geometry::wkb_ndr);
|
|
|
|
str->q_append((uint32)Geometry::wkb_point);
|
2003-05-30 12:22:34 +02:00
|
|
|
str->q_append(x);
|
|
|
|
str->q_append(y);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2004-07-02 23:22:46 +02:00
|
|
|
Concatenates various items into various collections
|
2003-05-30 12:22:34 +02:00
|
|
|
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)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String arg_value;
|
|
|
|
uint i;
|
2009-04-28 11:47:26 +02:00
|
|
|
uint32 srid= 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-09-07 13:44:25 +02:00
|
|
|
str->set_charset(&my_charset_bin);
|
2003-05-30 12:22:34 +02:00
|
|
|
str->length(0);
|
2009-04-28 11:47:26 +02:00
|
|
|
if (str->reserve(4/*SRID*/ + 1 + 4 + 4, 512))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2009-04-28 11:47:26 +02:00
|
|
|
str->q_append(srid);
|
2004-03-12 09:04:00 +01:00
|
|
|
str->q_append((char) Geometry::wkb_ndr);
|
2003-05-30 12:22:34 +02:00
|
|
|
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);
|
2007-02-21 11:45:19 +01:00
|
|
|
uint32 len;
|
|
|
|
if (args[i]->null_value || ((len= res->length()) < WKB_HEADER_SIZE))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if (coll_type == Geometry::wkb_geometrycollection)
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
|
|
|
/*
|
2004-03-04 07:50:37 +01:00
|
|
|
In the case of GeometryCollection we don't need any checkings
|
|
|
|
for item types, so just copy them into target collection
|
2003-05-30 12:22:34 +02:00
|
|
|
*/
|
2009-04-28 11:47:26 +02:00
|
|
|
if (str->append(res->ptr() + 4/*SRID*/, len - 4/*SRID*/, (uint32) 512))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
enum Geometry::wkbType wkb_type;
|
2009-06-17 16:58:33 +02:00
|
|
|
const uint data_offset= 4/*SRID*/ + 1;
|
|
|
|
if (res->length() < data_offset + sizeof(uint32))
|
|
|
|
goto err;
|
|
|
|
const char *data= res->ptr() + data_offset;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
/*
|
2004-07-02 23:22:46 +02:00
|
|
|
In the case of named collection we must check that items
|
2004-03-04 07:50:37 +01:00
|
|
|
are of specific type, let's do this checking now
|
2003-05-30 12:22:34 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
wkb_type= (Geometry::wkbType) uint4korr(data);
|
|
|
|
data+= 4;
|
2009-04-28 11:47:26 +02:00
|
|
|
len-= 5 + 4/*SRID*/;
|
2003-05-30 12:22:34 +02:00
|
|
|
if (wkb_type != item_type)
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
switch (coll_type) {
|
2004-03-12 09:04:00 +01:00
|
|
|
case Geometry::wkb_multipoint:
|
|
|
|
case Geometry::wkb_multilinestring:
|
|
|
|
case Geometry::wkb_multipolygon:
|
2004-03-04 07:50:37 +01:00
|
|
|
if (len < WKB_HEADER_SIZE ||
|
|
|
|
str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
|
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
case Geometry::wkb_linestring:
|
2009-06-17 16:58:33 +02:00
|
|
|
if (len < POINT_DATA_SIZE || str->append(data, POINT_DATA_SIZE, 512))
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
break;
|
2004-03-12 09:04:00 +01:00
|
|
|
case Geometry::wkb_polygon:
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
|
|
|
uint32 n_points;
|
|
|
|
double x1, y1, x2, y2;
|
2004-03-04 07:50:37 +01:00
|
|
|
const char *org_data= data;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2009-06-17 16:58:33 +02:00
|
|
|
if (len < 4)
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
n_points= uint4korr(data);
|
|
|
|
data+= 4;
|
2009-06-17 16:58:33 +02:00
|
|
|
|
|
|
|
if (n_points < 2 || len < 4 + n_points * POINT_DATA_SIZE)
|
|
|
|
goto err;
|
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
float8get(x1, data);
|
2004-03-04 07:50:37 +01:00
|
|
|
data+= SIZEOF_STORED_DOUBLE;
|
2003-05-30 12:22:34 +02:00
|
|
|
float8get(y1, data);
|
2004-03-04 07:50:37 +01:00
|
|
|
data+= SIZEOF_STORED_DOUBLE;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
data+= (n_points - 2) * POINT_DATA_SIZE;
|
|
|
|
|
|
|
|
float8get(x2, data);
|
2004-03-04 07:50:37 +01:00
|
|
|
float8get(y2, data + SIZEOF_STORED_DOUBLE);
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
if ((x1 != x2) || (y1 != y2) ||
|
|
|
|
str->append(org_data, len, 512))
|
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (str->length() > current_thd->variables.max_allowed_packet)
|
2004-06-29 16:55:13 +02:00
|
|
|
{
|
|
|
|
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
|
2004-07-21 18:27:45 +02:00
|
|
|
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
|
|
|
|
func_name(), current_thd->variables.max_allowed_packet);
|
2004-03-04 07:50:37 +01:00
|
|
|
goto err;
|
2004-06-29 16:55:13 +02:00
|
|
|
}
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value = 0;
|
2004-03-04 07:50:37 +01:00
|
|
|
return str;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
err:
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
/*
|
|
|
|
Functions for spatial relations
|
|
|
|
*/
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
const char *Item_func_spatial_mbr_rel::func_name() const
|
|
|
|
{
|
|
|
|
switch (spatial_rel) {
|
|
|
|
case SP_CONTAINS_FUNC:
|
|
|
|
return "mbrcontains";
|
|
|
|
case SP_WITHIN_FUNC:
|
|
|
|
return "mbrwithin";
|
|
|
|
case SP_EQUALS_FUNC:
|
|
|
|
return "mbrequals";
|
|
|
|
case SP_DISJOINT_FUNC:
|
|
|
|
return "mbrdisjoint";
|
|
|
|
case SP_INTERSECTS_FUNC:
|
|
|
|
return "mbrintersects";
|
|
|
|
case SP_TOUCHES_FUNC:
|
|
|
|
return "mbrtouches";
|
|
|
|
case SP_CROSSES_FUNC:
|
|
|
|
return "mbrcrosses";
|
|
|
|
case SP_OVERLAPS_FUNC:
|
|
|
|
return "mbroverlaps";
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0); // Should never happened
|
|
|
|
return "mbrsp_unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_spatial_mbr_rel::val_int()
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2009-11-17 15:06:46 +01:00
|
|
|
String *res1= args[0]->val_str(&cmp.value1);
|
|
|
|
String *res2= args[1]->val_str(&cmp.value2);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer1, buffer2;
|
|
|
|
Geometry *g1, *g2;
|
2003-05-30 12:22:34 +02:00
|
|
|
MBR mbr1, mbr2;
|
2004-03-04 07:50:37 +01:00
|
|
|
const char *dummy;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
2004-03-12 09:04:00 +01:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value ||
|
|
|
|
args[1]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
|
|
|
|
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
|
2013-03-26 18:47:06 +01:00
|
|
|
g1->get_mbr(&mbr1, &dummy) || !mbr1.valid() ||
|
|
|
|
g2->get_mbr(&mbr2, &dummy) || !mbr2.valid())))
|
2003-05-30 12:22:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
switch (spatial_rel) {
|
2003-05-30 12:22:34 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
Item_func_spatial_rel::Item_func_spatial_rel(Item *a,Item *b,
|
|
|
|
enum Functype sp_rel) :
|
|
|
|
Item_bool_func2(a,b), collector()
|
|
|
|
{
|
|
|
|
spatial_rel = sp_rel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Item_func_spatial_rel::~Item_func_spatial_rel()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *Item_func_spatial_rel::func_name() const
|
|
|
|
{
|
|
|
|
switch (spatial_rel) {
|
|
|
|
case SP_CONTAINS_FUNC:
|
|
|
|
return "st_contains";
|
|
|
|
case SP_WITHIN_FUNC:
|
|
|
|
return "st_within";
|
|
|
|
case SP_EQUALS_FUNC:
|
|
|
|
return "st_equals";
|
|
|
|
case SP_DISJOINT_FUNC:
|
|
|
|
return "st_disjoint";
|
|
|
|
case SP_INTERSECTS_FUNC:
|
|
|
|
return "st_intersects";
|
|
|
|
case SP_TOUCHES_FUNC:
|
|
|
|
return "st_touches";
|
|
|
|
case SP_CROSSES_FUNC:
|
|
|
|
return "st_crosses";
|
|
|
|
case SP_OVERLAPS_FUNC:
|
|
|
|
return "st_overlaps";
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0); // Should never happened
|
|
|
|
return "sp_unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static double count_edge_t(const Gcalc_heap::Info *ea,
|
|
|
|
const Gcalc_heap::Info *eb,
|
|
|
|
const Gcalc_heap::Info *v,
|
|
|
|
double &ex, double &ey, double &vx, double &vy,
|
|
|
|
double &e_sqrlen)
|
|
|
|
{
|
2016-02-14 20:57:48 +01:00
|
|
|
ex= eb->node.shape.x - ea->node.shape.x;
|
|
|
|
ey= eb->node.shape.y - ea->node.shape.y;
|
|
|
|
vx= v->node.shape.x - ea->node.shape.x;
|
|
|
|
vy= v->node.shape.y - ea->node.shape.y;
|
2011-05-04 20:20:17 +02:00
|
|
|
e_sqrlen= ex * ex + ey * ey;
|
|
|
|
return (ex * vx + ey * vy) / e_sqrlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static double distance_to_line(double ex, double ey, double vx, double vy,
|
|
|
|
double e_sqrlen)
|
|
|
|
{
|
|
|
|
return fabs(vx * ey - vy * ex) / sqrt(e_sqrlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static double distance_points(const Gcalc_heap::Info *a,
|
|
|
|
const Gcalc_heap::Info *b)
|
|
|
|
{
|
2016-02-14 20:57:48 +01:00
|
|
|
double x= a->node.shape.x - b->node.shape.x;
|
|
|
|
double y= a->node.shape.y - b->node.shape.y;
|
2011-05-04 20:20:17 +02:00
|
|
|
return sqrt(x * x + y * y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define GIS_ZERO 0.00000000001
|
|
|
|
|
|
|
|
longlong Item_func_spatial_rel::val_int()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_spatial_rel::val_int");
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
String *res1;
|
|
|
|
String *res2;
|
|
|
|
Geometry_buffer buffer1, buffer2;
|
|
|
|
Geometry *g1, *g2;
|
|
|
|
int result= 0;
|
|
|
|
int mask= 0;
|
2011-09-22 15:53:36 +02:00
|
|
|
uint shape_a, shape_b;
|
2011-12-08 13:29:45 +01:00
|
|
|
MBR umbr, mbr1, mbr2;
|
|
|
|
const char *c_end;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
res1= args[0]->val_str(&tmp_value1);
|
|
|
|
res2= args[1]->val_str(&tmp_value2);
|
|
|
|
Gcalc_operation_transporter trn(&func, &collector);
|
|
|
|
|
|
|
|
if (func.reserve_op_buffer(1))
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
2011-09-22 15:53:36 +02:00
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value || args[1]->null_value ||
|
|
|
|
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
|
2013-03-22 14:32:27 +01:00
|
|
|
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
|
2013-03-26 18:47:06 +01:00
|
|
|
g1->get_mbr(&mbr1, &c_end) || !mbr1.valid() ||
|
|
|
|
g2->get_mbr(&mbr2, &c_end) || !mbr2.valid())))
|
2011-09-22 15:53:36 +02:00
|
|
|
goto exit;
|
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
umbr= mbr1;
|
|
|
|
umbr.add_mbr(&mbr2);
|
|
|
|
collector.set_extent(umbr.xmin, umbr.xmax, umbr.ymin, umbr.ymax);
|
|
|
|
|
|
|
|
mbr1.buffer(1e-5);
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
switch (spatial_rel) {
|
|
|
|
case SP_CONTAINS_FUNC:
|
2011-12-08 13:29:45 +01:00
|
|
|
if (!mbr1.contains(&mbr2))
|
|
|
|
goto exit;
|
2011-05-04 20:20:17 +02:00
|
|
|
mask= 1;
|
2011-09-22 15:53:36 +02:00
|
|
|
func.add_operation(Gcalc_function::op_difference, 2);
|
|
|
|
/* Mind the g2 goes first. */
|
|
|
|
null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn);
|
2011-05-04 20:20:17 +02:00
|
|
|
break;
|
|
|
|
case SP_WITHIN_FUNC:
|
2011-12-08 13:29:45 +01:00
|
|
|
mbr2.buffer(2e-5);
|
|
|
|
if (!mbr1.within(&mbr2))
|
|
|
|
goto exit;
|
2011-05-04 20:20:17 +02:00
|
|
|
mask= 1;
|
|
|
|
func.add_operation(Gcalc_function::op_difference, 2);
|
2011-09-22 15:53:36 +02:00
|
|
|
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
2011-05-04 20:20:17 +02:00
|
|
|
break;
|
|
|
|
case SP_EQUALS_FUNC:
|
2011-12-08 13:29:45 +01:00
|
|
|
if (!mbr1.contains(&mbr2))
|
|
|
|
goto exit;
|
2011-09-22 15:53:36 +02:00
|
|
|
mask= 1;
|
|
|
|
func.add_operation(Gcalc_function::op_symdifference, 2);
|
|
|
|
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
2011-05-04 20:20:17 +02:00
|
|
|
break;
|
|
|
|
case SP_DISJOINT_FUNC:
|
|
|
|
mask= 1;
|
|
|
|
func.add_operation(Gcalc_function::op_intersection, 2);
|
2011-09-22 15:53:36 +02:00
|
|
|
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
2011-05-04 20:20:17 +02:00
|
|
|
break;
|
|
|
|
case SP_INTERSECTS_FUNC:
|
2011-12-08 13:29:45 +01:00
|
|
|
if (!mbr1.intersects(&mbr2))
|
|
|
|
goto exit;
|
2011-05-04 20:20:17 +02:00
|
|
|
func.add_operation(Gcalc_function::op_intersection, 2);
|
2011-09-22 15:53:36 +02:00
|
|
|
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
2011-05-04 20:20:17 +02:00
|
|
|
break;
|
|
|
|
case SP_OVERLAPS_FUNC:
|
|
|
|
case SP_CROSSES_FUNC:
|
|
|
|
func.add_operation(Gcalc_function::op_intersection, 2);
|
2011-09-22 15:53:36 +02:00
|
|
|
func.add_operation(Gcalc_function::v_find_t |
|
|
|
|
Gcalc_function::op_intersection, 2);
|
|
|
|
shape_a= func.get_next_expression_pos();
|
|
|
|
if ((null_value= g1->store_shapes(&trn)))
|
|
|
|
break;
|
|
|
|
shape_b= func.get_next_expression_pos();
|
|
|
|
if ((null_value= g2->store_shapes(&trn)))
|
|
|
|
break;
|
|
|
|
func.add_operation(Gcalc_function::v_find_t |
|
|
|
|
Gcalc_function::op_intersection, 2);
|
|
|
|
func.add_operation(Gcalc_function::v_find_t |
|
|
|
|
Gcalc_function::op_difference, 2);
|
|
|
|
func.repeat_expression(shape_a);
|
|
|
|
func.repeat_expression(shape_b);
|
|
|
|
func.add_operation(Gcalc_function::v_find_t |
|
|
|
|
Gcalc_function::op_difference, 2);
|
|
|
|
func.repeat_expression(shape_b);
|
|
|
|
func.repeat_expression(shape_a);
|
|
|
|
break;
|
|
|
|
case SP_TOUCHES_FUNC:
|
|
|
|
func.add_operation(Gcalc_function::op_intersection, 2);
|
|
|
|
func.add_operation(Gcalc_function::v_find_f |
|
|
|
|
Gcalc_function::op_not |
|
|
|
|
Gcalc_function::op_intersection, 2);
|
|
|
|
func.add_operation(Gcalc_function::op_internals, 1);
|
|
|
|
shape_a= func.get_next_expression_pos();
|
|
|
|
if ((null_value= g1->store_shapes(&trn)))
|
|
|
|
break;
|
|
|
|
func.add_operation(Gcalc_function::op_internals, 1);
|
|
|
|
shape_b= func.get_next_expression_pos();
|
|
|
|
if ((null_value= g2->store_shapes(&trn)))
|
|
|
|
break;
|
|
|
|
func.add_operation(Gcalc_function::v_find_t |
|
|
|
|
Gcalc_function::op_intersection, 2);
|
|
|
|
func.add_operation(Gcalc_function::op_border, 1);
|
|
|
|
func.repeat_expression(shape_a);
|
|
|
|
func.add_operation(Gcalc_function::op_border, 1);
|
|
|
|
func.repeat_expression(shape_b);
|
2011-05-04 20:20:17 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-22 15:53:36 +02:00
|
|
|
if (null_value)
|
2011-05-04 20:20:17 +02:00
|
|
|
goto exit;
|
|
|
|
|
|
|
|
collector.prepare_operation();
|
|
|
|
scan_it.init(&collector);
|
2011-11-20 09:30:43 +01:00
|
|
|
scan_it.killed= (int *) &(current_thd->killed);
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
if (func.alloc_states())
|
|
|
|
goto exit;
|
|
|
|
|
2011-09-22 15:53:36 +02:00
|
|
|
result= func.check_function(scan_it) ^ mask;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
exit:
|
|
|
|
collector.reset();
|
|
|
|
func.reset();
|
|
|
|
scan_it.reset();
|
|
|
|
DBUG_RETURN(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Item_func_spatial_operation::~Item_func_spatial_operation()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_spatial_operation::val_str(String *str_value)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_spatial_operation::val_str");
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
String *res1= args[0]->val_str(&tmp_value1);
|
|
|
|
String *res2= args[1]->val_str(&tmp_value2);
|
|
|
|
Geometry_buffer buffer1, buffer2;
|
|
|
|
Geometry *g1, *g2;
|
|
|
|
uint32 srid= 0;
|
|
|
|
Gcalc_operation_transporter trn(&func, &collector);
|
2011-12-08 13:29:45 +01:00
|
|
|
MBR mbr1, mbr2;
|
|
|
|
const char *c_end;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
if (func.reserve_op_buffer(1))
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
func.add_operation(spatial_op, 2);
|
|
|
|
|
|
|
|
if ((null_value=
|
|
|
|
(args[0]->null_value || args[1]->null_value ||
|
|
|
|
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
|
2013-03-22 14:32:27 +01:00
|
|
|
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
|
2013-03-26 18:47:06 +01:00
|
|
|
g1->get_mbr(&mbr1, &c_end) || !mbr1.valid() ||
|
|
|
|
g2->get_mbr(&mbr2, &c_end) || !mbr2.valid())))
|
2011-07-04 13:17:34 +02:00
|
|
|
{
|
|
|
|
str_value= 0;
|
2011-05-04 20:20:17 +02:00
|
|
|
goto exit;
|
2011-07-04 13:17:34 +02:00
|
|
|
}
|
2011-05-04 20:20:17 +02:00
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
mbr1.add_mbr(&mbr2);
|
|
|
|
collector.set_extent(mbr1.xmin, mbr1.xmax, mbr1.ymin, mbr1.ymax);
|
2011-05-04 20:20:17 +02:00
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
if ((null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn)))
|
|
|
|
{
|
|
|
|
str_value= 0;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
collector.prepare_operation();
|
|
|
|
if (func.alloc_states())
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
operation.init(&func);
|
|
|
|
|
|
|
|
if (operation.count_all(&collector) ||
|
|
|
|
operation.get_result(&res_receiver))
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
|
|
|
|
str_value->set_charset(&my_charset_bin);
|
|
|
|
if (str_value->reserve(SRID_SIZE, 512))
|
|
|
|
goto exit;
|
|
|
|
str_value->length(0);
|
|
|
|
str_value->q_append(srid);
|
|
|
|
|
2014-02-18 14:15:25 +01:00
|
|
|
if (Geometry::create_from_opresult(&buffer1, str_value, res_receiver))
|
2011-05-04 20:20:17 +02:00
|
|
|
goto exit;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
collector.reset();
|
|
|
|
func.reset();
|
|
|
|
res_receiver.reset();
|
|
|
|
DBUG_RETURN(str_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *Item_func_spatial_operation::func_name() const
|
|
|
|
{
|
|
|
|
switch (spatial_op) {
|
|
|
|
case Gcalc_function::op_intersection:
|
|
|
|
return "st_intersection";
|
|
|
|
case Gcalc_function::op_difference:
|
|
|
|
return "st_difference";
|
|
|
|
case Gcalc_function::op_union:
|
|
|
|
return "st_union";
|
|
|
|
case Gcalc_function::op_symdifference:
|
|
|
|
return "st_symdifference";
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0); // Should never happen
|
|
|
|
return "sp_unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const int SINUSES_CALCULATED= 32;
|
|
|
|
static double n_sinus[SINUSES_CALCULATED+1]=
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
0.04906767432741802,
|
|
|
|
0.0980171403295606,
|
|
|
|
0.1467304744553618,
|
|
|
|
0.1950903220161283,
|
|
|
|
0.2429801799032639,
|
|
|
|
0.2902846772544623,
|
|
|
|
0.3368898533922201,
|
|
|
|
0.3826834323650898,
|
|
|
|
0.4275550934302821,
|
|
|
|
0.4713967368259976,
|
|
|
|
0.5141027441932217,
|
|
|
|
0.5555702330196022,
|
|
|
|
0.5956993044924334,
|
|
|
|
0.6343932841636455,
|
|
|
|
0.6715589548470183,
|
|
|
|
0.7071067811865475,
|
|
|
|
0.7409511253549591,
|
|
|
|
0.773010453362737,
|
|
|
|
0.8032075314806448,
|
|
|
|
0.8314696123025452,
|
|
|
|
0.8577286100002721,
|
|
|
|
0.8819212643483549,
|
|
|
|
0.9039892931234433,
|
|
|
|
0.9238795325112867,
|
|
|
|
0.9415440651830208,
|
|
|
|
0.9569403357322089,
|
|
|
|
0.970031253194544,
|
|
|
|
0.9807852804032304,
|
|
|
|
0.989176509964781,
|
|
|
|
0.9951847266721968,
|
|
|
|
0.9987954562051724,
|
|
|
|
1
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void get_n_sincos(int n, double *sinus, double *cosinus)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(n > 0 && n < SINUSES_CALCULATED*2+1);
|
|
|
|
if (n < (SINUSES_CALCULATED + 1))
|
|
|
|
{
|
|
|
|
*sinus= n_sinus[n];
|
|
|
|
*cosinus= n_sinus[SINUSES_CALCULATED - n];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
n-= SINUSES_CALCULATED;
|
|
|
|
*sinus= n_sinus[SINUSES_CALCULATED - n];
|
|
|
|
*cosinus= -n_sinus[n];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int fill_half_circle(Gcalc_shape_transporter *trn, double x, double y,
|
|
|
|
double ax, double ay)
|
|
|
|
{
|
|
|
|
double n_sin, n_cos;
|
|
|
|
double x_n, y_n;
|
|
|
|
for (int n = 1; n < (SINUSES_CALCULATED * 2 - 1); n++)
|
|
|
|
{
|
|
|
|
get_n_sincos(n, &n_sin, &n_cos);
|
|
|
|
x_n= ax * n_cos - ay * n_sin;
|
|
|
|
y_n= ax * n_sin + ay * n_cos;
|
|
|
|
if (trn->add_point(x_n + x, y_n + y))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int fill_gap(Gcalc_shape_transporter *trn,
|
|
|
|
double x, double y,
|
|
|
|
double ax, double ay, double bx, double by, double d,
|
|
|
|
bool *empty_gap)
|
|
|
|
{
|
|
|
|
double ab= ax * bx + ay * by;
|
|
|
|
double cosab= ab / (d * d) + GIS_ZERO;
|
|
|
|
double n_sin, n_cos;
|
|
|
|
double x_n, y_n;
|
|
|
|
int n=1;
|
|
|
|
|
|
|
|
*empty_gap= true;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
get_n_sincos(n++, &n_sin, &n_cos);
|
|
|
|
if (n_cos <= cosab)
|
|
|
|
break;
|
|
|
|
*empty_gap= false;
|
|
|
|
x_n= ax * n_cos - ay * n_sin;
|
|
|
|
y_n= ax * n_sin + ay * n_cos;
|
|
|
|
if (trn->add_point(x_n + x, y_n + y))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Calculates the vector (p2,p1) and
|
|
|
|
negatively orthogonal to it with the length of d.
|
|
|
|
The result is (ex,ey) - the vector, (px,py) - the orthogonal.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void calculate_perpendicular(
|
|
|
|
double x1, double y1, double x2, double y2, double d,
|
|
|
|
double *ex, double *ey,
|
|
|
|
double *px, double *py)
|
|
|
|
{
|
|
|
|
double q;
|
|
|
|
*ex= x1 - x2;
|
|
|
|
*ey= y1 - y2;
|
|
|
|
q= d / sqrt((*ex) * (*ex) + (*ey) * (*ey));
|
|
|
|
*px= (*ey) * q;
|
|
|
|
*py= -(*ex) * q;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::single_point(double x, double y)
|
|
|
|
{
|
2012-04-29 14:18:38 +02:00
|
|
|
if (buffer_op == Gcalc_function::op_difference)
|
|
|
|
{
|
|
|
|
m_fn->add_operation(Gcalc_function::op_false, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nshapes= 0;
|
2011-05-04 20:20:17 +02:00
|
|
|
return add_point_buffer(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::add_edge_buffer(
|
|
|
|
double x3, double y3, bool round_p1, bool round_p2)
|
|
|
|
{
|
|
|
|
Gcalc_operation_transporter trn(m_fn, m_heap);
|
|
|
|
double e1_x, e1_y, e2_x, e2_y, p1_x, p1_y, p2_x, p2_y;
|
|
|
|
double e1e2;
|
|
|
|
double sin1, cos1;
|
|
|
|
double x_n, y_n;
|
|
|
|
bool empty_gap1, empty_gap2;
|
|
|
|
|
|
|
|
++m_nshapes;
|
|
|
|
if (trn.start_simple_poly())
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
|
|
|
|
calculate_perpendicular(x3, y3, x2, y2, m_d, &e2_x, &e2_y, &p2_x, &p2_y);
|
|
|
|
|
|
|
|
e1e2= e1_x * e2_y - e2_x * e1_y;
|
|
|
|
sin1= n_sinus[1];
|
|
|
|
cos1= n_sinus[31];
|
|
|
|
if (e1e2 < 0)
|
|
|
|
{
|
|
|
|
empty_gap2= false;
|
|
|
|
x_n= x2 + p2_x * cos1 - p2_y * sin1;
|
|
|
|
y_n= y2 + p2_y * cos1 + p2_x * sin1;
|
|
|
|
if (fill_gap(&trn, x2, y2, -p1_x,-p1_y, p2_x,p2_y, m_d, &empty_gap1) ||
|
|
|
|
trn.add_point(x2 + p2_x, y2 + p2_y) ||
|
|
|
|
trn.add_point(x_n, y_n))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x_n= x2 - p2_x * cos1 - p2_y * sin1;
|
|
|
|
y_n= y2 - p2_y * cos1 + p2_x * sin1;
|
|
|
|
if (trn.add_point(x_n, y_n) ||
|
|
|
|
trn.add_point(x2 - p2_x, y2 - p2_y) ||
|
|
|
|
fill_gap(&trn, x2, y2, -p2_x, -p2_y, p1_x, p1_y, m_d, &empty_gap2))
|
|
|
|
return 1;
|
|
|
|
empty_gap1= false;
|
|
|
|
}
|
|
|
|
if ((!empty_gap2 && trn.add_point(x2 + p1_x, y2 + p1_y)) ||
|
|
|
|
trn.add_point(x1 + p1_x, y1 + p1_y))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (round_p1 && fill_half_circle(&trn, x1, y1, p1_x, p1_y))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (trn.add_point(x1 - p1_x, y1 - p1_y) ||
|
|
|
|
(!empty_gap1 && trn.add_point(x2 - p1_x, y2 - p1_y)))
|
|
|
|
return 1;
|
|
|
|
return trn.complete_simple_poly();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::add_last_edge_buffer()
|
|
|
|
{
|
|
|
|
Gcalc_operation_transporter trn(m_fn, m_heap);
|
|
|
|
double e1_x, e1_y, p1_x, p1_y;
|
|
|
|
|
|
|
|
++m_nshapes;
|
|
|
|
if (trn.start_simple_poly())
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
|
|
|
|
|
|
|
|
if (trn.add_point(x1 + p1_x, y1 + p1_y) ||
|
|
|
|
trn.add_point(x1 - p1_x, y1 - p1_y) ||
|
|
|
|
trn.add_point(x2 - p1_x, y2 - p1_y) ||
|
|
|
|
fill_half_circle(&trn, x2, y2, -p1_x, -p1_y) ||
|
|
|
|
trn.add_point(x2 + p1_x, y2 + p1_y))
|
|
|
|
return 1;
|
|
|
|
return trn.complete_simple_poly();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::add_point_buffer(double x, double y)
|
|
|
|
{
|
|
|
|
Gcalc_operation_transporter trn(m_fn, m_heap);
|
|
|
|
|
|
|
|
m_nshapes++;
|
|
|
|
if (trn.start_simple_poly())
|
|
|
|
return 1;
|
|
|
|
if (trn.add_point(x - m_d, y) ||
|
|
|
|
fill_half_circle(&trn, x, y, -m_d, 0.0) ||
|
|
|
|
trn.add_point(x + m_d, y) ||
|
|
|
|
fill_half_circle(&trn, x, y, m_d, 0.0))
|
|
|
|
return 1;
|
|
|
|
return trn.complete_simple_poly();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::start_line()
|
|
|
|
{
|
2011-07-04 13:03:36 +02:00
|
|
|
if (buffer_op == Gcalc_function::op_difference)
|
|
|
|
{
|
2014-02-18 14:15:25 +01:00
|
|
|
if (m_fn->reserve_op_buffer(1))
|
|
|
|
return 1;
|
2012-04-29 14:18:38 +02:00
|
|
|
m_fn->add_operation(Gcalc_function::op_false, 0);
|
2011-07-04 13:03:36 +02:00
|
|
|
skip_line= TRUE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nshapes= 0;
|
|
|
|
|
|
|
|
if (m_fn->reserve_op_buffer(2))
|
|
|
|
return 1;
|
2011-09-22 15:53:36 +02:00
|
|
|
last_shape_pos= m_fn->get_next_expression_pos();
|
2011-07-04 13:03:36 +02:00
|
|
|
m_fn->add_operation(buffer_op, 0);
|
2011-05-04 20:20:17 +02:00
|
|
|
m_npoints= 0;
|
|
|
|
int_start_line();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::start_poly()
|
|
|
|
{
|
2011-07-04 13:03:36 +02:00
|
|
|
m_nshapes= 1;
|
|
|
|
|
|
|
|
if (m_fn->reserve_op_buffer(2))
|
|
|
|
return 1;
|
2011-09-22 15:53:36 +02:00
|
|
|
last_shape_pos= m_fn->get_next_expression_pos();
|
2011-07-04 13:03:36 +02:00
|
|
|
m_fn->add_operation(buffer_op, 0);
|
2011-05-04 20:20:17 +02:00
|
|
|
return Gcalc_operation_transporter::start_poly();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-04 13:03:36 +02:00
|
|
|
int Item_func_buffer::Transporter::complete_poly()
|
|
|
|
{
|
|
|
|
if (Gcalc_operation_transporter::complete_poly())
|
|
|
|
return 1;
|
|
|
|
m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
int Item_func_buffer::Transporter::start_ring()
|
|
|
|
{
|
|
|
|
m_npoints= 0;
|
|
|
|
return Gcalc_operation_transporter::start_ring();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-04 13:03:36 +02:00
|
|
|
int Item_func_buffer::Transporter::start_collection(int n_objects)
|
|
|
|
{
|
|
|
|
if (m_fn->reserve_op_buffer(1))
|
|
|
|
return 1;
|
|
|
|
m_fn->add_operation(Gcalc_function::op_union, n_objects);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
int Item_func_buffer::Transporter::add_point(double x, double y)
|
|
|
|
{
|
2011-07-04 13:03:36 +02:00
|
|
|
if (skip_line)
|
|
|
|
return 0;
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
if (m_npoints && x == x2 && y == y2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
++m_npoints;
|
|
|
|
|
|
|
|
if (m_npoints == 1)
|
|
|
|
{
|
|
|
|
x00= x;
|
|
|
|
y00= y;
|
|
|
|
}
|
|
|
|
else if (m_npoints == 2)
|
|
|
|
{
|
|
|
|
x01= x;
|
|
|
|
y01= y;
|
|
|
|
}
|
|
|
|
else if (add_edge_buffer(x, y, (m_npoints == 3) && line_started(), false))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
x1= x2;
|
|
|
|
y1= y2;
|
|
|
|
x2= x;
|
|
|
|
y2= y;
|
|
|
|
|
|
|
|
return line_started() ? 0 : Gcalc_operation_transporter::add_point(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::complete()
|
|
|
|
{
|
|
|
|
if (m_npoints)
|
|
|
|
{
|
|
|
|
if (m_npoints == 1)
|
|
|
|
{
|
|
|
|
if (add_point_buffer(x2, y2))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (m_npoints == 2)
|
|
|
|
{
|
|
|
|
if (add_edge_buffer(x1, y1, true, true))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (line_started())
|
|
|
|
{
|
|
|
|
if (add_last_edge_buffer())
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-07-07 18:30:51 +02:00
|
|
|
if (x2 != x00 || y2 != y00)
|
2011-05-04 20:20:17 +02:00
|
|
|
{
|
|
|
|
if (add_edge_buffer(x00, y00, false, false))
|
|
|
|
return 1;
|
|
|
|
x1= x2;
|
|
|
|
y1= y2;
|
|
|
|
x2= x00;
|
|
|
|
y2= y00;
|
|
|
|
}
|
|
|
|
if (add_edge_buffer(x01, y01, false, false))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::complete_line()
|
|
|
|
{
|
2011-07-04 13:03:36 +02:00
|
|
|
if (!skip_line)
|
|
|
|
{
|
|
|
|
if (complete())
|
|
|
|
return 1;
|
|
|
|
int_complete_line();
|
|
|
|
m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
|
|
|
|
}
|
|
|
|
skip_line= FALSE;
|
2011-05-04 20:20:17 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Item_func_buffer::Transporter::complete_ring()
|
|
|
|
{
|
|
|
|
return complete() ||
|
|
|
|
Gcalc_operation_transporter::complete_ring();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_buffer::val_str(String *str_value)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_buffer::val_str");
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
String *obj= args[0]->val_str(&tmp_value);
|
|
|
|
double dist= args[1]->val_real();
|
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *g;
|
|
|
|
uint32 srid= 0;
|
|
|
|
String *str_result= NULL;
|
|
|
|
Transporter trn(&func, &collector, dist);
|
2011-12-08 13:29:45 +01:00
|
|
|
MBR mbr;
|
|
|
|
const char *c_end;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
null_value= 1;
|
|
|
|
if (args[0]->null_value || args[1]->null_value ||
|
2011-12-08 13:29:45 +01:00
|
|
|
!(g= Geometry::construct(&buffer, obj->ptr(), obj->length())) ||
|
|
|
|
g->get_mbr(&mbr, &c_end))
|
2011-05-04 20:20:17 +02:00
|
|
|
goto mem_error;
|
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
if (dist > 0.0)
|
|
|
|
mbr.buffer(dist);
|
2015-02-10 13:16:31 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* This happens when dist is too far negative. */
|
|
|
|
if (mbr.xmax + dist < mbr.xmin || mbr.ymax + dist < mbr.ymin)
|
|
|
|
goto return_empty_result;
|
|
|
|
}
|
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
|
2011-06-30 16:24:52 +02:00
|
|
|
/*
|
|
|
|
If the distance given is 0, the Buffer function is in fact NOOP,
|
|
|
|
so it's natural just to return the argument1.
|
|
|
|
Besides, internal calculations here can't handle zero distance anyway.
|
|
|
|
*/
|
|
|
|
if (fabs(dist) < GIS_ZERO)
|
|
|
|
{
|
|
|
|
null_value= 0;
|
|
|
|
str_result= obj;
|
|
|
|
goto mem_error;
|
|
|
|
}
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
if (g->store_shapes(&trn))
|
|
|
|
goto mem_error;
|
|
|
|
|
|
|
|
collector.prepare_operation();
|
|
|
|
if (func.alloc_states())
|
|
|
|
goto mem_error;
|
|
|
|
operation.init(&func);
|
2011-11-20 09:30:43 +01:00
|
|
|
operation.killed= (int *) &(current_thd->killed);
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
if (operation.count_all(&collector) ||
|
|
|
|
operation.get_result(&res_receiver))
|
|
|
|
goto mem_error;
|
|
|
|
|
|
|
|
|
2015-02-10 13:16:31 +01:00
|
|
|
return_empty_result:
|
2011-05-04 20:20:17 +02:00
|
|
|
str_value->set_charset(&my_charset_bin);
|
|
|
|
if (str_value->reserve(SRID_SIZE, 512))
|
|
|
|
goto mem_error;
|
|
|
|
str_value->length(0);
|
|
|
|
str_value->q_append(srid);
|
|
|
|
|
2014-02-18 14:15:25 +01:00
|
|
|
if (Geometry::create_from_opresult(&buffer, str_value, res_receiver))
|
2011-05-04 20:20:17 +02:00
|
|
|
goto mem_error;
|
|
|
|
|
|
|
|
null_value= 0;
|
|
|
|
str_result= str_value;
|
|
|
|
mem_error:
|
|
|
|
collector.reset();
|
|
|
|
func.reset();
|
|
|
|
res_receiver.reset();
|
|
|
|
DBUG_RETURN(str_result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_isempty::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2007-02-21 11:45:19 +01:00
|
|
|
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;
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_issimple::val_int()
|
|
|
|
{
|
2007-02-21 11:45:19 +01:00
|
|
|
String *swkb= args[0]->val_str(&tmp);
|
|
|
|
Geometry_buffer buffer;
|
2011-05-04 20:20:17 +02:00
|
|
|
Gcalc_operation_transporter trn(&func, &collector);
|
|
|
|
Geometry *g;
|
|
|
|
int result= 1;
|
2011-10-14 13:10:55 +02:00
|
|
|
const Gcalc_scan_iterator::event_point *ev;
|
2011-12-08 13:29:45 +01:00
|
|
|
MBR mbr;
|
|
|
|
const char *c_end;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
DBUG_ENTER("Item_func_issimple::val_int");
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2007-02-21 11:45:19 +01:00
|
|
|
|
2013-03-22 14:32:27 +01:00
|
|
|
if ((null_value= (args[0]->null_value ||
|
|
|
|
!(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
|
|
|
|
g->get_mbr(&mbr, &c_end))))
|
2011-05-04 20:20:17 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax);
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
if (g->get_class_info()->m_type_id == Geometry::wkb_point)
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
|
|
|
if (g->store_shapes(&trn))
|
|
|
|
goto mem_error;
|
|
|
|
|
|
|
|
collector.prepare_operation();
|
|
|
|
scan_it.init(&collector);
|
|
|
|
|
|
|
|
while (scan_it.more_points())
|
|
|
|
{
|
|
|
|
if (scan_it.step())
|
|
|
|
goto mem_error;
|
|
|
|
|
2011-09-01 08:44:56 +02:00
|
|
|
ev= scan_it.get_events();
|
|
|
|
if (ev->simple_event())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((ev->event == scev_thread || ev->event == scev_single_point) &&
|
|
|
|
!ev->get_next())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ev->event == scev_two_threads && !ev->get_next()->get_next())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
result= 0;
|
|
|
|
break;
|
2011-05-04 20:20:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
collector.reset();
|
|
|
|
func.reset();
|
|
|
|
scan_it.reset();
|
|
|
|
DBUG_RETURN(result);
|
|
|
|
mem_error:
|
|
|
|
null_value= 1;
|
|
|
|
DBUG_RETURN(0);
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_isclosed::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String tmp;
|
|
|
|
String *swkb= args[0]->val_str(&tmp);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2004-03-04 07:50:37 +01:00
|
|
|
int isclosed= 0; // In case of error
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
|
|
|
args[0]->null_value ||
|
2004-03-12 09:04:00 +01:00
|
|
|
!(geom=
|
2005-09-21 11:35:01 +02:00
|
|
|
Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->is_closed(&isclosed));
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
return (longlong) isclosed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Numerical functions
|
|
|
|
*/
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_dimension::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 dim= 0; // In case of error
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2004-03-04 07:50:37 +01:00
|
|
|
const char *dummy;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
|
|
|
args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->dimension(&dim, &dummy));
|
2003-05-30 12:22:34 +02:00
|
|
|
return (longlong) dim;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_numinteriorring::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 num= 0; // In case of error
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->num_interior_ring(&num));
|
2003-05-30 12:22:34 +02:00
|
|
|
return (longlong) num;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_numgeometries::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 num= 0; // In case of errors
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->num_geometries(&num));
|
2003-05-30 12:22:34 +02:00
|
|
|
return (longlong) num;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2003-05-30 12:22:34 +02:00
|
|
|
longlong Item_func_numpoints::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
uint32 num= 0; // In case of errors
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
|
|
|
args[0]->null_value ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->num_points(&num));
|
2003-05-30 12:22:34 +02:00
|
|
|
return (longlong) num;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_x::val_real()
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
double res= 0.0; // In case of errors
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->get_x(&res));
|
2003-05-30 12:22:34 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_y::val_real()
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
double res= 0; // In case of errors
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->get_y(&res));
|
2003-05-30 12:22:34 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2004-03-04 07:50:37 +01:00
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_area::val_real()
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
double res= 0; // In case of errors
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2004-03-04 07:50:37 +01:00
|
|
|
const char *dummy;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length())) ||
|
2004-03-12 09:04:00 +01:00
|
|
|
geom->area(&res, &dummy));
|
2003-05-30 12:22:34 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_glength::val_real()
|
2003-05-30 12:22:34 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-04 07:50:37 +01:00
|
|
|
double res= 0; // In case of errors
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
|
|
|
Geometry *geom;
|
2011-09-21 10:26:21 +02:00
|
|
|
const char *end;
|
2003-05-30 12:22:34 +02:00
|
|
|
|
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!(geom= Geometry::construct(&buffer,
|
2006-12-14 23:51:37 +01:00
|
|
|
swkb->ptr(),
|
|
|
|
swkb->length())) ||
|
2011-09-21 10:26:21 +02:00
|
|
|
geom->geom_length(&res, &end));
|
2003-05-30 12:22:34 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
longlong Item_func_srid::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-30 12:22:34 +02:00
|
|
|
String *swkb= args[0]->val_str(&value);
|
2004-03-12 09:04:00 +01:00
|
|
|
Geometry_buffer buffer;
|
2004-05-05 07:59:17 +02:00
|
|
|
|
2004-04-05 12:56:05 +02:00
|
|
|
null_value= (!swkb ||
|
2005-09-21 11:35:01 +02:00
|
|
|
!Geometry::construct(&buffer,
|
|
|
|
swkb->ptr(), swkb->length()));
|
2004-03-04 07:50:37 +01:00
|
|
|
if (null_value)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return (longlong) (uint4korr(swkb->ptr()));
|
2003-05-30 12:22:34 +02:00
|
|
|
}
|
2004-01-15 18:06:22 +01:00
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
double Item_func_distance::val_real()
|
|
|
|
{
|
2011-11-18 15:15:06 +01:00
|
|
|
bool cur_point_edge;
|
2011-05-04 20:20:17 +02:00
|
|
|
const Gcalc_scan_iterator::point *evpos;
|
|
|
|
const Gcalc_heap::Info *cur_point, *dist_point;
|
2011-10-14 13:10:55 +02:00
|
|
|
const Gcalc_scan_iterator::event_point *ev;
|
2011-05-04 20:20:17 +02:00
|
|
|
double t, distance, cur_distance;
|
|
|
|
double x1, x2, y1, y2;
|
|
|
|
double ex, ey, vx, vy, e_sqrlen;
|
|
|
|
uint obj2_si;
|
|
|
|
Gcalc_operation_transporter trn(&func, &collector);
|
|
|
|
|
|
|
|
DBUG_ENTER("Item_func_distance::val_real");
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
String *res1= args[0]->val_str(&tmp_value1);
|
|
|
|
String *res2= args[1]->val_str(&tmp_value2);
|
|
|
|
Geometry_buffer buffer1, buffer2;
|
|
|
|
Geometry *g1, *g2;
|
2011-12-08 13:29:45 +01:00
|
|
|
MBR mbr1, mbr2;
|
|
|
|
const char *c_end;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
|
|
|
|
if ((null_value= (args[0]->null_value || args[1]->null_value ||
|
|
|
|
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
|
2013-03-22 14:32:27 +01:00
|
|
|
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
|
|
|
|
g1->get_mbr(&mbr1, &c_end) ||
|
|
|
|
g2->get_mbr(&mbr2, &c_end))))
|
2011-05-04 20:20:17 +02:00
|
|
|
goto mem_error;
|
|
|
|
|
2011-12-08 13:29:45 +01:00
|
|
|
mbr1.add_mbr(&mbr2);
|
|
|
|
collector.set_extent(mbr1.xmin, mbr1.xmax, mbr1.ymin, mbr1.ymax);
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
if ((g1->get_class_info()->m_type_id == Geometry::wkb_point) &&
|
|
|
|
(g2->get_class_info()->m_type_id == Geometry::wkb_point))
|
|
|
|
{
|
|
|
|
if (((Gis_point *) g1)->get_xy(&x1, &y1) ||
|
|
|
|
((Gis_point *) g2)->get_xy(&x2, &y2))
|
|
|
|
goto mem_error;
|
|
|
|
ex= x2 - x1;
|
|
|
|
ey= y2 - y1;
|
|
|
|
DBUG_RETURN(sqrt(ex * ex + ey * ey));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (func.reserve_op_buffer(1))
|
|
|
|
goto mem_error;
|
|
|
|
func.add_operation(Gcalc_function::op_intersection, 2);
|
|
|
|
|
|
|
|
if (g1->store_shapes(&trn))
|
|
|
|
goto mem_error;
|
|
|
|
obj2_si= func.get_nshapes();
|
|
|
|
if (g2->store_shapes(&trn) || func.alloc_states())
|
|
|
|
goto mem_error;
|
|
|
|
|
2011-09-13 10:59:11 +02:00
|
|
|
if (obj2_si == 0 || func.get_nshapes() == obj2_si)
|
|
|
|
{
|
|
|
|
distance= 0.0;
|
|
|
|
null_value= 1;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-04 20:20:17 +02:00
|
|
|
collector.prepare_operation();
|
|
|
|
scan_it.init(&collector);
|
|
|
|
|
|
|
|
distance= DBL_MAX;
|
|
|
|
while (scan_it.more_points())
|
|
|
|
{
|
|
|
|
if (scan_it.step())
|
|
|
|
goto mem_error;
|
|
|
|
evpos= scan_it.get_event_position();
|
2011-09-01 08:44:56 +02:00
|
|
|
ev= scan_it.get_events();
|
2011-05-04 20:20:17 +02:00
|
|
|
|
2011-09-01 08:44:56 +02:00
|
|
|
if (ev->simple_event())
|
2011-05-04 20:20:17 +02:00
|
|
|
{
|
2011-09-01 08:44:56 +02:00
|
|
|
cur_point= ev->pi;
|
|
|
|
goto count_distance;
|
2011-05-04 20:20:17 +02:00
|
|
|
}
|
|
|
|
/*
|
2011-09-01 08:44:56 +02:00
|
|
|
handling intersection we only need to check if it's the intersecion
|
|
|
|
of objects 1 and 2. In this case distance is 0
|
2011-05-04 20:20:17 +02:00
|
|
|
*/
|
2011-09-01 08:44:56 +02:00
|
|
|
cur_point= NULL;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
having these events we need to check for possible intersection
|
|
|
|
of objects
|
|
|
|
scev_thread | scev_two_threads | scev_single_point
|
|
|
|
*/
|
2011-09-22 15:53:36 +02:00
|
|
|
func.clear_i_states();
|
2011-05-04 20:20:17 +02:00
|
|
|
for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit)
|
|
|
|
{
|
|
|
|
gcalc_shape_info si= pit.point()->get_shape();
|
|
|
|
if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
|
2011-09-22 15:53:36 +02:00
|
|
|
func.invert_i_state(si);
|
2011-05-04 20:20:17 +02:00
|
|
|
}
|
2011-09-01 08:44:56 +02:00
|
|
|
|
2011-09-22 15:53:36 +02:00
|
|
|
func.clear_b_states();
|
2011-09-01 08:44:56 +02:00
|
|
|
for (; ev; ev= ev->get_next())
|
2011-05-04 20:20:17 +02:00
|
|
|
{
|
2011-09-01 08:44:56 +02:00
|
|
|
if (ev->event != scev_intersection)
|
|
|
|
cur_point= ev->pi;
|
2011-09-22 15:53:36 +02:00
|
|
|
func.set_b_state(ev->get_shape());
|
2011-09-01 08:44:56 +02:00
|
|
|
if (func.count())
|
|
|
|
{
|
|
|
|
/* Point of one object is inside the other - intersection found */
|
|
|
|
distance= 0;
|
|
|
|
goto exit;
|
|
|
|
}
|
2011-05-04 20:20:17 +02:00
|
|
|
}
|
|
|
|
|
2011-09-01 08:44:56 +02:00
|
|
|
if (!cur_point)
|
|
|
|
continue;
|
2011-05-04 20:20:17 +02:00
|
|
|
|
|
|
|
count_distance:
|
2016-02-14 20:57:48 +01:00
|
|
|
if (cur_point->node.shape.shape >= obj2_si)
|
2011-05-04 20:20:17 +02:00
|
|
|
continue;
|
|
|
|
cur_point_edge= !cur_point->is_bottom();
|
|
|
|
|
|
|
|
for (dist_point= collector.get_first(); dist_point; dist_point= dist_point->get_next())
|
|
|
|
{
|
|
|
|
/* We only check vertices of object 2 */
|
2012-08-31 16:50:45 +02:00
|
|
|
if (dist_point->type != Gcalc_heap::nt_shape_node ||
|
2016-02-14 20:57:48 +01:00
|
|
|
dist_point->node.shape.shape < obj2_si)
|
2011-05-04 20:20:17 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* if we have an edge to check */
|
2016-02-14 20:57:48 +01:00
|
|
|
if (dist_point->node.shape.left)
|
2011-05-04 20:20:17 +02:00
|
|
|
{
|
2016-02-14 20:57:48 +01:00
|
|
|
t= count_edge_t(dist_point, dist_point->node.shape.left, cur_point,
|
2011-05-04 20:20:17 +02:00
|
|
|
ex, ey, vx, vy, e_sqrlen);
|
|
|
|
if ((t>0.0) && (t<1.0))
|
|
|
|
{
|
|
|
|
cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
|
|
|
|
if (distance > cur_distance)
|
|
|
|
distance= cur_distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cur_point_edge)
|
|
|
|
{
|
2016-02-14 20:57:48 +01:00
|
|
|
t= count_edge_t(cur_point, cur_point->node.shape.left, dist_point,
|
2011-05-04 20:20:17 +02:00
|
|
|
ex, ey, vx, vy, e_sqrlen);
|
|
|
|
if ((t>0.0) && (t<1.0))
|
|
|
|
{
|
|
|
|
cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
|
|
|
|
if (distance > cur_distance)
|
|
|
|
distance= cur_distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur_distance= distance_points(cur_point, dist_point);
|
|
|
|
if (distance > cur_distance)
|
|
|
|
distance= cur_distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exit:
|
|
|
|
collector.reset();
|
|
|
|
func.reset();
|
|
|
|
scan_it.reset();
|
|
|
|
DBUG_RETURN(distance);
|
|
|
|
mem_error:
|
|
|
|
null_value= 1;
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 18:06:22 +01:00
|
|
|
#endif /*HAVE_SPATIAL*/
|