diff options
-rw-r--r-- | mysql-test/r/gis-precise.result | 15 | ||||
-rw-r--r-- | mysql-test/r/gis.result | 6 | ||||
-rw-r--r-- | mysql-test/t/gis-precise.test | 5 | ||||
-rw-r--r-- | sql/gcalc_tools.cc | 79 | ||||
-rw-r--r-- | sql/gcalc_tools.h | 8 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 39 |
6 files changed, 106 insertions, 46 deletions
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result index 953459d10fc..73aac9dbe05 100644 --- a/mysql-test/r/gis-precise.result +++ b/mysql-test/r/gis-precise.result @@ -178,7 +178,7 @@ st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)')) 0 select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)')); st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)')) -0 +1 select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)')); st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)')) 0 @@ -187,7 +187,7 @@ st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0 select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))')); st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))')) -1 +0 select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))')); st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))')) 1 @@ -437,7 +437,7 @@ ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) 0 SELECT ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) ')); ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) ')) -0 +1 select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY'))); ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY'))) GEOMETRYCOLLECTION EMPTY @@ -477,6 +477,15 @@ ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, select astext(buffer(st_linestringfromwkb(linestring(point(-1,1), point(-1,-2))),-1)); astext(buffer(st_linestringfromwkb(linestring(point(-1,1), point(-1,-2))),-1)) GEOMETRYCOLLECTION EMPTY +select ST_Touches(ST_LineFromText('LINESTRING(0 0,5 5)'),ST_PointFromText('POINT(0 0)')); +ST_Touches(ST_LineFromText('LINESTRING(0 0,5 5)'),ST_PointFromText('POINT(0 0)')) +1 +select ST_Touches(ST_PolygonFromText('POLYGON((0 0,0 5,5 5,5 0,0 0))'),ST_PointFromText('POINT(0 0)')); +ST_Touches(ST_PolygonFromText('POLYGON((0 0,0 5,5 5,5 0,0 0))'),ST_PointFromText('POINT(0 0)')) +1 +select ST_Touches(ST_PointFromText('POINT(0 0)'),ST_PointFromText('POINT(0 0)')); +ST_Touches(ST_PointFromText('POINT(0 0)'),ST_PointFromText('POINT(0 0)')) +0 DROP TABLE IF EXISTS p1; CREATE PROCEDURE p1(dist DOUBLE, geom TEXT) BEGIN diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 3c8adf4aa9c..b462d7dbbea 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -408,7 +408,7 @@ first second w c o e d t i r 120 122 NULL NULL NULL NULL NULL NULL NULL NULL 120 123 NULL NULL NULL NULL NULL NULL NULL NULL 121 120 0 0 1 0 0 0 1 0 -121 121 1 1 0 1 0 1 1 0 +121 121 1 1 0 1 0 0 1 0 121 122 NULL NULL NULL NULL NULL NULL NULL NULL 121 123 NULL NULL NULL NULL NULL NULL NULL NULL 122 120 NULL NULL NULL NULL NULL NULL NULL NULL @@ -877,7 +877,7 @@ mbroverlaps down,left,right,up SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; mbrtouches -big,center,down,down2,left,left2,right,right2,small,up,up2 +down2,left2,right2,up2 SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; mbrwithin big,center @@ -898,7 +898,7 @@ overlaps down,left,right,up SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; touches -big,center,down,down2,left,left2,right,right2,small,up,up2 +down2,left2,right2,up2 SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; within big,center diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test index c6cf42e86e4..5e57569a912 100644 --- a/mysql-test/t/gis-precise.test +++ b/mysql-test/t/gis-precise.test @@ -357,5 +357,10 @@ SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 # MDEV-5615 crash in Gcalc_function::add_operation select astext(buffer(st_linestringfromwkb(linestring(point(-1,1), point(-1,-2))),-1)); +# MDEV-7925 Inconsistent behavior of ST_Touches with a POINT as one of arguments +select ST_Touches(ST_LineFromText('LINESTRING(0 0,5 5)'),ST_PointFromText('POINT(0 0)')); +select ST_Touches(ST_PolygonFromText('POLYGON((0 0,0 5,5 5,5 0,0 0))'),ST_PointFromText('POINT(0 0)')); +select ST_Touches(ST_PointFromText('POINT(0 0)'),ST_PointFromText('POINT(0 0)')); + --source include/gis_debug.inc diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 2d770fd45d6..5aac8a71249 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -143,6 +143,9 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, { if (set_type == 0) result= i_states[n_shape] | b_states[n_shape]; + /* the last call for the count_internal outside of all shapes. */ + else if (set_type == 1) + result= 0; else if (set_type == op_border) result= b_states[n_shape]; else if (set_type == op_internals) @@ -158,7 +161,8 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, if (next_func == op_border || next_func == op_internals) { - result= count_internal(cur_func, next_func, &cur_func); + result= count_internal(cur_func, + (set_type == 1) ? set_type : next_func, &cur_func); goto exit; } @@ -180,16 +184,34 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, switch (next_func) { case op_union: - result= result | next_res; + if (result == result_true || next_res == result_true) + result= result_true; + else if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result_false; break; case op_intersection: - result= result & next_res; + if (result == result_false || next_res == result_false) + result= result_false; + else if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result_true; break; case op_symdifference: - result= result ^ next_res; + if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result ^ next_res; break; case op_difference: - result= result & !next_res; + if (result == result_false || next_res == result_true) + result= result_false; + else if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result_true; break; default: GCALC_DBUG_ASSERT(FALSE); @@ -197,24 +219,35 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, } exit: - result^= mask; + if (result != result_unknown) + result^= mask; if (v_state != v_empty) { switch (v_state) { case v_find_t: - if (result) + if (result == result_true) { c_op= (c_op & ~v_mask) | v_t_found; int4store(sav_cur_func, c_op); - }; + } + else + { + if (set_type != 1) + result= result_unknown; + } break; case v_find_f: - if (!result) + if (result == result_false) { c_op= (c_op & ~v_mask) | v_f_found; int4store(sav_cur_func, c_op); - }; + } + else + { + if (set_type != 1) + result= result_unknown; + } break; case v_t_found: result= 1; @@ -264,6 +297,7 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) { const Gcalc_scan_iterator::point *eq_start, *cur_eq; const Gcalc_scan_iterator::event_point *events; + int result; GCALC_DBUG_ENTER("Gcalc_function::check_function"); while (scan_it.more_points()) @@ -288,8 +322,8 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) if (events->event == scev_end) set_b_state(events->get_shape()); - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); clear_b_states(); continue; } @@ -307,8 +341,8 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) set_i_state(si); } - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); /* Set back states changed in the loop above. */ for (events= scan_it.get_events(); events; events= events->get_next()) @@ -316,10 +350,10 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) gcalc_shape_info si= events->get_shape(); if (events->event == scev_thread || events->event == scev_end || - events->event == scev_single_point || - (get_shape_kind(si) == Gcalc_function::shape_polygon)) + get_shape_kind(si) == Gcalc_function::shape_polygon) clear_b_state(si); - else if (get_shape_kind(si) == Gcalc_function::shape_line) + else if (events->event == scev_single_point || + get_shape_kind(si) == Gcalc_function::shape_line) clear_i_state(si); } @@ -343,8 +377,8 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) else invert_i_state(si); } - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next()) { @@ -357,12 +391,13 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) else invert_i_state(cur_eq->get_shape()); } - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); + eq_start= pit.point(); } while (pit.point() != scan_it.get_event_end()); } - GCALC_DBUG_RETURN(0); + GCALC_DBUG_RETURN(count_last()); } diff --git a/sql/gcalc_tools.h b/sql/gcalc_tools.h index 12ee56732a2..9e9b580b359 100644 --- a/sql/gcalc_tools.h +++ b/sql/gcalc_tools.h @@ -82,6 +82,12 @@ public: shape_polygon= 2, shape_hole= 3 }; + enum count_result + { + result_false= 0, + result_true= 1, + result_unknown= 2 + }; Gcalc_function() : n_shapes(0) {} gcalc_shape_info add_new_shape(uint32 shape_id, shape_type shape_kind); /* @@ -116,6 +122,8 @@ public: int get_b_state(gcalc_shape_info shape) { return b_states[shape]; } int count() { return count_internal(function_buffer.ptr(), 0, 0); } + int count_last() + { return count_internal(function_buffer.ptr(), 1, 0); } void clear_i_states(); void clear_b_states(); void reset(); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index fc7367dcd67..42e7029363c 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1104,8 +1104,10 @@ static int setup_relate_func(Geometry *g1, Geometry *g2, cur_op|= Gcalc_function::v_find_t; break; case 'F': - cur_op|= (Gcalc_function::op_not | Gcalc_function::v_find_t); + cur_op|= (Gcalc_function::op_not | Gcalc_function::v_find_f); break; + default: + return 1; }; ++n_operands; if (func->reserve_op_buffer(3)) @@ -1150,7 +1152,6 @@ longlong Item_func_spatial_precise_rel::val_int() Geometry_buffer buffer1, buffer2; Geometry *g1, *g2; int result= 0; - int mask= 0; uint shape_a, shape_b; MBR umbr, mbr1, mbr2; const char *c_end; @@ -1180,8 +1181,9 @@ longlong Item_func_spatial_precise_rel::val_int() case SP_CONTAINS_FUNC: if (!mbr1.contains(&mbr2)) goto exit; - mask= 1; - func.add_operation(Gcalc_function::op_difference, 2); + func.add_operation(Gcalc_function::v_find_f | + Gcalc_function::op_not | + Gcalc_function::op_difference, 2); /* Mind the g2 goes first. */ null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn); break; @@ -1189,32 +1191,36 @@ longlong Item_func_spatial_precise_rel::val_int() mbr2.buffer(2e-5); if (!mbr1.within(&mbr2)) goto exit; - mask= 1; - func.add_operation(Gcalc_function::op_difference, 2); + func.add_operation(Gcalc_function::v_find_f | + Gcalc_function::op_not | + Gcalc_function::op_difference, 2); null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_EQUALS_FUNC: if (!mbr1.contains(&mbr2)) goto exit; - mask= 1; - func.add_operation(Gcalc_function::op_symdifference, 2); + func.add_operation(Gcalc_function::v_find_f | + Gcalc_function::op_not | + Gcalc_function::op_symdifference, 2); null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_DISJOINT_FUNC: - mask= 1; - func.add_operation(Gcalc_function::op_intersection, 2); + func.add_operation(Gcalc_function::v_find_f | + Gcalc_function::op_not | + Gcalc_function::op_intersection, 2); null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_INTERSECTS_FUNC: if (!mbr1.intersects(&mbr2)) goto exit; - func.add_operation(Gcalc_function::op_intersection, 2); + func.add_operation(Gcalc_function::v_find_t | + Gcalc_function::op_intersection, 2); null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_OVERLAPS_FUNC: case SP_CROSSES_FUNC: func.add_operation(Gcalc_function::op_intersection, 2); - if (func.reserve_op_buffer(1)) + if (func.reserve_op_buffer(3)) break; func.add_operation(Gcalc_function::v_find_t | Gcalc_function::op_intersection, 2); @@ -1226,8 +1232,7 @@ longlong Item_func_spatial_precise_rel::val_int() break; if (func.reserve_op_buffer(7)) break; - func.add_operation(Gcalc_function::v_find_t | - Gcalc_function::op_intersection, 2); + func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::v_find_t | Gcalc_function::op_difference, 2); func.repeat_expression(shape_a); @@ -1238,7 +1243,7 @@ longlong Item_func_spatial_precise_rel::val_int() func.repeat_expression(shape_a); break; case SP_TOUCHES_FUNC: - if (func.reserve_op_buffer(2)) + if (func.reserve_op_buffer(5)) break; func.add_operation(Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::v_find_f | @@ -1254,9 +1259,7 @@ longlong Item_func_spatial_precise_rel::val_int() break; func.add_operation(Gcalc_function::v_find_t | Gcalc_function::op_intersection, 2); - func.add_operation(Gcalc_function::op_border, 1); func.repeat_expression(shape_a); - func.add_operation(Gcalc_function::op_border, 1); func.repeat_expression(shape_b); break; case SP_RELATE_FUNC: @@ -1281,7 +1284,7 @@ longlong Item_func_spatial_precise_rel::val_int() if (func.alloc_states()) goto exit; - result= func.check_function(scan_it) ^ mask; + result= func.check_function(scan_it); exit: collector.reset(); |