summaryrefslogtreecommitdiff
path: root/sql/item_geofunc.cc
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2011-07-04 16:03:36 +0500
committerAlexey Botchkov <holyfoot@askmonty.org>2011-07-04 16:03:36 +0500
commit0e6c889c83bcf6c37526e3a3fee192bb59cab92e (patch)
treedf83f696c25331e8fe04874a9a22ebe3483a96fd /sql/item_geofunc.cc
parenta9a6597d598c735ba6b8a136864b888d8d626b70 (diff)
downloadmariadb-git-0e6c889c83bcf6c37526e3a3fee192bb59cab92e.tar.gz
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.
Diffstat (limited to 'sql/item_geofunc.cc')
-rw-r--r--sql/item_geofunc.cc60
1 files changed, 47 insertions, 13 deletions
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index f65df790dfb..8cae6dd6564 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -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;