diff options
author | unknown <hf@deer.(none)> | 2004-03-12 12:04:00 +0400 |
---|---|---|
committer | unknown <hf@deer.(none)> | 2004-03-12 12:04:00 +0400 |
commit | f84ec3c062d62a2ed623461a51e7106af0a8ae22 (patch) | |
tree | cb3e50fde9831da43587ba8f7d68c19837d201a3 /sql | |
parent | 188535bba0964652678c3ce82b2dae3a1ef8bb25 (diff) | |
download | mariadb-git-f84ec3c062d62a2ed623461a51e7106af0a8ae22.tar.gz |
Spatial code changed to get rid of inconsistent this->* operation
Now we use virtual calls instead and redirect VMT pointer of the
geometry object with 'new' operation
sql/field.cc:
Usage of the Geometry class changed
sql/item_geofunc.cc:
Usage of the Geometry class changed
sql/spatial.cc:
Now we rewrite the real VMT of the object with new operation
sql/spatial.h:
No need for the VMT-like structure and pointers to it
sql/sql_yacc.yy:
enum items was renamed accordingly to coding standards
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 18 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 253 | ||||
-rw-r--r-- | sql/spatial.cc | 386 | ||||
-rw-r--r-- | sql/spatial.h | 273 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 14 |
5 files changed, 497 insertions, 447 deletions
diff --git a/sql/field.cc b/sql/field.cc index 93827a8cd1f..c4aef133e6d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4765,7 +4765,8 @@ void Field_blob::get_key_image(char *buff,uint length, { const char *dummy; MBR mbr; - Geometry gobj; + Geometry_buffer buffer; + Geometry *gobj; if (blob_length < SRID_SIZE) { @@ -4773,8 +4774,9 @@ void Field_blob::get_key_image(char *buff,uint length, return; } get_ptr(&blob); - gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE); - if (gobj.get_mbr(&mbr, &dummy)) + gobj= Geometry::create_from_wkb(&buffer, + blob + SRID_SIZE, blob_length - SRID_SIZE); + if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else { @@ -5013,9 +5015,11 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs, return; } get_ptr(&blob); - Geometry gobj; - gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE); - if (gobj.get_mbr(&mbr, &dummy)) + Geometry_buffer buffer; + Geometry *gobj; + gobj= Geometry::create_from_wkb(&buffer, + blob + SRID_SIZE, blob_length - SRID_SIZE); + if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else { @@ -5075,7 +5079,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) 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 || + if (wkb_type < (uint32) Geometry::wkb_point || wkb_type > (uint32) Geometry::wkb_end) return 1; Field_blob::store_length(length); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index cbf286a2101..02c0f5829fd 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -30,7 +30,8 @@ String *Item_func_geometry_from_text::val_str(String *str) { - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; String arg_val; String *wkt= args[0]->val_str(&arg_val); Gis_read_stream trs(wkt->c_ptr(), wkt->length()); @@ -43,7 +44,8 @@ String *Item_func_geometry_from_text::val_str(String *str) return 0; str->length(0); str->q_append(srid); - if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0)))) + if ((null_value=(args[0]->null_value || + !(geom= Geometry::create_from_wkt(&buffer, &trs, str, 0))))) return 0; return str; } @@ -59,7 +61,8 @@ String *Item_func_geometry_from_wkb::val_str(String *str) { String arg_val; String *wkb= args[0]->val_str(&arg_val); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; uint32 srid= 0; if ((arg_count == 2) && !args[1]->null_value) @@ -69,9 +72,10 @@ String *Item_func_geometry_from_wkb::val_str(String *str) return 0; str->length(0); str->q_append(srid); - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(wkb->ptr(), wkb->length()))) || - str->append(*wkb)) + if ((null_value= + (args[0]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length())) || + str->append(*wkb)))) return 0; return str; } @@ -87,16 +91,18 @@ String *Item_func_as_wkt::val_str(String *str) { String arg_val; String *swkb= args[0]->val_str(&arg_val); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom= NULL; const char *dummy; - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + if ((null_value= + (args[0]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE))))) return 0; str->length(0); - if ((null_value= geom.as_wkt(str, &dummy))) + if ((null_value= geom->as_wkt(str, &dummy))) return 0; return str; @@ -113,11 +119,13 @@ String *Item_func_as_wkb::val_str(String *str) { String arg_val; String *swkb= args[0]->val_str(&arg_val); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + if ((null_value= + (args[0]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE))))) return 0; str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE, @@ -135,15 +143,17 @@ void Item_func_as_wkb::fix_length_and_dec() String *Item_func_geometry_type::val_str(String *str) { String *swkb= args[0]->val_str(str); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom= NULL; - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + if ((null_value= + (args[0]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE))))) return 0; /* String will not move */ - str->set(geom.get_class_info()->m_name.str, - geom.get_class_info()->m_name.length, + str->set(geom->get_class_info()->m_name.str, + geom->get_class_info()->m_name.length, default_charset()); return str; } @@ -153,12 +163,14 @@ String *Item_func_envelope::val_str(String *str) { String arg_val; String *swkb= args[0]->val_str(&arg_val); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom= NULL; uint32 srid; - if ((null_value= args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))) + if ((null_value= + args[0]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) return 0; srid= uint4korr(swkb->ptr()); @@ -166,7 +178,7 @@ String *Item_func_envelope::val_str(String *str) if (str->reserve(SRID_SIZE, 512)) return 0; str->q_append(srid); - return (null_value= geom.envelope(str)) ? 0 : str; + return (null_value= geom->envelope(str)) ? 0 : str; } @@ -174,13 +186,13 @@ String *Item_func_centroid::val_str(String *str) { String arg_val; String *swkb= args[0]->val_str(&arg_val); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom= NULL; 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= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)))) return 0; if (str->reserve(SRID_SIZE, 512)) @@ -189,7 +201,7 @@ String *Item_func_centroid::val_str(String *str) srid= uint4korr(swkb->ptr()); str->q_append(srid); - return (null_value= test(geom.centroid(str))) ? 0 : str; + return (null_value= test(geom->centroid(str))) ? 0 : str; } @@ -201,12 +213,14 @@ String *Item_func_spatial_decomp::val_str(String *str) { String arg_val; String *swkb= args[0]->val_str(&arg_val); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom= NULL; uint32 srid; - if ((null_value= (args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + if ((null_value= + (args[0]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE))))) return 0; srid= uint4korr(swkb->ptr()); @@ -216,17 +230,17 @@ String *Item_func_spatial_decomp::val_str(String *str) str->q_append(srid); switch (decomp_func) { case SP_STARTPOINT: - if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str)) + if (geom->start_point(str)) goto err; break; case SP_ENDPOINT: - if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str)) + if (geom->end_point(str)) goto err; break; case SP_EXTERIORRING: - if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str)) + if (geom->exterior_ring(str)) goto err; break; @@ -246,12 +260,14 @@ String *Item_func_spatial_decomp_n::val_str(String *str) String arg_val; String *swkb= args[0]->val_str(&arg_val); long n= (long) args[1]->val_int(); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom= NULL; 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)))) + if ((null_value= + (args[0]->null_value || args[1]->null_value || + !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE))))) return 0; if (str->reserve(SRID_SIZE, 512)) @@ -262,18 +278,17 @@ String *Item_func_spatial_decomp_n::val_str(String *str) switch (decomp_func_n) { case SP_POINTN: - if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str)) + if (geom->point_n(n,str)) goto err; break; case SP_GEOMETRYN: - if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str)) + if (geom->geometry_n(n,str)) goto err; break; case SP_INTERIORRINGN: - if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) || - geom.interior_ring_n(n,str)) + if (geom->interior_ring_n(n,str)) goto err; break; @@ -309,8 +324,8 @@ String *Item_func_point::val_str(String *str) return 0; str->length(0); - str->q_append((char)Geometry::wkbNDR); - str->q_append((uint32)Geometry::wkbPoint); + str->q_append((char)Geometry::wkb_ndr); + str->q_append((uint32)Geometry::wkb_point); str->q_append(x); str->q_append(y); return str; @@ -336,7 +351,7 @@ String *Item_func_spatial_collection::val_str(String *str) if (str->reserve(1 + 4 + 4, 512)) goto err; - str->q_append((char) Geometry::wkbNDR); + str->q_append((char) Geometry::wkb_ndr); str->q_append((uint32) coll_type); str->q_append((uint32) arg_count); @@ -346,7 +361,7 @@ String *Item_func_spatial_collection::val_str(String *str) if (args[i]->null_value) goto err; - if (coll_type == Geometry::wkbGeometryCollection) + if (coll_type == Geometry::wkb_geometrycollection) { /* In the case of GeometryCollection we don't need any checkings @@ -375,19 +390,19 @@ String *Item_func_spatial_collection::val_str(String *str) goto err; switch (coll_type) { - case Geometry::wkbMultiPoint: - case Geometry::wkbMultiLineString: - case Geometry::wkbMultiPolygon: + case Geometry::wkb_multipoint: + case Geometry::wkb_multilinestring: + case Geometry::wkb_multipolygon: if (len < WKB_HEADER_SIZE || str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512)) goto err; break; - case Geometry::wkbLineString: + case Geometry::wkb_linestring: if (str->append(data, POINT_DATA_SIZE, 512)) goto err; break; - case Geometry::wkbPolygon: + case Geometry::wkb_polygon: { uint32 n_points; double x1, y1, x2, y2; @@ -439,18 +454,20 @@ longlong Item_func_spatial_rel::val_int() { String *res1= args[0]->val_str(&tmp_value1); String *res2= args[1]->val_str(&tmp_value2); - Geometry g1, g2; + Geometry_buffer buffer1, buffer2; + Geometry *g1, *g2; MBR mbr1, mbr2; const char *dummy; - if ((null_value= (args[0]->null_value || - args[1]->null_value || - g1.create_from_wkb(res1->ptr() + SRID_SIZE, - res1->length() - SRID_SIZE) || - g2.create_from_wkb(res2->ptr() + SRID_SIZE, - res2->length() - SRID_SIZE) || - g1.get_mbr(&mbr1, &dummy) || - g2.get_mbr(&mbr2, &dummy)))) + if ((null_value= + (args[0]->null_value || + args[1]->null_value || + !(g1= Geometry::create_from_wkb(&buffer1, res1->ptr() + SRID_SIZE, + res1->length() - SRID_SIZE)) || + !(g2= Geometry::create_from_wkb(&buffer2, res2->ptr() + SRID_SIZE, + res2->length() - SRID_SIZE)) || + g1->get_mbr(&mbr1, &dummy) || + g2->get_mbr(&mbr2, &dummy)))) return 0; switch (spatial_rel) { @@ -503,15 +520,16 @@ longlong Item_func_isclosed::val_int() { String tmp; String *swkb= args[0]->val_str(&tmp); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; int isclosed= 0; // In case of error null_value= (!swkb || args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom,is_closed) || - geom.is_closed(&isclosed)); + !(geom= + Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->is_closed(&isclosed)); return (longlong) isclosed; } @@ -525,14 +543,16 @@ longlong Item_func_dimension::val_int() { uint32 dim= 0; // In case of error String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + 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, &dummy)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->dimension(&dim, &dummy)); return (longlong) dim; } @@ -541,13 +561,14 @@ longlong Item_func_numinteriorring::val_int() { uint32 num= 0; // In case of error String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, num_interior_ring) || - geom.num_interior_ring(&num)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->num_interior_ring(&num)); return (longlong) num; } @@ -556,13 +577,14 @@ longlong Item_func_numgeometries::val_int() { uint32 num= 0; // In case of errors String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, num_geometries) || - geom.num_geometries(&num)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->num_geometries(&num)); return (longlong) num; } @@ -571,14 +593,15 @@ longlong Item_func_numpoints::val_int() { uint32 num= 0; // In case of errors String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; null_value= (!swkb || args[0]->null_value || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, num_points) || - geom.num_points(&num)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->num_points(&num)); return (longlong) num; } @@ -587,13 +610,14 @@ double Item_func_x::val() { double res= 0.0; // In case of errors String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, get_x) || - geom.get_x(&res)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->get_x(&res)); return res; } @@ -602,13 +626,14 @@ double Item_func_y::val() { double res= 0; // In case of errors String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, get_y) || - geom.get_y(&res)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->get_y(&res)); return res; } @@ -617,14 +642,15 @@ double Item_func_area::val() { double res= 0; // In case of errors String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + 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, &dummy)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->area(&res, &dummy)); return res; } @@ -632,24 +658,27 @@ double Item_func_glength::val() { double res= 0; // In case of errors String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE) || - !GEOM_METHOD_PRESENT(geom, length) || - geom.length(&res)); + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)) || + geom->length(&res)); return res; } longlong Item_func_srid::val_int() { String *swkb= args[0]->val_str(&value); - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; - null_value= (!swkb || - geom.create_from_wkb(swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)); + null_value= !swkb || + !(geom= Geometry::create_from_wkb(&buffer, + swkb->ptr() + SRID_SIZE, + swkb->length() - SRID_SIZE)); if (null_value) return 0; diff --git a/sql/spatial.cc b/sql/spatial.cc index 908fe6b8af4..f98799e26d1 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -19,91 +19,105 @@ /***************************** Gis_class_info *******************************/ -#define IMPLEMENT_GEOM(class_name, type_id, name) \ -{ \ - (GF_InitFromText) &class_name::init_from_wkt, \ - (GF_GetDataAsText) &class_name::get_data_as_wkt, \ - (GF_GetDataSize) &class_name::get_data_size, \ - (GF_GetMBR) &class_name::get_mbr, \ - (GF_GetD) &class_name::get_x, \ - (GF_GetD) &class_name::get_y, \ - (GF_GetD) &class_name::length, \ - (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_AND_END) &class_name::dimension, \ - (GF_GetWS) &class_name::start_point, \ - (GF_GetWS) &class_name::end_point, \ - (GF_GetWS) &class_name::exterior_ring, \ - (GF_GetWS) &class_name::centroid, \ - (GF_GetUIWS) &class_name::point_n, \ - (GF_GetUIWS) &class_name::interior_ring_n, \ - (GF_GetUIWS) &class_name::geometry_n, \ - 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::Gis_class_info ci_collection[]= -{ - 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) +Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_end]= +{ + NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static Geometry::Gis_class_info *ci_collection_end= -(ci_collection + array_elements(ci_collection)); +static Geometry::Class_info **ci_collection_end= + Geometry::ci_collection+Geometry::wkb_end; +Geometry::Class_info::Class_info(const char *name, int type_id, + void(*create_func)(void *)): + m_name(name, strlen(name)), m_type_id(type_id), m_create_func(create_func) +{ + ci_collection[type_id]= this; +} -/***************************** Geometry *******************************/ +static void create_point(void *buffer) +{ + new(buffer) Gis_point; +} -Geometry::Gis_class_info *Geometry::find_class(int type_id) +static void create_linestring(void *buffer) { - 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 0; + new(buffer) Gis_line_string; +} + +static void create_polygon(void *buffer) +{ + new(buffer) Gis_polygon; +} + +static void create_multipoint(void *buffer) +{ + new(buffer) Gis_multi_point; } - -Geometry::Gis_class_info *Geometry::find_class(const char *name, uint32 len) +static void create_multipolygon(void *buffer) { - for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++) + new(buffer) Gis_multi_polygon; +} + +static void create_multilinestring(void *buffer) +{ + new(buffer) Gis_multi_line_string; +} + +static void create_geometrycollection(void *buffer) +{ + new(buffer) Gis_geometry_collection; +} + + + +static Geometry::Class_info point_class("POINT", + Geometry::wkb_point, create_point); + +static Geometry::Class_info linestring_class("LINESTRING", + Geometry::wkb_linestring, + create_linestring); +static Geometry::Class_info polygon_class("POLYGON", + Geometry::wkb_polygon, + create_polygon); +static Geometry::Class_info multipoint_class("MULTIPOINT", + Geometry::wkb_multipoint, + create_multipoint); +static Geometry::Class_info +multilinestring_class("MULTILINESTRING", + Geometry::wkb_multilinestring, create_multilinestring); +static Geometry::Class_info multipolygon_class("MULTIPOLYGON", + Geometry::wkb_multipolygon, + create_multipolygon); +static Geometry::Class_info +geometrycollection_class("GEOMETRYCOLLECTION",Geometry::wkb_geometrycollection, + create_geometrycollection); + +/***************************** Geometry *******************************/ + +Geometry::Class_info *Geometry::find_class(const char *name, uint32 len) +{ + for (Class_info **cur_rt= ci_collection; + cur_rt < ci_collection_end; cur_rt++) { - if ((cur_rt->m_name.length == len) && + if (*cur_rt && + ((*cur_rt)->m_name.length == len) && (my_strnncoll(&my_charset_latin1, - (const uchar*) cur_rt->m_name.str, len, + (const uchar*) (*cur_rt)->m_name.str, len, (const uchar*) name, len) == 0)) - return cur_rt; + return *cur_rt; } return 0; } - -int Geometry::create_from_wkb(const char *data, uint32 data_len) +Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer, + const char *data, uint32 data_len) { uint32 geom_type; + Geometry *result; if (data_len < 1 + 4) - return 1; + return NULL; data++; /* FIXME: check byte ordering @@ -111,39 +125,44 @@ int Geometry::create_from_wkb(const char *data, uint32 data_len) */ geom_type= uint4korr(data); data+= 4; - if (!(m_vmt= find_class((int) geom_type))) - return 1; - m_data= data; - m_data_end= data + data_len; - return 0; + if (!(result= create_by_typeid(buffer, (int) geom_type))) + return NULL; + result->m_data= data; + result->m_data_end= data + data_len; + return result; } -int Geometry::create_from_wkt(Gis_read_stream *trs, String *wkt, - bool init_stream) +Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer, + Gis_read_stream *trs, String *wkt, + bool init_stream) { LEX_STRING name; + Class_info *ci; if (trs->get_next_word(&name)) { trs->set_error_msg("Geometry name expected"); - return 1; + return NULL; } - if (!(m_vmt= find_class(name.str, name.length)) || + if (!(ci= 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); + return NULL; + (*ci->m_create_func)((void *)buffer); + Geometry *result= (Geometry *)buffer; + + wkt->q_append((char) wkb_ndr); + wkt->q_append((uint32) result->get_class_info()->m_type_id); if (trs->check_next_symbol('(') || - init_from_wkt(trs, wkt) || + result->init_from_wkt(trs, wkt) || trs->check_next_symbol(')')) - return 1; + return NULL; if (init_stream) { - init_from_wkb(wkt->ptr(), wkt->length()); - shift_wkb_header(); + result->init_from_wkb(wkt->ptr(), wkt->length()); + result->shift_wkb_header(); } - return 0; + return result; } @@ -155,8 +174,8 @@ bool Geometry::envelope(String *result) const 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((char) wkb_ndr); + result->q_append((uint32) wkb_polygon); result->q_append((uint32) 1); result->q_append((uint32) 5); result->q_append(mbr.xmin); @@ -187,13 +206,13 @@ bool Geometry::envelope(String *result) const 1 Can't reallocate 'result' */ -bool Geometry::create_point(String *result, const char *data) +bool Geometry::create_point(String *result, const char *data) const { 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); + result->q_append((char) wkb_ndr); + result->q_append((uint32) wkb_point); /* Copy two double in same format */ result->q_append(data, SIZEOF_STORED_DOUBLE*2); return 0; @@ -213,13 +232,13 @@ bool Geometry::create_point(String *result, const char *data) 1 Can't reallocate 'result' */ -bool Geometry::create_point(String *result, double x, double y) +bool Geometry::create_point(String *result, double x, double y) const { if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2)) return 1; - result->q_append((char) wkbNDR); - result->q_append((uint32) wkbPoint); + result->q_append((char) wkb_ndr); + result->q_append((uint32) wkb_point); result->q_append(x); result->q_append(y); return 0; @@ -240,7 +259,7 @@ bool Geometry::create_point(String *result, double x, double y) */ const char *Geometry::append_points(String *txt, uint32 n_points, - const char *data, uint32 offset) + const char *data, uint32 offset) const { while (n_points--) { @@ -317,7 +336,7 @@ bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_point::get_data_as_wkt(String *txt, const char **end) +bool Gis_point::get_data_as_wkt(String *txt, const char **end) const { double x, y; if (get_xy(&x, &y)) @@ -332,7 +351,7 @@ bool Gis_point::get_data_as_wkt(String *txt, const char **end) } -int Gis_point::get_mbr(MBR *mbr, const char **end) const +bool Gis_point::get_mbr(MBR *mbr, const char **end) const { double x, y; if (get_xy(&x, &y)) @@ -342,6 +361,11 @@ int Gis_point::get_mbr(MBR *mbr, const char **end) const return 0; } +const Geometry::Class_info *Gis_point::get_class_info() const +{ + return &point_class; +} + /***************************** LineString *******************************/ @@ -381,7 +405,7 @@ bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) +bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; const char *data= m_data; @@ -419,7 +443,7 @@ bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const } -bool Gis_line_string::length(double *len) const +int Gis_line_string::length(double *len) const { uint32 n_points; double prev_x, prev_y; @@ -451,7 +475,7 @@ bool Gis_line_string::length(double *len) const } -bool Gis_line_string::is_closed(int *closed) const +int Gis_line_string::is_closed(int *closed) const { uint32 n_points; double x1, y1, x2, y2; @@ -478,21 +502,21 @@ bool Gis_line_string::is_closed(int *closed) const } -bool Gis_line_string::num_points(uint32 *n_points) const +int Gis_line_string::num_points(uint32 *n_points) const { *n_points= uint4korr(m_data); return 0; } -bool Gis_line_string::start_point(String *result) +int Gis_line_string::start_point(String *result) const { /* +4 is for skipping over number of points */ return create_point(result, m_data + 4); } -bool Gis_line_string::end_point(String *result) +int Gis_line_string::end_point(String *result) const { uint32 n_points; if (no_data(m_data, 4)) @@ -502,7 +526,7 @@ bool Gis_line_string::end_point(String *result) } -bool Gis_line_string::point_n(uint32 num, String *result) +int Gis_line_string::point_n(uint32 num, String *result) const { uint32 n_points; if (no_data(m_data, 4)) @@ -514,6 +538,11 @@ bool Gis_line_string::point_n(uint32 num, String *result) return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE); } +const Geometry::Class_info *Gis_line_string::get_class_info() const +{ + return &linestring_class; +} + /***************************** Polygon *******************************/ @@ -570,7 +599,7 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) +bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_linear_rings; const char *data= m_data; @@ -622,7 +651,7 @@ bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const } -bool Gis_polygon::area(double *ar, const char **end_of_data) const +int Gis_polygon::area(double *ar, const char **end_of_data) const { uint32 n_linear_rings; double result= -1.0; @@ -671,7 +700,7 @@ bool Gis_polygon::area(double *ar, const char **end_of_data) const } -bool Gis_polygon::exterior_ring(String *result) +int Gis_polygon::exterior_ring(String *result) const { uint32 n_points, length; const char *data= m_data + 4; // skip n_linerings @@ -684,15 +713,15 @@ bool Gis_polygon::exterior_ring(String *result) 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) wkb_ndr); + result->q_append((uint32) wkb_linestring); result->q_append(n_points); result->q_append(data, n_points * POINT_DATA_SIZE); return 0; } -bool Gis_polygon::num_interior_ring(uint32 *n_int_rings) const +int Gis_polygon::num_interior_ring(uint32 *n_int_rings) const { if (no_data(m_data, 4)) return 1; @@ -701,7 +730,7 @@ bool Gis_polygon::num_interior_ring(uint32 *n_int_rings) const } -bool Gis_polygon::interior_ring_n(uint32 num, String *result) const +int Gis_polygon::interior_ring_n(uint32 num, String *result) const { const char *data= m_data; uint32 n_linear_rings; @@ -730,8 +759,8 @@ bool Gis_polygon::interior_ring_n(uint32 num, String *result) const 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) wkb_ndr); + result->q_append((uint32) wkb_linestring); result->q_append(n_points); result->q_append(data, points_size); @@ -739,7 +768,7 @@ bool Gis_polygon::interior_ring_n(uint32 num, String *result) const } -bool Gis_polygon::centroid_xy(double *x, double *y) const +int Gis_polygon::centroid_xy(double *x, double *y) const { uint32 n_linear_rings; double res_area, res_cx, res_cy; @@ -812,7 +841,7 @@ bool Gis_polygon::centroid_xy(double *x, double *y) const } -bool Gis_polygon::centroid(String *result) +int Gis_polygon::centroid(String *result) const { double x, y; if (centroid_xy(&x, &y)) @@ -820,6 +849,11 @@ bool Gis_polygon::centroid(String *result) return create_point(result, x, y); } +const Geometry::Class_info *Gis_polygon::get_class_info() const +{ + return &polygon_class; +} + /***************************** MultiPoint *******************************/ @@ -845,8 +879,8 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb) { if (wkb->reserve(1+4, 512)) return 1; - wkb->q_append((char) wkbNDR); - wkb->q_append((uint32) wkbPoint); + wkb->q_append((char) wkb_ndr); + wkb->q_append((uint32) wkb_point); if (p.init_from_wkt(trs, wkb)) return 1; n_points++; @@ -858,7 +892,7 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) +bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; if (no_data(m_data, 4)) @@ -881,14 +915,14 @@ bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const } -bool Gis_multi_point::num_geometries(uint32 *num) const +int Gis_multi_point::num_geometries(uint32 *num) const { *num= uint4korr(m_data); return 0; } -bool Gis_multi_point::geometry_n(uint32 num, String *result) const +int Gis_multi_point::geometry_n(uint32 num, String *result) const { const char *data= m_data; uint32 n_points; @@ -907,10 +941,15 @@ bool Gis_multi_point::geometry_n(uint32 num, String *result) const return 0; } +const Geometry::Class_info *Gis_multi_point::get_class_info() const +{ + return &multipoint_class; +} + /***************************** MultiLineString *******************************/ -uint32 Gis_multi_line_stringg::get_data_size() const +uint32 Gis_multi_line_string::get_data_size() const { uint32 n_line_strings; const char *data= m_data; @@ -931,7 +970,7 @@ uint32 Gis_multi_line_stringg::get_data_size() const } -bool Gis_multi_line_stringg::init_from_wkt(Gis_read_stream *trs, String *wkb) +bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) { uint32 n_line_strings= 0; uint32 ls_pos= wkb->length(); @@ -946,8 +985,8 @@ bool Gis_multi_line_stringg::init_from_wkt(Gis_read_stream *trs, String *wkb) if (wkb->reserve(1+4, 512)) return 1; - wkb->q_append((char) wkbNDR); - wkb->q_append((uint32) wkbLineString); + wkb->q_append((char) wkb_ndr); + wkb->q_append((uint32) wkb_linestring); if (trs->check_next_symbol('(') || ls.init_from_wkt(trs, wkb) || @@ -962,7 +1001,8 @@ bool Gis_multi_line_stringg::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_multi_line_stringg::get_data_as_wkt(String *txt, const char **end) +bool Gis_multi_line_string::get_data_as_wkt(String *txt, + const char **end) const { uint32 n_line_strings; const char *data= m_data; @@ -993,7 +1033,7 @@ bool Gis_multi_line_stringg::get_data_as_wkt(String *txt, const char **end) } -bool Gis_multi_line_stringg::get_mbr(MBR *mbr, const char **end) const +bool Gis_multi_line_string::get_mbr(MBR *mbr, const char **end) const { uint32 n_line_strings; const char *data= m_data; @@ -1014,14 +1054,14 @@ bool Gis_multi_line_stringg::get_mbr(MBR *mbr, const char **end) const } -bool Gis_multi_line_stringg::num_geometries(uint32 *num) const +int Gis_multi_line_string::num_geometries(uint32 *num) const { *num= uint4korr(m_data); return 0; } -bool Gis_multi_line_stringg::geometry_n(uint32 num, String *result) const +int Gis_multi_line_string::geometry_n(uint32 num, String *result) const { uint32 n_line_strings, n_points, length; const char *data= m_data; @@ -1050,7 +1090,7 @@ bool Gis_multi_line_stringg::geometry_n(uint32 num, String *result) const } -bool Gis_multi_line_stringg::length(double *len) const +int Gis_multi_line_string::length(double *len) const { uint32 n_line_strings; const char *data= m_data; @@ -1080,7 +1120,7 @@ bool Gis_multi_line_stringg::length(double *len) const } -bool Gis_multi_line_stringg::is_closed(int *closed) const +int Gis_multi_line_string::is_closed(int *closed) const { uint32 n_line_strings; const char *data= m_data; @@ -1109,6 +1149,11 @@ bool Gis_multi_line_stringg::is_closed(int *closed) const return 0; } +const Geometry::Class_info *Gis_multi_line_string::get_class_info() const +{ + return &multilinestring_class; +} + /***************************** MultiPolygon *******************************/ @@ -1156,8 +1201,8 @@ bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) { if (wkb->reserve(1+4, 512)) return 1; - wkb->q_append((char) wkbNDR); - wkb->q_append((uint32) wkbPolygon); + wkb->q_append((char) wkb_ndr); + wkb->q_append((uint32) wkb_polygon); if (trs->check_next_symbol('(') || p.init_from_wkt(trs, wkb) || @@ -1172,7 +1217,7 @@ bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) +bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_polygons; const char *data= m_data; @@ -1245,14 +1290,14 @@ bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const } -bool Gis_multi_polygon::num_geometries(uint32 *num) const +int Gis_multi_polygon::num_geometries(uint32 *num) const { *num= uint4korr(m_data); return 0; } -bool Gis_multi_polygon::geometry_n(uint32 num, String *result) const +int Gis_multi_polygon::geometry_n(uint32 num, String *result) const { uint32 n_polygons; const char *data= m_data, *start_of_polygon; @@ -1291,7 +1336,7 @@ bool Gis_multi_polygon::geometry_n(uint32 num, String *result) const } -bool Gis_multi_polygon::area(double *ar, const char **end_of_data) const +int Gis_multi_polygon::area(double *ar, const char **end_of_data) const { uint32 n_polygons; const char *data= m_data; @@ -1319,7 +1364,7 @@ bool Gis_multi_polygon::area(double *ar, const char **end_of_data) const } -bool Gis_multi_polygon::centroid(String *result) +int Gis_multi_polygon::centroid(String *result) const { uint32 n_polygons; bool first_loop= 1; @@ -1363,6 +1408,11 @@ bool Gis_multi_polygon::centroid(String *result) return create_point(result, res_cx, res_cy); } +const Geometry::Class_info *Gis_multi_polygon::get_class_info() const +{ + return &multipolygon_class; +} + /************************* GeometryCollection ****************************/ @@ -1370,6 +1420,8 @@ uint32 Gis_geometry_collection::get_data_size() const { uint32 n_objects; const char *data= m_data; + Geometry_buffer buffer; + Geometry *geom; if (no_data(data, 4)) return GET_SIZE_ERROR; @@ -1379,17 +1431,16 @@ uint32 Gis_geometry_collection::get_data_size() const while (n_objects--) { uint32 wkb_type,object_size; - Geometry geom; if (no_data(data, WKB_HEADER_SIZE)) return GET_SIZE_ERROR; wkb_type= uint4korr(data + 1); data+= WKB_HEADER_SIZE; - if (geom.init(wkb_type)) + if (!(geom= create_by_typeid(&buffer, 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) + 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; } @@ -1401,7 +1452,8 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb) { uint32 n_objects= 0; uint32 no_pos= wkb->length(); - Geometry g; + Geometry_buffer buffer; + Geometry *g; if (wkb->reserve(4, 512)) return 1; @@ -1409,10 +1461,10 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb) for (;;) { - if (g.create_from_wkt(trs, wkb)) + if (!(g= create_from_wkt(&buffer, trs, wkb))) return 1; - if (g.get_class_info()->m_type_id == wkbGeometryCollection) + if (g->get_class_info()->m_type_id == wkb_geometrycollection) { trs->set_error_msg("Unexpected GEOMETRYCOLLECTION"); return 1; @@ -1427,10 +1479,12 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb) } -bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end) +bool Gis_geometry_collection::get_data_as_wkt(String *txt, + const char **end) const { uint32 n_objects; - Geometry geom; + Geometry_buffer buffer; + Geometry *geom; const char *data= m_data; if (no_data(data, 4)) @@ -1447,10 +1501,10 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end) wkb_type= uint4korr(data + 1); data+= WKB_HEADER_SIZE; - if (geom.init(wkb_type)) + if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom.init_from_wkb(data, (uint) (m_data_end - data)); - if (geom.as_wkt(txt, &data)) + 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; @@ -1465,6 +1519,8 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const { uint32 n_objects; const char *data= m_data; + Geometry_buffer buffer; + Geometry *geom; if (no_data(data, 4)) return 1; @@ -1474,17 +1530,16 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const while (n_objects--) { uint32 wkb_type; - Geometry geom; if (no_data(data, WKB_HEADER_SIZE)) return 1; wkb_type= uint4korr(data + 1); data+= WKB_HEADER_SIZE; - if (geom.init(wkb_type)) + if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom.init_from_wkb(data, (uint32) (m_data_end - data)); - if (geom.get_mbr(mbr, &data)) + geom->init_from_wkb(data, (uint32) (m_data_end - data)); + if (geom->get_mbr(mbr, &data)) return 1; } *end= data; @@ -1492,7 +1547,7 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const } -bool Gis_geometry_collection::num_geometries(uint32 *num) const +int Gis_geometry_collection::num_geometries(uint32 *num) const { if (no_data(m_data, 4)) return 1; @@ -1501,10 +1556,12 @@ bool Gis_geometry_collection::num_geometries(uint32 *num) const } -bool Gis_geometry_collection::geometry_n(uint32 num, String *result) const +int Gis_geometry_collection::geometry_n(uint32 num, String *result) const { uint32 n_objects, wkb_type, length; const char *data= m_data; + Geometry_buffer buffer; + Geometry *geom; if (no_data(data, 4)) return 1; @@ -1515,17 +1572,15 @@ bool Gis_geometry_collection::geometry_n(uint32 num, String *result) const do { - Geometry geom; - if (no_data(data, WKB_HEADER_SIZE)) return 1; wkb_type= uint4korr(data + 1); data+= WKB_HEADER_SIZE; - if (geom.init(wkb_type)) + if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom.init_from_wkb(data, (uint) (m_data_end - data)); - if ((length= geom.get_data_size()) == GET_SIZE_ERROR) + 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); @@ -1533,7 +1588,7 @@ bool Gis_geometry_collection::geometry_n(uint32 num, String *result) const /* Copy found object to result */ if (result->reserve(1+4+length)) return 1; - result->q_append((char) wkbNDR); + result->q_append((char) wkb_ndr); result->q_append((uint32) wkb_type); result->q_append(data-length, length); // data-length = start_of_data return 0; @@ -1557,6 +1612,8 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const { uint32 n_objects; const char *data= m_data; + Geometry_buffer buffer; + Geometry *geom; if (no_data(data, 4)) return 1; @@ -1568,21 +1625,20 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const { uint32 wkb_type, length, dim; const char *end_data; - Geometry geom; if (no_data(data, WKB_HEADER_SIZE)) return 1; wkb_type= uint4korr(data + 1); data+= WKB_HEADER_SIZE; - if (geom.init(wkb_type)) + if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom.init_from_wkb(data, (uint32) (m_data_end - data)); - if (geom.dimension(&dim, &end_data)) + geom->init_from_wkb(data, (uint32) (m_data_end - data)); + if (geom->dimension(&dim, &end_data)) return 1; set_if_bigger(*res_dim, dim); if (end_data) // Complex object data= end_data; - else if ((length= geom.get_data_size()) == GET_SIZE_ERROR) + else if ((length= geom->get_data_size()) == GET_SIZE_ERROR) return 1; else data+= length; @@ -1590,3 +1646,9 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const *end= data; return 0; } + +const Geometry::Class_info *Gis_geometry_collection::get_class_info() const +{ + return &geometrycollection_class; +} + diff --git a/sql/spatial.h b/sql/spatial.h index bc064724ab7..5d425725437 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -152,142 +152,80 @@ struct MBR /***************************** Geometry *******************************/ -class Geometry; - -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 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) +struct Geometry_buffer; class Geometry { public: + static void *operator new(unsigned size_t, void *buffer) + { + return buffer; + } + enum wkbType { - wkbPoint= 1, - wkbLineString= 2, - wkbPolygon= 3, - wkbMultiPoint= 4, - wkbMultiLineString= 5, - wkbMultiPolygon= 6, - wkbGeometryCollection= 7, - wkb_end=8 + wkb_point= 1, + wkb_linestring= 2, + wkb_polygon= 3, + wkb_multipoint= 4, + wkb_multilinestring= 5, + wkb_multipolygon= 6, + wkb_geometrycollection= 7, + wkb_end=7 }; enum wkbByteOrder { - wkbXDR= 0, /* Big Endian */ - wkbNDR= 1 /* Little Endian */ + wkb_xdr= 0, /* Big Endian */ + wkb_ndr= 1 /* Little Endian */ }; - class Gis_class_info + class Class_info { public: - GF_InitFromText init_from_wkt; - GF_GetDataAsText get_data_as_wkt; - GF_GetDataSize get_data_size; - GF_GetMBR get_mbr; - GF_GetD get_x; - GF_GetD get_y; - GF_GetD length; - GF_GetD_AND_END area; - - GF_GetI is_closed; - - GF_GetUI num_interior_ring; - GF_GetUI num_points; - GF_GetUI num_geometries; - GF_GetUI_AND_END dimension; - - GF_GetWS start_point; - GF_GetWS end_point; - GF_GetWS exterior_ring; - GF_GetWS centroid; - - GF_GetUIWS point_n; - GF_GetUIWS interior_ring_n; - GF_GetUIWS geometry_n; - - LEX_STRING m_name; + LEX_STRING_WITH_INIT m_name; int m_type_id; - Gis_class_info *m_next_rt; + void (*m_create_func)(void *); + Class_info(const char *name, int type_id, void(*create_func)(void *)); }; - Gis_class_info *m_vmt; - - const Gis_class_info *get_class_info() const { return m_vmt; } - uint32 get_data_size() const { return (this->*m_vmt->get_data_size)(); } - - bool init_from_wkt(Gis_read_stream *trs, String *wkb) - { return (this->*m_vmt->init_from_wkt)(trs, wkb); } - - 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 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); - } - 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); - } - - bool is_closed(int *closed) const - { return (this->*m_vmt->is_closed)(closed); } - - bool num_interior_ring(uint32 *n_int_rings) const - { return (this->*m_vmt->num_interior_ring)(n_int_rings); } - bool num_points(uint32 *n_points) const - { return (this->*m_vmt->num_points)(n_points); } - - bool num_geometries(uint32 *num) const - { return (this->*m_vmt->num_geometries)(num); } - - bool start_point(String *point) - { return (this->*m_vmt->start_point)(point); } - bool end_point(String *point) - { return (this->*m_vmt->end_point)(point); } - bool exterior_ring(String *ring) - { return (this->*m_vmt->exterior_ring)(ring); } - bool centroid(String *point) - { return (this->*m_vmt->centroid)(point); } - - bool point_n(uint32 num, String *result) const - { return (this->*m_vmt->point_n)(num, result); } - bool interior_ring_n(uint32 num, String *result) const - { return (this->*m_vmt->interior_ring_n)(num, result); } - bool geometry_n(uint32 num, String *result) const - { return (this->*m_vmt->geometry_n)(num, result); } + virtual const Class_info *get_class_info() const=0; + virtual uint32 get_data_size() const=0; + virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0; + virtual bool get_data_as_wkt(String *txt, const char **end) const=0; + virtual bool get_mbr(MBR *mbr, const char **end) const=0; + 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 length(double *len) 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; } + virtual int num_points(uint32 *n_points) const { return -1; } + virtual int num_geometries(uint32 *num) const { return -1; } + virtual int start_point(String *point) const { return -1; } + virtual int end_point(String *point) const { return -1; } + virtual int exterior_ring(String *ring) const { return -1; } + virtual int centroid(String *point) const { return -1; } + virtual int point_n(uint32 num, String *result) const { return -1; } + virtual int interior_ring_n(uint32 num, String *result) const { return -1; } + virtual int geometry_n(uint32 num, String *result) const { return -1; } public: - int create_from_wkb(const char *data, uint32 data_len); - 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); - return !m_vmt; - } - int new_geometry(const char *name, uint32 len) - { - m_vmt= find_class(name, len); - return !m_vmt; + static Geometry *Geometry::create_by_typeid(Geometry_buffer *buffer, + int type_id) + { + Class_info *ci; + if (!(ci= find_class((int) type_id))) + return NULL; + (*ci->m_create_func)((void *)buffer); + return (Geometry *)buffer; } + + static Geometry *create_from_wkb(Geometry_buffer *buffer, + const char *data, uint32 data_len); + static Geometry *create_from_wkt(Geometry_buffer *buffer, + Gis_read_stream *trs, String *wkt, + bool init_stream=1); int as_wkt(String *wkt, const char **end) { uint32 len= get_class_info()->m_name.length; @@ -313,14 +251,19 @@ public: } bool envelope(String *result) const; + static Geometry::Class_info *ci_collection[Geometry::wkb_end]; protected: - static Gis_class_info *find_class(int type_id); - static Gis_class_info *find_class(const char *name, uint32 len); + static Class_info *find_class(int type_id) + { + return ((type_id < wkb_point) || (type_id > wkb_end)) ? + NULL : ci_collection[type_id]; + } + static 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 *data, uint32 offset) const; + bool create_point(String *result, const char *data) const; + bool create_point(String *result, double x, double y) const; const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset) const; @@ -340,10 +283,10 @@ class Gis_point: public Geometry public: 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; + bool get_data_as_wkt(String *txt, const char **end) const; + bool get_mbr(MBR *mbr, const char **end) const; - bool get_xy(double *x, double *y) const + int get_xy(double *x, double *y) const { const char *data= m_data; if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) @@ -353,7 +296,7 @@ public: return 0; } - bool get_x(double *x) const + int get_x(double *x) const { if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1; @@ -361,7 +304,7 @@ public: return 0; } - bool get_y(double *y) const + int get_y(double *y) const { const char *data= m_data; if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; @@ -375,6 +318,7 @@ public: *end= 0; /* No default end */ return 0; } + const Class_info *get_class_info() const; }; @@ -385,20 +329,21 @@ class Gis_line_string: public Geometry public: 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_data_as_wkt(String *txt, const char **end) const; 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); + 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; bool dimension(uint32 *dim, const char **end) const { *dim= 1; *end= 0; /* No default end */ return 0; } + const Class_info *get_class_info() const; }; @@ -409,20 +354,21 @@ class Gis_polygon: public Geometry public: 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_data_as_wkt(String *txt, const char **end) const; 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); + int area(double *ar, const char **end) 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; bool dimension(uint32 *dim, const char **end) const { *dim= 2; *end= 0; /* No default end */ return 0; } + const Class_info *get_class_info() const; }; @@ -433,38 +379,40 @@ class Gis_multi_point: public Geometry public: 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_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; - bool num_geometries(uint32 *num) const; - bool geometry_n(uint32 num, String *result) const; + int num_geometries(uint32 *num) const; + int geometry_n(uint32 num, String *result) const; bool dimension(uint32 *dim, const char **end) const { *dim= 0; *end= 0; /* No default end */ return 0; } + const Class_info *get_class_info() const; }; /***************************** MultiLineString *******************************/ -class Gis_multi_line_stringg: public Geometry +class Gis_multi_line_string: public Geometry { public: 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_data_as_wkt(String *txt, const char **end) const; 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; + 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; bool dimension(uint32 *dim, const char **end) const { *dim= 1; *end= 0; /* No default end */ return 0; } + const Class_info *get_class_info() const; }; @@ -475,19 +423,19 @@ class Gis_multi_polygon: public Geometry public: 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_data_as_wkt(String *txt, const char **end) const; 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); + int num_geometries(uint32 *num) const; + int geometry_n(uint32 num, String *result) const; + int area(double *ar, const char **end) const; + int centroid(String *result) const; bool dimension(uint32 *dim, const char **end) const { *dim= 2; *end= 0; /* No default end */ return 0; } - + const Class_info *get_class_info() const; }; @@ -498,11 +446,18 @@ class Gis_geometry_collection: public Geometry public: 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_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; - bool num_geometries(uint32 *num) const; - bool geometry_n(uint32 num, String *result) const; + int num_geometries(uint32 *num) const; + int geometry_n(uint32 num, String *result) const; bool dimension(uint32 *dim, const char **end) const; + const Class_info *get_class_info() const; +}; + +const int geometry_buffer_size= sizeof(Gis_point); +struct Geometry_buffer +{ + void *arr[(geometry_buffer_size - 1)/sizeof(void *) + 1]; }; #endif diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 382a6e65549..f317219bd38 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2941,14 +2941,14 @@ geometry_function: { $$= GEOM_NEW(Item_func_geometry_from_wkb($3, $5)); } | GEOMETRYCOLLECTION '(' expr_list ')' { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkbGeometryCollection, - Geometry::wkbPoint)); } + Geometry::wkb_geometrycollection, + Geometry::wkb_point)); } | LINESTRING '(' expr_list ')' { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkbLineString, Geometry::wkbPoint)); } + Geometry::wkb_linestring, Geometry::wkb_point)); } | MULTILINESTRING '(' expr_list ')' { $$= GEOM_NEW( Item_func_spatial_collection(* $3, - Geometry::wkbMultiLineString, Geometry::wkbLineString)); } + Geometry::wkb_multilinestring, Geometry::wkb_linestring)); } | MLINEFROMTEXT '(' expr ')' { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } | MLINEFROMTEXT '(' expr ',' expr ')' @@ -2963,10 +2963,10 @@ geometry_function: { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } | MULTIPOINT '(' expr_list ')' { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkbMultiPoint, Geometry::wkbPoint)); } + Geometry::wkb_multipoint, Geometry::wkb_point)); } | MULTIPOLYGON '(' expr_list ')' { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkbMultiPolygon, Geometry::wkbPolygon)); } + Geometry::wkb_multipolygon, Geometry::wkb_polygon)); } | POINT_SYM '(' expr ',' expr ')' { $$= GEOM_NEW(Item_func_point($3,$5)); } | POINTFROMTEXT '(' expr ')' @@ -2979,7 +2979,7 @@ geometry_function: { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } | POLYGON '(' expr_list ')' { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkbPolygon, Geometry::wkbLineString)); } + Geometry::wkb_polygon, Geometry::wkb_linestring)); } | GEOMCOLLFROMTEXT '(' expr ')' { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } | GEOMCOLLFROMTEXT '(' expr ',' expr ')' |