diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2011-07-04 16:03:36 +0500 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2011-07-04 16:03:36 +0500 |
commit | 0e6c889c83bcf6c37526e3a3fee192bb59cab92e (patch) | |
tree | df83f696c25331e8fe04874a9a22ebe3483a96fd | |
parent | a9a6597d598c735ba6b8a136864b888d8d626b70 (diff) | |
download | mariadb-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.
-rw-r--r-- | mysql-test/r/gis-precise.result | 3 | ||||
-rw-r--r-- | mysql-test/t/gis-precise.test | 3 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 60 | ||||
-rw-r--r-- | sql/item_geofunc.h | 15 |
4 files changed, 66 insertions, 15 deletions
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result index 48c00c4a468..e4cc9028236 100644 --- a/mysql-test/r/gis-precise.result +++ b/mysql-test/r/gis-precise.result @@ -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 diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test index e75316a0805..e267bcf57c1 100644 --- a/mysql-test/t/gis-precise.test +++ b/mysql-test/t/gis-precise.test @@ -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); 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; diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 1838a3783e8..d5ed2c1f764 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -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; |