summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/gis-precise.result94
-rw-r--r--mysql-test/t/gis-precise.test36
-rw-r--r--sql/gcalc_slicescan.h1
-rw-r--r--sql/gcalc_tools.cc211
-rw-r--r--sql/gcalc_tools.h60
-rw-r--r--sql/item_create.cc6
-rw-r--r--sql/item_geofunc.cc213
-rw-r--r--sql/item_geofunc.h3
-rw-r--r--sql/spatial.cc6
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;