Skip to content

Commit

Permalink
OGR: add a "wfs_use_default_extent_for_getfeature" "yes" LAYER.METADATA
Browse files Browse the repository at this point in the history
When this is defined and a WFS request has no BBOX filter, do not use the MAP.EXTENT
as a default BBX filter, which can hurt performance and is useless if MAP.EXTENT
covers the whole layer.

CREDITS: Funded by:
Regione Toscana - Settore Sistema Informativo Territoriale ed
Ambientale (CIG: 644544015A)
  • Loading branch information
rouault committed Dec 1, 2016
1 parent 829eef9 commit 45037eb
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 9 deletions.
14 changes: 12 additions & 2 deletions mapogcfilter.c
Expand Up @@ -667,9 +667,19 @@ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map,

pszExpression = FLTGetCommonExpression(psNode, lp);
if (pszExpression) {
const char* pszUseDefaultExtent;
FilterEncodingNode* psTopBBOX;
rectObj rect = map->extent;

pszUseDefaultExtent = msOWSLookupMetadata(&(lp->metadata), "F",
"use_default_extent_for_getfeature");
if( pszUseDefaultExtent && CSLTestBoolean(pszUseDefaultExtent) &&
lp->connectiontype == MS_OGR )
{
const rectObj rectInvalid = MS_INIT_INVALID_RECT;
rect = rectInvalid;
}

psTopBBOX = FLTGetTopBBOX(psNode);
if( psTopBBOX )
{
Expand Down Expand Up @@ -706,9 +716,9 @@ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map,
if(map->debug == MS_DEBUGLEVEL_VVV)
{
if( pszExpression )
msDebug("FLTLayerApplyPlainFilterToLayer(): %s, rect=%f,%f,%f,%f\n", pszExpression, rect.minx, rect.miny, rect.maxx, rect.maxy);
msDebug("FLTLayerApplyPlainFilterToLayer(): %s, rect=%.15g,%.15g,%.15g,%.15g\n", pszExpression, rect.minx, rect.miny, rect.maxx, rect.maxy);
else
msDebug("FLTLayerApplyPlainFilterToLayer(): rect=%f,%f,%f,%f\n", rect.minx, rect.miny, rect.maxx, rect.maxy);
msDebug("FLTLayerApplyPlainFilterToLayer(): rect=%.15g,%.15g,%.15g,%.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy);
}

status = FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex,
Expand Down
12 changes: 8 additions & 4 deletions mapogr.cpp
Expand Up @@ -2092,6 +2092,8 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
}

char *select = (psInfo->pszSelect) ? msStrdup(psInfo->pszSelect) : NULL;
const rectObj rectInvalid = MS_INIT_INVALID_RECT;
bool bIsValidRect = memcmp(&rect, &rectInvalid, sizeof(rect)) != 0;

// we'll go strictly two possible ways:
// 1) GetLayer + SetFilter
Expand Down Expand Up @@ -2192,13 +2194,15 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
rect.miny = MAX(psInfo->rect.miny, rect.miny);
rect.maxx = MIN(psInfo->rect.maxx, rect.maxx);
rect.maxy = MIN(psInfo->rect.maxy, rect.maxy);
bIsValidRect = true;
}
psInfo->rect = rect;

bool bSpatialiteAddOrderByFID = false;

if( psInfo->dialect && EQUAL(psInfo->dialect, "Spatialite") &&
psInfo->pszMainTableName != NULL && psInfo->bHasSpatialIndex )
psInfo->pszMainTableName != NULL && psInfo->bHasSpatialIndex &&
bIsValidRect )
{
select = msStringConcatenate(select, " JOIN ");

Expand Down Expand Up @@ -2255,7 +2259,7 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps

bool bOffsetAlreadyAdded = false;
// use spatial index
if (psInfo->dialect) {
if (psInfo->dialect && bIsValidRect ) {
if (EQUAL(psInfo->dialect, "PostgreSQL")) {
if (filter) filter = msStringConcatenate(filter, " AND");
const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field??
Expand Down Expand Up @@ -2391,7 +2395,7 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps

ACQUIRE_OGR_LOCK;

if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone ) {
if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone && bIsValidRect ) {
if (rect.minx == rect.maxx && rect.miny == rect.maxy) {
OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint );

Expand Down Expand Up @@ -2423,7 +2427,7 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
psInfo->rect = rect;

if (layer->debug >= MS_DEBUGLEVEL_VVV)
msDebug("msOGRFileWhichShapes: Setting spatial filter to %f %f %f %f\n", rect.minx, rect.miny, rect.maxx, rect.maxy );
msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy );

/* ------------------------------------------------------------------
* Apply an attribute filter if we have one prefixed with a WHERE
Expand Down
4 changes: 3 additions & 1 deletion mapquery.c
Expand Up @@ -670,6 +670,7 @@ int msQueryByFilter(mapObj *map)
expressionObj old_filter;

rectObj search_rect;
const rectObj invalid_rect = MS_INIT_INVALID_RECT;

shapeObj shape;

Expand Down Expand Up @@ -761,9 +762,10 @@ int msQueryByFilter(mapObj *map)
if(status != MS_SUCCESS) goto query_error;

search_rect = map->query.rect;

#ifdef USE_PROJ
lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection));
if(lp->project)
if(lp->project && memcmp( &search_rect, &invalid_rect, sizeof(search_rect) ) != 0 )
msProjectRect(&(map->projection), &(lp->projection), &search_rect); /* project the searchrect to source coords */
#endif

Expand Down
4 changes: 3 additions & 1 deletion mapserver.h
Expand Up @@ -474,7 +474,9 @@ extern "C" {
#define MS_IS_VALID_ARRAY_INDEX(index, size) ((index<0 || index>=size)?MS_FALSE:MS_TRUE)

#define MS_CONVERT_UNIT(src_unit, dst_unit, value) (value * msInchesPerUnit(src_unit,0) / msInchesPerUnit(dst_unit,0))


#define MS_INIT_INVALID_RECT { -1e300, -1e300, 1e300, 1e300 }

#endif

/* General enumerated types - needed by scripts */
Expand Down
12 changes: 11 additions & 1 deletion mapwfs.c
Expand Up @@ -37,6 +37,7 @@
/* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */
#include "cpl_minixml.h"
#include "cpl_conv.h"
#include "cpl_string.h"

#include "mapogcfilter.h"
#include "mapowscommon.h"
Expand Down Expand Up @@ -2138,6 +2139,7 @@ static int msWFSRunBasicGetFeature(mapObj* map,
const char *pszMapSRS=NULL, *pszLayerSRS=NULL;
rectObj ext;
int status;
const char* pszUseDefaultExtent;

map->query.type = MS_QUERY_BY_RECT; /* setup the query */
map->query.mode = MS_QUERY_MULTIPLE;
Expand All @@ -2149,7 +2151,15 @@ static int msWFSRunBasicGetFeature(mapObj* map,
if(!paramsObj->pszSrs)
pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_TRUE);

if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) {
pszUseDefaultExtent = msOWSLookupMetadata(&(lp->metadata), "F",
"use_default_extent_for_getfeature");
if( pszUseDefaultExtent && CSLTestBoolean(pszUseDefaultExtent) &&
lp->connectiontype == MS_OGR )
{
const rectObj rectInvalid = MS_INIT_INVALID_RECT;
map->query.rect = rectInvalid;
}
else if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) {

/* For a single point layer, to avoid numerical precision issues */
/* when reprojection is involved */
Expand Down
@@ -0,0 +1,38 @@
Content-Type: text/xml; charset=UTF-8

<?xml version='1.0' encoding="UTF-8" ?>
<wfs:FeatureCollection
xmlns:ms="http://mapserver.gis.umn.edu/mapserver"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:gml="http://www.opengis.net/gml"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd
http://mapserver.gis.umn.edu/mapserver http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=towns_disable_default_extent_for_getfeature&amp;OUTPUTFORMAT=XMLSCHEMA">
<gml:boundedBy>
<gml:Box srsName="EPSG:32632">
<gml:coordinates>643513.360000,4896928.190000 643513.360000,4896928.190000</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<!-- WARNING: FeatureId item 'ID' not found in typename 'towns_disable_default_extent_for_getfeature'. -->
<gml:featureMember>
<ms:towns_disable_default_extent_for_getfeature>
<gml:boundedBy>
<gml:Box srsName="EPSG:32632">
<gml:coordinates>643513.360000,4896928.190000 643513.360000,4896928.190000</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<ms:msGeometry>
<gml:Point srsName="EPSG:32632">
<gml:coordinates>643513.360000,4896928.190000</gml:coordinates>
</gml:Point>
</ms:msGeometry>
<ms:name>Fanano</ms:name>
<ms:peoples>2910</ms:peoples>
<ms:localcounc>1</ms:localcounc>
<ms:county>0</ms:county>
<ms:region>0</ms:region>
</ms:towns_disable_default_extent_for_getfeature>
</gml:featureMember>
</wfs:FeatureCollection>

38 changes: 38 additions & 0 deletions msautotest/wxs/expected/wfs_ogr_native_sql_42.xml
@@ -0,0 +1,38 @@
Content-Type: text/xml; subtype=gml/2.1.2; 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"
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=towns_disable_default_extent_for_getfeature&amp;OUTPUTFORMAT=XMLSCHEMA http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd"
timeStamp="" numberMatched="unknown" numberReturned="1"
next="http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=2.0.0&amp;REQUEST=GetFeature&amp;TYPENAME=towns_disable_default_extent_for_getfeature&amp;OUTPUTFORMAT=GML2&amp;COUNT=1&amp;STARTINDEX=1">
<wfs:boundedBy>
<gml:Box srsName="urn:ogc:def:crs:EPSG::32632">
<gml:coordinates>672130.72000,4902785.47000 672130.72000,4902785.47000</gml:coordinates>
</gml:Box>
</wfs:boundedBy>
<!-- WARNING: FeatureId item 'ID' not found in typename 'towns_disable_default_extent_for_getfeature'. -->
<wfs:member>
<ms:towns_disable_default_extent_for_getfeature>
<gml:boundedBy>
<gml:Box srsName="urn:ogc:def:crs:EPSG::32632">
<gml:coordinates>672130.72000,4902785.47000 672130.72000,4902785.47000</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<ms:msGeometry>
<gml:Point srsName="urn:ogc:def:crs:EPSG::32632">
<gml:coordinates>672130.72000,4902785.47000</gml:coordinates>
</gml:Point>
</ms:msGeometry>
<ms:name>Grizzana Morandi</ms:name>
<ms:peoples>3694</ms:peoples>
<ms:localcounc>1</ms:localcounc>
<ms:county>0</ms:county>
<ms:region>0</ms:region>
</ms:towns_disable_default_extent_for_getfeature>
</wfs:member>
</wfs:FeatureCollection>

28 changes: 28 additions & 0 deletions msautotest/wxs/wfs_ogr_native_sql.map
Expand Up @@ -20,6 +20,9 @@
#
# RUN_PARMS: wfs_ogr_native_sql_05.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><PropertyIsEqualTo matchCase="false"><PropertyName>name</PropertyName><Literal>fanano</Literal></PropertyIsEqualTo></Filter>" > [RESULT]
# RUN_PARMS: wfs_ogr_native_sql_06.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><PropertyIsEqualTo><PropertyName>name</PropertyName><Literal>Fanano</Literal></PropertyIsEqualTo></Filter>" > [RESULT]

# RUN_PARMS: wfs_ogr_native_sql_06_disable_default_extent_for_getfeature.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns_disable_default_extent_for_getfeature&OUTPUTFORMAT=GML2&FILTER=<Filter><PropertyIsEqualTo><PropertyName>name</PropertyName><Literal>Fanano</Literal></PropertyIsEqualTo></Filter>" > [RESULT]

# RUN_PARMS: wfs_ogr_native_sql_07.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><PropertyIsEqualTo matchCase="false"><PropertyName>name</PropertyName><Literal>fanano</Literal></PropertyIsEqualTo></Filter>" > [RESULT]
# RUN_PARMS: wfs_ogr_native_sql_08.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><PropertyIsNotEqualTo><PropertyName>name</PropertyName><Literal>Fanano</Literal></PropertyIsNotEqualTo></Filter>" > [RESULT]
#
Expand Down Expand Up @@ -90,6 +93,8 @@
# SortBy
# RUN_PARMS: wfs_ogr_native_sql_41.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><PropertyIsNotEqualTo><PropertyName>name</PropertyName><Literal>Fanano</Literal></PropertyIsNotEqualTo></Filter>&SORTBY=name" > [RESULT_DEVERSION]

# RUN_PARMS: wfs_ogr_native_sql_42.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAME=towns_disable_default_extent_for_getfeature&OUTPUTFORMAT=GML2&COUNT=1" > [RESULT_DEVERSION]

MAP

NAME WFS_OGR_NATIVE_SQL_TEST
Expand Down Expand Up @@ -146,6 +151,29 @@ LAYER
TEMPLATE "wfs_ogr_native_sql.map"
END # Layer

LAYER
NAME towns_disable_default_extent_for_getfeature
DATA towns
CONNECTIONTYPE OGR
CONNECTION "./data/db.sqlite"
PROCESSING "NATIVE_SQL=YES"
METADATA
"ows_title" "towns_disable_default_extent_for_getfeature"
"wfs_featureid" "ID"
"gml_include_items" "all"
"gml_types" "auto"
"wfs_getfeature_formatlist" "ogrgml"
"wfs_use_default_extent_for_getfeature" "yes"
END
TYPE POINT
STATUS ON
PROJECTION
"init=epsg:32632"
END

TEMPLATE "wfs_ogr_native_sql.map"
END # Layer

LAYER
NAME towns_spatial_index_disabled
DATA towns
Expand Down

0 comments on commit 45037eb

Please sign in to comment.