diff options
-rw-r--r-- | mysql-test/r/gis-precise.result | 94 | ||||
-rw-r--r-- | mysql-test/t/gis-precise.test | 36 | ||||
-rw-r--r-- | sql/gcalc_slicescan.h | 1 | ||||
-rw-r--r-- | sql/gcalc_tools.cc | 211 | ||||
-rw-r--r-- | sql/gcalc_tools.h | 60 | ||||
-rw-r--r-- | sql/item_create.cc | 6 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 213 | ||||
-rw-r--r-- | sql/item_geofunc.h | 3 | ||||
-rw-r--r-- | sql/spatial.cc | 6 |
9 files changed, 372 insertions, 258 deletions
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result index 5adecfb5a35..ef621d11e54 100644 --- a/mysql-test/r/gis-precise.result +++ b/mysql-test/r/gis-precise.result @@ -7,7 +7,7 @@ select 0, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFro 0 0 select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)')); 1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)')) -1 1 +1 0 select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')); 1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')) 1 1 @@ -25,48 +25,90 @@ insert into t1 values (GeomFromText('POINT(8 2)')), (GeomFromText('POINT(8 4)')), (GeomFromText('POINT(8 6)')), (GeomFromText('POINT(8 8)')); select astext(g) from t1 where ST_Within(g, GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))')); astext(g) +POINT(2 2) +POINT(2 4) +POINT(2 6) +POINT(2 8) POINT(4 2) POINT(4 4) POINT(4 6) +POINT(4 8) POINT(6 2) POINT(6 4) POINT(6 6) +POINT(6 8) +POINT(8 2) +POINT(8 4) +POINT(8 6) +POINT(8 8) select 'Contains'; Contains Contains select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g); astext(g) +POINT(2 2) +POINT(2 4) +POINT(2 6) +POINT(2 8) +POINT(4 2) POINT(4 4) +POINT(4 6) +POINT(4 8) POINT(6 2) POINT(6 4) POINT(6 6) +POINT(6 8) +POINT(8 2) +POINT(8 4) +POINT(8 6) +POINT(8 8) select 'Intersects'; Intersects Intersects select astext(g) from t1 where ST_Intersects(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g); astext(g) -POINT(4 4) -POINT(6 2) -POINT(6 4) -POINT(6 6) select 'Contains'; Contains Contains select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g); astext(g) +POINT(2 2) +POINT(2 4) +POINT(2 6) +POINT(2 8) +POINT(4 2) POINT(4 4) +POINT(4 6) +POINT(4 8) POINT(6 2) POINT(6 4) POINT(6 6) +POINT(6 8) +POINT(8 2) +POINT(8 4) +POINT(8 6) +POINT(8 8) select 'Contains2'; Contains2 Contains2 select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1), (5.01 3.01, 6 5, 9 5, 8 3, 5.01 3.01))'), g); astext(g) +POINT(2 2) +POINT(2 4) +POINT(2 6) +POINT(2 8) +POINT(4 2) POINT(4 4) +POINT(4 6) +POINT(4 8) POINT(6 2) +POINT(6 4) POINT(6 6) +POINT(6 8) +POINT(8 2) POINT(8 4) +POINT(8 6) +POINT(8 8) DROP TABLE t1; select 0, ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')); 0 ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))')) @@ -94,7 +136,7 @@ ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('P 1 select ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)')); ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)')) -0 +1 select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))')); ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))')) 1 @@ -177,10 +219,10 @@ st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)')) 0 select st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)')); st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 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)')) -1 +0 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 @@ -189,7 +231,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))')) -0 +1 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 @@ -319,7 +361,7 @@ PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 3 3 , 2 5 , 2 2 ) ) ') ) ) POLYGON((2 0,2 5,3 3,3 2,7 5,2 0)) SELECT AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)'))); AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)'))) -GEOMETRYCOLLECTION() +GEOMETRYCOLLECTION EMPTY SELECT AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))'))); AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))'))) GEOMETRYCOLLECTION(POINT(8 1),LINESTRING(2 4,2 5,3 5,3 4,2 4)) @@ -355,17 +397,6 @@ ST_NUMGEOMETRIES(ST_DIFFERENCE ( ST_UNION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 4 , 5 0 , 2 9 , 6 2 , 0 2 ) , ( 4 3 , 5 6 , 9 4 , 0 7 , 7 2 , 2 0 , 8 2 ) , ( 5 0 , 1 5 , 3 7 , 7 7 ) , ( 2 3 , 9 5 , 2 0 , 8 1 ) , ( 0 9 , 9 3 , 2 8 , 8 1 , 9 4 ) 123 -SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER ( -ST_UNION ( -MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) , -MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 4 5 , 3 0 , 3 1 , 4 7 , 4 2 ) , ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) -) , 1 -))); -ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER ( -ST_UNION ( -MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) , -MULTILINESTRI -653 SELECT ASTEXT(ST_DIFFERENCE ( POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) , ST_UNION ( @@ -414,9 +445,24 @@ NULL SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ; ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , NULL -SELECT ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6 , 7 2 , 3 4 ) ' ) , ST_BUFFER ( ST_UNION ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 6 2 , 1 3 , 2 2 , 2 2 ) ) ) ' ) , GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 1 4 , 9 9 , 3 0 , 6 6 ) , ( 3 5 , 1 0 , 5 8 , 6 1 ) , ( 8 9 , 6 1 , 5 1 , 6 2 ) , ( 2 2 , 7 5 , 5 8 , 6 9 , 3 0 ) , ( 8 0 , 8 4 , 6 7 , 5 5 ) ) ' ) ) , NUMPOINTS( EXTERIORRING( POLYGONFROMTEXT( ' POLYGON( ( 0 0 , 2 1 , 8 2 , 0 0 ) ) ' ) ) ) ) ) ) , ST_INTERSECTION ( POLYGONFROMTEXT( ' POLYGON( ( 2 3, 5 7 , 3 7 , 4 1 , 0 5, 2 3 ) ) ' ) , MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 3 , 1 4 , 6 4 , 9 1 , 3 4 , 1 8 ) , ( 9 9 , 0 3 , 1 7 , 9 9 ) ) ' ) ) ) , POLYGONFROMTEXT( ' POLYGON( ( 1 3, 7 2 , 1 5 , 3 8 , 5 0, 1 3) ) ' ) ) ) ; -ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6 -25 SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') )); ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)) MULTIPOINT(7 5,7 5.14285714285714,5.9 5.3,5.8 5.6,3 7) +SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) ')); +ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) ')) +0 +SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') ); +ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') ) +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 ) ) ) ')) +1 +select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY'))); +ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY'))) +NULL +SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') ); +ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') ) +0 +SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') ); +ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') ) +0 diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test index 8e630766004..bf5c48d11f6 100644 --- a/mysql-test/t/gis-precise.test +++ b/mysql-test/t/gis-precise.test @@ -237,14 +237,6 @@ SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE ( )); -#bug 841638 Assertion `!m_prev || m_prev->x != x || m_prev->y != y' failed in Gcalc_shape_transporter::int_add_point in maria-5.3-gis -SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER ( - ST_UNION ( - MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 7 3 , 1 8 , 4 0 , 7 9 ) , ( 5 4 , 9 8 , 7 4 , 3 7 ) , ( 5 8 , 5 4 , 9 2 , 5 6 ) , ( 4 0 , 3 2 , 0 1 , 3 9 ) , ( 2 0 , 3 5 , 9 5 , 0 9 ) ) ' ) , - MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 4 5 , 3 0 , 3 1 , 4 7 , 4 2 ) , ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) - ) , 1 -))); - #bug 841745 ssertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis SELECT ASTEXT(ST_DIFFERENCE ( POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) , @@ -279,10 +271,30 @@ SELECT ST_BUFFER ( ) ; SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ; -#bug 848901 Assertion `fabs(cur_isc->x-m_cur_intersection->x) + fabs(cur_isc->y-m_cur_intersection->y) < 0.000000000001' failed in Gcalc_scan_iterator::intersection_scan() in maria-5.3-gis - -SELECT ST_NUMGEOMETRIES( ST_SYMDIFFERENCE ( ST_SYMDIFFERENCE ( ST_INTERSECTION ( MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 6 4 , 3 7 , 9 4 , 3 8 ) , ( 2 2 , 2 9 , 1 2 , 9 8 ) ) ' ) , ST_SYMDIFFERENCE ( MULTIPOINTFROMTEXT( ' MULTIPOINT( 6 1 , 3 8 , 3 3 , 0 6 , 7 2 , 3 4 ) ' ) , ST_BUFFER ( ST_UNION ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 6 2 , 1 3 , 2 2 , 2 2 ) ) ) ' ) , GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 1 4 , 9 9 , 3 0 , 6 6 ) , ( 3 5 , 1 0 , 5 8 , 6 1 ) , ( 8 9 , 6 1 , 5 1 , 6 2 ) , ( 2 2 , 7 5 , 5 8 , 6 9 , 3 0 ) , ( 8 0 , 8 4 , 6 7 , 5 5 ) ) ' ) ) , NUMPOINTS( EXTERIORRING( POLYGONFROMTEXT( ' POLYGON( ( 0 0 , 2 1 , 8 2 , 0 0 ) ) ' ) ) ) ) ) ) , ST_INTERSECTION ( POLYGONFROMTEXT( ' POLYGON( ( 2 3, 5 7 , 3 7 , 4 1 , 0 5, 2 3 ) ) ' ) , MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 3 , 1 4 , 6 4 , 9 1 , 3 4 , 1 8 ) , ( 9 9 , 0 3 , 1 7 , 9 9 ) ) ' ) ) ) , POLYGONFROMTEXT( ' POLYGON( ( 1 3, 7 2 , 1 5 , 3 8 , 5 0, 1 3) ) ' ) ) ) ; - #bug 848939 Wrong result with ST_INTERSECTION between linestrings and a polygon in 5.3-gis SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') )); +#bug 855485 ST_CROSSES returns different result than PostGIS for overlapping polygons + +SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) ')); + +#bug 855487 ST_WITHIN returns wrong result for partially overlapping polygons + +SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') ); + +#bug 855492 ST_WITHIN returns TRUE on point on the edge of a polygon + +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 ) ) ) ')); + +#bug 855497 ST_ENVELOPE of GEOMETRYCOLLECTION EMPTY returns NULL and not GEOMETRYCOLLECTION EMPTY + +select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY'))); + +#bug 855503 ST_EQUALS reports TRUE between a POLYGON and a MULTILINESTRING + +SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') ); + +#bug 855505 ST_TOUCHES reports TRUE for intersecting polygon and linestring + +SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') ); + diff --git a/sql/gcalc_slicescan.h b/sql/gcalc_slicescan.h index d1c81ca4648..fe7959c4172 100644 --- a/sql/gcalc_slicescan.h +++ b/sql/gcalc_slicescan.h @@ -307,6 +307,7 @@ public: virtual int complete_ring()=0; virtual int add_point(double x, double y)=0; virtual int start_collection(int n_objects) { return 0; } + virtual int empty_shape() { return 0; } int start_simple_poly() { return start_poly() || start_ring(); diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 90c39f08d0b..6a2fdbccacb 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -43,7 +43,7 @@ gcalc_shape_info Gcalc_function::add_new_shape(uint32 shape_id, in prefix style. */ -void Gcalc_function::add_operation(op_type operation, uint32 n_operands) +void Gcalc_function::add_operation(uint operation, uint32 n_operands) { uint32 op_code= (uint32 ) operation + n_operands; function_buffer.q_append(op_code); @@ -84,6 +84,15 @@ int Gcalc_function::single_shape_op(shape_type shape_kind, gcalc_shape_info *si) } +int Gcalc_function::repeat_expression(uint32 exp_pos) +{ + if (reserve_op_buffer(1)) + return 1; + add_operation(op_repeat, exp_pos); + return 0; +} + + /* Specify how many arguments we're going to have. */ @@ -109,42 +118,61 @@ int Gcalc_function::alloc_states() if (function_buffer.reserve((n_shapes+1) * 2 * sizeof(int))) return 1; i_states= (int *) (function_buffer.ptr() + ALIGN_SIZE(function_buffer.length())); - saved_i_states= i_states + (n_shapes + 1); + b_states= i_states + (n_shapes + 1); return 0; } -void Gcalc_function::save_states() +int Gcalc_function::count_internal(const char *cur_func, uint set_type, + const char **end) { - memcpy(saved_i_states, i_states, (n_shapes+1) * sizeof(int)); -} - - -void Gcalc_function::restore_states() -{ - memcpy(i_states, saved_i_states, (n_shapes+1) * sizeof(int)); -} - - -int Gcalc_function::count_internal() -{ - int c_op= uint4korr(cur_func); + uint c_op= uint4korr(cur_func); op_type next_func= (op_type) (c_op & op_any); int mask= (c_op & op_not) ? 1:0; - int n_ops= c_op & ~op_any; + uint n_ops= c_op & ~(op_any | op_not | v_mask); + uint n_shape= c_op & ~(op_any | op_not | v_mask); /* same as n_ops */ + value v_state= (value) (c_op & v_mask); int result; + const char *sav_cur_func= cur_func; cur_func+= 4; if (next_func == op_shape) - return i_states[c_op & ~(op_any | op_not)] ^ mask; + { + if (set_type == 0) + result= i_states[n_shape] | b_states[n_shape]; + else if (set_type == op_border) + result= b_states[n_shape]; + else if (set_type == op_internals) + result= i_states[n_shape] && !b_states[n_shape]; + goto exit; + } + + if (next_func == op_false) + { + result= 0; + goto exit; + } + + if (next_func == op_border || next_func == op_internals) + { + result= count_internal(cur_func, next_func, &cur_func); + goto exit; + } + + if (next_func == op_repeat) + { + result= count_internal(function_buffer.ptr() + n_ops, set_type, 0); + goto exit; + } + if (n_ops == 0) return mask; - result= count_internal(); + result= count_internal(cur_func, set_type, &cur_func); while (--n_ops) { - int next_res= count_internal(); + int next_res= count_internal(cur_func, set_type, &cur_func); switch (next_func) { case op_union: @@ -159,15 +187,59 @@ int Gcalc_function::count_internal() case op_difference: result= result & !next_res; break; - case op_backdifference: - result= !result & next_res; - break; default: DBUG_ASSERT(FALSE); }; } - return result ^ mask; +exit: + result^= mask; + if (v_state != v_empty) + { + switch (v_state) + { + case v_find_t: + if (result) + { + c_op= (c_op & ~v_mask) | v_t_found; + int4store(sav_cur_func, c_op); + }; + break; + case v_find_f: + if (!result) + { + c_op= (c_op & ~v_mask) | v_f_found; + int4store(sav_cur_func, c_op); + }; + break; + case v_t_found: + result= 1; + break; + case v_f_found: + result= 0; + break; + default: + DBUG_ASSERT(0); + }; + } + + if (end) + *end= cur_func; + return result; +} + + +void Gcalc_function::clear_i_states() +{ + for (uint i= 0; i < n_shapes; i++) + i_states[i]= 0; +} + + +void Gcalc_function::clear_b_states() +{ + for (uint i= 0; i < n_shapes; i++) + b_states[i]= 0; } @@ -183,7 +255,7 @@ void Gcalc_function::reset() } -int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it) +int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) { const Gcalc_scan_iterator::point *eq_start, *cur_eq, *events; @@ -194,31 +266,58 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it) events= scan_it.get_events(); /* these kinds of events don't change the function */ - if (events->simple_event()) - continue; - Gcalc_point_iterator pit(&scan_it); - clear_state(); + clear_b_states(); + clear_i_states(); /* Walk to the event, marking polygons we met */ for (; pit.point() != scan_it.get_event_position(); ++pit) { gcalc_shape_info si= pit.point()->get_shape(); if ((get_shape_kind(si) == Gcalc_function::shape_polygon)) - invert_state(si); + invert_i_state(si); } - save_states(); + if (events->simple_event()) + { + if (events->event == scev_end) + set_b_state(events->get_shape()); + + if (count()) + return 1; + clear_b_states(); + continue; + } + /* Check the status of the event point */ for (; events; events= events->get_next()) - set_on_state(events->get_shape()); + { + gcalc_shape_info si= events->get_shape(); + if (events->event == scev_thread || + events->event == scev_end || + (get_shape_kind(si) == Gcalc_function::shape_polygon)) + set_b_state(si); + else if (get_shape_kind(si) == Gcalc_function::shape_line) + invert_i_state(si); + } if (count()) return 1; + /* Set back states changed in the loop above. */ + for (events= scan_it.get_events(); events; events= events->get_next()) + { + gcalc_shape_info si= events->get_shape(); + if (events->event == scev_thread || + events->event == scev_end || + (get_shape_kind(si) == Gcalc_function::shape_polygon)) + clear_b_state(si); + else if (get_shape_kind(si) == Gcalc_function::shape_line) + invert_i_state(si); + } + if (scan_it.get_event_position() == scan_it.get_event_end()) continue; /* Check the status after the event */ - restore_states(); eq_start= pit.point(); do { @@ -226,18 +325,28 @@ int Gcalc_function::find_function(Gcalc_scan_iterator &scan_it) if (pit.point() != scan_it.get_event_end() && eq_start->cmp_dx_dy(pit.point()) == 0) continue; - save_states(); for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next()) - set_on_state(cur_eq->get_shape()); + { + gcalc_shape_info si= cur_eq->get_shape(); + if (get_shape_kind(si) == Gcalc_function::shape_polygon) + set_b_state(si); + else + invert_i_state(si); + } if (count()) return 1; - restore_states(); + for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next()) { gcalc_shape_info si= cur_eq->get_shape(); if ((get_shape_kind(si) == Gcalc_function::shape_polygon)) - invert_state(si); + { + clear_b_state(si); + invert_i_state(si); + } + else + invert_i_state(cur_eq->get_shape()); } if (count()) return 1; @@ -313,6 +422,15 @@ int Gcalc_operation_transporter::start_collection(int n_objects) } +int Gcalc_operation_transporter::empty_shape() +{ + if (m_fn->reserve_op_buffer(1)) + return 1; + m_fn->add_operation(Gcalc_function::op_false, 0); + return 0; +} + + int Gcalc_result_receiver::start_shape(Gcalc_function::shape_type shape) { if (buffer.reserve(4*2, 512)) @@ -661,7 +779,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) if (ca_counter == 11522) call_checkpoint(89); #endif /*NO_TESTING*/ - m_fn->clear_state(); + m_fn->clear_i_states(); /* Walk to the event, remembering what is needed. */ #ifndef NO_TESTING if (si->get_event_position() == pi.point()) @@ -678,7 +796,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) prev_range= prev_state ? cur_t : 0; } if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon) - m_fn->invert_state(pi.get_shape()); + m_fn->invert_i_state(pi.get_shape()); } events= si->get_events(); @@ -800,6 +918,7 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) eq_start= pi.point(); eq_thread= point_thread= *starting_t_hook; + m_fn->clear_b_states(); while (eq_start != si->get_event_end()) { const Gcalc_scan_iterator::point *cur_eq; @@ -812,17 +931,16 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) eq_start->cmp_dx_dy(pi.point()) == 0) continue; - m_fn->save_states(); for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next()) - m_fn->set_on_state(cur_eq->get_shape()); + m_fn->set_b_state(cur_eq->get_shape()); in_state= m_fn->count(); - m_fn->restore_states(); + m_fn->clear_b_states(); for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next()) { gcalc_shape_info si= cur_eq->get_shape(); if ((m_fn->get_shape_kind(si) == Gcalc_function::shape_polygon)) - m_fn->invert_state(si); + m_fn->invert_i_state(si); } after_state= m_fn->count(); if (prev_state != after_state) @@ -844,14 +962,15 @@ int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si) if (!sav_prev_state && !m_poly_borders && !m_lines) { /* Check if we need to add the event point itself */ - m_fn->clear_state(); + m_fn->clear_i_states(); + /* b_states supposed to be clean already */ for (pi.restart(si); pi.point() != si->get_event_position(); ++pi) { if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon) - m_fn->invert_state(pi.get_shape()); + m_fn->invert_i_state(pi.get_shape()); } for (events= si->get_events(); events; events= events->get_next()) - m_fn->set_on_state(events->get_shape()); + m_fn->set_b_state(events->get_shape()); return m_fn->count() ? add_single_point(si) : 0; } diff --git a/sql/gcalc_tools.h b/sql/gcalc_tools.h index 39704dfeb56..5e98d46a90f 100644 --- a/sql/gcalc_tools.h +++ b/sql/gcalc_tools.h @@ -43,23 +43,35 @@ class Gcalc_function private: String shapes_buffer; String function_buffer; - const char *cur_func; int *i_states; - int *saved_i_states; + int *b_states; uint32 cur_object_id; uint n_shapes; - int count_internal(); + int count_internal(const char *cur_func, uint set_type, + const char **end); public: + enum value + { + v_empty= 0x0000000, + v_find_t= 0x1000000, + v_find_f= 0x2000000, + v_t_found= 0x3000000, + v_f_found= 0x4000000, + v_mask= 0x7000000 + }; enum op_type { - op_shape= 0, - op_not= 0x80000000, - op_union= 0x10000000, - op_intersection= 0x20000000, + op_not= 0x80000000, + op_shape= 0x00000000, + op_union= 0x10000000, + op_intersection= 0x20000000, op_symdifference= 0x30000000, - op_difference= 0x40000000, - op_backdifference= 0x50000000, - op_any= 0x70000000 + op_difference= 0x40000000, + op_repeat= 0x50000000, + op_border= 0x60000000, + op_internals= 0x70000000, + op_false= 0x08000000, + op_any= 0x78000000 /* The mask to get any of the operations */ }; enum shape_type { @@ -75,10 +87,11 @@ public: Also adds the shape to the list of operands. */ int single_shape_op(shape_type shape_kind, gcalc_shape_info *si); - void add_operation(op_type operation, uint32 n_operands); + void add_operation(uint operation, uint32 n_operands); void add_not_operation(op_type operation, uint32 n_operands); - uint32 get_next_operation_pos() { return function_buffer.length(); } + uint32 get_next_expression_pos() { return function_buffer.length(); } void add_operands_to_op(uint32 operation_pos, uint32 n_operands); + int repeat_expression(uint32 exp_pos); void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; } int reserve_shape_buffer(uint n_shapes); int reserve_op_buffer(uint n_ops); @@ -90,20 +103,20 @@ public: void set_states(int *shape_states) { i_states= shape_states; } int alloc_states(); - void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; } - void set_on_state(gcalc_shape_info shape) { i_states[shape]= 1; } - int get_state(gcalc_shape_info shape) { return i_states[shape]; } - void save_states(); - void restore_states(); + void invert_i_state(gcalc_shape_info shape) { i_states[shape]^= 1; } + void set_b_state(gcalc_shape_info shape) { b_states[shape]= 1; } + void clear_b_state(gcalc_shape_info shape) { b_states[shape]= 0; } + int get_state(gcalc_shape_info shape) + { return i_states[shape] | b_states[shape]; } + int get_i_state(gcalc_shape_info shape) { return i_states[shape]; } + int get_b_state(gcalc_shape_info shape) { return b_states[shape]; } int count() - { - cur_func= function_buffer.ptr(); - return count_internal(); - } - void clear_state() { bzero(i_states, n_shapes * sizeof(int)); } + { return count_internal(function_buffer.ptr(), 0, 0); } + void clear_i_states(); + void clear_b_states(); void reset(); - int find_function(Gcalc_scan_iterator &scan_it); + int check_function(Gcalc_scan_iterator &scan_it); }; @@ -132,6 +145,7 @@ public: int complete_ring(); int add_point(double x, double y); int start_collection(int n_objects); + int empty_shape(); }; diff --git a/sql/item_create.cc b/sql/item_create.cc index 2a8f7eec52a..626f0c5d91e 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5144,7 +5144,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)}, { { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)}, { { C_STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)}, - { { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)}, + { { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_equals)}, { { C_STRING_WITH_LEN("EXP") }, BUILDER(Create_func_exp)}, { { C_STRING_WITH_LEN("EXPORT_SET") }, BUILDER(Create_func_export_set)}, { { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)}, @@ -5283,7 +5283,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)}, { { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)}, { { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)}, - { { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)}, + { { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)}, { { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)}, { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)}, { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)}, @@ -5323,7 +5323,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)}, { { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)}, { { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)}, - { { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_mbr_within)}, + { { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)}, { { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)}, { { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)}, { { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)}, diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index e490643f88b..4db8ee02d7f 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -660,6 +660,7 @@ static double distance_points(const Gcalc_heap::Info *a, Calculates the distance between objects. */ +#ifdef TMP_BLOCK static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si, Gcalc_function *func, Gcalc_scan_iterator *scan_it) { @@ -786,139 +787,11 @@ exit: mem_error: DBUG_RETURN(1); } +#endif /*TMP_BLOCK*/ #define GIS_ZERO 0.00000000001 -int Item_func_spatial_rel::func_touches() -{ - bool above_cur_point; - double x1, x2, y1, y2, ex, ey; - double distance, area; - int result= 0; - int cur_func= 0; - - Gcalc_operation_transporter trn(&func, &collector); - - String *res1= args[0]->val_str(&tmp_value1); - String *res2= args[1]->val_str(&tmp_value2); - Geometry_buffer buffer1, buffer2; - Geometry *g1, *g2; - int obj2_si; - - DBUG_ENTER("Item_func_spatial_rel::func_touches"); - DBUG_ASSERT(fixed == 1); - - if ((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()))))) - goto mem_error; - - if ((g1->get_class_info()->m_type_id == Geometry::wkb_point) && - (g2->get_class_info()->m_type_id == Geometry::wkb_point)) - { - if (((Gis_point *) g1)->get_xy(&x1, &y1) || - ((Gis_point *) g2)->get_xy(&x2, &y2)) - goto mem_error; - ex= x2 - x1; - ey= y2 - y1; - DBUG_RETURN((ex * ex + ey * ey) < GIS_ZERO); - } - - if (func.reserve_op_buffer(1)) - goto mem_error; - func.add_operation(Gcalc_function::op_intersection, 2); - - if (g1->store_shapes(&trn)) - goto mem_error; - obj2_si= func.get_nshapes(); - - if (g2->store_shapes(&trn) || func.alloc_states()) - goto mem_error; - - collector.prepare_operation(); - scan_it.init(&collector); - - if (calc_distance(&distance, &collector, obj2_si, &func, &scan_it)) - goto mem_error; - if (distance > GIS_ZERO) - goto exit; - - scan_it.reset(); - scan_it.init(&collector); - - above_cur_point= false; - distance= DBL_MAX; - - while (scan_it.more_trapezoids()) - { - if (scan_it.step()) - goto mem_error; - - func.clear_state(); - for (Gcalc_trapezoid_iterator ti(&scan_it); ti.more(); ++ti) - { - gcalc_shape_info si= ti.lb()->get_shape(); - if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon)) - { - func.invert_state(si); - cur_func= func.count(); - } - if (cur_func) - { - area= scan_it.get_h() * - ((scan_it.get_sp_x(ti.rb()) - scan_it.get_sp_x(ti.lb())) + - (scan_it.get_sp_x(ti.rt()) - scan_it.get_sp_x(ti.lt()))); - if (area > GIS_ZERO) - { - result= 0; - goto exit; - } - } - } - } - result= 1; - -exit: - collector.reset(); - func.reset(); - scan_it.reset(); - DBUG_RETURN(result); -mem_error: - null_value= 1; - DBUG_RETURN(0); -} - - -int Item_func_spatial_rel::func_equals() -{ - Gcalc_heap::Info *pi_s1, *pi_s2; - Gcalc_heap::Info *cur_pi= collector.get_first(); - double d; - - if (!cur_pi) - return 1; - - do { - pi_s1= cur_pi; - pi_s2= 0; - while ((cur_pi= cur_pi->get_next())) - { - d= fabs(pi_s1->x - cur_pi->x) + fabs(pi_s1->y - cur_pi->y); - if (d > GIS_ZERO) - break; - if (!pi_s2 && pi_s1->shape != cur_pi->shape) - pi_s2= cur_pi; - } - - if (!pi_s2) - return 0; - } while (cur_pi); - - return 1; -} - - longlong Item_func_spatial_rel::val_int() { DBUG_ENTER("Item_func_spatial_rel::val_int"); @@ -929,9 +802,7 @@ longlong Item_func_spatial_rel::val_int() Geometry *g1, *g2; int result= 0; int mask= 0; - - if (spatial_rel == SP_TOUCHES_FUNC) - DBUG_RETURN(func_touches()); + uint shape_a, shape_b; res1= args[0]->val_str(&tmp_value1); res2= args[1]->val_str(&tmp_value2); @@ -940,56 +811,103 @@ longlong Item_func_spatial_rel::val_int() if (func.reserve_op_buffer(1)) DBUG_RETURN(0); + if ((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()))))) + goto exit; + switch (spatial_rel) { case SP_CONTAINS_FUNC: mask= 1; - func.add_operation(Gcalc_function::op_backdifference, 2); + func.add_operation(Gcalc_function::op_difference, 2); + /* Mind the g2 goes first. */ + null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn); break; case SP_WITHIN_FUNC: mask= 1; func.add_operation(Gcalc_function::op_difference, 2); + null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_EQUALS_FUNC: + mask= 1; + func.add_operation(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); + null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_INTERSECTS_FUNC: func.add_operation(Gcalc_function::op_intersection, 2); + null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn); break; case SP_OVERLAPS_FUNC: - func.add_operation(Gcalc_function::op_backdifference, 2); - break; case SP_CROSSES_FUNC: func.add_operation(Gcalc_function::op_intersection, 2); + func.add_operation(Gcalc_function::v_find_t | + Gcalc_function::op_intersection, 2); + shape_a= func.get_next_expression_pos(); + if ((null_value= g1->store_shapes(&trn))) + break; + shape_b= func.get_next_expression_pos(); + if ((null_value= g2->store_shapes(&trn))) + break; + func.add_operation(Gcalc_function::v_find_t | + Gcalc_function::op_intersection, 2); + func.add_operation(Gcalc_function::v_find_t | + Gcalc_function::op_difference, 2); + func.repeat_expression(shape_a); + func.repeat_expression(shape_b); + func.add_operation(Gcalc_function::v_find_t | + Gcalc_function::op_difference, 2); + func.repeat_expression(shape_b); + func.repeat_expression(shape_a); + break; + case SP_TOUCHES_FUNC: + 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); + func.add_operation(Gcalc_function::op_internals, 1); + shape_a= func.get_next_expression_pos(); + if ((null_value= g1->store_shapes(&trn))) + break; + func.add_operation(Gcalc_function::op_internals, 1); + shape_b= func.get_next_expression_pos(); + if ((null_value= g2->store_shapes(&trn))) + 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; default: DBUG_ASSERT(FALSE); break; } - - if ((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(&trn) || g2->store_shapes(&trn)))) + if (null_value) goto exit; collector.prepare_operation(); scan_it.init(&collector); +#ifdef TMP_BLOCK if (spatial_rel == SP_EQUALS_FUNC) { result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) && func_equals(); goto exit; } +#endif /*TMP_BLOCK*/ if (func.alloc_states()) goto exit; - result= func.find_function(scan_it) ^ mask; + result= func.check_function(scan_it) ^ mask; exit: collector.reset(); @@ -1307,7 +1225,7 @@ int Item_func_buffer::Transporter::start_line() if (m_fn->reserve_op_buffer(2)) return 1; - last_shape_pos= m_fn->get_next_operation_pos(); + last_shape_pos= m_fn->get_next_expression_pos(); m_fn->add_operation(buffer_op, 0); m_npoints= 0; int_start_line(); @@ -1321,7 +1239,7 @@ int Item_func_buffer::Transporter::start_poly() if (m_fn->reserve_op_buffer(2)) return 1; - last_shape_pos= m_fn->get_next_operation_pos(); + last_shape_pos= m_fn->get_next_expression_pos(); m_fn->add_operation(buffer_op, 0); return Gcalc_operation_transporter::start_poly(); } @@ -1827,19 +1745,20 @@ double Item_func_distance::val_real() of objects scev_thread | scev_two_threads | scev_single_point */ - func.clear_state(); + func.clear_i_states(); for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit) { gcalc_shape_info si= pit.point()->get_shape(); if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon)) - func.invert_state(si); + func.invert_i_state(si); } + func.clear_b_states(); for (; ev; ev= ev->get_next()) { if (ev->event != scev_intersection) cur_point= ev->pi; - func.set_on_state(ev->get_shape()); + func.set_b_state(ev->get_shape()); if (func.count()) { /* Point of one object is inside the other - intersection found */ diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index d5ed2c1f764..b4e495f39a8 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -251,9 +251,6 @@ public: void fix_length_and_dec() { maybe_null= 1; } bool is_null() { (void) val_int(); return null_value; } -protected: - int func_touches(); - int func_equals(); }; diff --git a/sql/spatial.cc b/sql/spatial.cc index 15dc42441a8..d18600dd7de 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -2519,6 +2519,12 @@ int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const n_objects= uint4korr(data); data+= 4; + if (!n_objects) + { + trn->empty_shape(); + return 0; + } + if (trn->start_collection(n_objects)) return 1; |