Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
PostGIS: use ST_Intersects instead of && for bounding box (fixes #6181,
fixes #6230)
  • Loading branch information
rouault committed Jun 9, 2021
1 parent fe3c28a commit e2ef155
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 6 deletions.
26 changes: 20 additions & 6 deletions mappostgis.c
Expand Up @@ -2055,7 +2055,6 @@ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid, rectObj
char *strBox = 0;
char *strSRID = 0;
size_t strBoxLength = 0;
static const char *strRectTemplate = "\"%s\" && %s";

/* We see to set the SRID on the box, but to what SRID? */
strSRID = msPostGISBuildSQLSRID(layer);
Expand All @@ -2066,27 +2065,42 @@ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid, rectObj
}

strBox = msPostGISBuildSQLBox(layer, rect, strSRID);
msFree(strSRID);
if ( strBox ) {
strBoxLength = strlen(strBox);
} else {
msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISBuildSQLWhere()");
free( strLimit );
free( strOffset );
msFree(strSRID);
return NULL;
}

strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 );
sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox);
if( strstr(strSRID, "find_srid(") == NULL )
{
// If the SRID is known, we can safely use ST_Intersects()
// otherwise if find_srid() would return 0, ST_Intersects() would not
// work at all, which breaks the msautotest/query/query_postgis.map
// tests, releated to bdry_counpy2 layer that has no SRID
static const char *strRectTemplate = "ST_Intersects(\"%s\", %s)";
strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 );
sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox);
}
else
{
static const char *strRectTemplate = "\"%s\" && %s";
strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 );
sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox);
}
strRectLength = strlen(strRect);
free(strBox);
msFree(strSRID);

