summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/gis-precise.result14
-rw-r--r--mysql-test/t/gis-precise.test9
-rw-r--r--sql/gcalc_tools.cc31
-rw-r--r--sql/gcalc_tools.h11
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,