mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
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.
This commit is contained in:
@@ -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 (complete())
|
||||
return 1;
|
||||
int_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 @@ protected:
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user