Commit 0e6c889c authored by Alexey Botchkov's avatar Alexey Botchkov

bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT

        Collections were treated mistakenly, so the counter for the final UNION operation
        received the wrong value.
        As a fix we implement Item_func_buffer::Transporter::start_collection() method,
        where we set the proper operation and the operand counter.
        start_poly() and start_line() were also modified to function correctly for the 
        polygon as a part of a collection.

per-file comments:
  mysql-test/r/gis-precise.result
bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT
        test result updated.

  mysql-test/t/gis-precise.test
bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT
        test case added.

  sql/item_geofunc.cc
bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT
        start_collection() implemented.

  sql/item_geofunc.h
bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT
        Item_func_buffer::Transporter::start_collection() defined.
parent a9a6597d
...@@ -212,3 +212,6 @@ GEOMETRYCOLLECTION(POLYGON((0 0,1 9,8 2,0 0),(2 2,2 7,3 2,2 2)),LINESTRING(0 0,5 ...@@ -212,3 +212,6 @@ GEOMETRYCOLLECTION(POLYGON((0 0,1 9,8 2,0 0),(2 2,2 7,3 2,2 2)),LINESTRING(0 0,5
SELECT astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0)); SELECT astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0));
astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0)) astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0))
LINESTRING(0 0,1 1) LINESTRING(0 0,1 1)
SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5);
Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5)
78.68426
...@@ -114,3 +114,6 @@ SELECT astext(ST_UNION ( ...@@ -114,3 +114,6 @@ SELECT astext(ST_UNION (
#bug 801189 ST_BUFFER asserts if radius = 0 #bug 801189 ST_BUFFER asserts if radius = 0
SELECT astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0)); SELECT astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0));
#buf 801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT
SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5);
...@@ -1284,6 +1284,18 @@ int Item_func_buffer::Transporter::add_point_buffer(double x, double y) ...@@ -1284,6 +1284,18 @@ int Item_func_buffer::Transporter::add_point_buffer(double x, double y)
int Item_func_buffer::Transporter::start_line() int Item_func_buffer::Transporter::start_line()
{ {
if (buffer_op == Gcalc_function::op_difference)
{
skip_line= TRUE;
return 0;
}
m_nshapes= 0;
if (m_fn->reserve_op_buffer(2))
return 1;
last_shape_pos= m_fn->get_next_operation_pos();
m_fn->add_operation(buffer_op, 0);
m_npoints= 0; m_npoints= 0;
int_start_line(); int_start_line();
return 0; return 0;
...@@ -1292,11 +1304,25 @@ int Item_func_buffer::Transporter::start_line() ...@@ -1292,11 +1304,25 @@ int Item_func_buffer::Transporter::start_line()
int Item_func_buffer::Transporter::start_poly() int Item_func_buffer::Transporter::start_poly()
{ {
++m_nshapes; m_nshapes= 1;
if (m_fn->reserve_op_buffer(2))
return 1;
last_shape_pos= m_fn->get_next_operation_pos();
m_fn->add_operation(buffer_op, 0);
return Gcalc_operation_transporter::start_poly(); return Gcalc_operation_transporter::start_poly();
} }
int Item_func_buffer::Transporter::complete_poly()
{
if (Gcalc_operation_transporter::complete_poly())
return 1;
m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
return 0;
}
int Item_func_buffer::Transporter::start_ring() int Item_func_buffer::Transporter::start_ring()
{ {
m_npoints= 0; m_npoints= 0;
...@@ -1304,8 +1330,20 @@ int Item_func_buffer::Transporter::start_ring() ...@@ -1304,8 +1330,20 @@ int Item_func_buffer::Transporter::start_ring()
} }
int Item_func_buffer::Transporter::start_collection(int n_objects)
{
if (m_fn->reserve_op_buffer(1))
return 1;
m_fn->add_operation(Gcalc_function::op_union, n_objects);
return 0;
}
int Item_func_buffer::Transporter::add_point(double x, double y) int Item_func_buffer::Transporter::add_point(double x, double y)
{ {
if (skip_line)
return 0;
if (m_npoints && x == x2 && y == y2) if (m_npoints && x == x2 && y == y2)
return 0; return 0;
...@@ -1374,9 +1412,14 @@ int Item_func_buffer::Transporter::complete() ...@@ -1374,9 +1412,14 @@ int Item_func_buffer::Transporter::complete()
int Item_func_buffer::Transporter::complete_line() int Item_func_buffer::Transporter::complete_line()
{ {
if (complete()) if (!skip_line)
return 1; {
int_complete_line(); if (complete())
return 1;
int_complete_line();
m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
}
skip_line= FALSE;
return 0; return 0;
} }
...@@ -1396,7 +1439,6 @@ String *Item_func_buffer::val_str(String *str_value) ...@@ -1396,7 +1439,6 @@ String *Item_func_buffer::val_str(String *str_value)
double dist= args[1]->val_real(); double dist= args[1]->val_real();
Geometry_buffer buffer; Geometry_buffer buffer;
Geometry *g; Geometry *g;
uint32 union_pos;
uint32 srid= 0; uint32 srid= 0;
String *str_result= NULL; String *str_result= NULL;
Transporter trn(&func, &collector, dist); Transporter trn(&func, &collector, dist);
...@@ -1418,17 +1460,9 @@ String *Item_func_buffer::val_str(String *str_value) ...@@ -1418,17 +1460,9 @@ String *Item_func_buffer::val_str(String *str_value)
goto mem_error; goto mem_error;
} }
if (func.reserve_op_buffer(2))
goto mem_error;
/* will specify operands later */
union_pos= func.get_next_operation_pos();
func.add_operation((dist > 0.0) ? Gcalc_function::op_union :
Gcalc_function::op_difference, 0);
if (g->store_shapes(&trn)) if (g->store_shapes(&trn))
goto mem_error; goto mem_error;
func.add_operands_to_op(union_pos, trn.m_nshapes);
collector.prepare_operation(); collector.prepare_operation();
if (func.alloc_states()) if (func.alloc_states())
goto mem_error; goto mem_error;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#endif #endif
#include "gcalc_slicescan.h" #include "gcalc_slicescan.h"
#include "gcalc_tools.h"
class Item_geometry_func: public Item_str_func class Item_geometry_func: public Item_str_func
{ {
...@@ -298,18 +299,28 @@ class Item_func_buffer: public Item_geometry_func ...@@ -298,18 +299,28 @@ class Item_func_buffer: public Item_geometry_func
int add_last_edge_buffer(); int add_last_edge_buffer();
int add_point_buffer(double x, double y); int add_point_buffer(double x, double y);
int complete(); int complete();
public:
int m_nshapes; int m_nshapes;
Gcalc_function::op_type buffer_op;
int last_shape_pos;
bool skip_line;
public:
Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) : Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) :
Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d), m_nshapes(0) Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d),
m_nshapes(0), buffer_op((d > 0.0) ? Gcalc_function::op_union :
Gcalc_function::op_difference),
skip_line(FALSE)
{} {}
int single_point(double x, double y); int single_point(double x, double y);
int start_line(); int start_line();
int complete_line(); int complete_line();
int start_poly(); int start_poly();
int complete_poly();
int start_ring(); int start_ring();
int complete_ring(); int complete_ring();
int add_point(double x, double y); int add_point(double x, double y);
int start_collection(int n_objects);
}; };
Gcalc_heap collector; Gcalc_heap collector;
Gcalc_function func; Gcalc_function func;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment