diff options
-rw-r--r-- | mysql-test/r/gis-precise.result | 14 | ||||
-rw-r--r-- | mysql-test/t/gis-precise.test | 9 | ||||
-rw-r--r-- | sql/gcalc_tools.cc | 31 | ||||
-rw-r--r-- | sql/gcalc_tools.h | 11 |
4 files changed, 53 insertions, 12 deletions
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result index 4f07333e6a3..75028e484dd 100644 --- a/mysql-test/r/gis-precise.result +++ b/mysql-test/r/gis-precise.result @@ -218,3 +218,17 @@ Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), SELECT ST_INTERSECTION(NULL, NULL); ST_INTERSECTION(NULL, NULL) NULL +SELECT ASTEXT(ST_INTERSECTION( +MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)), + ((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)), + ((2 2,5 2,4 4,2 8,2 2)))'), +MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((3 5,2 4,2 5,3 5)), + ((2 2,9 2,0 2,2 6,2 2)), + ((2 2,2 8,8 8,8 2,2 2), (4 4,4 6,6 6,6 4,4 4)), + ((9 9,6 8,7 0,9 9)))'))); +ASTEXT(ST_INTERSECTION( +MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)), + ((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)), + ((2 2,5 2,4 4,2 8,2 2)))'), +MULTIPOLY +MULTIPOLYGON(((2 2,3 2,2 2)),((5 2,0 2,5 2)),((2 2,0 2,1.5 5,2 5,2 2),(1 3,1 4,2 4,2 3,1 3)),((2 2,2 8,8 8,8 2,5 2,2 2),(6 4,4 4,4 6,6 6,6 4))) diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test index 72ba6b748be..87b56dc0040 100644 --- a/mysql-test/t/gis-precise.test +++ b/mysql-test/t/gis-precise.test @@ -121,3 +121,12 @@ SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 #bug 801212 Assertion with ST_INTERSECTION on NULL values SELECT ST_INTERSECTION(NULL, NULL); +#bug 804305 Crash in wkb_get_double with ST_INTERSECTION +SELECT ASTEXT(ST_INTERSECTION( + MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)), + ((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)), + ((2 2,5 2,4 4,2 8,2 2)))'), + MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((3 5,2 4,2 5,3 5)), + ((2 2,9 2,0 2,2 6,2 2)), + ((2 2,2 8,8 8,8 2,2 2), (4 4,4 6,6 6,6 4,4 4)), + ((9 9,6 8,7 0,9 9)))'))); diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 0e2970116ce..11d452cd8cf 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -419,17 +419,16 @@ int Gcalc_result_receiver::get_result_typeid() int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position, - uint32 *new_dest_position) + uint32 *position_shift) { char *ptr; int source_len; + + *position_shift= source_len= buffer.length() - source_position; + if (dest_position == source_position) - { - *new_dest_position= position(); return 0; - } - source_len= buffer.length() - source_position; if (buffer.reserve(source_len, MY_ALIGN(source_len, 512))) return 1; @@ -437,7 +436,6 @@ int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_positio memmove(ptr + dest_position + source_len, ptr + dest_position, buffer.length() - dest_position); memcpy(ptr + dest_position, ptr + buffer.length(), source_len); - *new_dest_position= dest_position + source_len; return 0; } @@ -1098,6 +1096,8 @@ int Gcalc_operation_reducer::get_line_result(res_point *cur, int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage) { + poly_instance *polygons= NULL; + *m_res_hook= NULL; while (m_result) { @@ -1112,19 +1112,28 @@ int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage) { if (m_result->outer_poly) { - uint32 *insert_position, hole_position; - insert_position= &m_result->outer_poly->first_poly_node->poly_position; - DBUG_ASSERT(*insert_position); + uint32 insert_position, hole_position, position_shift; + poly_instance *cur_poly; + insert_position= m_result->outer_poly->first_poly_node->poly_position; + DBUG_ASSERT(insert_position); hole_position= storage->position(); storage->start_shape(Gcalc_function::shape_hole); if (get_polygon_result(m_result, storage) || - storage->move_hole(*insert_position, hole_position, - insert_position)) + storage->move_hole(insert_position, hole_position, + &position_shift)) return 1; + for (cur_poly= polygons; + cur_poly && *cur_poly->after_poly_position >= insert_position; + cur_poly= cur_poly->get_next()) + *cur_poly->after_poly_position+= position_shift; } else { uint32 *poly_position= &m_result->poly_position; + poly_instance *p= new_poly(); + p->after_poly_position= poly_position; + p->next= polygons; + polygons= p; storage->start_shape(Gcalc_function::shape_polygon); if (get_polygon_result(m_result, storage)) return 1; diff --git a/sql/gcalc_tools.h b/sql/gcalc_tools.h index 7df236618fb..32835d68666 100644 --- a/sql/gcalc_tools.h +++ b/sql/gcalc_tools.h @@ -170,7 +170,7 @@ public: int get_result_typeid(); uint32 position() { return buffer.length(); } int move_hole(uint32 dest_position, uint32 source_position, - uint32 *new_dest_position); + uint32 *position_shift); }; @@ -233,6 +233,13 @@ public: active_thread *get_next() { return (active_thread *)next; } }; + class poly_instance : public Gcalc_dyn_list::Item + { + public: + uint32 *after_poly_position; + poly_instance *get_next() { return (poly_instance *)next; } + }; + protected: Gcalc_function *m_fn; Gcalc_dyn_list::Item **m_res_hook; @@ -253,6 +260,8 @@ protected: active_thread *new_active_thread() { return (active_thread *)new_item(); } + poly_instance *new_poly() { return (poly_instance *) new_item(); } + private: int continue_range(active_thread *t, const Gcalc_heap::Info *p); int continue_i_range(active_thread *t, const Gcalc_heap::Info *p, |