#At file:///home/hf/work/mysql_common/gis-bugfix/ based on revid:holyfoot@stripped
2665 Alexey Botchkov 2009-12-20
Bug#45883 Buffer function crashes mysqld
When two next nodes of an polygon have exactly same coordinates,
the calculation of the buffer can crash.
modified:
sql/gcalc_slicescan.cc
Bug#45883 Buffer function crashes mysqld
sql/gcalc_slicescan.h
Bug#45883 Buffer function crashes mysqld
sql/gcalc_tools.cc
Bug#45883 Buffer function crashes mysqld
sql/gcalc_tools.h
Bug#45883 Buffer function crashes mysqld
sql/item_geofunc.cc
Bug#45883 Buffer function crashes mysqld
sql/item_geofunc.h
Bug#45883 Buffer function crashes mysqld
sql/spatial.cc
Bug#45883 Buffer function crashes mysqld
sql/spatial.h
Bug#45883 Buffer function crashes mysqld
modified:
sql/gcalc_slicescan.cc
sql/gcalc_slicescan.h
sql/gcalc_tools.cc
sql/gcalc_tools.h
sql/item_geofunc.cc
sql/item_geofunc.h
sql/spatial.cc
sql/spatial.h
=== modified file 'sql/gcalc_slicescan.cc'
--- a/sql/gcalc_slicescan.cc 2009-12-05 08:58:34 +0000
+++ b/sql/gcalc_slicescan.cc 2009-12-20 10:39:40 +0000
@@ -203,6 +203,18 @@ void gcalc_dyn_list::reset()
}
+/* should be removed
+void gcalc_heap::free_point_info(gcalc_heap::info **pi_hook)
+{
+ DBUG_ASSERT(m_n_points);
+ gcalc_heap::info *pi= *pi_hook;
+ *pi_hook= pi->next;
+ free_item(pi);
+ --m_n_points;
+}
+*/
+
+
static inline void trim_node(gcalc_heap::info *node, gcalc_heap::info *prev_node)
{
if (!node)
@@ -281,6 +293,66 @@ void gcalc_heap::reset()
m_n_points= 0;
}
+int gcalc_shape_transporter::int_single_point(gcalc_shape_info info,
+ double x, double y)
+{
+ gcalc_heap::info *point= m_heap->new_point_info(x, y, info);
+ if (!point)
+ return 1;
+ point->left= point->right= 0;
+ return 0;
+}
+
+
+int gcalc_shape_transporter::int_add_point(gcalc_shape_info info,
+ double x, double y)
+{
+ gcalc_heap::info *point;
+ GCALC_DBUG_ADD_POINT(x, y);
+ if (!(point= m_heap->new_point_info(x, y, info)))
+ return 1;
+ if (m_first)
+ {
+ m_prev->left= point;
+ point->right= m_prev;
+ }
+ else
+ m_first= point;
+ m_prev= point;
+ return 0;
+}
+
+
+void gcalc_shape_transporter::int_complete()
+{
+ DBUG_ASSERT(m_shape_started == 1 || m_shape_started == 3);
+ GCALC_DBUG_COMPLETE;
+
+ if (!m_first)
+ return;
+
+ /* simple point */
+ if (m_first == m_prev)
+ {
+ m_first->right= m_first->left= NULL;
+ return;
+ }
+
+ /* line */
+ if (m_shape_started == 1)
+ {
+ m_first->right= NULL;
+ m_prev->left= m_prev->right;
+ m_prev->right= NULL;
+ return;
+ }
+
+ /* polygon */
+ m_first->right= m_prev;
+ m_prev->left= m_first;
+}
+
+
inline int GET_DX_DY(double *dxdy,
const gcalc_heap::info *p0, const gcalc_heap::info *p1)
{
=== modified file 'sql/gcalc_slicescan.h'
--- a/sql/gcalc_slicescan.h 2009-12-05 08:58:34 +0000
+++ b/sql/gcalc_slicescan.h 2009-12-20 10:39:40 +0000
@@ -128,7 +128,7 @@ public:
/* void reset_keep(int (*keep_point)(sc_point_info info, const void *parameter),
const void *parameter);
*/
- info *new_point_info()
+ info *new_point_info(double x, double y, gcalc_shape_info shape)
{
info *result= (info *)new_item();
if (!result)
@@ -136,8 +136,14 @@ public:
*m_hook= result;
m_hook= &result->next;
m_n_points++;
+ result->x= x;
+ result->y= y;
+ result->shape= shape;
return result;
}
+ /* should be removed
+ void free_point_info(info **pi_hook);
+ */
void prepare_operation();
inline bool ready() const { return m_hook == NULL; }
info *get_first() { return (info *)m_first; }
@@ -156,80 +162,74 @@ class gcalc_shape_transporter
private:
gcalc_heap::info *m_first;
gcalc_heap::info *m_prev;
+ int m_shape_started;
+ void int_complete();
+protected:
gcalc_heap *m_heap;
- gcalc_shape_info m_shape_info;
- bool m_line_flag;
-public:
- gcalc_shape_transporter(gcalc_heap *heap) : m_heap(heap) {}
-
- int single_point(gcalc_shape_info info, double x, double y)
- {
- gcalc_heap::info *point= m_heap->new_point_info();
- if (!point)
- return 1;
- point->x= x;
- point->y= y;
- point->shape= info;
- point->left= point->right= 0;
- return 0;
- }
-
- void start_line(gcalc_shape_info info)
+ int int_single_point(gcalc_shape_info info, double x, double y);
+ int int_add_point(gcalc_shape_info info, double x, double y);
+ void int_start_line()
{
- m_shape_info= info;
+ DBUG_ASSERT(!m_shape_started);
+ m_shape_started= 1;
m_first= m_prev= NULL;
- m_line_flag= TRUE;
GCALC_DBUG_START_LINE;
}
-
- void start_ring(gcalc_shape_info info)
+ void int_complete_line()
+ {
+ DBUG_ASSERT(m_shape_started== 1);
+ int_complete();
+ m_shape_started= 0;
+ }
+ void int_start_ring()
{
- m_shape_info= info;
+ DBUG_ASSERT(m_shape_started== 2);
+ m_shape_started= 3;
m_first= m_prev= NULL;
- m_line_flag= FALSE;
GCALC_DBUG_START_RING;
}
-
- int add_point(double x, double y)
+ void int_complete_ring()
{
- gcalc_heap::info *point= m_heap->new_point_info();
- if (!point)
- return 1;
- point->x= x;
- point->y= y;
- point->shape= m_shape_info;
- if (m_first)
- {
- m_prev->left= point;
- point->right= m_prev;
- }
- else
- m_first= point;
- m_prev= point;
- GCALC_DBUG_ADD_POINT(x, y);
- return 0;
+ DBUG_ASSERT(m_shape_started== 3);
+ int_complete();
+ m_shape_started= 2;
+ }
+ void int_start_poly()
+ {
+ DBUG_ASSERT(!m_shape_started);
+ m_shape_started= 2;
}
+ void int_complete_poly()
+ {
+ DBUG_ASSERT(m_shape_started== 2);
+ m_shape_started= 0;
+ }
+ bool line_started() { return m_shape_started == 1; };
+public:
+ gcalc_shape_transporter(gcalc_heap *heap) :
+ m_shape_started(0), m_heap(heap) {}
- void complete()
+ virtual int single_point(double x, double y)=0;
+ virtual int start_line()=0;
+ virtual int complete_line()=0;
+ virtual int start_poly()=0;
+ virtual int complete_poly()=0;
+ virtual int start_ring()=0;
+ virtual int complete_ring()=0;
+ virtual int add_point(double x, double y)=0;
+ virtual int start_collection(int n_objects) { return 0; }
+ int start_simple_poly()
{
- if (m_first)
- {
- if (m_line_flag)
- {
- m_first->right= NULL;
- m_prev->left= m_prev->right;
- m_prev->right= NULL;
- }
- else
- {
- m_first->right= m_prev;
- m_prev->left= m_first;
- }
- }
- GCALC_DBUG_COMPLETE;
+ return start_poly() || start_ring();
}
+ int complete_simple_poly()
+ {
+ return complete_ring() || complete_poly();
+ }
+ virtual ~gcalc_shape_transporter() {}
};
+
enum gcalc_scan_events
{
scev_point= 1, /* Just a new point in thread */
=== modified file 'sql/gcalc_tools.cc'
--- a/sql/gcalc_tools.cc 2009-12-05 08:58:34 +0000
+++ b/sql/gcalc_tools.cc 2009-12-20 10:39:40 +0000
@@ -155,6 +155,71 @@ int gcalc_function::find_function(gcalc_
}
+int gcalc_operation_transporter::single_point(double x, double y)
+{
+ gcalc_shape_info si;
+ return m_fn->single_shape_op(gcalc_function::shape_point, &si) ||
+ int_single_point(si, x, y);
+}
+
+
+int gcalc_operation_transporter::start_line()
+{
+ int_start_line();
+ return m_fn->single_shape_op(gcalc_function::shape_line, &m_si);
+}
+
+
+int gcalc_operation_transporter::complete_line()
+{
+ int_complete_line();
+ return 0;
+}
+
+
+int gcalc_operation_transporter::start_poly()
+{
+ int_start_poly();
+ return m_fn->single_shape_op(gcalc_function::shape_polygon, &m_si);
+}
+
+
+int gcalc_operation_transporter::complete_poly()
+{
+ int_complete_poly();
+ return 0;
+}
+
+
+int gcalc_operation_transporter::start_ring()
+{
+ int_start_ring();
+ return 0;
+}
+
+
+int gcalc_operation_transporter::complete_ring()
+{
+ int_complete_ring();
+ return 0;
+}
+
+
+int gcalc_operation_transporter::add_point(double x, double y)
+{
+ return int_add_point(m_si, x, y);
+}
+
+
+int gcalc_operation_transporter::start_collection(int n_objects)
+{
+ if (m_fn->reserve_shape_buffer(n_objects) || m_fn->reserve_op_buffer(1))
+ return 1;
+ m_fn->add_operation(gcalc_function::op_union, n_objects);
+ return 0;
+}
+
+
gcalc_result_receiver::gcalc_result_receiver() :
collection_result(FALSE), n_shapes(0), n_holes(0)
{}
=== modified file 'sql/gcalc_tools.h'
--- a/sql/gcalc_tools.h 2009-12-05 08:58:34 +0000
+++ b/sql/gcalc_tools.h 2009-12-20 10:39:40 +0000
@@ -65,6 +65,27 @@ public:
};
+class gcalc_operation_transporter : public gcalc_shape_transporter
+{
+protected:
+ gcalc_function *m_fn;
+ gcalc_shape_info m_si;
+public:
+ gcalc_operation_transporter(gcalc_function *fn, gcalc_heap *heap) :
+ gcalc_shape_transporter(heap), m_fn(fn) {}
+
+ 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);
+};
+
+
/* class to receive the result of the geometry operation */
/* to store it in appropriate format */
=== modified file 'sql/item_geofunc.cc'
--- a/sql/item_geofunc.cc 2009-12-05 08:58:34 +0000
+++ b/sql/item_geofunc.cc 2009-12-20 10:39:40 +0000
@@ -641,6 +641,7 @@ longlong Item_func_spatial_rel::val_int(
Geometry *g1, *g2;
int result= 0;
int mask= 0;
+ gcalc_operation_transporter trn(&func, &collector);
if (func.reserve_op_buffer(1))
DBUG_RETURN(0);
@@ -678,12 +679,10 @@ longlong Item_func_spatial_rel::val_int(
if ((null_value=
- (args[0]->null_value ||
- args[1]->null_value ||
+ (args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
- g1->store_shapes(&collector, &func) ||
- g2->store_shapes(&collector, &func))))
+ g1->store_shapes(&trn) || g2->store_shapes(&trn))))
goto exit;
collector.prepare_operation();
@@ -722,18 +721,17 @@ String *Item_func_spatial_operation::val
Geometry_buffer buffer1, buffer2;
Geometry *g1, *g2;
uint32 srid= 0;
+ gcalc_operation_transporter trn(&func, &collector);
if (func.reserve_op_buffer(1))
DBUG_RETURN(0);
func.add_operation(spatial_op, 2);
if ((null_value=
- (args[0]->null_value ||
- args[1]->null_value ||
+ (args[0]->null_value || args[1]->null_value ||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
- g1->store_shapes(&collector, &func) ||
- g2->store_shapes(&collector, &func))))
+ g1->store_shapes(&trn) || g2->store_shapes(&trn))))
goto exit;
@@ -908,27 +906,42 @@ static void calculate_perpendicular(cons
}
-int Item_func_buffer::add_edge_buffer(const gcalc_heap::info *p1,
- const gcalc_heap::info *p2,
- const gcalc_heap::info *p3,
- double d,
- bool round_p1, bool round_p2)
+static void calculate_perpendicular(
+ double x1, double y1, double x2, double y2, double d,
+ double *ex, double *ey,
+ double *px, double *py)
{
- gcalc_shape_transporter trn(&collector);
- gcalc_shape_info si;
+ double q;
+ *ex= x1 - x2;
+ *ey= y1 - y2;
+ q= d / sqrt((*ex) * (*ex) + (*ey) * (*ey));
+ *px= (*ey) * q;
+ *py= -(*ex) * q;
+}
+
+
+int Item_func_buffer::transporter::single_point(double x, double y)
+{
+ return add_point_buffer(x, y);
+}
+
+
+int Item_func_buffer::transporter::add_edge_buffer(
+ double x3, double y3, bool round_p1, bool round_p2)
+{
+ gcalc_operation_transporter trn(m_fn, m_heap);
double e1_x, e1_y, e2_x, e2_y, p1_x, p1_y, p2_x, p2_y;
double e1e2;
double sin1, cos1;
double x_n, y_n;
bool empty_gap1, empty_gap2;
- if (func.single_shape_op(gcalc_function::shape_polygon, &si))
+ ++m_nshapes;
+ if (trn.start_simple_poly())
return 1;
- trn.start_ring(si);
-
- calculate_perpendicular(p1, p2, d, &e1_x, &e1_y, &p1_x, &p1_y);
- calculate_perpendicular(p3, p2, d, &e2_x, &e2_y, &p2_x, &p2_y);
+ calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
+ calculate_perpendicular(x3, y3, x2, y2, m_d, &e2_x, &e2_y, &p2_x, &p2_y);
e1e2= e1_x * e2_y - e2_x * e1_y;
sin1= n_sinus[1];
@@ -936,161 +949,180 @@ int Item_func_buffer::add_edge_buffer(co
if (e1e2 < 0)
{
empty_gap2= false;
- x_n= p2->x + p2_x * cos1 - p2_y * sin1;
- y_n= p2->y + p2_y * cos1 + p2_x * sin1;
- if (fill_gap(&trn, p2->x,p2->y, -p1_x,-p1_y, p2_x,p2_y, d, &empty_gap1) ||
- trn.add_point(p2->x + p2_x, p2->y + p2_y) ||
+ x_n= x2 + p2_x * cos1 - p2_y * sin1;
+ y_n= y2 + p2_y * cos1 + p2_x * sin1;
+ if (fill_gap(&trn, x2, y2, -p1_x,-p1_y, p2_x,p2_y, m_d, &empty_gap1) ||
+ trn.add_point(x2 + p2_x, y2 + p2_y) ||
trn.add_point(x_n, y_n))
return 1;
}
else
{
- x_n= p2->x - p2_x * cos1 - p2_y * sin1;
- y_n= p2->y - p2_y * cos1 + p2_x * sin1;
+ x_n= x2 - p2_x * cos1 - p2_y * sin1;
+ y_n= y2 - p2_y * cos1 + p2_x * sin1;
if (trn.add_point(x_n, y_n) ||
- trn.add_point(p2->x - p2_x, p2->y - p2_y) ||
- fill_gap(&trn, p2->x, p2->y, -p2_x, -p2_y, p1_x, p1_y, d, &empty_gap2))
+ trn.add_point(x2 - p2_x, y2 - p2_y) ||
+ fill_gap(&trn, x2, y2, -p2_x, -p2_y, p1_x, p1_y, m_d, &empty_gap2))
return 1;
empty_gap1= false;
}
- if ((!empty_gap2 && trn.add_point(p2->x + p1_x, p2->y + p1_y)) ||
- trn.add_point(p1->x + p1_x, p1->y + p1_y))
+ if ((!empty_gap2 && trn.add_point(x2 + p1_x, y2 + p1_y)) ||
+ trn.add_point(x1 + p1_x, y1 + p1_y))
return 1;
- if (round_p1 && fill_half_circle(&trn, p1->x, p1->y, p1_x, p1_y))
+ if (round_p1 && fill_half_circle(&trn, x1, y1, p1_x, p1_y))
return 1;
- if (trn.add_point(p1->x - p1_x, p1->y - p1_y) ||
- (!empty_gap1 && trn.add_point(p2->x - p1_x, p2->y - p1_y)))
+ if (trn.add_point(x1 - p1_x, y1 - p1_y) ||
+ (!empty_gap1 && trn.add_point(x2 - p1_x, y2 - p1_y)))
return 1;
- trn.complete();
- return 0;
+ return trn.complete_simple_poly();
}
-int Item_func_buffer::add_last_edge_buffer(const gcalc_heap::info *p1,
- const gcalc_heap::info *p2,
- double d)
+int Item_func_buffer::transporter::add_last_edge_buffer()
{
- gcalc_shape_transporter trn(&collector);
- gcalc_shape_info si;
+ gcalc_operation_transporter trn(m_fn, m_heap);
double e1_x, e1_y, p1_x, p1_y;
- if (func.single_shape_op(gcalc_function::shape_polygon, &si))
+ ++m_nshapes;
+ if (trn.start_simple_poly())
return 1;
- trn.start_ring(si);
+ calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
- calculate_perpendicular(p1, p2, d, &e1_x, &e1_y, &p1_x, &p1_y);
-
- if (trn.add_point(p1->x + p1_x, p1->y + p1_y) ||
- trn.add_point(p1->x - p1_x, p1->y - p1_y) ||
- trn.add_point(p2->x - p1_x, p2->y - p1_y) ||
- fill_half_circle(&trn, p2->x, p2->y, -p1_x, -p1_y) ||
- trn.add_point(p2->x + p1_x, p2->y + p1_y))
+ if (trn.add_point(x1 + p1_x, y1 + p1_y) ||
+ trn.add_point(x1 - p1_x, y1 - p1_y) ||
+ trn.add_point(x2 - p1_x, y2 - p1_y) ||
+ fill_half_circle(&trn, x2, y2, -p1_x, -p1_y) ||
+ trn.add_point(x2 + p1_x, y2 + p1_y))
return 1;
- trn.complete();
- return 0;
+ return trn.complete_simple_poly();
}
-int Item_func_buffer::add_point_buffer(const gcalc_heap::info *p, double d)
+int Item_func_buffer::transporter::add_point_buffer(double x, double y)
{
- gcalc_shape_transporter trn(&collector);
- gcalc_shape_info si;
+ gcalc_operation_transporter trn(m_fn, m_heap);
- if (func.single_shape_op(gcalc_function::shape_polygon, &si))
+ m_nshapes++;
+ if (trn.start_simple_poly())
return 1;
-
- trn.start_ring(si);
- if (trn.add_point(p->x - d, p->y) ||
- fill_half_circle(&trn, p->x, p->y, -d, 0.0) ||
- trn.add_point(p->x + d, p->y) ||
- fill_half_circle(&trn, p->x, p->y, d, 0.0))
+ if (trn.add_point(x - m_d, y) ||
+ fill_half_circle(&trn, x, y, -m_d, 0.0) ||
+ trn.add_point(x + m_d, y) ||
+ fill_half_circle(&trn, x, y, m_d, 0.0))
return 1;
- trn.complete();
+ return trn.complete_simple_poly();
+}
+
+
+int Item_func_buffer::transporter::start_line()
+{
+ m_npoints= 0;
+ int_start_line();
return 0;
}
-int Item_func_buffer::add_poly_buffer(gcalc_heap::info **ptr_p,
- uint32 *n_p, double d)
+int Item_func_buffer::transporter::start_poly()
{
- gcalc_shape_transporter trn(&collector);
- gcalc_heap::info *p1= *ptr_p;
- gcalc_heap::info *p_cur= p1;
- gcalc_heap::info *p_next;
+ ++m_nshapes;
+ return gcalc_operation_transporter::start_poly();
+}
- if (p_cur->left == p1) /* Polygon consists of a single point */
- {
- if (add_point_buffer(p_cur, d))
- return 1;
- (*n_p)++;
- return 0;
- }
- for (;;)
- {
- p_next= p_cur->left;
- if (add_edge_buffer(p_cur, p_next, p_next->left, d, false, false))
- return 1;
- (*n_p)++;
- if (p_next == p1)
- break;
- p_cur= p_next;
- }
- *ptr_p= p_cur;
- return 0;
+int Item_func_buffer::transporter::start_ring()
+{
+ m_npoints= 0;
+ return gcalc_operation_transporter::start_ring();
}
-int Item_func_buffer::add_line_buffer(gcalc_heap::info **ptr_p,
- uint32 *n_p, double d)
+int Item_func_buffer::transporter::add_point(double x, double y)
{
- gcalc_shape_transporter trn(&collector);
- gcalc_heap::info *p1= *ptr_p;
- gcalc_heap::info *p_cur= p1;
- gcalc_heap::info *p_next= p_cur->left;
+ if (m_npoints && x == x2 && y == y2)
+ return 0;
+
+ ++m_npoints;
- if (!p_next) /* Line consists of a single point */
+ if (m_npoints == 1)
{
- if (add_point_buffer(p_cur, d))
- return 1;
- (*n_p)++;
- return 0;
+ x00= x;
+ y00= y;
}
-
- if (p_next->left == p1) /* Line consists of two points */
+ else if (m_npoints == 2)
{
- if (add_edge_buffer(p_cur, p_next, p_next->left, d, true, true))
- return 1;
- (*n_p)++;
- *ptr_p= p_cur->get_next();
- return 0;
+ x01= x;
+ y01= y;
}
-
- if (add_edge_buffer(p_cur, p_next, p_next->left, d, true, false))
+ else if (add_edge_buffer(x, y, (m_npoints == 3) && line_started(), false))
return 1;
- (*n_p)++;
- p_cur= p_next;
- p_next= p_next->left;
- while (p_next->left != p_cur)
+ x1= x2;
+ y1= y2;
+ x2= x;
+ y2= y;
+
+ return line_started() ? 0 : gcalc_operation_transporter::add_point(x, y);
+}
+
+
+int Item_func_buffer::transporter::complete()
+{
+ if (m_npoints)
{
- if (add_edge_buffer(p_cur, p_next, p_next->left, d, false, false))
- return 1;
- (*n_p)++;
- p_cur= p_next;
- p_next= p_next->left;
+ if (m_npoints == 1)
+ {
+ if (add_point_buffer(x2, y2))
+ return 1;
+ }
+ else if (m_npoints == 2)
+ {
+ if (add_edge_buffer(x1, y1, true, true))
+ return 1;
+ }
+ else if (line_started())
+ {
+ if (add_last_edge_buffer())
+ return 1;
+ }
+ else
+ {
+ if (x2 != x00 && y2 != y00)
+ {
+ if (add_edge_buffer(x00, y00, false, false))
+ return 1;
+ x1= x2;
+ y1= y2;
+ x2= x00;
+ y2= y00;
+ }
+ if (add_edge_buffer(x01, y01, false, false))
+ return 1;
+ }
}
- if (add_last_edge_buffer(p_cur, p_next, d))
+
+ return 0;
+}
+
+
+int Item_func_buffer::transporter::complete_line()
+{
+ if (complete())
return 1;
- (*n_p)++;
- *ptr_p= p_next;
+ int_complete_line();
return 0;
}
+int Item_func_buffer::transporter::complete_ring()
+{
+ return complete() ||
+ gcalc_operation_transporter::complete_ring();
+}
+
+
String *Item_func_buffer::val_str(String *str_value)
{
DBUG_ENTER("Item_func_buffer::val_str");
@@ -1099,12 +1131,10 @@ String *Item_func_buffer::val_str(String
double dist= args[1]->val_real();
Geometry_buffer buffer;
Geometry *g;
- gcalc_heap::info *dist_point;
- gcalc_dyn_list::item **last_hook; /* used to make loop */
- uint32 n_operands, union_pos;
+ uint32 union_pos;
uint32 srid= 0;
String *str_result= NULL;
-
+ transporter trn(&func, &collector, dist);
null_value= 1;
if (args[0]->null_value || args[1]->null_value ||
@@ -1113,46 +1143,17 @@ String *Item_func_buffer::val_str(String
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, 2);
+ gcalc_function::op_difference, 0);
GCALC_DBUG_STARTFILE("/home/hf/linebuffer");
- if (g->store_shapes(&collector, &func))
+ if (g->store_shapes(&trn))
goto mem_error;
- /* will specify operands later */
- union_pos= func.get_next_operation_pos();
- func.add_operation(gcalc_function::op_union, 0);
- dist_point= collector.get_first();
- last_hook= collector.get_last_hook();
- n_operands= 0;
- for (;;)
- {
- if (dist_point->left)
- {
- if (dist_point->right)
- {
- if (add_poly_buffer(&dist_point, &n_operands, dist))
- goto mem_error;
- }
- else
- {
- if (add_line_buffer(&dist_point, &n_operands, dist))
- goto mem_error;
- }
- }
- else
- {
- ++n_operands;
- if (add_point_buffer(dist_point, dist))
- goto mem_error;
- }
- if (last_hook == &dist_point->next)
- break;
- dist_point= dist_point->get_next();
- }
GCALC_DBUG_STOP;
- func.add_operands_to_op(union_pos, n_operands);
+ func.add_operands_to_op(union_pos, trn.m_nshapes);
collector.prepare_operation();
if (func.alloc_states())
goto mem_error;
@@ -1424,6 +1425,7 @@ double Item_func_distance::val_real()
double x1, x2, y1, y2;
double ex, ey, vx, vy, e_sqrlen;
uint obj2_si;
+ gcalc_operation_transporter trn(&func, &collector);
DBUG_ENTER("Item_func_distance::val_real");
DBUG_ASSERT(fixed == 1);
@@ -1453,10 +1455,10 @@ double Item_func_distance::val_real()
goto mem_error;
func.add_operation(gcalc_function::op_intersection, 2);
- if (g1->store_shapes(&collector, &func))
+ if (g1->store_shapes(&trn))
goto mem_error;
obj2_si= func.get_nshapes();
- if (g2->store_shapes(&collector, &func) || func.alloc_states())
+ if (g2->store_shapes(&trn) || func.alloc_states())
goto mem_error;
collector.prepare_operation();
=== modified file 'sql/item_geofunc.h'
--- a/sql/item_geofunc.h 2008-03-14 15:37:08 +0000
+++ b/sql/item_geofunc.h 2009-12-20 10:39:40 +0000
@@ -278,6 +278,29 @@ public:
class Item_func_buffer: public Item_geometry_func
{
protected:
+ class transporter : public gcalc_operation_transporter
+ {
+ int m_npoints;
+ double m_d;
+ double x1,y1,x2,y2;
+ double x00,y00,x01,y01;
+ int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2);
+ int add_last_edge_buffer();
+ int add_point_buffer(double x, double y);
+ int complete();
+ public:
+ int m_nshapes;
+ transporter(gcalc_function *fn, gcalc_heap *heap, double d) :
+ gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d), m_nshapes(0)
+ {}
+ int single_point(double x, double y);
+ int start_line();
+ int complete_line();
+ int start_poly();
+ int start_ring();
+ int complete_ring();
+ int add_point(double x, double y);
+ };
gcalc_heap collector;
gcalc_function func;
gcalc_scan_iterator scan_it;
@@ -291,15 +314,6 @@ public:
Item_geometry_func(obj, distance) {}
const char *func_name() const { return "Buffer"; }
String *val_str(String *);
-private:
- int add_edge_buffer(const gcalc_heap::info *p1, const gcalc_heap::info *p2,
- const gcalc_heap::info *p3, double d,
- bool round_p1, bool round_p2);
- int add_last_edge_buffer(const gcalc_heap::info *p1,
- const gcalc_heap::info *p2, double d);
- int add_point_buffer(const gcalc_heap::info *p, double d);
- int add_poly_buffer(gcalc_heap::info **ptr_p, uint32 *n_p, double d);
- int add_line_buffer(gcalc_heap::info **ptr_p, uint32 *n_p, double d);
};
=== modified file 'sql/spatial.cc'
--- a/sql/spatial.cc 2009-12-05 08:58:34 +0000
+++ b/sql/spatial.cc 2009-12-20 10:39:40 +0000
@@ -481,15 +481,11 @@ bool Gis_point::get_mbr(MBR *mbr, const
}
-int Gis_point::store_shapes(gcalc_heap *heap, gcalc_function *fn) const
+int Gis_point::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
double x, y;
- gcalc_shape_info si;
- return fn->single_shape_op(gcalc_function::shape_point, &si) ||
- get_xy(&x, &y) ||
- trn.single_point(si, x, y);
+ return get_xy(&x, &y) || trn->single_point(x, y);
}
@@ -697,16 +693,11 @@ int Gis_line_string::point_n(uint32 num,
}
-int Gis_line_string::store_shapes(gcalc_heap *heap, gcalc_function *fn) const
+int Gis_line_string::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
uint32 n_points;
double x, y;
const char *data= m_data;
- gcalc_shape_info si;
-
- if (fn->single_shape_op(gcalc_function::shape_line, &si))
- return 1;
if (no_data(m_data, 4))
return 1;
@@ -715,18 +706,17 @@ int Gis_line_string::store_shapes(gcalc_
if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points))
return 1;
- trn.start_line(si);
+ trn->start_line();
while (n_points--)
{
get_point(&x, &y, data);
data+= POINT_DATA_SIZE;
- if (trn.add_point(x, y))
+ if (trn->add_point(x, y))
return 1;
}
- trn.complete();
- return 0;
+ return trn->complete_line();
}
@@ -1118,14 +1108,12 @@ int Gis_polygon::centroid(String *result
}
-int Gis_polygon::store_shapes(gcalc_heap *heap, gcalc_function *fn) const
+int Gis_polygon::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
uint32 n_linear_rings;
const char *data= m_data;
- gcalc_shape_info si;
- if (fn->single_shape_op(gcalc_function::shape_polygon, &si))
+ if (trn->start_poly())
return 1;
if (no_data(data, 4))
@@ -1144,19 +1132,20 @@ int Gis_polygon::store_shapes(gcalc_heap
if (no_data(data, POINT_DATA_SIZE * n_points))
return 1;
- trn.start_ring(si);
+ trn->start_ring();
while (--n_points)
{
double x, y;
get_point(&x, &y, data);
data+= POINT_DATA_SIZE;
- if (trn.add_point(x, y))
+ if (trn->add_point(x, y))
return 1;
}
data+= POINT_DATA_SIZE;
- trn.complete();
+ trn->complete_ring();
}
+ trn->complete_poly();
return 0;
}
@@ -1310,9 +1299,8 @@ int Gis_multi_point::geometry_n(uint32 n
}
-int Gis_multi_point::store_shapes(gcalc_heap *heap, gcalc_function *fn) const
+int Gis_multi_point::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
uint32 n_points;
Gis_point pt;
const char *data= m_data;
@@ -1322,9 +1310,8 @@ int Gis_multi_point::store_shapes(gcalc_
n_points= uint4korr(data);
data+= 4;
- if (fn->reserve_shape_buffer(n_points) || fn->reserve_op_buffer(1))
+ if (trn->start_collection(n_points))
return 1;
- fn->add_operation(gcalc_function::op_union, n_points);
while (n_points--)
{
@@ -1332,7 +1319,7 @@ int Gis_multi_point::store_shapes(gcalc_
return 1;
data+= WKB_HEADER_SIZE;
pt.set_data_ptr(data, (uint32) (m_data_end - data));
- if (pt.store_shapes(heap, fn))
+ if (pt.store_shapes(trn))
return 1;
data+= pt.get_data_size();
}
@@ -1615,9 +1602,8 @@ int Gis_multi_line_string::is_closed(int
}
-int Gis_multi_line_string::store_shapes(gcalc_heap *heap, gcalc_function *fn) const
+int Gis_multi_line_string::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
uint32 n_lines;
Gis_line_string ls;
const char *data= m_data;
@@ -1627,9 +1613,8 @@ int Gis_multi_line_string::store_shapes(
n_lines= uint4korr(data);
data+= 4;
- if (fn->reserve_shape_buffer(n_lines) || fn->reserve_op_buffer(1))
+ if (trn->start_collection(n_lines))
return 1;
- fn->add_operation(gcalc_function::op_union, n_lines);
while (n_lines--)
{
@@ -1637,7 +1622,7 @@ int Gis_multi_line_string::store_shapes(
return 1;
data+= WKB_HEADER_SIZE;
ls.set_data_ptr(data, (uint32) (m_data_end - data));
- if (ls.store_shapes(heap, fn))
+ if (ls.store_shapes(trn))
return 1;
data+= ls.get_data_size();
}
@@ -1969,9 +1954,8 @@ int Gis_multi_polygon::centroid(String *
}
-int Gis_multi_polygon::store_shapes(gcalc_heap *heap, gcalc_function *fn) const
+int Gis_multi_polygon::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
uint32 n_polygons;
Gis_polygon p;
const char *data= m_data;
@@ -1981,9 +1965,8 @@ int Gis_multi_polygon::store_shapes(gcal
n_polygons= uint4korr(data);
data+= 4;
- if (fn->reserve_shape_buffer(n_polygons) || fn->reserve_op_buffer(1))
+ if (trn->start_collection(n_polygons))
return 1;
- fn->add_operation(gcalc_function::op_union, n_polygons);
while (n_polygons--)
{
@@ -1991,7 +1974,7 @@ int Gis_multi_polygon::store_shapes(gcal
return 1;
data+= WKB_HEADER_SIZE;
p.set_data_ptr(data, (uint32) (m_data_end - data));
- if (p.store_shapes(heap, fn))
+ if (p.store_shapes(trn))
return 1;
data+= p.get_data_size();
}
@@ -2320,10 +2303,8 @@ bool Gis_geometry_collection::dimension(
}
-int Gis_geometry_collection::store_shapes(gcalc_heap *heap,
- gcalc_function *fn) const
+int Gis_geometry_collection::store_shapes(gcalc_shape_transporter *trn) const
{
- gcalc_shape_transporter trn(heap);
uint32 n_objects;
const char *data= m_data;
Geometry_buffer buffer;
@@ -2334,9 +2315,8 @@ int Gis_geometry_collection::store_shape
n_objects= uint4korr(data);
data+= 4;
- if (fn->reserve_shape_buffer(n_objects) || fn->reserve_op_buffer(1))
+ if (trn->start_collection(n_objects))
return 1;
- fn->add_operation(gcalc_function::op_union, n_objects);
while (n_objects--)
{
@@ -2349,7 +2329,7 @@ int Gis_geometry_collection::store_shape
if (!(geom= create_by_typeid(&buffer, wkb_type)))
return 1;
geom->set_data_ptr(data, (uint32) (m_data_end - data));
- if (geom->store_shapes(heap, fn))
+ if (geom->store_shapes(trn))
return 1;
data+= geom->get_data_size();
=== modified file 'sql/spatial.h'
--- a/sql/spatial.h 2009-11-18 13:40:52 +0000
+++ b/sql/spatial.h 2009-12-20 10:39:40 +0000
@@ -266,7 +266,7 @@ public:
virtual int point_n(uint32 num, String *result) const { return -1; }
virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
virtual int geometry_n(uint32 num, String *result) const { return -1; }
- virtual int store_shapes(gcalc_heap *heap, gcalc_function *fn) const=0;
+ virtual int store_shapes(gcalc_shape_transporter *trn) const=0;
public:
static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id)
@@ -382,7 +382,7 @@ public:
*end= 0; /* No default end */
return 0;
}
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -411,7 +411,7 @@ public:
*end= 0; /* No default end */
return 0;
}
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -447,7 +447,7 @@ public:
*end= 0; /* No default end */
return 0;
}
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -473,7 +473,7 @@ public:
*end= 0; /* No default end */
return 0;
}
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -501,7 +501,7 @@ public:
*end= 0; /* No default end */
return 0;
}
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -528,7 +528,7 @@ public:
*end= 0; /* No default end */
return 0;
}
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
};
@@ -550,7 +550,7 @@ public:
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
bool dimension(uint32 *dim, const char **end) const;
- int store_shapes(gcalc_heap *heap, gcalc_function *fn) const;
+ int store_shapes(gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
Attachment: [text/bzr-bundle] bzr/holyfoot@mysql.com-20091220103940-to3cgcfcczbfd0gz.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-bugteam branch (holyfoot:2665) Bug#45883 | Alexey Botchkov | 21 Dec |