-
Alexander Barkov authored
Bug#13832749 HANDLE_FATAL_SIGNAL IN GCALC_FUNCTION::COUNT_INTERNAL 1. ST_Buffer() did not work well due to a few bugs in the buffer transporter implementation. a. The sequence of: func.get_next_operation_pos(); ... func.add_operands_to_op(union_pos, trn.m_nshapes); did not work in case of collection geometries (MultiPoint, MultiLineString, MultiPolygon, GeometryCollection), which already create a union of m_nshapes items themself. In this case the caller should have generated a union1 operation instead of unionN operation, i.e. the above add_operands_to_op() call should have passed 1 instead of trn.m_nshapes, to get this function execution plan: union1(unionN(shape1,shape2,...,shapeN)) instead of bad: unionN(unionN(shape1,shape2,..,shapeN)) The fix moves the code generating the upper-most union command *inside* store_shape() for all geometry types. b. The next problem after moving union generating inside store_shapes() was that the Item_func_buffer::Transporter::m_nshapes member was erroneously shared by both collection itself and its items, e.g.: - lines of multilinestring and the multiline itself - items of a geometry collection and the collection itself The fix removes the m_nshapes member from Item_func_buffer::Transporter and passes the current shape transformation status as a parameter to all tranformation methods line stat_xxx/complete_xxx/add_point, etc. This simplifies simultanious access to the transformation statistics of the collection itself and of the current item. A new class Gcalc_shape_status was introduces to store transformation status. Before a collection processing code enters an item, a new transformation status variable is created on stack and passed to the item processing routine. c. ST_Buffer did not include the very last edge of a polygon with 4+ points due to the bug in the point comparison code in Item_func_buffer::Transporter::complete: - if (x2 != x00 && y2 != y00) + if (x2 != x00 || y2 != y00) 2. Area() of a geometry collection consisting of polygons mistakenly returned NULL, because Gis_geometry_collection::area was not implemented. Area() of Points and LineStrings also returned NULL. Fixing to return 0. 3. Negative buffer values worked wrong: - ST_Buffer(GeomFromText('POINT(0 0)',-1)); Returned similar value to ST_Buffer(GeomFromText('POINT(0 0)',1)); - ST_Buffer(GeomFromText('LineString(0 0)'),-1) returned similar value to ST_Buffer(GeomFromText('LineString(0 0)'),1) Fixing negative buffers to return empty sets for Points and LineStrings, according to the OCG specifications. 4. Zero buffer made server crash: ST_Buffer(<polygon>, 0) because of division-by-zero-alike problem. Changing zero buffer to return the original geometry itself, instead of going through the zero-unsafe buffer generating code. 5. Adding GIS debug output functionality, to print debug information into server log and into client side warnings. The latter is very useful for mtr purposes. GIS debug output is available only in debug builds and does not exist in production builds. 6. Adding ST_GIS_DEBUG() function to turn client-side GIS debug warnings on/off: SELECT ST_GIS_DEBUG(1); -- turn debug output on SELECT ST_GIS_DEBUG(0); -- turn debug output off Client side debug warnings are off by default. Per file comments: added: @ mysql-test/include/gis_debug.inc - Adding a shared file to test various GIS functions @ mysql-test/r/gis-debug.result @ mysql-test/t/gis-debug.test - Adding a debug test with client-side GIS debug warnings. modified: @ mysql-test/r/gis-precise.result @ mysql-test/t/gis-precise.test - Including gis_debug.inc, to make sure the results are correct in non-debugs. @ sql/gcalc_slicescan.h.diff - Introducing a new class Gcalc_shape_status and passing a parameter of Gcalc_shape_status type into transformation methods. - Adding prototypes for collection_add_item() and complete_collection() transformation methods. Previously these methods did not exist because Item_func_buffer::val_str() tried to process the upper-most union itself (incorrectly). - Adding skip_xxx() methods, to exclude certain geometries during transformation. For example, negative buffer does not need Points and LineStrings. @ sql/gcalc_tools.cc.diff - Adding debug routines - Adding Gcalc_shape_status parameter into the transformation methods - Adding the default implementation of start_collection(), collection_add_item() and complete_collection() routines. @ sql/gcalc_tools.h.diff - Adding prototype for the debug routine - Adding an Gcalc_shape_status parameter to transformation routines @ sql/item_create.cc.diff - Adding a code to create ST_GIS_DEBUG() SQL function in debug builds @ sql/item_geofunc.cc.diff - Adding Gcalc_shape_status parameter into the transformation methods - Adding a new code to catch zero distance - Adding a new code to catch empty buffer set after transformation - Removing the top-level union generating code - Adding Item_func_gis_debug::val_int() implementation - Adding calls for debug_print_function_buffer() near all store_shapes() calls. @ sql/item_geofunc.h.diff - Removing the m_nshapes member - Adding Gcalc_shape_status parameter to the transformation methods - Adding prototype for Item_func_gis_debug, the item behind the new ST_GIS_DEBUG() SQL function. @ sql/spatial.cc.diff - Implementing Geometry::collection_store_shapes() and Geometry::collection_area() methods, which are shared between collection geometry types: GeometryCollection, MultiPoint, MultiLineString,MultiPolygon - Adding Gcalc_shape_status parameter to the transformation methods - Implementing the missing Gis_geometry_collection::area(). @ sql/spatial.h.diff - Adding prototypes for collection_store_shapes() and collection_area(). - Adding prototype for the missing Gis_geometry_collection::area(). - Adding the default implementation for area(), for the geometry types who have empty area. - Adding Gcalc_shape_status parameter to the transformation methods @ sql/sql_class.cc.diff - Adding gis_debug initialization into THD constructor @ sql/sql_class.h.diff - Introducing gis_debug member and related methods.
Alexander Barkov authoredBug#13832749 HANDLE_FATAL_SIGNAL IN GCALC_FUNCTION::COUNT_INTERNAL 1. ST_Buffer() did not work well due to a few bugs in the buffer transporter implementation. a. The sequence of: func.get_next_operation_pos(); ... func.add_operands_to_op(union_pos, trn.m_nshapes); did not work in case of collection geometries (MultiPoint, MultiLineString, MultiPolygon, GeometryCollection), which already create a union of m_nshapes items themself. In this case the caller should have generated a union1 operation instead of unionN operation, i.e. the above add_operands_to_op() call should have passed 1 instead of trn.m_nshapes, to get this function execution plan: union1(unionN(shape1,shape2,...,shapeN)) instead of bad: unionN(unionN(shape1,shape2,..,shapeN)) The fix moves the code generating the upper-most union command *inside* store_shape() for all geometry types. b. The next problem after moving union generating inside store_shapes() was that the Item_func_buffer::Transporter::m_nshapes member was erroneously shared by both collection itself and its items, e.g.: - lines of multilinestring and the multiline itself - items of a geometry collection and the collection itself The fix removes the m_nshapes member from Item_func_buffer::Transporter and passes the current shape transformation status as a parameter to all tranformation methods line stat_xxx/complete_xxx/add_point, etc. This simplifies simultanious access to the transformation statistics of the collection itself and of the current item. A new class Gcalc_shape_status was introduces to store transformation status. Before a collection processing code enters an item, a new transformation status variable is created on stack and passed to the item processing routine. c. ST_Buffer did not include the very last edge of a polygon with 4+ points due to the bug in the point comparison code in Item_func_buffer::Transporter::complete: - if (x2 != x00 && y2 != y00) + if (x2 != x00 || y2 != y00) 2. Area() of a geometry collection consisting of polygons mistakenly returned NULL, because Gis_geometry_collection::area was not implemented. Area() of Points and LineStrings also returned NULL. Fixing to return 0. 3. Negative buffer values worked wrong: - ST_Buffer(GeomFromText('POINT(0 0)',-1)); Returned similar value to ST_Buffer(GeomFromText('POINT(0 0)',1)); - ST_Buffer(GeomFromText('LineString(0 0)'),-1) returned similar value to ST_Buffer(GeomFromText('LineString(0 0)'),1) Fixing negative buffers to return empty sets for Points and LineStrings, according to the OCG specifications. 4. Zero buffer made server crash: ST_Buffer(<polygon>, 0) because of division-by-zero-alike problem. Changing zero buffer to return the original geometry itself, instead of going through the zero-unsafe buffer generating code. 5. Adding GIS debug output functionality, to print debug information into server log and into client side warnings. The latter is very useful for mtr purposes. GIS debug output is available only in debug builds and does not exist in production builds. 6. Adding ST_GIS_DEBUG() function to turn client-side GIS debug warnings on/off: SELECT ST_GIS_DEBUG(1); -- turn debug output on SELECT ST_GIS_DEBUG(0); -- turn debug output off Client side debug warnings are off by default. Per file comments: added: @ mysql-test/include/gis_debug.inc - Adding a shared file to test various GIS functions @ mysql-test/r/gis-debug.result @ mysql-test/t/gis-debug.test - Adding a debug test with client-side GIS debug warnings. modified: @ mysql-test/r/gis-precise.result @ mysql-test/t/gis-precise.test - Including gis_debug.inc, to make sure the results are correct in non-debugs. @ sql/gcalc_slicescan.h.diff - Introducing a new class Gcalc_shape_status and passing a parameter of Gcalc_shape_status type into transformation methods. - Adding prototypes for collection_add_item() and complete_collection() transformation methods. Previously these methods did not exist because Item_func_buffer::val_str() tried to process the upper-most union itself (incorrectly). - Adding skip_xxx() methods, to exclude certain geometries during transformation. For example, negative buffer does not need Points and LineStrings. @ sql/gcalc_tools.cc.diff - Adding debug routines - Adding Gcalc_shape_status parameter into the transformation methods - Adding the default implementation of start_collection(), collection_add_item() and complete_collection() routines. @ sql/gcalc_tools.h.diff - Adding prototype for the debug routine - Adding an Gcalc_shape_status parameter to transformation routines @ sql/item_create.cc.diff - Adding a code to create ST_GIS_DEBUG() SQL function in debug builds @ sql/item_geofunc.cc.diff - Adding Gcalc_shape_status parameter into the transformation methods - Adding a new code to catch zero distance - Adding a new code to catch empty buffer set after transformation - Removing the top-level union generating code - Adding Item_func_gis_debug::val_int() implementation - Adding calls for debug_print_function_buffer() near all store_shapes() calls. @ sql/item_geofunc.h.diff - Removing the m_nshapes member - Adding Gcalc_shape_status parameter to the transformation methods - Adding prototype for Item_func_gis_debug, the item behind the new ST_GIS_DEBUG() SQL function. @ sql/spatial.cc.diff - Implementing Geometry::collection_store_shapes() and Geometry::collection_area() methods, which are shared between collection geometry types: GeometryCollection, MultiPoint, MultiLineString,MultiPolygon - Adding Gcalc_shape_status parameter to the transformation methods - Implementing the missing Gis_geometry_collection::area(). @ sql/spatial.h.diff - Adding prototypes for collection_store_shapes() and collection_area(). - Adding prototype for the missing Gis_geometry_collection::area(). - Adding the default implementation for area(), for the geometry types who have empty area. - Adding Gcalc_shape_status parameter to the transformation methods @ sql/sql_class.cc.diff - Adding gis_debug initialization into THD constructor @ sql/sql_class.h.diff - Introducing gis_debug member and related methods.
Loading