Permalink
Browse files

WFS 2.0: implement stored queries; also fix maximum feature count sup…

…port for GetFeature involving filters or featureid
  • Loading branch information...
rouault committed Nov 6, 2013
1 parent fb393d6 commit 68be3a0ef0f1016a500e5349405575372547da98
Showing with 1,637 additions and 565 deletions.
  1. +2 −0 mapgml.c
  2. +75 −38 mapogcfilter.c
  3. +8 −6 mapogcfilter.h
  4. +18 −5 mapogcfiltercommon.c
  5. +1 −1 mapogcsld.c
  6. +2 −5 mapogcsos.c
  7. +12 −1 mapows.h
  8. +3 −1 mapowscommon.c
  9. +5 −0 mapowscommon.h
  10. +7 −3 mapquery.c
  11. +1 −4 mapwcs11.c
  12. +3 −4 mapwcs20.c
  13. +875 −490 mapwfs.c
  14. +1 −4 mapwfs11.c
  15. +623 −2 mapwfs20.c
  16. +1 −1 msautotest
View
@@ -1184,6 +1184,8 @@ static void msGMLWriteGroup(FILE *stream, gmlGroupObj *group, shapeObj *shape, g
else
msIO_fprintf(stream, "%s</%s>\n", tab, group->name);
+ msFree(itemtab);
+
return;
}
#endif
View
@@ -42,7 +42,7 @@
-int FLTIsNumeric(char *pszValue)
+int FLTIsNumeric(const char *pszValue)
{
if (pszValue != NULL && *pszValue != '\0' && !isspace(*pszValue)) {
/*the regex seems to have a problem on windows when mapserver is built using
@@ -78,7 +78,7 @@ int FLTIsNumeric(char *pszValue)
** Apply an expression to the layer's filter element.
**
*/
-int FLTApplyExpressionToLayer(layerObj *lp, char *pszExpression)
+int FLTApplyExpressionToLayer(layerObj *lp, const char *pszExpression)
{
char *pszFinalExpression=NULL, *pszBuffer = NULL;
/*char *escapedTextString=NULL;*/
@@ -143,7 +143,7 @@ int FLTApplyExpressionToLayer(layerObj *lp, char *pszExpression)
return MS_FALSE;
}
-char *FLTGetExpressionForValuesRanges(layerObj *lp, char *item, char *value, int forcecharcter)
+char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char *value, int forcecharcter)
{
int bIscharacter, bSqlLayer;
char *pszExpression = NULL, *pszEscapedStr=NULL, *pszTmpExpression=NULL;
@@ -665,7 +665,7 @@ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map,
/* Calling function should use FreeFilterEncodingNode function */
/* to free memeory. */
/************************************************************************/
-FilterEncodingNode *FLTParseFilterEncoding(char *szXMLString)
+FilterEncodingNode *FLTParseFilterEncoding(const char *szXMLString)
{
CPLXMLNode *psRoot = NULL, *psChild=NULL, *psFilter=NULL;
FilterEncodingNode *psFilterNode = NULL;
@@ -947,8 +947,6 @@ void FLTInsertElementInNode(FilterEncodingNode *psFilterNode,
CPLXMLNode *psFeatureIdNode = NULL;
const char *pszFeatureId=NULL;
char *pszFeatureIdList=NULL;
- char **tokens = NULL;
- int nTokens = 0;
if (psFilterNode && psXMLNode && psXMLNode->pszValue) {
psFilterNode->pszValue = msStrdup(psXMLNode->pszValue);
@@ -1455,15 +1453,7 @@ void FLTInsertElementInNode(FilterEncodingNode *psFilterNode,
if (pszFeatureIdList)
pszFeatureIdList = msStringConcatenate(pszFeatureIdList, ",");
- /*typname could be part of the value : INWATERA_1M.1234*/
- tokens = msStringSplit(pszFeatureId,'.', &nTokens);
- if (tokens && nTokens == 2)
- pszFeatureIdList = msStringConcatenate(pszFeatureIdList, tokens[1]);
- else
- pszFeatureIdList = msStringConcatenate(pszFeatureIdList, pszFeatureId);
-
- if (tokens)
- msFreeCharArray(tokens, nTokens);
+ pszFeatureIdList = msStringConcatenate(pszFeatureIdList, pszFeatureId);
}
psFeatureIdNode = psFeatureIdNode->psNext;
}
@@ -1863,7 +1853,6 @@ char *FLTGetMapserverExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
char szTmp[256];
char **tokens = NULL;
int nTokens = 0, i=0,bString=0;
- char *pszTmp;
if (!psFilterNode)
return NULL;
@@ -1897,15 +1886,18 @@ char *FLTGetMapserverExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens);
if (tokens && nTokens > 0) {
for (i=0; i<nTokens; i++) {
+ const char* pszId = tokens[i];
+ const char* pszDot = strchr(pszId, '.');
+ if( pszDot )
+ pszId = pszDot + 1;
if (i == 0) {
- pszTmp = tokens[0];
- if(FLTIsNumeric(pszTmp) == MS_FALSE)
+ if(FLTIsNumeric(pszId) == MS_FALSE)
bString = 1;
}
if (bString)
- snprintf(szTmp, sizeof(szTmp), "('[%s]' = '%s')" , pszAttribute, tokens[i]);
+ snprintf(szTmp, sizeof(szTmp), "('[%s]' = '%s')" , pszAttribute, pszId);
else
- snprintf(szTmp, sizeof(szTmp), "([%s] = %s)" , pszAttribute, tokens[i]);
+ snprintf(szTmp, sizeof(szTmp), "([%s] = %s)" , pszAttribute, pszId);
if (pszExpression != NULL)
pszExpression = msStringConcatenate(pszExpression, " OR ");
@@ -1989,13 +1981,18 @@ char *FLTGetSQLExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
if (tokens && nTokens > 0) {
for (i=0; i<nTokens; i++) {
char *pszEscapedStr = NULL;
- if (strlen(tokens[i]) <= 0)
+ const char* pszId = tokens[i];
+ const char* pszDot = strchr(pszId, '.');
+ if( pszDot )
+ pszId = pszDot + 1;
+
+ if (strlen(pszId) <= 0)
continue;
- if (FLTIsNumeric((tokens[i])) == MS_FALSE)
+ if (FLTIsNumeric(pszId) == MS_FALSE)
bString = 1;
- pszEscapedStr = msLayerEscapeSQLParam(lp, tokens[i]);
+ pszEscapedStr = msLayerEscapeSQLParam(lp, pszId);
if (bString)
snprintf(szTmp, sizeof(szTmp), "(%s = '%s')" , pszAttribute, pszEscapedStr);
else
@@ -2950,21 +2947,11 @@ int FLTHasSpatialFilter(FilterEncodingNode *psNode)
FilterEncodingNode *FLTCreateFeatureIdFilterEncoding(char *pszString)
{
FilterEncodingNode *psFilterNode = NULL;
- char **tokens = NULL;
- int nTokens = 0;
if (pszString) {
psFilterNode = FLTCreateFilterEncodingNode();
psFilterNode->eType = FILTER_NODE_TYPE_FEATUREID;
- /*split if tyname is included in the string*/
- tokens = msStringSplit(pszString,'.', &nTokens);
- if (tokens && nTokens == 2)
- psFilterNode->pszValue = msStrdup(tokens[1]);
- else
- psFilterNode->pszValue = msStrdup(pszString);
-
- if (tokens)
- msFreeCharArray(tokens, nTokens);
+ psFilterNode->pszValue = msStrdup(pszString);
return psFilterNode;
}
return NULL;
@@ -3267,12 +3254,12 @@ static void FLTRemoveGroupName(FilterEncodingNode *psFilterNode,
}
/************************************************************************/
-/* FLTPreParseFilterForAlias */
+/* FLTPreParseFilterForAliasAndGroup */
/* */
-/* Utility function to replace aliased' attributes with their */
-/* real name. */
+/* Utility function to replace aliased' and grouped attributes */
+/* with their internal name. */
/************************************************************************/
-void FLTPreParseFilterForAlias(FilterEncodingNode *psFilterNode,
+void FLTPreParseFilterForAliasAndGroup(FilterEncodingNode *psFilterNode,
mapObj *map, int i, const char *namespaces)
{
layerObj *lp=NULL;
@@ -3317,6 +3304,56 @@ void FLTPreParseFilterForAlias(FilterEncodingNode *psFilterNode,
#endif
}
+/************************************************************************/
+/* FLTCheckFeatureIdFilters */
+/* */
+/* Check that FeatureId filters match features in the active */
+/* layer. */
+/************************************************************************/
+int FLTCheckFeatureIdFilters(FilterEncodingNode *psFilterNode,
+ mapObj *map, int i)
+{
+ int status = MS_SUCCESS;
+
+ if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID)
+ {
+ char** tokens;
+ int nTokens = 0;
+ layerObj* lp;
+ int j;
+
+ lp = GET_LAYER(map, i);
+ tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens);
+ for (j=0; j<nTokens; j++) {
+ const char* pszId = tokens[j];
+ const char* pszDot = strchr(pszId, '.');
+ if( pszDot )
+ {
+ if( pszDot - pszId != strlen(lp->name) ||
+ strncasecmp(pszId, lp->name, strlen(lp->name)) != 0 )
+ {
+ msSetError(MS_MISCERR, "Feature id %s not consistant with feature type name %s.",
+ "FLTPreParseFilterForAlias()", pszId, lp->name);
+ status = MS_FAILURE;
+ break;
+ }
+ }
+ }
+ msFreeCharArray(tokens, nTokens);
+ }
+
+ if (psFilterNode->psLeftNode)
+ {
+ status = FLTCheckFeatureIdFilters(psFilterNode->psLeftNode, map, i);
+ if( status == MS_SUCCESS )
+ {
+ if (psFilterNode->psRightNode)
+ status = FLTCheckFeatureIdFilters(psFilterNode->psRightNode, map, i);
+ }
+ }
+ return status;
+}
+
#ifdef USE_LIBXML2
View
@@ -32,9 +32,9 @@
#include "mapserver.h"
/*dont need ogr for these functikons*/
-MS_DLL_EXPORT int FLTIsNumeric(char *pszValue);
-MS_DLL_EXPORT int FLTApplyExpressionToLayer(layerObj *lp, char *pszExpression);
-MS_DLL_EXPORT char *FLTGetExpressionForValuesRanges(layerObj *lp, char *item, char *value, int forcecharcter);
+MS_DLL_EXPORT int FLTIsNumeric(const char *pszValue);
+MS_DLL_EXPORT int FLTApplyExpressionToLayer(layerObj *lp, const char *pszExpression);
+MS_DLL_EXPORT char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char *value, int forcecharcter);
#ifdef USE_OGR
@@ -58,7 +58,7 @@ typedef struct {
/* -------------------------------------------------------------------- */
/* prototypes. */
/* -------------------------------------------------------------------- */
-MS_DLL_EXPORT FilterEncodingNode *FLTParseFilterEncoding(char *szXMLString);
+MS_DLL_EXPORT FilterEncodingNode *FLTParseFilterEncoding(const char *szXMLString);
MS_DLL_EXPORT FilterEncodingNode *FLTCreateFilterEncodingNode(void);
MS_DLL_EXPORT int FLTApplyFilterToLayer(FilterEncodingNode *psNode, mapObj *map,
int iLayerIndex);
@@ -137,8 +137,10 @@ MS_DLL_EXPORT xmlNodePtr FLTGetCapabilities(xmlNsPtr psNsParent, xmlNsPtr psNsOg
void FLTDoAxisSwappingIfNecessary(FilterEncodingNode *psFilterNode, int bDefaultSRSNeedsAxisSwapping);
-void FLTPreParseFilterForAlias(FilterEncodingNode *psFilterNode,
- mapObj *map, int i, const char *namespaces);
+void FLTPreParseFilterForAliasAndGroup(FilterEncodingNode *psFilterNode,
+ mapObj *map, int i, const char *namespaces);
+int FLTCheckFeatureIdFilters(FilterEncodingNode *psFilterNode,
+ mapObj *map, int i);
#endif
View
@@ -565,21 +565,25 @@ char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj
for (i=0; i<nTokens; i++) {
char *pszTmp = NULL;
int bufferSize = 0;
+ const char* pszId = tokens[i];
+ const char* pszDot = strchr(pszId, '.');
+ if( pszDot )
+ pszId = pszDot + 1;
if (i == 0) {
- if(FLTIsNumeric(tokens[0]) == MS_FALSE)
+ if(FLTIsNumeric(pszId) == MS_FALSE)
bString = 1;
}
if (bString) {
- bufferSize = 11+strlen(tokens[i])+strlen(pszAttribute)+1;
+ bufferSize = 11+strlen(pszId)+strlen(pszAttribute)+1;
pszTmp = (char *)msSmallMalloc(bufferSize);
- snprintf(pszTmp, bufferSize, "(\"[%s]\" ==\"%s\")" , pszAttribute, tokens[i]);
+ snprintf(pszTmp, bufferSize, "(\"[%s]\" ==\"%s\")" , pszAttribute, pszId);
} else {
- bufferSize = 8+strlen(tokens[i])+strlen(pszAttribute)+1;
+ bufferSize = 8+strlen(pszId)+strlen(pszAttribute)+1;
pszTmp = (char *)msSmallMalloc(bufferSize);
- snprintf(pszTmp, bufferSize, "([%s] == %s)" , pszAttribute, tokens[i]);
+ snprintf(pszTmp, bufferSize, "([%s] == %s)" , pszAttribute, pszId);
}
if (pszExpression != NULL)
@@ -636,8 +640,17 @@ char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, char *pszExpression)
{
int retval;
+ int save_startindex;
+ int save_maxfeatures;
+ int save_only_cache_result_count;
+ save_startindex = map->query.startindex;
+ save_maxfeatures = map->query.maxfeatures;
+ save_only_cache_result_count = map->query.only_cache_result_count;
msInitQuery(&(map->query));
+ map->query.startindex = save_startindex;
+ map->query.maxfeatures = save_maxfeatures;
+ map->query.only_cache_result_count = save_only_cache_result_count;
map->query.type = MS_QUERY_BY_FILTER;
View
@@ -837,7 +837,7 @@ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer)
msInsertHashTable(&psLayer->metadata, key,
msLookupHashTable(&psCurrentLayer->metadata, key));
}
- FLTPreParseFilterForAlias(psNode, psLayer->map, j, "G");
+ FLTPreParseFilterForAliasAndGroup(psNode, psLayer->map, j, "G");
}
pszExpression = FLTGetCommonExpression(psNode, psLayer);
View
@@ -80,7 +80,6 @@ static int msSOSException(mapObj *map, char *locator, char *exceptionCode)
{
int size = 0;
char *errorString = NULL;
- char *errorMessage = NULL;
char *schemasLocation = NULL;
xmlDocPtr psDoc = NULL;
@@ -91,12 +90,11 @@ static int msSOSException(mapObj *map, char *locator, char *exceptionCode)
psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows");
errorString = msGetErrorString("\n");
- errorMessage = msEncodeHTMLEntities(errorString);
schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
psDoc = xmlNewDoc(BAD_CAST "1.0");
- psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_1_0, schemasLocation, pszSOSVersion, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage);
+ psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_1_0, schemasLocation, pszSOSVersion, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorString);
xmlDocSetRootElement(psDoc, psRootNode);
@@ -111,7 +109,6 @@ static int msSOSException(mapObj *map, char *locator, char *exceptionCode)
/*free buffer and the document */
free(errorString);
- free(errorMessage);
free(schemasLocation);
xmlFree(buffer);
xmlFreeDoc(psDoc);
@@ -2173,7 +2170,7 @@ this request. Check sos/ows_enable_request settings.", "msSOSGetObservation()",
lp = GET_LAYER(map, i);
if (lp->status == MS_ON) {
/* preparse parser so that alias for fields can be used */
- FLTPreParseFilterForAlias(psFilterNode, map, i, "S");
+ FLTPreParseFilterForAliasAndGroup(psFilterNode, map, i, "S");
/* validate that the property names used are valid
(there is a corresponding layer attribute) */
if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) {
View
@@ -64,8 +64,11 @@ typedef struct {
char *pszAcceptVersions;
char *pszSections;
char *pszSortBy; /* Not implemented yet */
- char *pszLanguage;
+ char *pszLanguage; /* Inspire extension */
char *pszValueReference; /* For GetValueReference */
+ char *pszStoredQueryId; /* For DescribeStoredQueries */
+ int countGetFeatureById; /* Number of urn:ogc:def:query:OGC-WFS::GetFeatureById GetFeature requests */
+ int bHasPostStoredQuery; /* TRUE if a XML GetFeature StoredQuery is present */
} wfsParamsObj;
/*
@@ -477,6 +480,14 @@ int msWFSException20(mapObj *map, const char *locator,
const char *exceptionCode);
int msWFSGetCapabilities20(mapObj *map, wfsParamsObj *params,
cgiRequestObj *req, owsRequestObj *ows_request);
+int msWFSListStoredQueries20(mapObj *map, wfsParamsObj *params,
+ cgiRequestObj *req, owsRequestObj *ows_request);
+int msWFSDescribeStoredQueries20(mapObj *map, wfsParamsObj *params,
+ cgiRequestObj *req, owsRequestObj *ows_request);
+char* msWFSGetResolvedStoredQuery20(mapObj *map,
+ wfsParamsObj *wfsparams,
+ const char* id,
+ hashTableObj* hashTable);
#endif
View
@@ -489,7 +489,9 @@ xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const c
}
if (ExceptionText != NULL) {
- xmlNewChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST ExceptionText);
+ char* errorMessage = msEncodeHTMLEntities(ExceptionText);
+ xmlNewChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST errorMessage);
+ msFree(errorMessage);
}
free(xsi_schemaLocation);
Oops, something went wrong.

0 comments on commit 68be3a0

Please sign in to comment.