Permalink
Browse files

OGR: add a "wfs_use_default_extent_for_getfeature" "yes" LAYER.METADATA

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...
1 parent 829eef9 commit 45037eb0601e2f48ae548e2cd28b29b429644870 @rouault rouault committed Dec 1, 2016
View
@@ -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 )
{
@@ -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,
View
@@ -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
@@ -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 ");
@@ -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??
@@ -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 );
@@ -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
View
@@ -670,6 +670,7 @@ int msQueryByFilter(mapObj *map)
expressionObj old_filter;
rectObj search_rect;
+ const rectObj invalid_rect = MS_INIT_INVALID_RECT;
shapeObj shape;
@@ -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
View
@@ -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 */
View
@@ -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"
@@ -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;
@@ -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 */
@@ -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>
+
@@ -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>
+
@@ -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]
#
@@ -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
@@ -147,6 +152,29 @@ LAYER
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
CONNECTIONTYPE OGR

0 comments on commit 45037eb

Please sign in to comment.