From d0f2e1e55176c7f674832444ea174c2445058ef7 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 21 Sep 2011 13:26:21 +0500 Subject: bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs fixed. per-file comments: mysql-test/r/gis.result bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs fixed. test result updated. mysql-test/t/gis.test bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs fixed. test case added. sql/item_geofunc.cc bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs fixed. geom_length() call fixed. sql/spatial.cc bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs fixed. Geometry_collection::geom_length implemented. sql/spatial.h bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs fixed. Geometry_collection::geom_length declaration added. --- mysql-test/r/gis.result | 3 +++ mysql-test/t/gis.test | 2 ++ sql/item_geofunc.cc | 3 ++- sql/spatial.cc | 59 ++++++++++++++++++++++++++++++++++++++++++++----- sql/spatial.h | 8 ++++--- 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 0755f106fba..7f54e088cf8 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1097,6 +1097,9 @@ DROP TABLE t2; select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')); ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')) 1.5 +select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')); +ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')) +160 DROP DATABASE IF EXISTS gis_ogs; CREATE DATABASE gis_ogs; USE gis_ogs; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 2eee4bab767..e8fa0e6b994 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -808,6 +808,8 @@ DROP TABLE t2; #bug 850775 ST_AREA does not work on GEOMETRYCOLLECTIONs in maria-5.3-gis select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')); +#bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs +select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')); # Conformance tests diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 2c3facb49c8..e490643f88b 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1719,12 +1719,13 @@ double Item_func_glength::val_real() String *swkb= args[0]->val_str(&value); Geometry_buffer buffer; Geometry *geom; + const char *end; null_value= (!swkb || !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) || - geom->geom_length(&res)); + geom->geom_length(&res, &end)); return res; } diff --git a/sql/spatial.cc b/sql/spatial.cc index 95ec4834e96..15dc42441a8 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -518,6 +518,14 @@ int Gis_point::area(double *ar, const char **end) const } +int Gis_point::geom_length(double *len, const char **end) const +{ + *len= 0; + *end= m_data+ POINT_DATA_SIZE; + return 0; +} + + int Gis_point::store_shapes(Gcalc_shape_transporter *trn) const { double x, y; @@ -634,7 +642,7 @@ bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const } -int Gis_line_string::geom_length(double *len) const +int Gis_line_string::geom_length(double *len, const char **end) const { uint32 n_points; double prev_x, prev_y; @@ -659,6 +667,7 @@ int Gis_line_string::geom_length(double *len) const prev_x= x; prev_y= y; } + *end= data; return 0; } @@ -1628,10 +1637,11 @@ int Gis_multi_line_string::geometry_n(uint32 num, String *result) const } -int Gis_multi_line_string::geom_length(double *len) const +int Gis_multi_line_string::geom_length(double *len, const char **end) const { uint32 n_line_strings; const char *data= m_data; + const char *line_end; if (no_data(data, 4)) return 1; @@ -1645,7 +1655,7 @@ int Gis_multi_line_string::geom_length(double *len) const Gis_line_string ls; data+= WKB_HEADER_SIZE; ls.set_data_ptr(data, (uint32) (m_data_end - data)); - if (ls.geom_length(&ls_len)) + if (ls.geom_length(&ls_len, &line_end)) return 1; *len+= ls_len; /* @@ -1654,6 +1664,7 @@ int Gis_multi_line_string::geom_length(double *len) const */ data+= ls.get_data_size(); } + *end= data; return 0; } @@ -2319,7 +2330,7 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const } -int Gis_geometry_collection::area(double *ar, const char **end_of_data) const +int Gis_geometry_collection::area(double *ar, const char **end) const { uint32 n_objects; const char *data= m_data; @@ -2351,12 +2362,50 @@ int Gis_geometry_collection::area(double *ar, const char **end_of_data) const return 1; result+= *ar; } - *end_of_data= data; + *end= data; *ar= result; return 0; } +int Gis_geometry_collection::geom_length(double *len, const char **end) const +{ + uint32 n_objects; + const char *data= m_data; + Geometry_buffer buffer; + Geometry *geom; + double result; + + if (no_data(data, 4)) + return 1; + n_objects= uint4korr(data); + data+= 4; + if (n_objects == 0) + return 1; + + result= 0.0; + while (n_objects--) + { + uint32 wkb_type; + + if (no_data(data, WKB_HEADER_SIZE)) + return 1; + wkb_type= uint4korr(data + 1); + data+= WKB_HEADER_SIZE; + + if (!(geom= create_by_typeid(&buffer, wkb_type))) + return 1; + geom->set_data_ptr(data, (uint32) (m_data_end - data)); + if (geom->geom_length(len, &data)) + return 1; + result+= *len; + } + *end= data; + *len= result; + return 0; +} + + int Gis_geometry_collection::num_geometries(uint32 *num) const { if (no_data(m_data, 4)) diff --git a/sql/spatial.h b/sql/spatial.h index cec80b3dacf..d55fc639acc 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -259,7 +259,7 @@ public: virtual bool dimension(uint32 *dim, const char **end) const=0; virtual int get_x(double *x) const { return -1; } virtual int get_y(double *y) const { return -1; } - virtual int geom_length(double *len) const { return -1; } + virtual int geom_length(double *len, const char **end) const { return -1; } virtual int area(double *ar, const char **end) const { return -1;} virtual int is_closed(int *closed) const { return -1; } virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; } @@ -364,6 +364,7 @@ public: return 0; } + int geom_length(double *len, const char **end) const; int area(double *ar, const char **end) const; bool dimension(uint32 *dim, const char **end) const { @@ -388,7 +389,7 @@ public: uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; - int geom_length(double *len) const; + int geom_length(double *len, const char **end) const; int area(double *ar, const char **end) const; int is_closed(int *closed) const; int num_points(uint32 *n_points) const; @@ -477,7 +478,7 @@ public: bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; int geometry_n(uint32 num, String *result) const; - int geom_length(double *len) const; + int geom_length(double *len, const char **end) const; int is_closed(int *closed) const; bool dimension(uint32 *dim, const char **end) const { @@ -532,6 +533,7 @@ public: bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int area(double *ar, const char **end) const; + int geom_length(double *len, const char **end) const; int num_geometries(uint32 *num) const; int geometry_n(uint32 num, String *result) const; bool dimension(uint32 *dim, const char **end) const; -- cgit v1.2.1