summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2004-03-04 08:50:37 +0200
committerunknown <monty@mashka.mysql.fi>2004-03-04 08:50:37 +0200
commitafa6728a9f7c00582b3dc9e96b2dce5c4ac1e56c (patch)
treef335ad0e2c6634a947a95d62cbee9a54ee9303e8 /sql
parentf96960f9e1605189cc49397c64ff1cff97faedf1 (diff)
downloadmariadb-git-afa6728a9f7c00582b3dc9e96b2dce5c4ac1e56c.tar.gz
Optimized GIS functions
heap/hp_delete.c: Added comments mysql-test/r/gis.result: Updated results after name changes (all results line are unchanged) mysql-test/r/show_check.result: Update test results after fix in hp_delete.cc mysql-test/t/gis.test: Changed table names to longer, hopefully non conflicting ones. Added missing drop table mysys/hash.c: Inendation cleanup mysys/tree.c: Updated comments Decrease tree->allocated on delete (for status) sql/field.cc: Added safety checking for GIS objects sql/gstream.cc: Added copyright message Made a lot of speed/space optimizations Changed class names to be MySQL compliant sql/gstream.h: Made a lot of speed/space optimizations Changed class names to be MySQL compliant sql/item_create.cc: Indentation fixup sql/item_geofunc.cc: Use new gis interface functions and new gis class names. Simple optimizations Indentation fixups Fixed a lot of unlikely but possible errors. sql/item_geofunc.h: Moved SRID_SIZE to spatial.h sql/spatial.cc: Added copyright message Made a lot of speed/space optimizations Changed class names to be MySQL compliant sql/spatial.h: Made a lot of speed/space optimizations Changed class names to be MySQL compliant Indentation fixes Use bool instead of int as result type for functions that only return 0 or 1 sql/sql_string.cc: Simple optimizations sql/sql_string.h: Simple cleanups sql/structs.h: Added LEX_STRING_WITH_INIT (needed by spatial.cc)
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc70
-rw-r--r--sql/gstream.cc174
-rw-r--r--sql/gstream.h40
-rw-r--r--sql/item_create.cc1
-rw-r--r--sql/item_geofunc.cc226
-rw-r--r--sql/item_geofunc.h2
-rw-r--r--sql/spatial.cc1646
-rw-r--r--sql/spatial.h480
-rw-r--r--sql/sql_string.cc16
-rw-r--r--sql/sql_string.h12
-rw-r--r--sql/structs.h12
11 files changed, 1359 insertions, 1320 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 4632fbc5c69..48e7dbb32ca 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4715,18 +4715,26 @@ void Field_blob::get_key_image(char *buff,uint length,
#ifdef HAVE_SPATIAL
if (type == itMBR)
{
- if (!blob_length)
- return;
- get_ptr(&blob);
-
+ const char *dummy;
MBR mbr;
Geometry gobj;
+
+ if (blob_length < SRID_SIZE)
+ {
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ return;
+ }
+ get_ptr(&blob);
gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
- gobj.get_mbr(&mbr);
- float8store(buff, mbr.xmin);
- float8store(buff+8, mbr.xmax);
- float8store(buff+16, mbr.ymin);
- float8store(buff+24, mbr.ymax);
+ if (gobj.get_mbr(&mbr, &dummy))
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ else
+ {
+ float8store(buff, mbr.xmin);
+ float8store(buff+8, mbr.xmax);
+ float8store(buff+16, mbr.ymin);
+ float8store(buff+24, mbr.ymax);
+ }
return;
}
#endif /*HAVE_SPATIAL*/
@@ -4939,6 +4947,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
+
#ifdef HAVE_SPATIAL
void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
@@ -4947,17 +4956,26 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
length-= HA_KEY_BLOB_LENGTH;
ulong blob_length= get_length(ptr);
char *blob;
- get_ptr(&blob);
-
+ const char *dummy;
MBR mbr;
+
+ if (blob_length < SRID_SIZE)
+ {
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ return;
+ }
+ get_ptr(&blob);
Geometry gobj;
gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
- gobj.get_mbr(&mbr);
- float8store(buff, mbr.xmin);
- float8store(buff + 8, mbr.xmax);
- float8store(buff + 16, mbr.ymin);
- float8store(buff + 24, mbr.ymax);
- return;
+ if (gobj.get_mbr(&mbr, &dummy))
+ bzero(buff, SIZEOF_STORED_DOUBLE*4);
+ else
+ {
+ float8store(buff, mbr.xmin);
+ float8store(buff + 8, mbr.xmax);
+ float8store(buff + 16, mbr.ymin);
+ float8store(buff + 24, mbr.ymax);
+ }
}
@@ -5001,16 +5019,16 @@ void Field_geom::sql_type(String &res) const
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{
if (!length)
- {
bzero(ptr, Field_blob::pack_length());
- }
else
{
- // Should check given WKB
- if (length < 4 + 1 + 4 + 8 + 8) // SRID + WKB_HEADER + X + Y
- return 1;
- uint32 wkb_type= uint4korr(from + 5);
- if (wkb_type < 1 || wkb_type > 7)
+ // Check given WKB
+ uint32 wkb_type;
+ if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
+ goto err;
+ wkb_type= uint4korr(from + WKB_HEADER_SIZE);
+ if (wkb_type < (uint32) Geometry::wkbPoint ||
+ wkb_type > (uint32) Geometry::wkb_end)
return 1;
Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
@@ -5021,6 +5039,10 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
bmove(ptr + packlength, (char*) &from, sizeof(char*));
}
return 0;
+
+err:
+ bzero(ptr, Field_blob::pack_length());
+ return 1;
}
#endif /*HAVE_SPATIAL*/
diff --git a/sql/gstream.cc b/sql/gstream.cc
index 17b85af22bd..6b1e12ec733 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -1,139 +1,115 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+/*
+ Functions to read and parse geometrical data.
+ NOTE: These functions assumes that the string is end \0 terminated!
+*/
+
#include "mysql_priv.h"
-int GTextReadStream::get_next_toc_type() const
+enum Gis_read_stream::enum_tok_types Gis_read_stream::get_next_toc_type()
{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
- {
- cur++;
- }
- if (!(*cur))
- {
+ skip_space();
+ if (!*m_cur)
return eostream;
- }
-
- if (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
- (*cur=='_'))
- {
+ if (my_isvar_start(&my_charset_bin, *m_cur))
return word;
- }
-
- if (((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') ||
- (*cur=='.'))
- {
+ if ((*m_cur >= '0' && *m_cur <= '9') || *m_cur == '-' || *m_cur == '+')
return numeric;
- }
-
- if (*cur == '(')
- {
+ if (*m_cur == '(')
return l_bra;
- }
-
- if (*cur == ')')
- {
+ if (*m_cur == ')')
return r_bra;
- }
-
- if (*cur == ',')
- {
+ if (*m_cur == ',')
return comma;
- }
-
return unknown;
}
-const char *GTextReadStream::get_next_word(int *word_len)
-{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
- {
- cur++;
- }
- m_last_text_position = cur;
-
- if (!(*cur))
- {
- return 0;
- }
- const char *wd_start = cur;
-
- if (((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
- {
- return NULL;
- }
+bool Gis_read_stream::get_next_word(LEX_STRING *res)
+{
+ skip_space();
+ res->str= (char*) m_cur;
+ /* The following will also test for \0 */
+ if (!my_isvar_start(&my_charset_bin, *m_cur))
+ return 1;
- ++cur;
+ /*
+ We can't combine the following increment with my_isvar() because
+ my_isvar() is a macro that would cause side effects
+ */
+ m_cur++;
+ while (my_isvar(&my_charset_bin, *m_cur))
+ m_cur++;
- while (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
- (*cur=='_') || ((*cur>='0') && (*cur<='9')))
- {
- ++cur;
- }
+ res->length= (uint32) (m_cur - res->str);
+ return 0;
+}
- *word_len = cur - wd_start;
- m_cur = cur;
+/*
+ Read a floating point number
- return wd_start;
-}
+ NOTE: Number must start with a digit or sign. It can't start with a decimal
+ point
+*/
-int GTextReadStream::get_next_number(double *d)
+bool Gis_read_stream::get_next_number(double *d)
{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
- {
- cur++;
- }
-
- m_last_text_position = cur;
- if (!(*cur))
- {
- set_error_msg("Numeric constant expected");
- return 1;
- }
+ char *endptr;
- if (((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.'))
+ skip_space();
+ /* The following will also test for end \0 */
+ if ((*m_cur < '0' || *m_cur > '9') && *m_cur != '-' && *m_cur != '+')
{
set_error_msg("Numeric constant expected");
return 1;
}
- char *endptr;
-
- *d = my_strtod(cur, &endptr);
-
+ *d = my_strtod(m_cur, &endptr);
if (endptr)
- {
m_cur = endptr;
- }
-
return 0;
}
-char GTextReadStream::get_next_symbol()
+
+bool Gis_read_stream::check_next_symbol(char symbol)
{
- const char *cur = m_cur;
- while ((*cur)&&(strchr(" \t\r\n",*cur)))
+ skip_space();
+ if (*m_cur != symbol)
{
- cur++;
- }
- if (!(*cur))
- {
- return 0;
+ char buff[32];
+ strmov(buff, "'?' expected");
+ buff[2]= symbol;
+ set_error_msg(buff);
+ return 1;
}
+ m_cur++;
+ return 0;
+}
- m_cur = cur + 1;
- m_last_text_position = cur;
- return *cur;
-}
+/*
+ Remember error message.
+*/
-void GTextReadStream::set_error_msg(const char *msg)
+void Gis_read_stream::set_error_msg(const char *msg)
{
- size_t len = strlen(msg);
- m_err_msg = (char *)my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
+ size_t len= strlen(msg); // ok in this context
+ m_err_msg= (char *) my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1);
}
-
-
diff --git a/sql/gstream.h b/sql/gstream.h
index a3914a534dd..2e9513d2639 100644
--- a/sql/gstream.h
+++ b/sql/gstream.h
@@ -15,10 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-class GTextReadStream
+class Gis_read_stream
{
public:
- enum TokTypes
+ enum enum_tok_types
{
unknown,
eostream,
@@ -29,41 +29,47 @@ public:
comma
};
- GTextReadStream(const char *buffer, int size)
- :m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer),
- m_err_msg(NULL)
+ Gis_read_stream(const char *buffer, int size)
+ :m_cur(buffer), m_limit(buffer + size), m_err_msg(NULL)
{}
- GTextReadStream(): m_cur(NULL), m_limit(NULL), m_err_msg(NULL)
+ Gis_read_stream(): m_cur(NullS), m_limit(NullS), m_err_msg(NullS)
{}
-
- ~GTextReadStream()
+ ~Gis_read_stream()
{
my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR));
}
- int get_next_toc_type() const;
- const char *get_next_word(int *word_len);
- int get_next_number(double *d);
- char get_next_symbol();
+ enum enum_tok_types get_next_toc_type();
+ bool get_next_word(LEX_STRING *);
+ bool get_next_number(double *);
+ bool check_next_symbol(char);
- const char *get_last_text_position() const
+ inline void skip_space()
{
- return m_last_text_position;
+ while (my_isspace(&my_charset_latin1, *m_cur))
+ m_cur++;
+ }
+ /* Skip next character, if match. Return 1 if no match */
+ inline bool skip_char(char skip)
+ {
+ skip_space();
+ if (*m_cur != skip)
+ return 1; /* Didn't find char */
+ m_cur++;
+ return 0;
}
-
void set_error_msg(const char *msg);
// caller should free this pointer
char *get_error_msg()
{
char *err_msg = m_err_msg;
- m_err_msg = NULL;
+ m_err_msg= NullS;
return err_msg;
}
protected:
const char *m_cur;
const char *m_limit;
- const char *m_last_text_position;
char *m_err_msg;
};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 4ed8182305d..b013e4747bb 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -455,6 +455,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len,
{
Item *res;
LINT_INIT(res);
+
switch (cast_type) {
case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 6934ad9d3b0..cbf286a2101 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -27,18 +27,17 @@
#include "sql_acl.h"
#include <m_ctype.h>
+
String *Item_func_geometry_from_text::val_str(String *str)
{
Geometry geom;
String arg_val;
String *wkt= args[0]->val_str(&arg_val);
- GTextReadStream trs(wkt->ptr(), wkt->length());
- uint32 srid;
+ Gis_read_stream trs(wkt->c_ptr(), wkt->length());
+ uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int();
- else
- srid= 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
@@ -61,22 +60,19 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
String arg_val;
String *wkb= args[0]->val_str(&arg_val);
Geometry geom;
- uint32 srid;
+ uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int();
- else
- srid= 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
str->q_append(srid);
if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(wkb->ptr(), wkb->length()))))
+ geom.create_from_wkb(wkb->ptr(), wkb->length()))) ||
+ str->append(*wkb))
return 0;
-
- str->append(*wkb);
return str;
}
@@ -92,6 +88,7 @@ String *Item_func_as_wkt::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
+ const char *dummy;
if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
@@ -99,18 +96,19 @@ String *Item_func_as_wkt::val_str(String *str)
return 0;
str->length(0);
-
- if ((null_value= geom.as_wkt(str)))
+ if ((null_value= geom.as_wkt(str, &dummy)))
return 0;
return str;
}
+
void Item_func_as_wkt::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
}
+
String *Item_func_as_wkb::val_str(String *str)
{
String arg_val;
@@ -127,11 +125,13 @@ String *Item_func_as_wkb::val_str(String *str)
return str;
}
+
void Item_func_as_wkb::fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
}
+
String *Item_func_geometry_type::val_str(String *str)
{
String *swkb= args[0]->val_str(str);
@@ -141,9 +141,10 @@ String *Item_func_geometry_type::val_str(String *str)
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))))
return 0;
- str->copy(geom.get_class_info()->m_name,
- strlen(geom.get_class_info()->m_name),
- default_charset());
+ /* String will not move */
+ str->set(geom.get_class_info()->m_name.str,
+ geom.get_class_info()->m_name.length,
+ default_charset());
return str;
}
@@ -153,13 +154,14 @@ String *Item_func_envelope::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
+ uint32 srid;
if ((null_value= args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE)))
return 0;
- uint32 srid= uint4korr(swkb->ptr());
+ srid= uint4korr(swkb->ptr());
str->length(0);
if (str->reserve(SRID_SIZE, 512))
return 0;
@@ -173,20 +175,21 @@ String *Item_func_centroid::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
+ uint32 srid;
if ((null_value= args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, centroid)))
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, centroid)))
return 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
+ srid= uint4korr(swkb->ptr());
str->q_append(srid);
- return (null_value= geom.centroid(str)) ? 0 : str;
+ return (null_value= test(geom.centroid(str))) ? 0 : str;
}
@@ -199,42 +202,42 @@ String *Item_func_spatial_decomp::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
+ uint32 srid;
if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))))
return 0;
- null_value= 1;
+ srid= uint4korr(swkb->ptr());
if (str->reserve(SRID_SIZE, 512))
- return 0;
+ goto err;
str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid);
- switch(decomp_func)
- {
+ switch (decomp_func) {
case SP_STARTPOINT:
if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
- goto ret;
+ goto err;
break;
case SP_ENDPOINT:
if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
- goto ret;
+ goto err;
break;
case SP_EXTERIORRING:
if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
- goto ret;
+ goto err;
break;
default:
- goto ret;
+ goto err;
}
- null_value= 0;
+ return str;
-ret:
- return null_value ? 0 : str;
+err:
+ null_value= 1;
+ return 0;
}
@@ -244,43 +247,44 @@ String *Item_func_spatial_decomp_n::val_str(String *str)
String *swkb= args[0]->val_str(&arg_val);
long n= (long) args[1]->val_int();
Geometry geom;
+ uint32 srid;
if ((null_value= (args[0]->null_value || args[1]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))))
return 0;
- null_value= 1;
if (str->reserve(SRID_SIZE, 512))
- return 0;
+ goto err;
+ srid= uint4korr(swkb->ptr());
str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid);
- switch(decomp_func_n)
+ switch (decomp_func_n)
{
case SP_POINTN:
if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str))
- goto ret;
+ goto err;
break;
case SP_GEOMETRYN:
if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str))
- goto ret;
+ goto err;
break;
case SP_INTERIORRINGN:
if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
geom.interior_ring_n(n,str))
- goto ret;
+ goto err;
break;
default:
- goto ret;
+ goto err;
}
- null_value= 0;
+ return str;
-ret:
- return null_value ? 0 : str;
+err:
+ null_value=1;
+ return 0;
}
@@ -299,9 +303,9 @@ String *Item_func_point::val_str(String *str)
double x= args[0]->val();
double y= args[1]->val();
- if ( (null_value= (args[0]->null_value ||
- args[1]->null_value ||
- str->realloc(1 + 4 + 8 + 8))))
+ if ((null_value= (args[0]->null_value ||
+ args[1]->null_value ||
+ str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
return 0;
str->length(0);
@@ -328,11 +332,9 @@ String *Item_func_spatial_collection::val_str(String *str)
String arg_value;
uint i;
- null_value= 1;
-
str->length(0);
if (str->reserve(1 + 4 + 4, 512))
- return 0;
+ goto err;
str->q_append((char) Geometry::wkbNDR);
str->q_append((uint32) coll_type);
@@ -342,19 +344,16 @@ String *Item_func_spatial_collection::val_str(String *str)
{
String *res= args[i]->val_str(&arg_value);
if (args[i]->null_value)
- goto ret;
+ goto err;
- if ( coll_type == Geometry::wkbGeometryCollection )
+ if (coll_type == Geometry::wkbGeometryCollection)
{
/*
- In the case of GeometryCollection we don't need
- any checkings for item types, so just copy them
- into target collection
+ In the case of GeometryCollection we don't need any checkings
+ for item types, so just copy them into target collection
*/
- if ((null_value= str->reserve(res->length(), 512)))
- goto ret;
-
- str->q_append(res->ptr(), res->length());
+ if (str->append(res->ptr(), res->length(), (uint32) 512))
+ goto err;
}
else
{
@@ -363,86 +362,75 @@ String *Item_func_spatial_collection::val_str(String *str)
const char *data= res->ptr() + 1;
/*
- In the case of named collection we must to
- check that items are of specific type, let's
- do this checking now
+ In the case of named collection we must to check that items
+ are of specific type, let's do this checking now
*/
if (len < 5)
- goto ret;
+ goto err;
wkb_type= (Geometry::wkbType) uint4korr(data);
data+= 4;
len-= 5;
if (wkb_type != item_type)
- goto ret;
+ goto err;
switch (coll_type) {
case Geometry::wkbMultiPoint:
case Geometry::wkbMultiLineString:
case Geometry::wkbMultiPolygon:
- if (len < WKB_HEADER_SIZE)
- goto ret;
-
- data-= WKB_HEADER_SIZE;
- len+= WKB_HEADER_SIZE;
- if (str->reserve(len, 512))
- goto ret;
- str->q_append(data, len);
+ if (len < WKB_HEADER_SIZE ||
+ str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
+ goto err;
break;
case Geometry::wkbLineString:
- if (str->reserve(POINT_DATA_SIZE, 512))
- goto ret;
- str->q_append(data, POINT_DATA_SIZE);
+ if (str->append(data, POINT_DATA_SIZE, 512))
+ goto err;
break;
-
case Geometry::wkbPolygon:
{
uint32 n_points;
double x1, y1, x2, y2;
+ const char *org_data= data;
if (len < 4 + 2 * POINT_DATA_SIZE)
- goto ret;
-
- uint32 llen= len;
- const char *ldata= data;
+ goto err;
n_points= uint4korr(data);
data+= 4;
float8get(x1, data);
- data+= 8;
+ data+= SIZEOF_STORED_DOUBLE;
float8get(y1, data);
- data+= 8;
+ data+= SIZEOF_STORED_DOUBLE;
data+= (n_points - 2) * POINT_DATA_SIZE;
float8get(x2, data);
- float8get(y2, data + 8);
+ float8get(y2, data + SIZEOF_STORED_DOUBLE);
- if ((x1 != x2) || (y1 != y2))
- goto ret;
-
- if (str->reserve(llen, 512))
- goto ret;
- str->q_append(ldata, llen);
+ if ((x1 != x2) || (y1 != y2) ||
+ str->append(org_data, len, 512))
+ goto err;
}
break;
default:
- goto ret;
+ goto err;
}
}
}
-
if (str->length() > current_thd->variables.max_allowed_packet)
- goto ret;
+ goto err;
null_value = 0;
+ return str;
-ret:
- return null_value ? 0 : str;
+err:
+ null_value= 1;
+ return 0;
}
+
/*
Functions for spatial relations
*/
@@ -453,6 +441,7 @@ longlong Item_func_spatial_rel::val_int()
String *res2= args[1]->val_str(&tmp_value2);
Geometry g1, g2;
MBR mbr1, mbr2;
+ const char *dummy;
if ((null_value= (args[0]->null_value ||
args[1]->null_value ||
@@ -460,12 +449,11 @@ longlong Item_func_spatial_rel::val_int()
res1->length() - SRID_SIZE) ||
g2.create_from_wkb(res2->ptr() + SRID_SIZE,
res2->length() - SRID_SIZE) ||
- g1.get_mbr(&mbr1) ||
- g2.get_mbr(&mbr2))))
+ g1.get_mbr(&mbr1, &dummy) ||
+ g2.get_mbr(&mbr2, &dummy))))
return 0;
- switch (spatial_rel)
- {
+ switch (spatial_rel) {
case SP_CONTAINS_FUNC:
return mbr1.contains(&mbr2);
case SP_WITHIN_FUNC:
@@ -490,6 +478,7 @@ longlong Item_func_spatial_rel::val_int()
return 0;
}
+
longlong Item_func_isempty::val_int()
{
String tmp;
@@ -497,23 +486,25 @@ longlong Item_func_isempty::val_int()
return args[0]->null_value ? 1 : 0;
}
+
longlong Item_func_issimple::val_int()
{
String tmp;
String *wkb=args[0]->val_str(&tmp);
- if ((null_value= (!wkb || args[0]->null_value )))
+ if ((null_value= (!wkb || args[0]->null_value)))
return 0;
/* TODO: Ramil or Holyfoot, add real IsSimple calculation */
return 0;
}
+
longlong Item_func_isclosed::val_int()
{
String tmp;
String *swkb= args[0]->val_str(&tmp);
Geometry geom;
- int isclosed;
+ int isclosed= 0; // In case of error
null_value= (!swkb ||
args[0]->null_value ||
@@ -529,23 +520,26 @@ longlong Item_func_isclosed::val_int()
Numerical functions
*/
+
longlong Item_func_dimension::val_int()
{
- uint32 dim;
+ uint32 dim= 0; // In case of error
String *swkb= args[0]->val_str(&value);
Geometry geom;
+ const char *dummy;
null_value= (!swkb ||
args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) ||
- geom.dimension(&dim));
+ geom.dimension(&dim, &dummy));
return (longlong) dim;
}
+
longlong Item_func_numinteriorring::val_int()
{
- uint32 num;
+ uint32 num= 0; // In case of error
String *swkb= args[0]->val_str(&value);
Geometry geom;
@@ -557,9 +551,10 @@ longlong Item_func_numinteriorring::val_int()
return (longlong) num;
}
+
longlong Item_func_numgeometries::val_int()
{
- uint32 num= 0;
+ uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
@@ -571,9 +566,10 @@ longlong Item_func_numgeometries::val_int()
return (longlong) num;
}
+
longlong Item_func_numpoints::val_int()
{
- uint32 num;
+ uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
@@ -586,9 +582,10 @@ longlong Item_func_numpoints::val_int()
return (longlong) num;
}
+
double Item_func_x::val()
{
- double res;
+ double res= 0.0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
@@ -600,9 +597,10 @@ double Item_func_x::val()
return res;
}
+
double Item_func_y::val()
{
- double res;
+ double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
@@ -614,23 +612,25 @@ double Item_func_y::val()
return res;
}
+
double Item_func_area::val()
{
- double res;
+ double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
+ const char *dummy;
null_value= (!swkb ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) ||
!GEOM_METHOD_PRESENT(geom, area) ||
- geom.area(&res));
+ geom.area(&res, &dummy));
return res;
}
double Item_func_glength::val()
{
- double res;
+ double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
@@ -650,8 +650,10 @@ longlong Item_func_srid::val_int()
null_value= (!swkb ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE));
- uint32 res= uint4korr(swkb->ptr());
- return (longlong) res;
+ if (null_value)
+ return 0;
+
+ return (longlong) (uint4korr(swkb->ptr()));
}
#endif /*HAVE_SPATIAL*/
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 545052807ec..a1f36130152 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -23,8 +23,6 @@
#pragma interface /* gcc class implementation */
#endif
-#define SRID_SIZE sizeof(uint32)
-
class Item_func_geometry_from_text: public Item_str_func
{
public:
diff --git a/sql/spatial.cc b/sql/spatial.cc
index d19429fdd9c..908fe6b8af4 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1,9 +1,23 @@
-#include "mysql_priv.h"
+/* Copyright (C) 2004 MySQL AB
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 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 */
+
+#include "mysql_priv.h"
#define MAX_DIGITS_IN_DOUBLE 16
-/***************************** GClassInfo *******************************/
+/***************************** Gis_class_info *******************************/
#define IMPLEMENT_GEOM(class_name, type_id, name) \
{ \
@@ -14,12 +28,12 @@
(GF_GetD) &class_name::get_x, \
(GF_GetD) &class_name::get_y, \
(GF_GetD) &class_name::length, \
- (GF_GetD) &class_name::area, \
+ (GF_GetD_AND_END) &class_name::area, \
(GF_GetI) &class_name::is_closed, \
(GF_GetUI) &class_name::num_interior_ring, \
(GF_GetUI) &class_name::num_points, \
(GF_GetUI) &class_name::num_geometries, \
- (GF_GetUI) &class_name::dimension, \
+ (GF_GetUI_AND_END) &class_name::dimension, \
(GF_GetWS) &class_name::start_point, \
(GF_GetWS) &class_name::end_point, \
(GF_GetWS) &class_name::exterior_ring, \
@@ -27,54 +41,63 @@
(GF_GetUIWS) &class_name::point_n, \
(GF_GetUIWS) &class_name::interior_ring_n, \
(GF_GetUIWS) &class_name::geometry_n, \
- class_name::type_id, \
name, \
+ class_name::type_id, \
NULL \
-},
+}
+
+static LEX_STRING_WITH_INIT point_name("POINT", 5);
+static LEX_STRING_WITH_INIT linestring_name("LINESTRING", 10);
+static LEX_STRING_WITH_INIT polygon_name("POLYGON",7);
+static LEX_STRING_WITH_INIT multipoint_name("MULTIPOINT",10);
+static LEX_STRING_WITH_INIT multilinestring_name("MULTILINESTRING",15);
+static LEX_STRING_WITH_INIT multipolygon_name("MULTIPOLYGON",12);
+static LEX_STRING_WITH_INIT geometrycollection_name("GEOMETRYCOLLECTION",18);
-static Geometry::GClassInfo ci_collection[] =
+static Geometry::Gis_class_info ci_collection[]=
{
- IMPLEMENT_GEOM(GPoint, wkbPoint, "POINT")
- IMPLEMENT_GEOM(GLineString, wkbLineString, "LINESTRING")
- IMPLEMENT_GEOM(GPolygon, wkbPolygon, "POLYGON")
- IMPLEMENT_GEOM(GMultiPoint, wkbMultiPoint, "MULTIPOINT")
- IMPLEMENT_GEOM(GMultiLineString, wkbMultiLineString, "MULTILINESTRING")
- IMPLEMENT_GEOM(GMultiPolygon, wkbMultiPolygon, "MULTIPOLYGON")
- IMPLEMENT_GEOM(GGeometryCollection, wkbGeometryCollection, "GEOMETRYCOLLECTION")
+ IMPLEMENT_GEOM(Gis_point, wkbPoint, point_name),
+ IMPLEMENT_GEOM(Gis_line_string, wkbLineString, linestring_name),
+ IMPLEMENT_GEOM(Gis_polygon, wkbPolygon, polygon_name),
+ IMPLEMENT_GEOM(Gis_multi_point, wkbMultiPoint, multipoint_name),
+ IMPLEMENT_GEOM(Gis_multi_line_stringg, wkbMultiLineString, multilinestring_name),
+ IMPLEMENT_GEOM(Gis_multi_polygon, wkbMultiPolygon, multipolygon_name),
+ IMPLEMENT_GEOM(Gis_geometry_collection, wkbGeometryCollection,
+ geometrycollection_name)
};
-static Geometry::GClassInfo *ci_collection_end = ci_collection + sizeof(ci_collection)/sizeof(ci_collection[0]);
+static Geometry::Gis_class_info *ci_collection_end=
+(ci_collection + array_elements(ci_collection));
+
/***************************** Geometry *******************************/
-Geometry::GClassInfo *Geometry::find_class(int type_id)
+Geometry::Gis_class_info *Geometry::find_class(int type_id)
{
- for (GClassInfo *cur_rt = ci_collection; cur_rt < ci_collection_end; ++cur_rt)
+ for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++)
{
if (cur_rt->m_type_id == type_id)
- {
return cur_rt;
- }
}
- return NULL;
+ return 0;
}
-Geometry::GClassInfo *Geometry::find_class(const char *name, size_t len)
+
+Geometry::Gis_class_info *Geometry::find_class(const char *name, uint32 len)
{
- for (GClassInfo *cur_rt = ci_collection;
- cur_rt < ci_collection_end; ++cur_rt)
+ for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++)
{
- if ((cur_rt->m_name[len] == 0) &&
- (my_strnncoll(&my_charset_latin1, (const uchar*)cur_rt->m_name, len,
- (const uchar*)name, len) == 0))
- {
+ if ((cur_rt->m_name.length == len) &&
+ (my_strnncoll(&my_charset_latin1,
+ (const uchar*) cur_rt->m_name.str, len,
+ (const uchar*) name, len) == 0))
return cur_rt;
- }
}
- return NULL;
+ return 0;
}
+
int Geometry::create_from_wkb(const char *data, uint32 data_len)
{
uint32 geom_type;
@@ -82,43 +105,39 @@ int Geometry::create_from_wkb(const char *data, uint32 data_len)
if (data_len < 1 + 4)
return 1;
data++;
-//FIXME: check byte ordering
+ /*
+ FIXME: check byte ordering
+ Also check if we could replace this with one byte
+ */
geom_type= uint4korr(data);
data+= 4;
- m_vmt= find_class(geom_type);
- if (!m_vmt)
- return -1;
+ if (!(m_vmt= find_class((int) geom_type)))
+ return 1;
m_data= data;
m_data_end= data + data_len;
return 0;
}
-int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream)
+
+int Geometry::create_from_wkt(Gis_read_stream *trs, String *wkt,
+ bool init_stream)
{
- int name_len;
- const char *name = trs->get_next_word(&name_len);
- if (!name)
+ LEX_STRING name;
+
+ if (trs->get_next_word(&name))
{
trs->set_error_msg("Geometry name expected");
- return -1;
- }
- if (!(m_vmt = find_class(name, name_len)))
- return -1;
- if (wkt->reserve(1 + 4, 512))
return 1;
- wkt->q_append((char)wkbNDR);
- wkt->q_append((uint32)get_class_info()->m_type_id);
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return -1;
}
- if (init_from_wkt(trs, wkt)) return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
- return -1;
- }
+ if (!(m_vmt= find_class(name.str, name.length)) ||
+ wkt->reserve(1 + 4, 512))
+ return 1;
+ wkt->q_append((char) wkbNDR);
+ wkt->q_append((uint32) get_class_info()->m_type_id);
+ if (trs->check_next_symbol('(') ||
+ init_from_wkt(trs, wkt) ||
+ trs->check_next_symbol(')'))
+ return 1;
if (init_stream)
{
init_from_wkb(wkt->ptr(), wkt->length());
@@ -127,19 +146,19 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream
return 0;
}
-int Geometry::envelope(String *result) const
+
+bool Geometry::envelope(String *result) const
{
MBR mbr;
+ const char *end;
- get_mbr(&mbr);
-
- if (result->reserve(1+4*3+sizeof(double)*10))
+ if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPolygon);
- result->q_append((uint32)1);
- result->q_append((uint32)5);
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbPolygon);
+ result->q_append((uint32) 1);
+ result->q_append((uint32) 5);
result->q_append(mbr.xmin);
result->q_append(mbr.ymin);
result->q_append(mbr.xmax);
@@ -154,29 +173,151 @@ int Geometry::envelope(String *result) const
return 0;
}
+
+/*
+ Create a point from data.
+
+ SYNPOSIS
+ create_point()
+ result Put result here
+ data Data for point is here.
+
+ RETURN
+ 0 ok
+ 1 Can't reallocate 'result'
+*/
+
+bool Geometry::create_point(String *result, const char *data)
+{
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2) ||
+ result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ return 1;
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbPoint);
+ /* Copy two double in same format */
+ result->q_append(data, SIZEOF_STORED_DOUBLE*2);
+ return 0;
+}
+
+/*
+ Create a point from coordinates.
+
+ SYNPOSIS
+ create_point()
+ result Put result here
+ x x coordinate for point
+ y y coordinate for point
+
+ RETURN
+ 0 ok
+ 1 Can't reallocate 'result'
+*/
+
+bool Geometry::create_point(String *result, double x, double y)
+{
+ if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ return 1;
+
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbPoint);
+ result->q_append(x);
+ result->q_append(y);
+ return 0;
+}
+
+/*
+ Append N points from packed format to text
+
+ SYNOPSIS
+ append_points()
+ txt Append points here
+ n_points Number of points
+ data Packed data
+ offset Offset between points
+
+ RETURN
+ # end of data
+*/
+
+const char *Geometry::append_points(String *txt, uint32 n_points,
+ const char *data, uint32 offset)
+{
+ while (n_points--)
+ {
+ double d;
+ data+= offset;
+ float8get(d, data);
+ txt->qs_append(d);
+ txt->qs_append(' ');
+ float8get(d, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ txt->qs_append(d);
+ txt->qs_append(',');
+ }
+ return data;
+}
+
+
+/*
+ Get most bounding rectangle (mbr) for X points
+
+ SYNOPSIS
+ get_mbr_for_points()
+ mbr MBR (store rectangle here)
+ points Number of points
+ data Packed data
+ offset Offset between points
+
+ RETURN
+ 0 Wrong data
+ # end of data
+*/
+
+const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
+ uint offset) const
+{
+ uint32 points;
+ /* read number of points */
+ if (no_data(data, 4))
+ return 0;
+ points= uint4korr(data);
+ data+= 4;
+
+ if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
+ return 0;
+
+ /* Calculate MBR for points */
+ while (points--)
+ {
+ data+= offset;
+ mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ }
+ return data;
+}
+
+
/***************************** Point *******************************/
-size_t GPoint::get_data_size() const
+uint32 Gis_point::get_data_size() const
{
return POINT_DATA_SIZE;
}
-int GPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
double x, y;
- if (wkb->reserve(sizeof(double)*2))
- return 1;
- if (trs->get_next_number(&x))
- return 1;
- if (trs->get_next_number(&y))
+ if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
+ wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
return 1;
wkb->q_append(x);
wkb->q_append(y);
-
return 0;
}
-int GPoint::get_data_as_wkt(String *txt) const
+
+bool Gis_point::get_data_as_wkt(String *txt, const char **end)
{
double x, y;
if (get_xy(&x, &y))
@@ -186,324 +327,250 @@ int GPoint::get_data_as_wkt(String *txt) const
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
+ *end= m_data+ POINT_DATA_SIZE;
return 0;
}
-int GPoint::get_mbr(MBR *mbr) const
+
+int Gis_point::get_mbr(MBR *mbr, const char **end) const
{
double x, y;
if (get_xy(&x, &y))
return 1;
mbr->add_xy(x, y);
+ *end= m_data+ POINT_DATA_SIZE;
return 0;
}
+
/***************************** LineString *******************************/
-size_t GLineString::get_data_size() const
+uint32 Gis_line_string::get_data_size() const
{
- uint32 n_points = uint4korr(m_data);
-
- return 4 + n_points*POINT_DATA_SIZE;
+ if (no_data(m_data, 4))
+ return GET_SIZE_ERROR;
+ return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
}
-int GLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_points = 0;
- int np_pos = wkb->length();
- GPoint p;
+ uint32 n_points= 0;
+ uint32 np_pos= wkb->length();
+ Gis_point p;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_points);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (p.init_from_wkt(trs, wkb))
return 1;
- ++n_points;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else break;
+ n_points++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
}
-
- if (n_points<2)
+ if (n_points < 2)
{
trs->set_error_msg("Too few points in LINESTRING");
return 1;
}
-
- wkb->WriteAtPosition(np_pos, n_points);
-
+ wkb->write_at_position(np_pos, n_points);
return 0;
}
-int GLineString::get_data_as_wkt(String *txt) const
+
+bool Gis_line_string::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_points;
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, 4))
return 1;
-
- n_points = uint4korr(data);
+ n_points= uint4korr(data);
data += 4;
- if (no_data(data, sizeof(double) * 2 * n_points))
+ if (n_points < 1 ||
+ no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
+ txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1;
- if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
- return 1;
- for (; n_points>0; --n_points)
+ while (n_points--)
{
double x, y;
float8get(x, data);
- data += sizeof(double);
- float8get(y, data);
- data += sizeof(double);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
txt->qs_append(',');
}
- txt->length(txt->length() - 1);
+ txt->length(txt->length() - 1); // Remove end ','
+ *end= data;
return 0;
}
-int GLineString::get_mbr(MBR *mbr) const
-{
- uint32 n_points;
- const char *data = m_data;
-
- if (no_data(data, 4))
- return 1;
-
- n_points = uint4korr(data);
- data += 4;
-
- if (no_data(data, sizeof(double) * 2 * n_points))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
- return 0;
+bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const
+{
+ return (*end=get_mbr_for_points(mbr, m_data, 0)) == 0;
}
-int GLineString::length(double *len) const
+
+bool Gis_line_string::length(double *len) const
{
uint32 n_points;
double prev_x, prev_y;
- const char *data = m_data;
+ const char *data= m_data;
- *len=0;
+ *len= 0; // In case of errors
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
-
- if (no_data(data, sizeof(double) * 2 * n_points))
+ n_points= uint4korr(data);
+ data+= 4;
+ if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
- --n_points;
float8get(prev_x, data);
- data += 8;
- float8get(prev_y, data);
- data += 8;
+ float8get(prev_y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE*2;
- for (; n_points>0; --n_points)
+ while (--n_points)
{
double x, y;
float8get(x, data);
- data += 8;
- float8get(y, data);
- data += 8;
- *len+=sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
- prev_x=x;
- prev_y=y;
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ *len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
+ prev_x= x;
+ prev_y= y;
}
return 0;
}
-int GLineString::is_closed(int *closed) const
+bool Gis_line_string::is_closed(int *closed) const
{
uint32 n_points;
double x1, y1, x2, y2;
-
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ n_points= uint4korr(data);
+ data+= 4;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
+
+ /* Get first point */
float8get(x1, data);
- data += 8;
- float8get(y1, data);
- data += 8 + (n_points-2)*POINT_DATA_SIZE;
- float8get(x2, data);
- data += 8;
- float8get(y2, data);
+ float8get(y1, data + SIZEOF_STORED_DOUBLE);
- *closed=(x1==x2)&&(y1==y2);
+ /* get last point */
+ data+= SIZEOF_STORED_DOUBLE*2 + (n_points-2)*POINT_DATA_SIZE;
+ float8get(x2, data);
+ float8get(y2, data + SIZEOF_STORED_DOUBLE);
+ *closed= (x1==x2) && (y1==y2);
return 0;
}
-int GLineString::num_points(uint32 *n_points) const
+
+bool Gis_line_string::num_points(uint32 *n_points) const
{
- *n_points = uint4korr(m_data);
+ *n_points= uint4korr(m_data);
return 0;
}
-int GLineString::start_point(String *result) const
-{
- const char *data= m_data + 4;
- if (no_data(data, 8 + 8))
- return 1;
-
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
-
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
- return 0;
+bool Gis_line_string::start_point(String *result)
+{
+ /* +4 is for skipping over number of points */
+ return create_point(result, m_data + 4);
}
-int GLineString::end_point(String *result) const
+
+bool Gis_line_string::end_point(String *result)
{
- const char *data= m_data;
uint32 n_points;
-
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- n_points= uint4korr(data);
-
- data+= 4 + (n_points - 1) * POINT_DATA_SIZE;
-
- if (no_data(data, 8 + 8))
- return 1;
-
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
-
- return 0;
+ n_points= uint4korr(m_data);
+ return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
}
-int GLineString::point_n(uint32 num, String *result) const
+bool Gis_line_string::point_n(uint32 num, String *result)
{
- const char *data= m_data;
uint32 n_points;
-
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- n_points= uint4korr(data);
-
+ n_points= uint4korr(m_data);
if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1)
return 1;
- data+= 4 + (num - 1) * POINT_DATA_SIZE;
-
- if (no_data(data, 8 + 8))
- return 1;
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
-
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
-
- return 0;
+ return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
}
+
/***************************** Polygon *******************************/
-size_t GPolygon::get_data_size() const
+uint32 Gis_polygon::get_data_size() const
{
- uint32 n_linear_rings = 0;
- const char *data = m_data;
+ uint32 n_linear_rings;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
+ return GET_SIZE_ERROR;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ while (n_linear_rings--)
{
if (no_data(data, 4))
- return 1;
- data += 4 + uint4korr(data)*POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_linear_rings = 0;
- int lr_pos = wkb->length();
+ uint32 n_linear_rings= 0;
+ uint32 lr_pos= wkb->length();
+ int closed;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_linear_rings);
-
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- GLineString ls;
- size_t ls_pos=wkb->length();
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (ls.init_from_wkt(trs, wkb))
- return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ Gis_line_string ls;
+ uint32 ls_pos=wkb->length();
+ if (trs->check_next_symbol('(') ||
+ ls.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
+
ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos);
- int closed;
- ls.is_closed(&closed);
- if (!closed)
+ if (ls.is_closed(&closed) || !closed)
{
trs->set_error_msg("POLYGON's linear ring isn't closed");
return 1;
}
- ++n_linear_rings;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_linear_rings++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(lr_pos, n_linear_rings);
+ wkb->write_at_position(lr_pos, n_linear_rings);
return 0;
}
-int GPolygon::get_data_as_wkt(String *txt) const
+
+bool Gis_polygon::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_linear_rings;
const char *data= m_data;
@@ -514,1059 +581,1012 @@ int GPolygon::get_data_as_wkt(String *txt) const
n_linear_rings= uint4korr(data);
data+= 4;
- for (; n_linear_rings > 0; --n_linear_rings)
+ while (n_linear_rings--)
{
+ uint32 n_points;
if (no_data(data, 4))
return 1;
- uint32 n_points= uint4korr(data);
+ n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (8 + 8) * n_points))
- return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
-
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1]= ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')'; // Replace end ','
txt->qs_append(',');
}
- txt->length(txt->length() - 1);
+ txt->length(txt->length() - 1); // Remove end ','
+ *end= data;
return 0;
}
-int GPolygon::get_mbr(MBR *mbr) const
+
+bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_linear_rings;
+ const char *data= m_data;
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
- uint32 n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8) * n_points))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
}
+ *end= data;
return 0;
}
-int GPolygon::area(double *ar) const
+
+bool Gis_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_linear_rings;
- double result = -1.0;
+ double result= -1.0;
+ const char *data= m_data;
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
{
double prev_x, prev_y;
- double lr_area=0;
+ double lr_area= 0;
+ uint32 n_points;
+
if (no_data(data, 4))
return 1;
- uint32 n_points = uint4korr(data);
- if (no_data(data, (8+8) * n_points))
+ n_points= uint4korr(data);
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data+4);
- float8get(prev_y, data+(4+8));
- data += (4+8+8);
+ float8get(prev_y, data+(4+SIZEOF_STORED_DOUBLE));
+ data+= (4+SIZEOF_STORED_DOUBLE*2);
- --n_points;
- for (; n_points>0; --n_points)
+ while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
- float8get(y, data + 8);
- lr_area+=(prev_x+x)*(prev_y-y);
- prev_x=x;
- prev_y=y;
- data += (8+8);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
+ /* QQ: Is the following prev_x+x right ? */
+ lr_area+= (prev_x + x)* (prev_y - y);
+ prev_x= x;
+ prev_y= y;
}
- lr_area=fabs(lr_area)/2;
- if (result==-1) result=lr_area;
- else result-=lr_area;
+ lr_area= fabs(lr_area)/2;
+ if (result == -1.0)
+ result= lr_area;
+ else
+ result-= lr_area;
}
- *ar=fabs(result);
+ *ar= fabs(result);
+ *end_of_data= data;
return 0;
}
-int GPolygon::exterior_ring(String *result) const
+bool Gis_polygon::exterior_ring(String *result)
{
- uint32 n_points;
- const char *data = m_data + 4; // skip n_linerings
+ uint32 n_points, length;
+ const char *data= m_data + 4; // skip n_linerings
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, n_points * POINT_DATA_SIZE))
- return 1;
-
- if (result->reserve(1+4+4+ n_points * POINT_DATA_SIZE))
+ n_points= uint4korr(data);
+ data+= 4;
+ length= n_points * POINT_DATA_SIZE;
+ if (no_data(data, length) || result->reserve(1+4+4+ length))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbLineString);
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbLineString);
result->q_append(n_points);
result->q_append(data, n_points * POINT_DATA_SIZE);
-
return 0;
}
-int GPolygon::num_interior_ring(uint32 *n_int_rings) const
+
+bool Gis_polygon::num_interior_ring(uint32 *n_int_rings) const
{
- const char *data = m_data;
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- *n_int_rings = uint4korr(data);
- --(*n_int_rings);
-
+ *n_int_rings= uint4korr(m_data)-1;
return 0;
}
-int GPolygon::interior_ring_n(uint32 num, String *result) const
+
+bool Gis_polygon::interior_ring_n(uint32 num, String *result) const
{
- const char *data = m_data;
+ const char *data= m_data;
uint32 n_linear_rings;
uint32 n_points;
+ uint32 points_size;
if (no_data(data, 4))
return 1;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- n_linear_rings = uint4korr(data);
- data += 4;
- if ((num >= n_linear_rings) || (num < 1))
- return -1;
+ if (num >= n_linear_rings || num < 1)
+ return 1;
- for (; num > 0; --num)
+ while (num--)
{
if (no_data(data, 4))
return 1;
- data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- int points_size = n_points * POINT_DATA_SIZE;
- data += 4;
- if (no_data(data, points_size))
- return 1;
-
- if (result->reserve(1+4+4+ points_size))
+ n_points= uint4korr(data);
+ points_size= n_points * POINT_DATA_SIZE;
+ data+= 4;
+ if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbLineString);
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbLineString);
result->q_append(n_points);
result->q_append(data, points_size);
return 0;
}
-int GPolygon::centroid_xy(double *x, double *y) const
+
+bool Gis_polygon::centroid_xy(double *x, double *y) const
{
uint32 n_linear_rings;
- uint32 i;
double res_area, res_cx, res_cy;
- const char *data = m_data;
+ const char *data= m_data;
+ bool first_loop= 1;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- for (i = 0; i < n_linear_rings; ++i)
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
+ uint32 n_points, org_n_points;
double prev_x, prev_y;
- double cur_area = 0;
- double cur_cx = 0;
- double cur_cy = 0;
+ double cur_area= 0;
+ double cur_cx= 0;
+ double cur_cy= 0;
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ if (no_data(data, 4))
+ return 1;
+ org_n_points= n_points= uint4korr(data);
+ data+= 4;
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data);
- float8get(prev_y, data+8);
- data += (8+8);
+ float8get(prev_y, data+SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
- uint32 n = n_points - 1;
- for (; n > 0; --n)
+ while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
- float8get(y, data + 8);
-
- cur_area += (prev_x + x) * (prev_y - y);
- cur_cx += x;
- cur_cy += y;
- prev_x = x;
- prev_y = y;
- data += (8+8);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
+ /* QQ: Is the following prev_x+x right ? */
+ cur_area+= (prev_x + x) * (prev_y - y);
+ cur_cx+= x;
+ cur_cy+= y;
+ prev_x= x;
+ prev_y= y;
}
- cur_area = fabs(cur_area) / 2;
- cur_cx = cur_cx / (n_points - 1);
- cur_cy = cur_cy / (n_points - 1);
+ cur_area= fabs(cur_area) / 2;
+ cur_cx= cur_cx / (org_n_points - 1);
+ cur_cy= cur_cy / (org_n_points - 1);
- if (i)
+ if (!first_loop)
{
- double d_area = res_area - cur_area;
+ double d_area= res_area - cur_area;
if (d_area <= 0)
return 1;
- res_cx = (res_area * res_cx - cur_area * cur_cx) / d_area;
- res_cy = (res_area * res_cy - cur_area * cur_cy) / d_area;
+ res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area;
+ res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area;
}
else
{
- res_area = cur_area;
- res_cx = cur_cx;
- res_cy = cur_cy;
+ first_loop= 0;
+ res_area= cur_area;
+ res_cx= cur_cx;
+ res_cy= cur_cy;
}
}
- *x = res_cx;
- *y = res_cy;
-
+ *x= res_cx;
+ *y= res_cy;
return 0;
}
-int GPolygon::centroid(String *result) const
+
+bool Gis_polygon::centroid(String *result)
{
double x, y;
-
- this->centroid_xy(&x, &y);
- if (result->reserve(1 + 4 + sizeof(double) * 2))
+ if (centroid_xy(&x, &y))
return 1;
-
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPoint);
- result->q_append(x);
- result->q_append(y);
-
- return 0;
+ return create_point(result, x, y);
}
/***************************** MultiPoint *******************************/
-size_t GMultiPoint::get_data_size() const
+uint32 Gis_multi_point::get_data_size() const
{
+ if (no_data(m_data, 4))
+ return GET_SIZE_ERROR;
return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
}
-int GMultiPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_points = 0;
- int np_pos = wkb->length();
- GPoint p;
+ uint32 n_points= 0;
+ uint32 np_pos= wkb->length();
+ Gis_point p;
if (wkb->reserve(4, 512))
return 1;
- wkb->q_append((uint32)n_points);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbPoint);
+ wkb->q_append((char) wkbNDR);
+ wkb->q_append((uint32) wkbPoint);
if (p.init_from_wkt(trs, wkb))
return 1;
- ++n_points;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_points++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(np_pos, n_points);
-
+ wkb->write_at_position(np_pos, n_points); // Store number of found points
return 0;
}
-int GMultiPoint::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_points;
- const char *data= m_data;
- if (no_data(data, 4))
- return 1;
-
- n_points= uint4korr(data);
- data+= 4;
- if (no_data(data, n_points * (8 + 8 + WKB_HEADER_SIZE)))
+ if (no_data(m_data, 4))
return 1;
- if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ n_points= uint4korr(m_data);
+ if (no_data(m_data+4,
+ n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
+ txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
-
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data + WKB_HEADER_SIZE);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + WKB_HEADER_SIZE + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= WKB_HEADER_SIZE + 8 + 8;
- }
- txt->length(txt->length()-1);
+ *end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
+ txt->length(txt->length()-1); // Remove end ','
return 0;
}
-int GMultiPoint::get_mbr(MBR *mbr) const
+
+bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const
{
- uint32 n_points;
- const char *data = m_data;
- if (no_data(data, 4))
- return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, n_points * (8+8+WKB_HEADER_SIZE)))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data + WKB_HEADER_SIZE, data + 8 + WKB_HEADER_SIZE);
- data += (8+8+WKB_HEADER_SIZE);
- }
- return 0;
+ return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0;
}
-int GMultiPoint::num_geometries(uint32 *num) const
+
+bool Gis_multi_point::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiPoint::geometry_n(uint32 num, String *result) const
+
+bool Gis_multi_point::geometry_n(uint32 num, String *result) const
{
const char *data= m_data;
uint32 n_points;
+
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
- data+= 4;
- if ((num > n_points) || (num < 1))
- return -1;
- data+= (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
- if (result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
+ data+= 4+ (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
+
+ if (num > n_points || num < 1 ||
+ no_data(data, WKB_HEADER_SIZE + POINT_DATA_SIZE) ||
+ result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
return 1;
- result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
+ result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
return 0;
}
+
/***************************** MultiLineString *******************************/
-size_t GMultiLineString::get_data_size() const
+uint32 Gis_multi_line_stringg::get_data_size() const
{
- uint32 n_line_strings = 0;
- const char *data = m_data;
+ uint32 n_line_strings;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_line_strings= uint4korr(data);
+ data+= 4;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
- return 1;
- data += WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
+ POINT_DATA_SIZE);
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GMultiLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_line_stringg::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_line_strings = 0;
- int ls_pos = wkb->length();
+ uint32 n_line_strings= 0;
+ uint32 ls_pos= wkb->length();
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_line_strings);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- GLineString ls;
+ Gis_line_string ls;
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbLineString);
-
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (ls.init_from_wkt(trs, wkb))
- return 1;
+ wkb->q_append((char) wkbNDR);
+ wkb->q_append((uint32) wkbLineString);
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ if (trs->check_next_symbol('(') ||
+ ls.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- ++n_line_strings;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_line_strings++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(ls_pos, n_line_strings);
-
+ wkb->write_at_position(ls_pos, n_line_strings);
return 0;
}
-int GMultiLineString::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_line_stringg::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_line_strings;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
- for (; n_line_strings > 0; --n_line_strings)
+
+ while (n_line_strings--)
{
+ uint32 n_points;
if (no_data(data, (WKB_HEADER_SIZE + 4)))
return 1;
- uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- if (no_data(data, n_points * (8 + 8)))
- return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1] = ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GMultiLineString::get_mbr(MBR *mbr) const
+
+bool Gis_multi_line_stringg::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_line_strings;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ n_line_strings= uint4korr(data);
+ data+= 4;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
- if (no_data(data, WKB_HEADER_SIZE + 4))
- return 1;
- uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
- data += 4+WKB_HEADER_SIZE;
- if (no_data(data, (8+8)*n_points))
+ data+= WKB_HEADER_SIZE;
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
-
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
}
+ *end= data;
return 0;
}
-int GMultiLineString::num_geometries(uint32 *num) const
+
+bool Gis_multi_line_stringg::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiLineString::geometry_n(uint32 num, String *result) const
+
+bool Gis_multi_line_stringg::geometry_n(uint32 num, String *result) const
{
- uint32 n_line_strings;
+ uint32 n_line_strings, n_points, length;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
if ((num > n_line_strings) || (num < 1))
- return -1;
+ return 1;
- for (; num > 0; --num)
+ for (;;)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
- uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
- if (num == 1)
- {
- if (result->reserve(WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points))
- return 1;
- result->q_append(data, WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE *n_points);
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
+ length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
+ if (no_data(data, length))
+ return 1;
+ if (!--num)
break;
- }
- else
- {
- data+= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points;
- }
+ data+= length;
}
- return 0;
+ return result->append(data, length, (uint32) 0);
}
-int GMultiLineString::length(double *len) const
+
+bool Gis_multi_line_stringg::length(double *len) const
{
uint32 n_line_strings;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ n_line_strings= uint4korr(data);
+ data+= 4;
+
*len=0;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
double ls_len;
- GLineString ls;
- data += WKB_HEADER_SIZE;
- ls.init_from_wkb(data, m_data_end - data);
+ Gis_line_string ls;
+ data+= WKB_HEADER_SIZE;
+ ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.length(&ls_len))
return 1;
- *len+=ls_len;
- data += ls.get_data_size();
+ *len+= ls_len;
+ /*
+ We know here that ls was ok, so we can call the trivial function
+ Gis_line_string::get_data_size without error checking
+ */
+ data+= ls.get_data_size();
}
return 0;
}
-int GMultiLineString::is_closed(int *closed) const
+
+bool Gis_multi_line_stringg::is_closed(int *closed) const
{
uint32 n_line_strings;
- const char *data = m_data;
- if (no_data(data, 1))
+ const char *data= m_data;
+
+ if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1;
- n_line_strings = uint4korr(data);
- data += 4 + WKB_HEADER_SIZE;
- for (; n_line_strings>0; --n_line_strings)
+ n_line_strings= uint4korr(data);
+ data+= 4 + WKB_HEADER_SIZE;
+
+ while (n_line_strings--)
{
- GLineString ls;
- ls.init_from_wkb(data, m_data_end - data);
+ Gis_line_string ls;
+ if (no_data(data, 0))
+ return 1;
+ ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.is_closed(closed))
return 1;
if (!*closed)
return 0;
- data += ls.get_data_size() + WKB_HEADER_SIZE;
+ /*
+ We know here that ls was ok, so we can call the trivial function
+ Gis_line_string::get_data_size without error checking
+ */
+ data+= ls.get_data_size() + WKB_HEADER_SIZE;
}
return 0;
}
+
/***************************** MultiPolygon *******************************/
-size_t GMultiPolygon::get_data_size() const
+uint32 Gis_multi_polygon::get_data_size() const
{
uint32 n_polygons;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
+ uint32 n_linear_rings;
if (no_data(data, 4 + WKB_HEADER_SIZE))
- return 1;
- uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
- data += 4 + WKB_HEADER_SIZE;
+ return GET_SIZE_ERROR;
- for (; n_linear_rings > 0; --n_linear_rings)
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+ data+= 4 + WKB_HEADER_SIZE;
+
+ while (n_linear_rings--)
{
- data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ if (no_data(data, 4))
+ return GET_SIZE_ERROR;
+ data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GMultiPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_polygons = 0;
- int np_pos = wkb->length();
- GPolygon p;
+ uint32 n_polygons= 0;
+ int np_pos= wkb->length();
+ Gis_polygon p;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_polygons);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbPolygon);
+ wkb->q_append((char) wkbNDR);
+ wkb->q_append((uint32) wkbPolygon);
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (p.init_from_wkt(trs, wkb))
- return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ if (trs->check_next_symbol('(') ||
+ p.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- ++n_polygons;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_polygons++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(np_pos, n_polygons);
+ wkb->write_at_position(np_pos, n_polygons);
return 0;
}
-int GMultiPolygon::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_polygons;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
- if (no_data(data, 4 + WKB_HEADER_SIZE))
- return 1;
- data+= WKB_HEADER_SIZE;
- uint32 n_linear_rings= uint4korr(data);
- data+= 4;
-
- if (txt->reserve(1, 512))
+ uint32 n_linear_rings;
+ if (no_data(data, 4 + WKB_HEADER_SIZE) ||
+ txt->reserve(1, 512))
return 1;
+ n_linear_rings= uint4korr(data+WKB_HEADER_SIZE);
+ data+= 4 + WKB_HEADER_SIZE;
txt->q_append('(');
- for (; n_linear_rings>0; --n_linear_rings)
+
+ while (n_linear_rings--)
{
if (no_data(data, 4))
return 1;
uint32 n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (8 + 8) * n_points)) return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
- 512)) return 1;
+ if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
+ 512))
+ return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1] = ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
- (*txt) [txt->length() - 1] = ')';
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GMultiPolygon::get_mbr(MBR *mbr) const
+
+bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_polygons;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
+ uint32 n_linear_rings;
if (no_data(data, 4+WKB_HEADER_SIZE))
return 1;
- uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
- data += WKB_HEADER_SIZE + 4;
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+ data+= WKB_HEADER_SIZE + 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8)*n_points))
- return 1;
-
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
+ return 1;
}
}
+ *end= data;
return 0;
}
-int GMultiPolygon::num_geometries(uint32 *num) const
+
+bool Gis_multi_polygon::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiPolygon::geometry_n(uint32 num, String *result) const
+
+bool Gis_multi_polygon::geometry_n(uint32 num, String *result) const
{
uint32 n_polygons;
- const char *data= m_data, *polygon_n;
- LINT_INIT(polygon_n);
+ const char *data= m_data, *start_of_polygon;
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
- if ((num > n_polygons) || (num < 1))
+ if (num > n_polygons || num < 1)
return -1;
- for (; num > 0; --num)
+ do
{
+ uint32 n_linear_rings;
+ start_of_polygon= data;
+
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
- uint32 n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
-
- if (num == 1)
- polygon_n= data;
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- for (; n_linear_rings > 0; --n_linear_rings)
+
+ while (n_linear_rings--)
{
+ uint32 n_points;
if (no_data(data, 4))
return 1;
- uint32 n_points= uint4korr(data);
+ n_points= uint4korr(data);
data+= 4 + POINT_DATA_SIZE * n_points;
}
- if (num == 1)
- {
- if (result->reserve(data - polygon_n))
- return -1;
- result->q_append(polygon_n, data - polygon_n);
- break;
- }
- }
- return 0;
+ } while (--num);
+ if (no_data(data, 0)) // We must check last segment
+ return 1;
+ return result->append(start_of_polygon, (uint32) (data - start_of_polygon),
+ (uint32) 0);
}
-int GMultiPolygon::area(double *ar) const
+
+bool Gis_multi_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_polygons;
- const char *data = m_data;
- double result = 0;
+ const char *data= m_data;
+ double result= 0;
+
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
double p_area;
+ Gis_polygon p;
- GPolygon p;
- data += WKB_HEADER_SIZE;
- p.init_from_wkb(data, m_data_end - data);
- if (p.area(&p_area))
+ data+= WKB_HEADER_SIZE;
+ p.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (p.area(&p_area, &data))
return 1;
- result += p_area;
- data += p.get_data_size();
+ result+= p_area;
}
- *ar = result;
+ *ar= result;
+ *end_of_data= data;
return 0;
}
-int GMultiPolygon::centroid(String *result) const
+
+bool Gis_multi_polygon::centroid(String *result)
{
uint32 n_polygons;
- uint i;
- GPolygon p;
+ bool first_loop= 1;
+ Gis_polygon p;
double res_area, res_cx, res_cy;
double cur_area, cur_cx, cur_cy;
+ const char *data= m_data;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (i = 0; i < n_polygons; ++i)
+ while (n_polygons--)
{
- data += WKB_HEADER_SIZE;
- p.init_from_wkb(data, m_data_end - data);
- if (p.area(&cur_area))
- return 1;
-
- if (p.centroid_xy(&cur_cx, &cur_cy))
+ data+= WKB_HEADER_SIZE;
+ p.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (p.area(&cur_area, &data) ||
+ p.centroid_xy(&cur_cx, &cur_cy))
return 1;
- if (i)
+ if (!first_loop)
{
- double sum_area = res_area + cur_area;
- res_cx = (res_area * res_cx + cur_area * cur_cx) / sum_area;
- res_cy = (res_area * res_cy + cur_area * cur_cy) / sum_area;
+ double sum_area= res_area + cur_area;
+ res_cx= (res_area * res_cx + cur_area * cur_cx) / sum_area;
+ res_cy= (res_area * res_cy + cur_area * cur_cy) / sum_area;
}
else
{
- res_area = cur_area;
- res_cx = cur_cx;
- res_cy = cur_cy;
+ first_loop= 0;
+ res_area= cur_area;
+ res_cx= cur_cx;
+ res_cy= cur_cy;
}
-
- data += p.get_data_size();
}
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPoint);
- result->q_append(res_cx);
- result->q_append(res_cy);
-
- return 0;
+ return create_point(result, res_cx, res_cy);
}
-/***************************** GeometryCollection *******************************/
-size_t GGeometryCollection::get_data_size() const
+/************************* GeometryCollection ****************************/
+
+uint32 Gis_geometry_collection::get_data_size() const
{
uint32 n_objects;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_objects = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects>0; --n_objects)
+ while (n_objects--)
{
- if (no_data(data, WKB_HEADER_SIZE))
- return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
-
+ uint32 wkb_type,object_size;
Geometry geom;
- if (geom.init(wkb_type))
- return 0;
+ if (no_data(data, WKB_HEADER_SIZE))
+ return GET_SIZE_ERROR;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- geom.init_from_wkb(data, m_data_end - data);
- size_t object_size=geom.get_data_size();
- data += object_size;
+ if (geom.init(wkb_type))
+ return GET_SIZE_ERROR;
+ geom.init_from_wkb(data, (uint) (m_data_end - data));
+ if ((object_size= geom.get_data_size()) == GET_SIZE_ERROR)
+ return GET_SIZE_ERROR;
+ data+= object_size;
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GGeometryCollection::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_objects = 0;
- int no_pos = wkb->length();
+ uint32 n_objects= 0;
+ uint32 no_pos= wkb->length();
Geometry g;
if (wkb->reserve(4, 512))
return 1;
- wkb->q_append((uint32)n_objects);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (g.create_from_wkt(trs, wkb))
return 1;
- if (g.get_class_info()->m_type_id==wkbGeometryCollection)
+ if (g.get_class_info()->m_type_id == wkbGeometryCollection)
{
trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
return 1;
}
- ++n_objects;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else break;
+ n_objects++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
}
- wkb->WriteAtPosition(no_pos, n_objects);
+ wkb->write_at_position(no_pos, n_objects);
return 0;
}
-int GGeometryCollection::get_data_as_wkt(String *txt) const
+
+bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_objects;
- const char *data = m_data;
Geometry geom;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects>0; --n_objects)
+ while (n_objects--)
{
+ uint32 wkb_type;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (geom.as_wkt(txt))
+ geom.init_from_wkb(data, (uint) (m_data_end - data));
+ if (geom.as_wkt(txt, &data))
+ return 1;
+ if (txt->append(",", 1, 512))
return 1;
- data += geom.get_data_size();
- txt->reserve(1, 512);
- txt->q_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GGeometryCollection::get_mbr(MBR *mbr) const
+
+bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_objects;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
- for (; n_objects>0; --n_objects)
+ n_objects= uint4korr(data);
+ data+= 4;
+
+ while (n_objects--)
{
+ uint32 wkb_type;
+ Geometry geom;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
- Geometry geom;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- geom.get_mbr(mbr);
- data += geom.get_data_size();
+ geom.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (geom.get_mbr(mbr, &data))
+ return 1;
}
+ *end= data;
return 0;
}
-int GGeometryCollection::num_geometries(uint32 *num) const
+
+bool Gis_geometry_collection::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ if (no_data(m_data, 4))
+ return 1;
+ *num= uint4korr(m_data);
return 0;
}
-int GGeometryCollection::geometry_n(uint32 num, String *result) const
+
+bool Gis_geometry_collection::geometry_n(uint32 num, String *result) const
{
- const char *data = m_data;
- uint32 n_objects;
+ uint32 n_objects, wkb_type, length;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
+ if (num > n_objects || num < 1)
+ return 1;
- if ((num > n_objects) || (num < 1))
- {
- return -1;
- }
- for (; num > 0; --num)
+ do
{
+ Geometry geom;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- Geometry geom;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (num == 1)
- {
- if (result->reserve(1+4+geom.get_data_size()))
- return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkb_type);
- result->q_append(data, geom.get_data_size());
- break;
- }
- else
- {
- data += geom.get_data_size();
- }
- }
+ geom.init_from_wkb(data, (uint) (m_data_end - data));
+ if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
+ return 1;
+ data+= length;
+ } while (--num);
+
+ /* Copy found object to result */
+ if (result->reserve(1+4+length))
+ return 1;
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkb_type);
+ result->q_append(data-length, length); // data-length = start_of_data
return 0;
}
-int GGeometryCollection::dimension(uint32 *dim) const
+
+/*
+ Return dimension for object
+
+ SYNOPSIS
+ dimension()
+ res_dim Result dimension
+ end End of object will be stored here. May be 0 for
+ simple objects!
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
{
uint32 n_objects;
- *dim = 0;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects > 0; --n_objects)
+ *res_dim= 0;
+ while (n_objects--)
{
+ uint32 wkb_type, length, dim;
+ const char *end_data;
+ Geometry geom;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
-
- uint32 d;
-
- Geometry geom;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (geom.dimension(&d))
+ geom.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (geom.dimension(&dim, &end_data))
return 1;
-
- if (d > *dim)
- *dim = d;
- data += geom.get_data_size();
+ set_if_bigger(*res_dim, dim);
+ if (end_data) // Complex object
+ data= end_data;
+ else if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
+ return 1;
+ else
+ data+= length;
}
+ *end= data;
return 0;
}
-
-/***************************** /objects *******************************/
diff --git a/sql/spatial.h b/sql/spatial.h
index 5fda257f1b1..bc064724ab7 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -17,118 +17,80 @@
#ifndef _spatial_h
#define _spatial_h
-const uint POINT_DATA_SIZE = 8+8;
-const uint WKB_HEADER_SIZE = 1+4;
+const uint SRID_SIZE= 4;
+const uint SIZEOF_STORED_DOUBLE= 8;
+const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
+const uint WKB_HEADER_SIZE= 1+4;
+const uint32 GET_SIZE_ERROR= ((uint32) -1);
-struct stPoint2D
+struct st_point_2d
{
double x;
double y;
};
-struct stLinearRing
+struct st_linear_ring
{
- size_t n_points;
- stPoint2D points;
+ uint32 n_points;
+ st_point_2d points;
};
/***************************** MBR *******************************/
+
+/*
+ It's ok that a lot of the functions are inline as these are only used once
+ in MySQL
+*/
+
struct MBR
{
+ double xmin, ymin, xmax, ymax;
+
MBR()
{
- xmin=DBL_MAX;
- ymin=DBL_MAX;
- xmax=-DBL_MAX;
- ymax=-DBL_MAX;
+ xmin= ymin= DBL_MAX;
+ xmax= ymax= -DBL_MAX;
}
- MBR(const double &_xmin, const double &_ymin,
- const double &_xmax, const double &_ymax)
- {
- xmin=_xmin;
- ymin=_ymin;
- xmax=_xmax;
- ymax=_ymax;
- }
+ MBR(const double xmin_arg, const double ymin_arg,
+ const double xmax_arg, const double ymax_arg)
+ :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg)
+ {}
- MBR(const stPoint2D &min, const stPoint2D &max)
- {
- xmin=min.x;
- ymin=min.y;
- xmax=max.x;
- ymax=max.y;
- }
-
- double xmin;
- double ymin;
- double xmax;
- double ymax;
-
- void add_xy(double x, double y)
+ MBR(const st_point_2d &min, const st_point_2d &max)
+ :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
+ {}
+
+ inline void add_xy(double x, double y)
{
/* Not using "else" for proper one point MBR calculation */
- if (x<xmin)
- {
- xmin=x;
- }
- if (x>xmax)
- {
- xmax=x;
- }
- if (y<ymin)
- {
- ymin=y;
- }
- if (y>ymax)
- {
- ymax=y;
- }
+ if (x < xmin)
+ xmin= x;
+ if (x > xmax)
+ xmax= x;
+ if (y < ymin)
+ ymin= y;
+ if (y > ymax)
+ ymax= y;
}
-
void add_xy(const char *px, const char *py)
{
double x, y;
float8get(x, px);
float8get(y, py);
- /* Not using "else" for proper one point MBR calculation */
- if (x<xmin)
- {
- xmin=x;
- }
- if (x>xmax)
- {
- xmax=x;
- }
- if (y<ymin)
- {
- ymin=y;
- }
- if (y>ymax)
- {
- ymax=y;
- }
+ add_xy(x,y);
}
-
void add_mbr(const MBR *mbr)
{
- if (mbr->xmin<xmin)
- {
- xmin=mbr->xmin;
- }
- if (mbr->xmax>xmax)
- {
- xmax=mbr->xmax;
- }
- if (mbr->ymin<ymin)
- {
- ymin=mbr->ymin;
- }
- if (mbr->ymax>ymax)
- {
- ymax=mbr->ymax;
- }
+ if (mbr->xmin < xmin)
+ xmin= mbr->xmin;
+ if (mbr->xmax > xmax)
+ xmax= mbr->xmax;
+ if (mbr->ymin < ymin)
+ ymin= mbr->ymin;
+ if (mbr->ymax > ymax)
+ ymax= mbr->ymax;
}
int equals(const MBR *mbr)
@@ -177,12 +139,12 @@ struct MBR
int overlaps(const MBR *mbr)
{
- int lb = mbr->inner_point(xmin, ymin);
- int rb = mbr->inner_point(xmax, ymin);
- int rt = mbr->inner_point(xmax, ymax);
- int lt = mbr->inner_point(xmin, ymax);
+ int lb= mbr->inner_point(xmin, ymin);
+ int rb= mbr->inner_point(xmax, ymin);
+ int rt= mbr->inner_point(xmax, ymax);
+ int lt= mbr->inner_point(xmin, ymax);
- int a = lb+rb+rt+lt;
+ int a = lb+rb+rt+lt;
return (a>0) && (a<4) && (!within(mbr));
}
};
@@ -192,16 +154,18 @@ struct MBR
class Geometry;
-typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *);
-typedef int (Geometry::*GF_GetDataAsText)(String *) const;
-typedef size_t (Geometry::*GF_GetDataSize)() const;
-typedef int (Geometry::*GF_GetMBR)(MBR *) const;
+typedef bool (Geometry::*GF_InitFromText)(Gis_read_stream *, String *);
+typedef bool (Geometry::*GF_GetDataAsText)(String *, const char **);
+typedef uint32 (Geometry::*GF_GetDataSize)() const;
+typedef bool (Geometry::*GF_GetMBR)(MBR *, const char **end) const;
-typedef int (Geometry::*GF_GetD)(double *) const;
-typedef int (Geometry::*GF_GetI)(int *) const;
-typedef int (Geometry::*GF_GetUI)(uint32 *) const;
-typedef int (Geometry::*GF_GetWS)(String *) const;
-typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const;
+typedef bool (Geometry::*GF_GetD)(double *) const;
+typedef bool (Geometry::*GF_GetD_AND_END)(double *, const char **) const;
+typedef bool (Geometry::*GF_GetI)(int *) const;
+typedef bool (Geometry::*GF_GetUI)(uint32 *) const;
+typedef bool (Geometry::*GF_GetUI_AND_END)(uint32 *, const char **) const;
+typedef bool (Geometry::*GF_GetWS)(String *);
+typedef bool (Geometry::*GF_GetUIWS)(uint32, String *) const;
#define GEOM_METHOD_PRESENT(geom_obj, method)\
(geom_obj.m_vmt->method != &Geometry::method)
@@ -211,21 +175,22 @@ class Geometry
public:
enum wkbType
{
- wkbPoint = 1,
- wkbLineString = 2,
- wkbPolygon = 3,
- wkbMultiPoint = 4,
- wkbMultiLineString = 5,
- wkbMultiPolygon = 6,
- wkbGeometryCollection = 7
+ wkbPoint= 1,
+ wkbLineString= 2,
+ wkbPolygon= 3,
+ wkbMultiPoint= 4,
+ wkbMultiLineString= 5,
+ wkbMultiPolygon= 6,
+ wkbGeometryCollection= 7,
+ wkb_end=8
};
enum wkbByteOrder
{
- wkbXDR = 0, /* Big Endian */
- wkbNDR = 1 /* Little Endian */
+ wkbXDR= 0, /* Big Endian */
+ wkbNDR= 1 /* Little Endian */
};
- class GClassInfo
+ class Gis_class_info
{
public:
GF_InitFromText init_from_wkt;
@@ -235,14 +200,14 @@ public:
GF_GetD get_x;
GF_GetD get_y;
GF_GetD length;
- GF_GetD area;
+ GF_GetD_AND_END area;
GF_GetI is_closed;
GF_GetUI num_interior_ring;
GF_GetUI num_points;
GF_GetUI num_geometries;
- GF_GetUI dimension;
+ GF_GetUI_AND_END dimension;
GF_GetWS start_point;
GF_GetWS end_point;
@@ -253,248 +218,291 @@ public:
GF_GetUIWS interior_ring_n;
GF_GetUIWS geometry_n;
+ LEX_STRING m_name;
int m_type_id;
- const char *m_name;
- GClassInfo *m_next_rt;
+ Gis_class_info *m_next_rt;
};
- GClassInfo *m_vmt;
+ Gis_class_info *m_vmt;
- const GClassInfo *get_class_info() const { return m_vmt; }
- size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); }
+ const Gis_class_info *get_class_info() const { return m_vmt; }
+ uint32 get_data_size() const { return (this->*m_vmt->get_data_size)(); }
- int init_from_wkt(GTextReadStream *trs, String *wkb)
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb)
{ return (this->*m_vmt->init_from_wkt)(trs, wkb); }
- int get_data_as_wkt(String *txt) const
- { return (this->*m_vmt->get_data_as_wkt)(txt); }
+ bool get_data_as_wkt(String *txt, const char **end)
+ { return (this->*m_vmt->get_data_as_wkt)(txt, end); }
- int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); }
- int dimension(uint32 *dim) const
- { return (this->*m_vmt->dimension)(dim); }
+ int get_mbr(MBR *mbr, const char **end) const
+ { return (this->*m_vmt->get_mbr)(mbr, end); }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ return (this->*m_vmt->dimension)(dim, end);
+ }
- int get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
- int get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
- int length(double *len) const { return (this->*m_vmt->length)(len); }
- int area(double *ar) const { return (this->*m_vmt->area)(ar); }
+ bool get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
+ bool get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
+ bool length(double *len) const { return (this->*m_vmt->length)(len); }
+ bool area(double *ar, const char **end) const
+ {
+ return (this->*m_vmt->area)(ar, end);
+ }
- int is_closed(int *closed) const
+ bool is_closed(int *closed) const
{ return (this->*m_vmt->is_closed)(closed); }
- int num_interior_ring(uint32 *n_int_rings) const
+ bool num_interior_ring(uint32 *n_int_rings) const
{ return (this->*m_vmt->num_interior_ring)(n_int_rings); }
- int num_points(uint32 *n_points) const
+ bool num_points(uint32 *n_points) const
{ return (this->*m_vmt->num_points)(n_points); }
- int num_geometries(uint32 *num) const
+ bool num_geometries(uint32 *num) const
{ return (this->*m_vmt->num_geometries)(num); }
- int start_point(String *point) const
+ bool start_point(String *point)
{ return (this->*m_vmt->start_point)(point); }
- int end_point(String *point) const
+ bool end_point(String *point)
{ return (this->*m_vmt->end_point)(point); }
- int exterior_ring(String *ring) const
+ bool exterior_ring(String *ring)
{ return (this->*m_vmt->exterior_ring)(ring); }
- int centroid(String *point) const
+ bool centroid(String *point)
{ return (this->*m_vmt->centroid)(point); }
- int point_n(uint32 num, String *result) const
+ bool point_n(uint32 num, String *result) const
{ return (this->*m_vmt->point_n)(num, result); }
- int interior_ring_n(uint32 num, String *result) const
+ bool interior_ring_n(uint32 num, String *result) const
{ return (this->*m_vmt->interior_ring_n)(num, result); }
- int geometry_n(uint32 num, String *result) const
+ bool geometry_n(uint32 num, String *result) const
{ return (this->*m_vmt->geometry_n)(num, result); }
public:
int create_from_wkb(const char *data, uint32 data_len);
- int create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream=1);
+ int create_from_wkt(Gis_read_stream *trs, String *wkt, bool init_stream=1);
int init(int type_id)
{
- m_vmt = find_class(type_id);
+ m_vmt= find_class(type_id);
return !m_vmt;
}
- int new_geometry(const char *name, size_t len)
+ int new_geometry(const char *name, uint32 len)
{
- m_vmt = find_class(name, len);
+ m_vmt= find_class(name, len);
return !m_vmt;
}
-
- int as_wkt(String *wkt) const
+ int as_wkt(String *wkt, const char **end)
{
- if (wkt->reserve(strlen(get_class_info()->m_name) + 2, 512))
+ uint32 len= get_class_info()->m_name.length;
+ if (wkt->reserve(len + 2, 512))
return 1;
- wkt->qs_append(get_class_info()->m_name);
+ wkt->qs_append(get_class_info()->m_name.str, len);
wkt->qs_append('(');
- if (get_data_as_wkt(wkt))
+ if (get_data_as_wkt(wkt, end))
return 1;
wkt->qs_append(')');
return 0;
}
- void init_from_wkb(const char *data, uint32 data_len)
+ inline void init_from_wkb(const char *data, uint32 data_len)
{
- m_data = data;
- m_data_end = data + data_len;
+ m_data= data;
+ m_data_end= data + data_len;
}
- void shift_wkb_header()
+ inline void shift_wkb_header()
{
- m_data += WKB_HEADER_SIZE;
+ m_data+= WKB_HEADER_SIZE;
}
- int envelope(String *result) const;
+ bool envelope(String *result) const;
protected:
- static GClassInfo *find_class(int type_id);
- static GClassInfo *find_class(const char *name, size_t len);
-
- bool no_data(const char *cur_data, uint32 data_amount) const
+ static Gis_class_info *find_class(int type_id);
+ static Gis_class_info *find_class(const char *name, uint32 len);
+ const char *append_points(String *txt, uint32 n_points,
+ const char *data, uint32 offset);
+ bool create_point(String *result, const char *data);
+ bool create_point(String *result, double x, double y);
+ const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset)
+ const;
+
+ inline bool no_data(const char *cur_data, uint32 data_amount) const
{
return (cur_data + data_amount > m_data_end);
}
-
const char *m_data;
const char *m_data_end;
};
-#define SIZEOF_STORED_DOUBLE 8
/***************************** Point *******************************/
-class GPoint: public Geometry
+class Gis_point: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ int get_mbr(MBR *mbr, const char **end) const;
- int get_xy(double *x, double *y) const
+ bool get_xy(double *x, double *y) const
{
- const char *data = m_data;
- if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
+ const char *data= m_data;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2))
+ return 1;
float8get(*x, data);
float8get(*y, data + SIZEOF_STORED_DOUBLE);
return 0;
}
- int get_x(double *x) const
+ bool get_x(double *x) const
{
- if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1;
+ if (no_data(m_data, SIZEOF_STORED_DOUBLE))
+ return 1;
float8get(*x, m_data);
return 0;
}
- int get_y(double *y) const
+ bool get_y(double *y) const
{
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
float8get(*y, data + SIZEOF_STORED_DOUBLE);
return 0;
}
- int dimension(uint32 *dim) const { *dim = 0; return 0; }
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 0;
+ *end= 0; /* No default end */
+ return 0;
+ }
};
+
/***************************** LineString *******************************/
-class GLineString: public Geometry
+class Gis_line_string: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int length(double *len) const;
- int is_closed(int *closed) const;
- int num_points(uint32 *n_points) const;
- int start_point(String *point) const;
- int end_point(String *point) const;
- int point_n(uint32 n, String *result) const;
- int dimension(uint32 *dim) const { *dim = 1; return 0; }
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ bool get_mbr(MBR *mbr, const char **end) const;
+ bool length(double *len) const;
+ bool is_closed(int *closed) const;
+ bool num_points(uint32 *n_points) const;
+ bool start_point(String *point);
+ bool end_point(String *point);
+ bool point_n(uint32 n, String *result);
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 1;
+ *end= 0; /* No default end */
+ return 0;
+ }
};
+
/***************************** Polygon *******************************/
-class GPolygon: public Geometry
+class Gis_polygon: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int area(double *ar) const;
- int exterior_ring(String *result) const;
- int num_interior_ring(uint32 *n_int_rings) const;
- int interior_ring_n(uint32 num, String *result) const;
- int centroid_xy(double *x, double *y) const;
- int centroid(String *result) const;
- int dimension(uint32 *dim) const { *dim = 2; return 0; }
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ bool get_mbr(MBR *mbr, const char **end) const;
+ bool area(double *ar, const char **end) const;
+ bool exterior_ring(String *result);
+ bool num_interior_ring(uint32 *n_int_rings) const;
+ bool interior_ring_n(uint32 num, String *result) const;
+ bool centroid_xy(double *x, double *y) const;
+ bool centroid(String *result);
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 2;
+ *end= 0; /* No default end */
+ return 0;
+ }
};
+
/***************************** MultiPoint *******************************/
-class GMultiPoint: public Geometry
+class Gis_multi_point: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int num_geometries(uint32 *num) const;
- int geometry_n(uint32 num, String *result) const;
- int dimension(uint32 *dim) const { *dim = 0; return 0; }
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ bool get_mbr(MBR *mbr, const char **end) const;
+ bool num_geometries(uint32 *num) const;
+ bool geometry_n(uint32 num, String *result) const;
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 0;
+ *end= 0; /* No default end */
+ return 0;
+ }
};
+
/***************************** MultiLineString *******************************/
-class GMultiLineString: public Geometry
+class Gis_multi_line_stringg: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int num_geometries(uint32 *num) const;
- int geometry_n(uint32 num, String *result) const;
- int length(double *len) const;
- int is_closed(int *closed) const;
- int dimension(uint32 *dim) const { *dim = 1; return 0; }
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ bool get_mbr(MBR *mbr, const char **end) const;
+ bool num_geometries(uint32 *num) const;
+ bool geometry_n(uint32 num, String *result) const;
+ bool length(double *len) const;
+ bool is_closed(int *closed) const;
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 1;
+ *end= 0; /* No default end */
+ return 0;
+ }
};
+
/***************************** MultiPolygon *******************************/
-class GMultiPolygon: public Geometry
+class Gis_multi_polygon: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int num_geometries(uint32 *num) const;
- int geometry_n(uint32 num, String *result) const;
- int area(double *ar) const;
- int centroid(String *result) const;
- int dimension(uint32 *dim) const { *dim = 2; return 0; }
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ bool get_mbr(MBR *mbr, const char **end) const;
+ bool num_geometries(uint32 *num) const;
+ bool geometry_n(uint32 num, String *result) const;
+ bool area(double *ar, const char **end) const;
+ bool centroid(String *result);
+ bool dimension(uint32 *dim, const char **end) const
+ {
+ *dim= 2;
+ *end= 0; /* No default end */
+ return 0;
+ }
+
};
-/***************************** GeometryCollection *******************************/
-class GGeometryCollection: public Geometry
+/*********************** GeometryCollection *******************************/
+
+class Gis_geometry_collection: public Geometry
{
public:
- size_t get_data_size() const;
- int init_from_wkt(GTextReadStream *trs, String *wkb);
- int get_data_as_wkt(String *txt) const;
- int get_mbr(MBR *mbr) const;
-
- int num_geometries(uint32 *num) const;
- int geometry_n(uint32 num, String *result) const;
- int dimension(uint32 *dim) const;
+ uint32 get_data_size() const;
+ bool init_from_wkt(Gis_read_stream *trs, String *wkb);
+ bool get_data_as_wkt(String *txt, const char **end);
+ bool get_mbr(MBR *mbr, const char **end) const;
+ bool num_geometries(uint32 *num) const;
+ bool geometry_n(uint32 num, String *result) const;
+ bool dimension(uint32 *dim, const char **end) const;
};
#endif
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index c6eda5f9fb2..e15beac90b0 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -126,8 +126,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- sprintf(buff,"%.14g",num); // Enough for a DATETIME
- return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
+ uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
+ return copy(buff, len, &my_charset_latin1, cs);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
@@ -671,9 +671,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by)
return FALSE;
}
-void String::qs_append(const char *str)
+void String::qs_append(const char *str, uint32 len)
{
- int len = strlen(str);
memcpy(Ptr + str_length, str, len + 1);
str_length += len;
}
@@ -681,8 +680,7 @@ void String::qs_append(const char *str)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- sprintf(buff,"%.14g", d);
- str_length += strlen(buff);
+ str_length+= my_sprintf(buff, (buff, "%.14g", d));
}
void String::qs_append(double *d)
@@ -692,12 +690,6 @@ void String::qs_append(double *d)
qs_append(ld);
}
-void String::qs_append(const char &c)
-{
- Ptr[str_length] = c;
- str_length += sizeof(c);
-}
-
/*
Compare strings according to collation, without end space.
diff --git a/sql/sql_string.h b/sql/sql_string.h
index cdfb00276d4..7f1c56dbfe7 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -237,7 +237,7 @@ public:
q_*** methods writes values of parameters itself
qs_*** methods writes string representation of value
*/
- void q_append(const char &c)
+ void q_append(const char c)
{
Ptr[str_length++] = c;
}
@@ -262,15 +262,19 @@ public:
str_length += data_len;
}
- void WriteAtPosition(int position, uint32 value)
+ void write_at_position(int position, uint32 value)
{
int4store(Ptr + position,value);
}
- void qs_append(const char *str);
+ void qs_append(const char *str, uint32 len);
void qs_append(double d);
void qs_append(double *d);
- void qs_append(const char &c);
+ inline void qs_append(const char c)
+ {
+ Ptr[str_length]= c;
+ str_length++;
+ }
/* Inline (general) functions used by the protocol functions */
diff --git a/sql/structs.h b/sql/structs.h
index 37208e63400..0e69bca305c 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,11 +20,21 @@
struct st_table;
class Field;
-typedef struct lex_string {
+typedef struct st_lex_string
+{
char *str;
uint length;
} LEX_STRING;
+typedef struct st_lex_string_with_init :public st_lex_string
+{
+ st_lex_string_with_init(const char *str_arg, uint length_arg)
+ {
+ str= (char*) str_arg;
+ length= length_arg;
+ }
+} LEX_STRING_WITH_INIT;
+
typedef struct st_date_time_format {
uchar positions[8];