/* Combine with other rectangle expressed in another SRS */
/* (generally equivalent to the above in current code paths) */
if( rectInOtherSRID != NULL && otherSRID > 0 )
{
char* strRectOtherSRID;
static const char *strRectOtherSRIDTemplate = "NOT ST_Disjoint(ST_Transform(%s,%d),%s)";
static const char *strRectOtherSRIDTemplate = "ST_Intersects(ST_Transform(%s,%d),%s)";
char szSRID[32];
char* strTmp = NULL;

Expand Down Expand Up @@ -2121,7 +2135,7 @@ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid, rectObj
{
char* strSRID;
char* strRectOtherSRID;
static const char *strRectOtherSRIDTemplate = "NOT ST_Disjoint(%s,%s)";
static const char *strRectOtherSRIDTemplate = "ST_Intersects(%s,%s)";
char* strTmp = NULL;

strSRID = msPostGISBuildSQLSRID(layer);
Expand Down
8 changes: 8 additions & 0 deletions msautotest/create_postgis_test_data.sh
Expand Up @@ -129,3 +129,11 @@ CREATE TABLE multipolygon3d (ID SERIAL);
SELECT AddGeometryColumn('public', 'multipolygon3d', 'the_geom', 27700, 'MULTIPOLYGON', 3);
INSERT INTO multipolygon3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;MULTIPOLYGON(((0 0 1,10 0 2,10 10 3,0 10 4,0 0 1),(1 1 2,1 9 3,9 9 4,9 1 5,1 1 2)),((10 10 0,10 20 1,20 20 2,20 10 3,10 10 0)))'));
"

psql -U postgres -d msautotest -c "
CREATE TABLE test_wfs_paging (ID SERIAL);
SELECT AddGeometryColumn('public', 'test_wfs_paging', 'the_geom', 27700, 'LINESTRING', 2);
INSERT INTO test_wfs_paging (the_geom) VALUES (GeomFromEWKT('SRID=27700;LINESTRING (1 0,0 1)'));
INSERT INTO test_wfs_paging (the_geom) VALUES (GeomFromEWKT('SRID=27700;LINESTRING(0 0,10 10)'));
INSERT INTO test_wfs_paging (the_geom) VALUES (GeomFromEWKT('SRID=27700;LINESTRING(5 2,5 8)'));
"
35 changes: 35 additions & 0 deletions msautotest/wxs/expected/wfs_postgis_issue_6181.xml
@@ -0,0 +1,35 @@
Content-Type: text/xml; subtype="gml/3.2.1"; charset=UTF-8

<?xml version='1.0' encoding="UTF-8" ?>
<wfs:FeatureCollection
xmlns:ms="http://mapserver.gis.umn.edu/mapserver"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mapserver.gis.umn.edu/mapserver http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=2.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=test_6181&amp;OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2 http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd"
timeStamp="" numberMatched="unknown" numberReturned="1"
next="http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=2.0.0&amp;REQUEST=GetFeature&amp;TYPENAMES=test_6181&amp;BBOX=0.75%2C0.75%2C9%2C9&amp;COUNT=1&amp;STARTINDEX=1">
<wfs:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::27700">
<gml:lowerCorner>0.00000 0.00000</gml:lowerCorner>
<gml:upperCorner>10.00000 10.00000</gml:upperCorner>
</gml:Envelope>
</wfs:boundedBy>
<wfs:member>
<ms:test_6181 gml:id="test_6181.2">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::27700">
<gml:lowerCorner>0.00000 0.00000</gml:lowerCorner>
<gml:upperCorner>10.00000 10.00000</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<ms:msGeometry>
<gml:LineString gml:id="test_6181.2.1" srsName="urn:ogc:def:crs:EPSG::27700">
<gml:posList srsDimension="2">0.00000 0.00000 10.00000 10.00000 </gml:posList>
</gml:LineString>
</ms:msGeometry>
<ms:id>2</ms:id>
</ms:test_6181>
</wfs:member>
</wfs:FeatureCollection>

35 changes: 35 additions & 0 deletions msautotest/wxs/expected/wfs_postgis_issue_6181_startindex_1.xml
@@ -0,0 +1,35 @@
Content-Type: text/xml; subtype="gml/3.2.1"; charset=UTF-8

<?xml version='1.0' encoding="UTF-8" ?>
<wfs:FeatureCollection
xmlns:ms="http://mapserver.gis.umn.edu/mapserver"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mapserver.gis.umn.edu/mapserver http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=2.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=test_6181&amp;OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2 http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd"
timeStamp="" numberMatched="unknown" numberReturned="1"
previous="http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=2.0.0&amp;REQUEST=GetFeature&amp;TYPENAMES=test_6181&amp;BBOX=0.75%2C0.75%2C9%2C9&amp;COUNT=1">
<wfs:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::27700">
<gml:lowerCorner>5.00000 2.00000</gml:lowerCorner>
<gml:upperCorner>5.00000 8.00000</gml:upperCorner>
</gml:Envelope>
</wfs:boundedBy>
<wfs:member>
<ms:test_6181 gml:id="test_6181.3">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::27700">
<gml:lowerCorner>5.00000 2.00000</gml:lowerCorner>
<gml:upperCorner>5.00000 8.00000</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<ms:msGeometry>
<gml:LineString gml:id="test_6181.3.1" srsName="urn:ogc:def:crs:EPSG::27700">
<gml:posList srsDimension="2">5.00000 2.00000 5.00000 8.00000 </gml:posList>
</gml:LineString>
</ms:msGeometry>
<ms:id>3</ms:id>
</ms:test_6181>
</wfs:member>
</wfs:FeatureCollection>

62 changes: 62 additions & 0 deletions msautotest/wxs/wfs_postgis_paging.map
@@ -0,0 +1,62 @@
#
# Test WFS paging with PostGIS
#
# REQUIRES: SUPPORTS=WFS INPUT=POSTGIS
#
# RUN_PARMS: wfs_postgis_issue_6181.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=test_6181&BBOX=0.75,0.75,9,9&COUNT=1" > [RESULT_DEVERSION]
# RUN_PARMS: wfs_postgis_issue_6181_startindex_1.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=test_6181&BBOX=0.75,0.75,9,9&COUNT=1&STARTINDEX=1" > [RESULT_DEVERSION]

MAP

NAME WFS_POSTGIS_PAGING
STATUS ON
SIZE 400 300
EXTENT 6 30 21 50
UNITS METERS
IMAGECOLOR 255 255 255

#
# Start of web interface definition
#

WEB

IMAGEPATH "tmp/"
IMAGEURL "/ms_tmp/"

METADATA
"wfs_title" "Test simple wfs"
"wfs_onlineresource" "http://localhost/path/to/wfs_simple?"
"wfs_srs" "EPSG:27700"
"wfs_enable_request" "*"
END
END

PROJECTION
"init=epsg:27700"
END

#
# Start of layer definitions
#

LAYER
NAME test_6181
INCLUDE "postgis.include"
DATA "the_geom from (select * from test_wfs_paging order by id) as foo using srid=27700 using unique id"
METADATA
"wfs_title" "test_6181"
"wfs_description" "test_6181"
"gml_include_items" "all"
"wfs_featureid" "id"
END
TYPE LINE
STATUS ON
PROJECTION
"init=epsg:27700"
END

END # Layer


END # Map File

0 comments on commit e2ef155

Please sign in to comment.