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
SELECT 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)
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 (
#bug 801189 ST_BUFFER asserts if radius = 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)
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;
int_start_line();
return 0;
......@@ -1292,11 +1304,25 @@ int Item_func_buffer::Transporter::start_line()
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();
}
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()
{
m_npoints= 0;
......@@ -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)
{
if (skip_line)
return 0;
if (m_npoints && x == x2 && y == y2)
return 0;
......@@ -1374,9 +1412,14 @@ int Item_func_buffer::Transporter::complete()
int Item_func_buffer::Transporter::complete_line()
{
if (!skip_line)
{
if (complete())
return 1;
int_complete_line();
m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
}
skip_line= FALSE;
return 0;
}
......@@ -1396,7 +1439,6 @@ String *Item_func_buffer::val_str(String *str_value)
double dist= args[1]->val_real();
Geometry_buffer buffer;
Geometry *g;
uint32 union_pos;
uint32 srid= 0;
String *str_result= NULL;
Transporter trn(&func, &collector, dist);
......@@ -1418,17 +1460,9 @@ String *Item_func_buffer::val_str(String *str_value)
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))
goto mem_error;
func.add_operands_to_op(union_pos, trn.m_nshapes);
collector.prepare_operation();
if (func.alloc_states())
goto mem_error;
......
......@@ -26,6 +26,7 @@
#endif
#include "gcalc_slicescan.h"
#include "gcalc_tools.h"
class Item_geometry_func: public Item_str_func
{
......@@ -298,18 +299,28 @@ class Item_func_buffer: public Item_geometry_func
int add_last_edge_buffer();
int add_point_buffer(double x, double y);
int complete();
public:
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) :
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 start_line();
int complete_line();
int start_poly();
int complete_poly();
int start_ring();
int complete_ring();
int add_point(double x, double y);
int start_collection(int n_objects);
};
Gcalc_heap collector;
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