From 8fdef257ae94bfc0f82a1444aac1bd3e1a254c77 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Sep 2005 14:35:01 +0500 Subject: [PATCH 1/5] Fix for bug #12839 (Endian support is absurd) mysql-test/r/gis.result: test result fixed mysql-test/t/gis.test: test case added sql/field.cc: ::construct calls added sql/item_geofunc.cc: ::construct calls added sql/spatial.cc: Geometry_*::init_from_wkb implemented sql/spatial.h: init_from_wkb methods declared --- mysql-test/r/gis.result | 6 + mysql-test/t/gis.test | 3 + sql/field.cc | 9 +- sql/item_geofunc.cc | 77 ++++------ sql/spatial.cc | 319 +++++++++++++++++++++++++++++++++++++--- sql/spatial.h | 19 ++- 6 files changed, 354 insertions(+), 79 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index c51b07f09d6..bf2f3e2bf03 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -655,3 +655,9 @@ t1 where object_id=85984; object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo)) 85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469) drop table t1; +select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); +(asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))) +POINT(10 10) +select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); +(asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))) +POINT(10 10) diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index b204bc11e2f..3eb17f3a484 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -360,4 +360,7 @@ t1 where object_id=85984; drop table t1; +select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); +select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); + # End of 4.1 tests diff --git a/sql/field.cc b/sql/field.cc index 6d2f92e27ea..ccf82bdbae3 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5745,8 +5745,8 @@ void Field_blob::get_key_image(char *buff,uint length, return; } get_ptr(&blob); - gobj= Geometry::create_from_wkb(&buffer, - blob + SRID_SIZE, blob_length - SRID_SIZE); + gobj= Geometry::construct(&buffer, + blob + SRID_SIZE, blob_length - SRID_SIZE); if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else @@ -6039,8 +6039,7 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs, return; } get_ptr(&blob); - gobj= Geometry::create_from_wkb(&buffer, - blob + SRID_SIZE, blob_length - SRID_SIZE); + gobj= Geometry::construct(&buffer, blob, blob_length); if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else @@ -6100,7 +6099,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) uint32 wkb_type; if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2) goto err; - wkb_type= uint4korr(from + WKB_HEADER_SIZE); + wkb_type= uint4korr(from + SRID_SIZE + 1); if (wkb_type < (uint32) Geometry::wkb_point || wkb_type > (uint32) Geometry::wkb_end) return -1; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 8b856d809d6..6bd2e65632f 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -78,8 +78,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str) str->q_append(srid); if ((null_value= (args[0]->null_value || - !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length()) || - str->append(*wkb)))) + !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length(), str)))) return 0; return str; } @@ -96,8 +95,7 @@ String *Item_func_as_wkt::val_str(String *str) if ((null_value= (args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; str->length(0); @@ -123,8 +121,7 @@ String *Item_func_as_wkb::val_str(String *str) if ((null_value= (args[0]->null_value || - !(Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE, @@ -142,8 +139,7 @@ String *Item_func_geometry_type::val_str(String *str) if ((null_value= (args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; /* String will not move */ str->copy(geom->get_class_info()->m_name.str, @@ -164,8 +160,7 @@ String *Item_func_envelope::val_str(String *str) if ((null_value= args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) return 0; srid= uint4korr(swkb->ptr()); @@ -188,8 +183,7 @@ String *Item_func_centroid::val_str(String *str) uint32 srid; if ((null_value= args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) return 0; str->set_charset(&my_charset_bin); @@ -218,8 +212,7 @@ String *Item_func_spatial_decomp::val_str(String *str) if ((null_value= (args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; srid= uint4korr(swkb->ptr()); @@ -267,8 +260,7 @@ String *Item_func_spatial_decomp_n::val_str(String *str) 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))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; str->set_charset(&my_charset_bin); @@ -475,10 +467,8 @@ longlong Item_func_spatial_rel::val_int() 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= Geometry::construct(&buffer1, res1->ptr(), res1->length())) || + !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) || g1->get_mbr(&mbr1, &dummy) || g2->get_mbr(&mbr2, &dummy)))) return 0; @@ -543,8 +533,7 @@ longlong Item_func_isclosed::val_int() null_value= (!swkb || args[0]->null_value || !(geom= - Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + Geometry::construct(&buffer, swkb->ptr(), swkb->length())) || geom->is_closed(&isclosed)); return (longlong) isclosed; @@ -566,9 +555,7 @@ longlong Item_func_dimension::val_int() null_value= (!swkb || args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) || geom->dimension(&dim, &dummy)); return (longlong) dim; } @@ -583,9 +570,8 @@ longlong Item_func_numinteriorring::val_int() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->num_interior_ring(&num)); return (longlong) num; } @@ -600,9 +586,8 @@ longlong Item_func_numgeometries::val_int() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->num_geometries(&num)); return (longlong) num; } @@ -618,9 +603,8 @@ longlong Item_func_numpoints::val_int() null_value= (!swkb || args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->num_points(&num)); return (longlong) num; } @@ -635,9 +619,8 @@ double Item_func_x::val() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->get_x(&res)); return res; } @@ -652,9 +635,8 @@ double Item_func_y::val() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->get_y(&res)); return res; } @@ -670,9 +652,8 @@ double Item_func_area::val() const char *dummy; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->area(&res, &dummy)); return res; } @@ -686,9 +667,8 @@ double Item_func_glength::val() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->length(&res)); return res; } @@ -700,9 +680,8 @@ longlong Item_func_srid::val_int() Geometry_buffer buffer; null_value= (!swkb || - !Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)); + !Geometry::construct(&buffer, + swkb->ptr(), swkb->length())); if (null_value) return 0; diff --git a/sql/spatial.cc b/sql/spatial.cc index 1afb7bb7dec..d37a4605a0b 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -119,25 +119,23 @@ Geometry::Class_info *Geometry::find_class(const char *name, uint32 len) return 0; } -Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer, - const char *data, uint32 data_len) + +Geometry *Geometry::construct(Geometry_buffer *buffer, + const char *data, uint32 data_len) { uint32 geom_type; Geometry *result; + char byte_order; - if (data_len < 1 + 4) + if (data_len < SRID_SIZE + 1 + 4) return NULL; - data++; - /* - FIXME: check byte ordering - Also check if we could replace this with one byte - */ - geom_type= uint4korr(data); - data+= 4; + byte_order= data[SRID_SIZE]; + geom_type= uint4korr(data + SRID_SIZE + 1); + data+= SRID_SIZE + WKB_HEADER_SIZE; if (!(result= create_by_typeid(buffer, (int) geom_type))) return NULL; result->m_data= data; - result->m_data_end= data + data_len; + result->m_data_end= data + (data_len - (SRID_SIZE + WKB_HEADER_SIZE)); return result; } @@ -168,13 +166,71 @@ Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer, return NULL; if (init_stream) { - result->init_from_wkb(wkt->ptr(), wkt->length()); + result->set_data_ptr(wkt->ptr(), wkt->length()); result->shift_wkb_header(); } return result; } +static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo) +{ + double res; + if (bo != Geometry::wkb_xdr) + float8get(res, ptr); + else + { + char inv_array[8]; + inv_array[0]= ptr[7]; + inv_array[1]= ptr[6]; + inv_array[2]= ptr[5]; + inv_array[3]= ptr[4]; + inv_array[4]= ptr[3]; + inv_array[5]= ptr[2]; + inv_array[6]= ptr[1]; + inv_array[7]= ptr[0]; + float8get(res, inv_array); + } + return res; +} + + +static uint32 wkb_get_uint(const char *ptr, Geometry::wkbByteOrder bo) +{ + if (bo != Geometry::wkb_xdr) + return uint4korr(ptr); + /* else */ + { + char inv_array[4]; + inv_array[0]= ptr[3]; + inv_array[1]= ptr[2]; + inv_array[2]= ptr[1]; + inv_array[3]= ptr[0]; + return uint4korr(inv_array); + } +} + + +int Geometry::create_from_wkb(Geometry_buffer *buffer, + const char *wkb, uint32 len, String *res) +{ + uint32 geom_type; + Geometry *geom; + + if (len < WKB_HEADER_SIZE) + return 1; + geom_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]); + if (!(geom= create_by_typeid(buffer, (int) geom_type)) || + res->reserve(WKB_HEADER_SIZE, 512)) + return 1; + + res->q_append((char)wkb_ndr); + res->q_append(geom_type); + return geom->init_from_wkb(wkb+WKB_HEADER_SIZE, len - WKB_HEADER_SIZE, + (wkbByteOrder)wkb[0], res); +} + + bool Geometry::envelope(String *result) const { MBR mbr; @@ -344,6 +400,20 @@ bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_point::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + double x, y; + if (len < POINT_DATA_SIZE || res->reserve(POINT_DATA_SIZE)) + return 0; + x= wkb_get_double(wkb, bo); + y= wkb_get_double(wkb + SIZEOF_STORED_DOUBLE, bo); + res->q_append(x); + res->q_append(y); + return POINT_DATA_SIZE; +} + + bool Gis_point::get_data_as_wkt(String *txt, const char **end) const { double x, y; @@ -413,6 +483,33 @@ bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_line_string::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_points, proper_length; + const char *wkb_end; + Gis_point p; + + if (len < 4) + return 0; + n_points= wkb_get_uint(wkb, bo); + proper_length= 4 + n_points * POINT_DATA_SIZE; + + if (len < proper_length || res->reserve(proper_length)) + return 0; + + res->q_append(n_points); + wkb_end= wkb + proper_length; + for (wkb+= 4; wkbcheck_next_symbol(')')) return 1; - ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos); + ls.set_data_ptr(wkb->ptr()+ls_pos, wkb->length()-ls_pos); if (ls.is_closed(&closed) || !closed) { trs->set_error_msg("POLYGON's linear ring isn't closed"); @@ -607,6 +704,43 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, + String *res) +{ + uint32 n_linear_rings; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + + n_linear_rings= wkb_get_uint(wkb, bo); + if (res->reserve(4, 512)) + return 0; + wkb+= 4; + len-= 4; + res->q_append(n_linear_rings); + + while (n_linear_rings--) + { + Gis_line_string ls; + uint32 ls_pos= res->length(); + int ls_len; + int closed; + + if (!(ls_len= ls.init_from_wkb(wkb, len, bo, res))) + return 0; + + ls.set_data_ptr(res->ptr()+ls_pos, res->length()-ls_pos); + + if (ls.is_closed(&closed) || !closed) + return 0; + wkb+= ls_len; + } + + return wkb - wkb_orig; +} + + bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_linear_rings; @@ -895,6 +1029,36 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, + String *res) +{ + uint32 n_points; + uint proper_size; + Gis_point p; + const char *wkb_end; + + if (len < 4) + return 0; + n_points= wkb_get_uint(wkb, bo); + proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE); + + if (len < proper_size || res->reserve(proper_size)) + return 0; + + res->q_append(n_points); + wkb_end= wkb + proper_size; + for (wkb+=4; wkb < wkb_end; wkb+= (WKB_HEADER_SIZE + POINT_DATA_SIZE)) + { + res->q_append((char)wkb_ndr); + res->q_append((uint32)wkb_point); + if (!p.init_from_wkb(wkb + WKB_HEADER_SIZE, + POINT_DATA_SIZE, (wkbByteOrder)wkb[0], res)) + return 0; + } + return proper_size; +} + + bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; @@ -1004,6 +1168,42 @@ bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_line_strings; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + n_line_strings= wkb_get_uint(wkb, bo); + + if (res->reserve(4, 512)) + return 0; + res->q_append(n_line_strings); + + for (wkb+=4; n_line_strings; n_line_strings--) + { + Gis_line_string ls; + int ls_len; + + if ((len < WKB_HEADER_SIZE) || + res->reserve(WKB_HEADER_SIZE, 512)) + return 0; + + res->q_append((char) wkb_ndr); + res->q_append((uint32) wkb_linestring); + + if (!(ls_len= ls.init_from_wkb(wkb + WKB_HEADER_SIZE, len, + (wkbByteOrder)wkb[0], res))) + return 0; + wkb+= (ls_len + WKB_HEADER_SIZE); + len-= (ls_len + WKB_HEADER_SIZE); + } + return wkb-wkb_orig; +} + + bool Gis_multi_line_string::get_data_as_wkt(String *txt, const char **end) const { @@ -1109,7 +1309,7 @@ int Gis_multi_line_string::length(double *len) const double ls_len; Gis_line_string ls; data+= WKB_HEADER_SIZE; - ls.init_from_wkb(data, (uint32) (m_data_end - data)); + ls.set_data_ptr(data, (uint32) (m_data_end - data)); if (ls.length(&ls_len)) return 1; *len+= ls_len; @@ -1138,7 +1338,7 @@ int Gis_multi_line_string::is_closed(int *closed) const Gis_line_string ls; if (no_data(data, 0)) return 1; - ls.init_from_wkb(data, (uint32) (m_data_end - data)); + ls.set_data_ptr(data, (uint32) (m_data_end - data)); if (ls.is_closed(closed)) return 1; if (!*closed) @@ -1220,6 +1420,41 @@ bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_poly; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + n_poly= wkb_get_uint(wkb, bo); + + if (res->reserve(4, 512)) + return 0; + res->q_append(n_poly); + + for (wkb+=4; n_poly; n_poly--) + { + Gis_polygon p; + int p_len; + + if (len < WKB_HEADER_SIZE || + res->reserve(WKB_HEADER_SIZE, 512)) + return 0; + res->q_append((char) wkb_ndr); + res->q_append((uint32) wkb_polygon); + + if (!(p_len= p.init_from_wkb(wkb + WKB_HEADER_SIZE, len, + (wkbByteOrder)wkb[0], res))) + return 0; + wkb+= (p_len + WKB_HEADER_SIZE); + len-= (p_len + WKB_HEADER_SIZE); + } + return wkb-wkb_orig; +} + + bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_polygons; @@ -1356,7 +1591,7 @@ int Gis_multi_polygon::area(double *ar, const char **end_of_data) const Gis_polygon p; data+= WKB_HEADER_SIZE; - p.init_from_wkb(data, (uint32) (m_data_end - data)); + p.set_data_ptr(data, (uint32) (m_data_end - data)); if (p.area(&p_area, &data)) return 1; result+= p_area; @@ -1388,7 +1623,7 @@ int Gis_multi_polygon::centroid(String *result) const while (n_polygons--) { data+= WKB_HEADER_SIZE; - p.init_from_wkb(data, (uint32) (m_data_end - data)); + p.set_data_ptr(data, (uint32) (m_data_end - data)); if (p.area(&cur_area, &data) || p.centroid_xy(&cur_cx, &cur_cy)) return 1; @@ -1442,7 +1677,7 @@ uint32 Gis_geometry_collection::get_data_size() const if (!(geom= create_by_typeid(&buffer, wkb_type))) return GET_SIZE_ERROR; - geom->init_from_wkb(data, (uint) (m_data_end - data)); + geom->set_data_ptr(data, (uint) (m_data_end - data)); if ((object_size= geom->get_data_size()) == GET_SIZE_ERROR) return GET_SIZE_ERROR; data+= object_size; @@ -1482,6 +1717,46 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_geom; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + n_geom= wkb_get_uint(wkb, bo); + + if (res->reserve(4, 512)) + return 0; + res->q_append(n_geom); + + for (wkb+=4; n_geom; n_geom--) + { + Geometry_buffer buffer; + Geometry *geom; + int g_len; + uint32 wkb_type; + + if (len < WKB_HEADER_SIZE || + res->reserve(WKB_HEADER_SIZE, 512)) + return 0; + + res->q_append((char) wkb_ndr); + wkb_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]); + res->q_append(wkb_type); + + if (!(geom= create_by_typeid(&buffer, wkb_type)) || + !(g_len= geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len, + (wkbByteOrder)wkb[0], res))) + return 0; + wkb+= (g_len + WKB_HEADER_SIZE); + len-= (g_len + WKB_HEADER_SIZE); + } + return wkb-wkb_orig; +} + + bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end) const { @@ -1506,7 +1781,7 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt, if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint) (m_data_end - data)); + geom->set_data_ptr(data, (uint) (m_data_end - data)); if (geom->as_wkt(txt, &data)) return 1; if (txt->append(",", 1, 512)) @@ -1541,7 +1816,7 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint32) (m_data_end - data)); + geom->set_data_ptr(data, (uint32) (m_data_end - data)); if (geom->get_mbr(mbr, &data)) return 1; } @@ -1582,7 +1857,7 @@ int Gis_geometry_collection::geometry_n(uint32 num, String *result) const if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint) (m_data_end - data)); + geom->set_data_ptr(data, (uint) (m_data_end - data)); if ((length= geom->get_data_size()) == GET_SIZE_ERROR) return 1; data+= length; @@ -1635,7 +1910,7 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const data+= WKB_HEADER_SIZE; if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint32) (m_data_end - data)); + geom->set_data_ptr(data, (uint32) (m_data_end - data)); if (geom->dimension(&dim, &end_data)) return 1; set_if_bigger(*res_dim, dim); diff --git a/sql/spatial.h b/sql/spatial.h index b96434831a1..acd16172fcc 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -202,6 +202,10 @@ public: 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; + + /* returns the length of the wkb that was read */ + virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, + String *res)=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; @@ -231,11 +235,13 @@ public: return my_reinterpret_cast(Geometry *)(buffer); } - static Geometry *create_from_wkb(Geometry_buffer *buffer, - const char *data, uint32 data_len); + static Geometry *construct(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); + static int Geometry::create_from_wkb(Geometry_buffer *buffer, + const char *wkb, uint32 len, String *res); int as_wkt(String *wkt, const char **end) { uint32 len= get_class_info()->m_name.length; @@ -249,7 +255,7 @@ public: return 0; } - inline void init_from_wkb(const char *data, uint32 data_len) + inline void set_data_ptr(const char *data, uint32 data_len) { m_data= data; m_data_end= data + data_len; @@ -293,6 +299,7 @@ class Gis_point: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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; @@ -339,6 +346,7 @@ class Gis_line_string: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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 length(double *len) const; @@ -364,6 +372,7 @@ class Gis_polygon: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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 area(double *ar, const char **end) const; @@ -389,6 +398,7 @@ class Gis_multi_point: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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 num_geometries(uint32 *num) const; @@ -410,6 +420,7 @@ class Gis_multi_line_string: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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 num_geometries(uint32 *num) const; @@ -433,6 +444,7 @@ class Gis_multi_polygon: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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 num_geometries(uint32 *num) const; @@ -456,6 +468,7 @@ class Gis_geometry_collection: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + 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 num_geometries(uint32 *num) const; From ab90b23a87ecb4fad984d59585367dc00b4e1282 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Oct 2005 11:05:59 -0700 Subject: [PATCH 2/5] Fix typo (thread_cache should be thread_cache_size) in example configuration files. (Bug #13811) support-files/my-huge.cnf.sh: Fix name of thread_cache_size setting. support-files/my-innodb-heavy-4G.cnf.sh: Fix name of thread_cache_size setting. support-files/my-large.cnf.sh: Fix name of thread_cache_size setting. --- support-files/my-huge.cnf.sh | 2 +- support-files/my-innodb-heavy-4G.cnf.sh | 2 +- support-files/my-large.cnf.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index d25686f1c21..06683994a72 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -33,7 +33,7 @@ sort_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 8M myisam_sort_buffer_size = 64M -thread_cache = 8 +thread_cache_size = 8 query_cache_size = 32M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 diff --git a/support-files/my-innodb-heavy-4G.cnf.sh b/support-files/my-innodb-heavy-4G.cnf.sh index 062d106ce6a..4204e172016 100644 --- a/support-files/my-innodb-heavy-4G.cnf.sh +++ b/support-files/my-innodb-heavy-4G.cnf.sh @@ -128,7 +128,7 @@ join_buffer_size = 8M # the amount of thread creations needed if you have a lot of new # connections. (Normally this doesn't give a notable performance # improvement if you have a good thread implementation.) -thread_cache = 8 +thread_cache_size = 8 # This permits the application to give the threads system a hint for the # desired number of threads that should be run at the same time. This diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 59aca4b32f2..85151eb1077 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -33,7 +33,7 @@ sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M -thread_cache = 8 +thread_cache_size = 8 query_cache_size= 16M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 From 8402aefe25121b6cbb57ae3990050985acbea8cc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Oct 2005 11:10:45 -0700 Subject: [PATCH 3/5] Force a server restart for the not_embedded_server test to satisfy conditions of its first test. (Bug #13796) mysql-test/t/not_embedded_server-master.opt: New BitKeeper file ``mysql-test/t/not_embedded_server-master.opt'' --- mysql-test/t/not_embedded_server-master.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 mysql-test/t/not_embedded_server-master.opt diff --git a/mysql-test/t/not_embedded_server-master.opt b/mysql-test/t/not_embedded_server-master.opt new file mode 100644 index 00000000000..35fcc5f30c6 --- /dev/null +++ b/mysql-test/t/not_embedded_server-master.opt @@ -0,0 +1 @@ +--loose-to-force-a-restart From cf59103d84e648467f8c95d4804e498b7113e61a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Oct 2005 14:50:08 -0700 Subject: [PATCH 4/5] BUG# 12123 Made change to mysqlimport to set character_set_database to binary to make importing various charsets/columns work correctly. client/mysqlimport.c: BUG# 12123 Added 'set @@character_set_database=binary' to make loading of tables with mixed charset types and non-latin characters load. mysql-test/mysql-test-run.pl: BUG #12123 Added $MYSQL_IMPORT in order to test mysqlimport bug. mysql-test/mysql-test-run.sh: BUG #12123 Added $MYSQL_IMPORT in order to test mysqlimport bug. mysql-test/r/mysqldump.result: BUG #12123 Added dumping and reloading (using mysql, mysqldump, and mysqlimport) to show that this fix handles dumping and reloading of non-latin1 charsets in table with different charset columns (mixing of charsets, also can be a UTF table with latin1 tables). Note the select before and after dump and restore - should be exact. mysql-test/t/mysqldump.test: BUG #12123 Added dumping and reloading (using mysql, mysqldump, and mysqlimport) to show that this fix handles dumping and reloading of non-latin1 charsets in table with different charset columns (mixing of charsets, also can be a UTF table with latin1 tables). Note the select before and after dump and restore - should be exact. (results of this) --- client/mysqlimport.c | 7 +++++++ mysql-test/mysql-test-run.pl | 11 +++++++++++ mysql-test/mysql-test-run.sh | 9 ++++++++- mysql-test/r/mysqldump.result | 10 ++++++++++ mysql-test/t/mysqldump.test | 12 ++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index ca4acd82db6..32e2a7ccffe 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -517,6 +517,13 @@ int main(int argc, char **argv) free_defaults(argv_to_free); return(1); /* purecov: deadcode */ } + + if (mysql_query(sock, "set @@character_set_database=binary;")) + { + db_error(sock); /* We shall countinue here, if --force was given */ + return(1); + } + if (lock_tables) lock_table(sock, argc, argv); for (; *argv != NULL; argv++) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4b055e0bb84..3583d8a7124 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -172,6 +172,7 @@ our $exe_mysqlbinlog; our $exe_mysql_client_test; our $exe_mysqld; our $exe_mysqldump; # Called from test case +our $exe_mysqlimport; # Called from test case our $exe_mysqlshow; # Called from test case our $exe_mysql_fix_system_tables; our $exe_mysqltest; @@ -861,6 +862,7 @@ sub executable_setup () { "/usr/bin/false"); } $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump"); + $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport"); $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow"); $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog"); $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); @@ -2076,6 +2078,14 @@ sub run_mysqltest ($) { $cmdline_mysqldump .= " --debug=d:t:A,$opt_vardir/log/mysqldump.trace"; } + my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " . + "--port=$master->[0]->{'path_myport'} " . + "--socket=$master->[0]->{'path_mysock'} --password="; + if ( $opt_debug ) + { + $cmdline_mysqlimport .= + " --debug=d:t:A,$opt_vardir/log/mysqlimport.trace"; + } my $cmdline_mysqlshow= "$exe_mysqlshow -uroot " . "--port=$master->[0]->{'path_myport'} " . @@ -2126,6 +2136,7 @@ sub run_mysqltest ($) { $ENV{'MYSQL'}= $cmdline_mysql; $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump; + $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport; $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow; $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog; $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 3e7a54fdead..259cb8cb5e4 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -546,6 +546,11 @@ if [ x$SOURCE_DIST = x1 ] ; then else MYSQL_DUMP="$BASEDIR/client/mysqldump" fi + if [ -f "$BASEDIR/client/.libs/mysqlimport" ] ; then + MYSQL_IMPORT="$BASEDIR/client/.libs/mysqlimport" + else + MYSQL_IMPORT="$BASEDIR/client/mysqlimport" + fi if [ -f "$BASEDIR/client/.libs/mysqlbinlog" ] ; then MYSQL_BINLOG="$BASEDIR/client/.libs/mysqlbinlog" else @@ -614,6 +619,7 @@ else fi MYSQL_TEST="$CLIENT_BINDIR/mysqltest" MYSQL_DUMP="$CLIENT_BINDIR/mysqldump" + MYSQL_IMPORT="$CLIENT_BINDIR/mysqlimport" MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog" MYSQLADMIN="$CLIENT_BINDIR/mysqladmin" WAIT_PID="$CLIENT_BINDIR/mysql_waitpid" @@ -693,10 +699,11 @@ fi MYSQL_DUMP_DIR="$MYSQL_DUMP" export MYSQL_DUMP_DIR MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" +MYSQL_IMPORT="$MYSQL_IMPORT -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD" -export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES +export MYSQL MYSQL_DUMP MYSQL_IMPORT MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR export NDB_TOOLS_DIR export NDB_MGM diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index cb2e8e5528a..fb72abe9b45 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1493,3 +1493,13 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +create table t1 (a text character set utf8, b text character set latin1); +insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); +select * from t1; +a b +Osnabrück Köln +test.t1: Records: 1 Deleted: 0 Skipped: 0 Warnings: 0 +select * from t1; +a b +Osnabrück Köln +drop table t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 4978da0bd67..ad1fb534836 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -635,4 +635,16 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; +# +# BUG #12123 +# +create table t1 (a text character set utf8, b text character set latin1); +insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); +select * from t1; +--exec $MYSQL_DUMP --tab=$MYSQL_TEST_DIR/var/tmp/ test +--exec $MYSQL test < $MYSQL_TEST_DIR/var/tmp/t1.sql +--exec $MYSQL_IMPORT test $MYSQL_TEST_DIR/var/tmp/t1.txt +select * from t1; + +drop table t1; # End of 4.1 tests From b47f1efb2557d4b4406c3563c1a340712cb00a9f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Oct 2005 12:05:27 +0400 Subject: [PATCH 5/5] Additional fix for #12839 sql/field.cc: This code still could work for VERY out-of-dated databases sql/spatial.cc: small syntax fixes --- sql/field.cc | 3 +-- sql/spatial.cc | 18 +++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index ccf82bdbae3..ab4474f681c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5745,8 +5745,7 @@ void Field_blob::get_key_image(char *buff,uint length, return; } get_ptr(&blob); - gobj= Geometry::construct(&buffer, - blob + SRID_SIZE, blob_length - SRID_SIZE); + gobj= Geometry::construct(&buffer, blob, blob_length); if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else diff --git a/sql/spatial.cc b/sql/spatial.cc index d37a4605a0b..9e72dfb9130 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -224,10 +224,10 @@ int Geometry::create_from_wkb(Geometry_buffer *buffer, res->reserve(WKB_HEADER_SIZE, 512)) return 1; - res->q_append((char)wkb_ndr); + res->q_append((char) wkb_ndr); res->q_append(geom_type); return geom->init_from_wkb(wkb+WKB_HEADER_SIZE, len - WKB_HEADER_SIZE, - (wkbByteOrder)wkb[0], res); + (wkbByteOrder) wkb[0], res); } @@ -689,7 +689,7 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) trs->check_next_symbol(')')) return 1; - ls.set_data_ptr(wkb->ptr()+ls_pos, wkb->length()-ls_pos); + ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos); if (ls.is_closed(&closed) || !closed) { trs->set_error_msg("POLYGON's linear ring isn't closed"); @@ -730,7 +730,7 @@ uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, if (!(ls_len= ls.init_from_wkb(wkb, len, bo, res))) return 0; - ls.set_data_ptr(res->ptr()+ls_pos, res->length()-ls_pos); + ls.set_data_ptr(res->ptr() + ls_pos, res->length() - ls_pos); if (ls.is_closed(&closed) || !closed) return 0; @@ -1052,7 +1052,7 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, res->q_append((char)wkb_ndr); res->q_append((uint32)wkb_point); if (!p.init_from_wkb(wkb + WKB_HEADER_SIZE, - POINT_DATA_SIZE, (wkbByteOrder)wkb[0], res)) + POINT_DATA_SIZE, (wkbByteOrder) wkb[0], res)) return 0; } return proper_size; @@ -1195,7 +1195,7 @@ uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len, res->q_append((uint32) wkb_linestring); if (!(ls_len= ls.init_from_wkb(wkb + WKB_HEADER_SIZE, len, - (wkbByteOrder)wkb[0], res))) + (wkbByteOrder) wkb[0], res))) return 0; wkb+= (ls_len + WKB_HEADER_SIZE); len-= (ls_len + WKB_HEADER_SIZE); @@ -1446,7 +1446,7 @@ uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len, res->q_append((uint32) wkb_polygon); if (!(p_len= p.init_from_wkb(wkb + WKB_HEADER_SIZE, len, - (wkbByteOrder)wkb[0], res))) + (wkbByteOrder) wkb[0], res))) return 0; wkb+= (p_len + WKB_HEADER_SIZE); len-= (p_len + WKB_HEADER_SIZE); @@ -1743,12 +1743,12 @@ uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, return 0; res->q_append((char) wkb_ndr); - wkb_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]); + wkb_type= wkb_get_uint(wkb+1, (wkbByteOrder) wkb[0]); res->q_append(wkb_type); if (!(geom= create_by_typeid(&buffer, wkb_type)) || !(g_len= geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len, - (wkbByteOrder)wkb[0], res))) + (wkbByteOrder) wkb[0], res))) return 0; wkb+= (g_len + WKB_HEADER_SIZE); len-= (g_len + WKB_HEADER_SIZE);