From: Alexey Botchkov Date: December 5 2009 9:00am Subject: bzr commit into mysql-5.1-bugteam branch (holyfoot:2664) Bug#46386 Bug#46498 List-Archive: http://lists.mysql.com/commits/92991 X-Bug: 46386,46498 Message-Id: <20091205090036.6D7AB2C380E3@hfmain.localdomain> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_9037a2yBOiPJj/yBG78Q9w)" --Boundary_(ID_9037a2yBOiPJj/yBG78Q9w) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///home/hf/work/mysql_common/gis-bugfix/ based on revid:holyfoot@stripped 2664 Alexey Botchkov 2009-12-05 Bug #46386 Intersection() and Difference() make the server disconnect there was a mistake in handling of 'holes' in the polygons. Fixed by adding the 'first_poly_node' pointer to the res_point structure to point to the first point of the surrounding polygon. Also a set of debugging functions was added. It doesn't affect the working fucntions, but greatly simplifies the debugging. This path fixes also bug#46498. per-file comments: sql/gcalc_slicescan.cc Bug #46386 Intersection() and Difference() make the server disconnect sql/gcalc_slicescan.h Bug #46386 Intersection() and Difference() make the server disconnect sql/gcalc_tools.cc Bug #46386 Intersection() and Difference() make the server disconnect sql/gcalc_tools.h Bug #46386 Intersection() and Difference() make the server disconnect sql/item_geofunc.cc Bug #46386 Intersection() and Difference() make the server disconnect sql/spatial.cc Bug #46386 Intersection() and Difference() make the server disconnect modified: sql/gcalc_slicescan.cc sql/gcalc_slicescan.h sql/gcalc_tools.cc sql/gcalc_tools.h sql/item_geofunc.cc sql/spatial.cc === modified file 'sql/gcalc_slicescan.cc' --- a/sql/gcalc_slicescan.cc 2009-11-24 16:35:34 +0000 +++ b/sql/gcalc_slicescan.cc 2009-12-05 08:58:34 +0000 @@ -66,12 +66,45 @@ void gcalc_dbug_env_struct::stop_recordi recfile= NULL; } + +void gcalc_dbug_env_struct::print(const char *ln) +{ + if (recfile) + fprintf(recfile, "%s", ln); +} + + gcalc_dbug_env_struct::~gcalc_dbug_env_struct() { if (recfile) fclose(recfile); } + +void gcalc_dbug_do_print(const char* fmt, ...) +{ + va_list args; + char buff[1000]; + va_start(args, fmt); + vsnprintf(buff, sizeof(buff), fmt, args); + va_end(args); + gcalc_dbug_cur_env->print(buff); +} + + +void gcalc_scan_iterator::point::dbug_print() +{ + const gcalc_scan_iterator::point *slice= this; + for (; slice; slice= slice->get_next()) + { + gcalc_dbug_do_print("(%d %.15g ", slice->thread, slice->x); + gcalc_dbug_do_print(slice->horiz_dir ? "-" : "/"); + gcalc_dbug_do_print(" %.15g) ", slice->dx_dy); + } + gcalc_dbug_do_print("\n"); +} + + static gcalc_dbug_env_struct gcalc_dbug_usual_env; gcalc_dbug_env_struct *gcalc_dbug_cur_env= &gcalc_dbug_usual_env; @@ -219,6 +252,18 @@ void gcalc_heap::prepare_operation() trim_node(cur->left, cur); trim_node(cur->right, cur); } +#ifdef GCALC_DBUG + { + info *cur= get_first(); + GCALC_DBUG_PRINT(("shape\t x\t y\tleft\tright\tthis\n")); + for (; cur; cur= cur->get_next()) + { + GCALC_DBUG_PRINT(("%d\t%.15g\t%.15g\t %d\t %d\t %d\n", cur->shape, + cur->x, cur->y,(int)cur->left, (int)cur->right, (int) cur)); + } + GCALC_DBUG_PRINT(("------------------\n")); + } +#endif /*GCALC_DBUG*/ } @@ -299,7 +344,7 @@ static bool slice_first_equal_x(const gc const gcalc_scan_iterator::point *p1) { if (p0->horiz_dir == p1->horiz_dir) - return p0->dx_dy < p1->dx_dy; + return p0->dx_dy <= p1->dx_dy; if (p0->horiz_dir) return p0->dx_dy < 0; return p1->dx_dy > 0; /* p1->horiz_dir case */ @@ -494,6 +539,12 @@ int gcalc_scan_iterator::normal_scan() free_list(sp1); } + GCALC_DBUG_PRINT(("Y%.15g", m_y0)); + GCALC_DBUG_SLICE(m_slice0); + GCALC_DBUG_PRINT(("Y%.15g", m_y1)); + GCALC_DBUG_SLICE(m_slice1); + GCALC_DBUG_PRINT(("\n")); + if (intersections_found) return handle_intersections(); @@ -589,6 +640,7 @@ int gcalc_scan_iterator::find_intersecti } while (intersections_found); *hook= NULL; + GCALC_DBUG_PRINT(("intersections found:%d\n", m_n_intersections)); return 0; } @@ -684,6 +736,11 @@ int gcalc_scan_iterator::intersection_sc free_list(m_slice1); m_slice1= m_sav_slice; free_list(m_intersections); + GCALC_DBUG_PRINT((" is Y%.15g", m_y0)); + GCALC_DBUG_SLICE(m_slice0); + GCALC_DBUG_PRINT((" is Y%.15g", m_y1)); + GCALC_DBUG_SLICE(m_slice1); + GCALC_DBUG_PRINT(("\n")); return 0; } } @@ -715,6 +772,7 @@ redo_loop: there's two intersections with the same Y Move suitable one to the beginning of the list */ + GCALC_DBUG_PRINT(("redo_loop needed\n")); pop_suitable_intersection(); goto redo_loop; } @@ -747,6 +805,11 @@ redo_loop: *psp1= NULL; } + GCALC_DBUG_PRINT((" is Y%.15g", m_y0)); + GCALC_DBUG_SLICE(m_slice0); + GCALC_DBUG_PRINT((" is Y%.15g", m_y1)); + GCALC_DBUG_SLICE(m_slice1); + GCALC_DBUG_PRINT(("\n")); return 0; } === modified file 'sql/gcalc_slicescan.h' --- a/sql/gcalc_slicescan.h 2009-11-24 16:35:34 +0000 +++ b/sql/gcalc_slicescan.h 2009-12-05 08:58:34 +0000 @@ -1,7 +1,7 @@ #ifndef gcalc_slicescan_h #define gcalc_slicescan_h -/* #define GCALC_DBUG */ +/*#define GCALC_DBUG*/ #ifdef GCALC_DBUG class gcalc_dbug_env_struct @@ -14,6 +14,7 @@ public: virtual void start_line(); virtual void add_point(double x, double y); virtual void complete(); + virtual void print(const char *ln); void start_newfile(const char *filename); void start_append(const char *filename); @@ -22,18 +23,24 @@ public: }; extern gcalc_dbug_env_struct *gcalc_dbug_cur_env; +void gcalc_dbug_do_print(const char* fmt, ...); #define GCALC_DBUG_START_RING gcalc_dbug_cur_env->start_ring() #define GCALC_DBUG_START_LINE gcalc_dbug_cur_env->start_line() #define GCALC_DBUG_ADD_POINT(X,Y) gcalc_dbug_cur_env->add_point(X,Y) #define GCALC_DBUG_COMPLETE gcalc_dbug_cur_env->complete() +#define GCALC_DBUG_SLICE(SLICE) SLICE->dbug_print() #define GCALC_DBUG_STARTFILE(FILENAME) gcalc_dbug_cur_env->start_newfile(FILENAME) #define GCALC_DBUG_STOP gcalc_dbug_cur_env->stop_recording() +#define GCALC_DBUG_PRINT(ARGLIST) gcalc_dbug_do_print ARGLIST #else #define GCALC_DBUG_START_RING +#define GCALC_DBUG_START_LINE #define GCALC_DBUG_ADD_POINT(X,Y) #define GCALC_DBUG_COMPLETE +#define GCALC_DBUG_SLICE(SLICE) #define GCALC_DBUG_STARTFILE(FILENAME) #define GCALC_DBUG_STOP +#define GCALC_DBUG_PRINT(ARGLIST) #endif /*GCLAC_DBUG*/ class gcalc_dyn_list @@ -268,6 +275,9 @@ public: next_pi= from->next_pi; thread= from->thread; } +#ifdef GCALC_DBUG + void dbug_print(); +#endif /*GCALC_DBUG*/ }; class intersection : public gcalc_dyn_list::item === modified file 'sql/gcalc_tools.cc' --- a/sql/gcalc_tools.cc 2009-05-13 07:03:17 +0000 +++ b/sql/gcalc_tools.cc 2009-12-05 08:58:34 +0000 @@ -82,26 +82,29 @@ int gcalc_function::count_internal() result= count_internal(); while (--n_ops) + { + int next_res= count_internal(); switch (next_func) { case op_union: - result= result || count_internal(); + result= result | next_res; break; case op_intersection: - result= result && count_internal(); + result= result & next_res; break; case op_symdifference: - result= result ^ count_internal(); + result= result ^ next_res; break; case op_difference: - result= result && !count_internal(); + result= result & !next_res; break; case op_backdifference: - result= !result && count_internal(); + result= !result & next_res; break; default: DBUG_ASSERT(FALSE); }; + } return result ^ mask; } @@ -161,48 +164,102 @@ int gcalc_result_receiver::start_shape(g { if (buffer.reserve(4*2, 512)) return 1; - buffer.q_append((uint32) shape); - if (shape != gcalc_function::shape_point) - { - n_points_pos= buffer.length(); - buffer.length(buffer.length() + 4); - n_points= 0; - } + cur_shape= shape; + shape_pos= buffer.length(); + buffer.length(shape_pos + ((shape == gcalc_function::shape_point) ? 4:8)); + n_points= 0; - if (!n_shapes++) - common_shapetype= shape; - else if (!collection_result && (shape != common_shapetype)) - { - if (shape == gcalc_function::shape_hole) - ++n_holes; - else - collection_result= TRUE; - } return 0; } int gcalc_result_receiver::add_point(double x, double y) { + if (n_points && x == prev_x && y == prev_y) + { + GCALC_DBUG_PRINT(("Skip same point %.15g\t%.15g\n", x, y)); + return 0; + } + + GCALC_DBUG_PRINT(("Add result point %.15g\t%.15g\n", x, y)); + if (!n_points++) + { + prev_x= first_x= x; + prev_y= first_y= y; + return 0; + } + if (buffer.reserve(8*2, 512)) return 1; - buffer.q_append(x); - buffer.q_append(y); - n_points++; + buffer.q_append(prev_x); + buffer.q_append(prev_y); + prev_x= x; + prev_y= y; return 0; } int gcalc_result_receiver::complete_shape() { - buffer.write_at_position(n_points_pos, n_points); + if (n_points == 0) + { + buffer.length(shape_pos); + return 0; + } + if (n_points == 1) + { + if (cur_shape != gcalc_function::shape_point) + { + cur_shape= gcalc_function::shape_point; + buffer.length(buffer.length()-4); + } + } + else + { + DBUG_ASSERT(cur_shape != gcalc_function::shape_point); + if ((cur_shape == gcalc_function::shape_polygon || + cur_shape == gcalc_function::shape_hole) && + prev_x == first_x && prev_y == first_y) + { + n_points--; + buffer.write_at_position(shape_pos+4, n_points); + goto do_complete; + } + buffer.write_at_position(shape_pos+4, n_points); + } + + if (buffer.reserve(8*2, 512)) + return 1; + buffer.q_append(prev_x); + buffer.q_append(prev_y); + +do_complete: + GCALC_DBUG_PRINT(("Complete shape %d\n", n_points)); + + buffer.write_at_position(shape_pos, (uint32) cur_shape); + + if (!n_shapes++) + { + DBUG_ASSERT(cur_shape != gcalc_function::shape_hole); + common_shapetype= cur_shape; + } + else if (cur_shape == gcalc_function::shape_hole) + { + ++n_holes; + } + else if (!collection_result && (cur_shape != common_shapetype)) + { + collection_result= true; + } return 0; } int gcalc_result_receiver::single_point(double x, double y) { - return start_shape(gcalc_function::shape_point) || add_point(x, y); + return start_shape(gcalc_function::shape_point) || + add_point(x, y) || + complete_shape(); } @@ -230,7 +287,7 @@ int gcalc_result_receiver::get_result_ty switch (common_shapetype) { case gcalc_function::shape_polygon: - return (get_nshapes() == 1) ? + return (n_shapes - n_holes == 1) ? Geometry::wkb_polygon : Geometry::wkb_multipolygon; case gcalc_function::shape_point: return (n_shapes == 1) ? Geometry::wkb_point : Geometry::wkb_multipoint; @@ -244,21 +301,26 @@ int gcalc_result_receiver::get_result_ty } -int gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position) +int gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position, + uint32 *new_dest_position) { char *ptr; int source_len; if (dest_position == source_position) + { + *new_dest_position= position(); return 0; + } - if (buffer.reserve(source_position - dest_position)) + source_len= buffer.length() - source_position; + if (buffer.reserve(source_len, MY_ALIGN(source_len, 512))) return 1; + ptr= (char *) buffer.ptr(); - source_len= buffer.length() - source_position; - memcpy(ptr + buffer.length(), ptr + source_position, source_len); memmove(ptr + dest_position + source_len, ptr + dest_position, - source_position - dest_position); + buffer.length() - dest_position); memcpy(ptr + dest_position, ptr + buffer.length(), source_len); + *new_dest_position= dest_position + source_len; return 0; } @@ -300,6 +362,8 @@ inline int gcalc_operation_reducer::cont rp->intersection_point= false; rp->pi= p; t->rp= rp; + GCALC_DBUG_PRINT(("Cont_range %d\t%d\t%.15g\t%.15g\n", (int) t, + (int) p->shape, p->x, p->y)); return 0; } @@ -320,6 +384,8 @@ inline int gcalc_operation_reducer::cont rp->pi= p; rp->y= y; t->rp= rp; + GCALC_DBUG_PRINT(("Cont_i_range %d\t%d\t%.15g\t%.15g\n", (int) t, + (int) p->shape, p->x, p->y)); return 0; } @@ -334,6 +400,8 @@ inline int gcalc_operation_reducer::star rp->pi= p; t->result_range= 1; t->rp= rp; + GCALC_DBUG_PRINT(("Start_range %d\t%d\t%.15g\t%.15g\n", (int) t, + (int) p->shape, p->x, p->y)); return 0; } @@ -351,6 +419,8 @@ inline int gcalc_operation_reducer::star rp->pi= p; t->result_range= 1; t->rp= rp; + GCALC_DBUG_PRINT(("Start_i_range %d\t%d\t%.15g\t%.15g\n", (int) t, + (int) p->shape, p->x, p->y)); return 0; } @@ -366,6 +436,8 @@ inline int gcalc_operation_reducer::end_ rp->pi= p; t->rp->up= rp; t->result_range= 0; + GCALC_DBUG_PRINT(("End_range %d\t%d\t%.15g\t%.15g\n", (int) t, + (int) p->shape, p->x, p->y)); return 0; } @@ -384,6 +456,8 @@ inline int gcalc_operation_reducer::end_ rp->y= y; t->rp->up= rp; t->result_range= 0; + GCALC_DBUG_PRINT(("End_i_range %d\t%d\t%.15g\t%.15g\n", (int) t, + (int) p->shape, p->x, p->y)); return 0; } @@ -411,6 +485,9 @@ int gcalc_operation_reducer::start_coupl rp0->outer_poly= 0; t0->thread_start= rp0; } + GCALC_DBUG_PRINT(("Start_couple t0 %d\tt1 %d\tshape %d\t%.15g\t%.15g\t%d\n", + (int) t0, (int) t1, (int) p->shape, p->x, p->y, + (int) prev_range)); return 0; } @@ -444,6 +521,9 @@ int gcalc_operation_reducer::start_i_cou rp0->outer_poly= 0; t0->thread_start= rp0; } + GCALC_DBUG_PRINT(("Start_i_couple t0 %d\tt1 %d\tshape0 %d\tshape1 %d\t%.15g\t%.15g\t%d\n", + (int) t0, (int) t1, (int) p0->shape, (int) p1->shape, x, y, + (int) prev_range)); return 0; } @@ -464,6 +544,8 @@ int gcalc_operation_reducer::end_couple( rp0->intersection_point= rp1->intersection_point= false; rp0->pi= rp1->pi= p; t0->result_range= t1->result_range= 0; + GCALC_DBUG_PRINT(("End_couple t0 %d\tt1 %d\tshape %d\t%.15g\t%.15g\n", + (int) t0, (int) t1, (int) p->shape, p->x, p->y)); return 0; } @@ -488,6 +570,8 @@ int gcalc_operation_reducer::end_i_coupl t0->result_range= t1->result_range= 0; t0->rp->up= rp0; t1->rp->up= rp1; + GCALC_DBUG_PRINT(("End_i_couple t0 %d\tt1 %d\tshape0 %d\tshape1 %d\t%.15g\t%.15g\n", + (int) t0, (int) t1, (int) p0->shape, (int) p1->shape, x, y)); return 0; } @@ -501,6 +585,8 @@ int gcalc_operation_reducer::add_single_ rp->pi= p; rp->x= p->x; rp->y= p->y; + GCALC_DBUG_PRINT(("Single point shape %d\t%.15g\t%.15g\n", + (int) p->shape, p->x, p->y)); return 0; } @@ -515,6 +601,8 @@ int gcalc_operation_reducer::add_i_singl rp->x= x; rp->pi= p; rp->y= y; + GCALC_DBUG_PRINT(("i_Single point shape %d\t%.15g\t%.15g\n", + (int) p->shape, x, y)); return 0; } @@ -833,25 +921,31 @@ inline int gcalc_operation_reducer::get_ } -inline int gcalc_operation_reducer::get_result_thread(res_point *cur, - gcalc_result_receiver *storage, - int move_upward) +int gcalc_operation_reducer::get_result_thread(res_point *cur, + gcalc_result_receiver *storage, + int move_upward) { res_point *next; bool glue_step= false; + res_point *first_poly_node= cur; + double x, y; + GCALC_DBUG_PRINT(("Result thread \n")); while (cur) { if (!glue_step) { if (cur->intersection_point) { - if (storage->add_point(float_to_coord(cur->x), - float_to_coord(cur->y))) - return 1; + x= float_to_coord(cur->x); + y= float_to_coord(cur->y); } else - if (storage->add_point(cur->pi->x, cur->pi->y)) - return 1; + { + x= cur->pi->x; + y= cur->pi->y; + } + if (storage->add_point(x, y)) + return 1; } next= move_upward ? cur->up : cur->down; @@ -865,6 +959,8 @@ inline int gcalc_operation_reducer::get_ } else glue_step= false; + + cur->first_poly_node= first_poly_node; free_result(cur); cur= next; } @@ -872,18 +968,19 @@ inline int gcalc_operation_reducer::get_ } -inline int gcalc_operation_reducer::get_polygon_result(res_point *cur, - gcalc_result_receiver *storage) +int gcalc_operation_reducer::get_polygon_result(res_point *cur, + gcalc_result_receiver *storage) { res_point *glue= cur->glue; glue->up->down= NULL; free_result(glue); - return get_result_thread(cur, storage, 1); + return get_result_thread(cur, storage, 1) || + storage->complete_shape(); } -inline int gcalc_operation_reducer::get_line_result(res_point *cur, - gcalc_result_receiver *storage) +int gcalc_operation_reducer::get_line_result(res_point *cur, + gcalc_result_receiver *storage) { res_point *next; int move_upward= 1; @@ -904,17 +1001,20 @@ inline int gcalc_operation_reducer::get_ } } - return get_result_thread(cur, storage, move_upward); + return get_result_thread(cur, storage, move_upward) || + storage->complete_shape(); } int gcalc_operation_reducer::get_result(gcalc_result_receiver *storage) { + GCALC_DBUG_PRINT(("get_result\n")); *m_res_hook= NULL; while (m_result) { if (!m_result->up) { + GCALC_DBUG_PRINT(("singlet\n")); if (get_single_result(m_result, storage)) return 1; continue; @@ -922,19 +1022,24 @@ int gcalc_operation_reducer::get_result( gcalc_function::shape_type shape= m_fn->get_shape_kind(m_result->pi->shape); if (shape == gcalc_function::shape_polygon) { + GCALC_DBUG_PRINT(("Polygon result \n")); if (m_result->outer_poly) { - uint32 insert_position, hole_position; - insert_position= m_result->outer_poly->poly_position; + uint32 *insert_position, hole_position; + GCALC_DBUG_PRINT(("\tOuter poly \n")); + insert_position= &m_result->outer_poly->first_poly_node->poly_position; + DBUG_ASSERT(*insert_position); hole_position= storage->position(); storage->start_shape(gcalc_function::shape_hole); if (get_polygon_result(m_result, storage) || - storage->move_hole(insert_position, hole_position)) + storage->move_hole(*insert_position, hole_position, + insert_position)) return 1; } else { uint32 *poly_position= &m_result->poly_position; + GCALC_DBUG_PRINT(("\tNo outer poly \n")); storage->start_shape(gcalc_function::shape_polygon); if (get_polygon_result(m_result, storage)) return 1; @@ -943,12 +1048,11 @@ int gcalc_operation_reducer::get_result( } else { + GCALC_DBUG_PRINT(("Line result \n")); storage->start_shape(shape); if (get_line_result(m_result, storage)) return 1; } - if (storage->complete_shape()) - return 1; } m_res_hook= (gcalc_dyn_list::item **)&m_result; === modified file 'sql/gcalc_tools.h' --- a/sql/gcalc_tools.h 2009-04-13 08:03:25 +0000 +++ b/sql/gcalc_tools.h 2009-12-05 08:58:34 +0000 @@ -71,12 +71,15 @@ public: class gcalc_result_receiver { String buffer; - uint32 n_points_pos; uint32 n_points; gcalc_function::shape_type common_shapetype; bool collection_result; uint32 n_shapes; uint32 n_holes; + + gcalc_function::shape_type cur_shape; + uint32 shape_pos; + double first_x, first_y, prev_x, prev_y; public: gcalc_result_receiver(); int start_shape(gcalc_function::shape_type shape); @@ -92,7 +95,8 @@ public: int get_nholes() { return n_holes; } int get_result_typeid(); uint32 position() { return buffer.length(); } - int move_hole(uint32 dest_position, uint32 source_position); + int move_hole(uint32 dest_position, uint32 source_position, + uint32 *new_dest_position); }; @@ -122,13 +126,17 @@ public: public: bool intersection_point; double x,y; - const gcalc_heap::info *pi; res_point *up; res_point *down; res_point *glue; union { - const res_point *outer_poly; + const gcalc_heap::info *pi; + res_point *first_poly_node; + }; + union + { + res_point *outer_poly; uint32 poly_position; }; gcalc_dyn_list::item **prev_hook; @@ -140,7 +148,7 @@ public: public: res_point *rp; int result_range; - const res_point *thread_start; + res_point *thread_start; active_thread *get_next() { return (active_thread *)next; } }; @@ -207,7 +215,7 @@ private: int get_single_result(res_point *res, gcalc_result_receiver *storage); int get_result_thread(res_point *cur, gcalc_result_receiver *storage, int move_upward); - int get_polygon_result(res_point *cur,gcalc_result_receiver *storage); + int get_polygon_result(res_point *cur, gcalc_result_receiver *storage); int get_line_result(res_point *cur, gcalc_result_receiver *storage); void free_result(res_point *res); === modified file 'sql/item_geofunc.cc' --- a/sql/item_geofunc.cc 2009-11-24 16:35:34 +0000 +++ b/sql/item_geofunc.cc 2009-12-05 08:58:34 +0000 @@ -737,6 +737,8 @@ String *Item_func_spatial_operation::val goto exit; + GCALC_DBUG_STARTFILE("/home/hf/gcalc_log"); + collector.prepare_operation(); scan_it.init(&collector); if (func.alloc_states()) @@ -759,6 +761,7 @@ String *Item_func_spatial_operation::val goto exit; exit: + GCALC_DBUG_STOP; collector.reset(); func.reset(); scan_it.reset(); === modified file 'sql/spatial.cc' --- a/sql/spatial.cc 2009-11-18 13:40:52 +0000 +++ b/sql/spatial.cc 2009-12-05 08:58:34 +0000 @@ -1757,6 +1757,8 @@ uint Gis_multi_polygon::init_from_opresu const char *opres_orig= opres; uint p_len; uint poly_shapes; + uint n_poly= 0; + uint32 np_pos= bin->length(); if (bin->reserve(4, 512)) return 0; @@ -1772,7 +1774,9 @@ uint Gis_multi_polygon::init_from_opresu return 0; n_shapes-= poly_shapes; opres+= p_len; + n_poly++; } + bin->write_at_position(np_pos, n_poly); return opres - opres_orig; } --Boundary_(ID_9037a2yBOiPJj/yBG78Q9w) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name="bzr/holyfoot@stripped" Content-transfer-encoding: 7BIT Content-disposition: inline; filename="bzr/holyfoot@stripped" # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: holyfoot@stripped # target_branch: file:///home/hf/work/mysql_common/gis-bugfix/ # testament_sha1: 4c80d587ae264b91c6d6800bec975572954fce3f # timestamp: 2009-12-05 13:00:36 +0400 # base_revision_id: holyfoot@stripped # # Begin bundle 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 SFA20SJwiF/+LuSKcKEgX1tT4g== --Boundary_(ID_9037a2yBOiPJj/yBG78Q9w)--