[mapserver-commits] r10828 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Mon Jan 3 00:55:07 EST 2011


Author: sdlime
Date: 2011-01-02 21:55:07 -0800 (Sun, 02 Jan 2011)
New Revision: 10828

Modified:
   trunk/mapserver/mapquery.c
   trunk/mapserver/mapserver.h
Log:
Whoops, forgot all about the query changes (new method) resulting from RFC 64. This change merges those and introduces the queryByFilter() method to SWIG-based MapScript. (#3613)

Modified: trunk/mapserver/mapquery.c
===================================================================
--- trunk/mapserver/mapquery.c	2011-01-03 05:54:54 UTC (rev 10827)
+++ trunk/mapserver/mapquery.c	2011-01-03 05:55:07 UTC (rev 10828)
@@ -55,6 +55,7 @@
   query->op = -1;
 
   query->item = query->str = NULL;
+  query->filter = NULL;
 
   return MS_SUCCESS;
 }
@@ -68,6 +69,10 @@
 
   if(query->item) free(query->item);
   if(query->str) free(query->str);
+  if(query->filter) {
+    freeExpression(query->filter);
+    free(query->filter);
+  }
 }
 
 /*
@@ -93,6 +98,9 @@
   case MS_QUERY_BY_ATTRIBUTE:
     status = msQueryByAttributes(map);
     break;
+  case MS_QUERY_BY_FILTER:
+    status = msQueryByFilter(map);
+    break;
   case MS_QUERY_BY_OPERATOR:
     status = msQueryByOperator(map);
     break;
@@ -685,6 +693,169 @@
   return(MS_FAILURE);
 }
 
+/*
+** Query using common expression syntax.
+*/
+int msQueryByFilter(mapObj *map)
+{
+  int l;
+  int start, stop=0;
+
+  layerObj *lp;
+
+  char status;
+  
+  expressionObj old_filter;
+
+  rectObj search_rect;
+
+  shapeObj shape;
+  
+  int nclasses = 0;
+  int *classgroup = NULL;
+
+  if(map->query.type != MS_QUERY_BY_FILTER) {
+    msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByFilter()");
+    return(MS_FAILURE);
+  }
+  if(!map->query.filter) { // TODO: check filter type too
+    msSetError(MS_QUERYERR, "Filter is not set.", "msQueryByFilter()");
+    return(MS_FAILURE);
+  }
+  
+  msInitShape(&shape);
+
+  if(map->query.layer < 0 || map->query.layer >= map->numlayers)
+    start = map->numlayers-1;
+  else
+    start = stop = map->query.layer;
+
+  for(l=start; l>=stop; l--) {
+    lp = (GET_LAYER(map, l));
+
+    /* conditions may have changed since this layer last drawn, so set 
+       layer->project true to recheck projection needs (Bug #673) */ 
+    lp->project = MS_TRUE; 
+
+    /* free any previous search results, do it now in case one of the next few tests fail */
+    if(lp->resultcache) {
+      if(lp->resultcache->results) free(lp->resultcache->results);
+      free(lp->resultcache);
+      lp->resultcache = NULL;
+    }
+
+    if(!msIsLayerQueryable(lp)) continue;
+    if(lp->status == MS_OFF) continue;
+    if(lp->type == MS_LAYER_RASTER) continue; /* ok to skip? */
+
+    if(map->scaledenom > 0) {
+      if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue;
+      if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue;
+    }
+
+    if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) {
+      if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue;
+      if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue;
+    }
+
+    initExpression(&old_filter);
+    msCopyExpression(&old_filter, &lp->filter); /* save existing filter */
+    if(msLayerSupportsCommonFilters(lp)) {
+      msCopyExpression(&lp->filter, map->query.filter); /* apply new filter */
+    }
+
+    status = msLayerOpen(lp);
+    if(status != MS_SUCCESS) goto query_error;
+
+    /* build item list, we want *all* items */
+    status = msLayerWhichItems(lp, MS_TRUE, NULL);
+    if(status != MS_SUCCESS) goto query_error;
+
+    if(!msLayerSupportsCommonFilters(lp)) {
+      freeExpression(&lp->filter); /* clear existing filter */
+      status = msTokenizeExpression(map->query.filter, lp->items, &(lp->numitems));
+      if(status != MS_SUCCESS) goto query_error;
+    }
+
+    search_rect = map->query.rect;
+#ifdef USE_PROJ
+    if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+      msProjectRect(&(map->projection), &(lp->projection), &search_rect); /* project the searchrect to source coords */
+    else
+      lp->project = MS_FALSE;
+#endif
+
+    status = msLayerWhichShapes(lp, search_rect);
+    if(status == MS_DONE) { /* no overlap */
+      msLayerClose(lp);
+      continue;
+    } else if(status != MS_SUCCESS) goto query_error;
+
+    lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */
+    initResultCache( lp->resultcache);
+
+    nclasses = 0;
+    classgroup = NULL;
+    if (lp->classgroup && lp->numclasses > 0)
+      classgroup = msAllocateValidClassGroups(lp, &nclasses);
+
+    while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */
+
+      if(!msLayerSupportsCommonFilters(lp)) { /* we have to apply the filter here instead of within the driver */
+	if(msEvalExpression(lp, &shape, map->query.filter, -1) != MS_TRUE) { /* next shape */
+          msFreeShape(&shape);
+	  continue;
+        }
+      }
+
+      shape.classindex = msShapeGetClass(lp, &shape, map->scaledenom, classgroup, nclasses);
+      if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */
+        msFreeShape(&shape);
+        continue;
+      }
+
+      if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */
+        msFreeShape(&shape);
+        continue;
+      }
+
+#ifdef USE_PROJ
+      if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+        msProjectShape(&(lp->projection), &(map->projection), &shape);
+      else
+        lp->project = MS_FALSE;
+#endif
+
+      addResult(lp->resultcache, &shape);
+      msFreeShape(&shape);
+    } /* next shape */
+
+    if(classgroup) msFree(classgroup);
+
+    msCopyExpression(&lp->filter, &old_filter); /* restore old filter */
+    freeExpression(&old_filter);
+
+    if(status != MS_DONE) goto query_error;
+    if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */
+
+  } /* next layer */
+
+  /* was anything found? */
+  for(l=start; l>=stop; l--) {    
+    if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0)
+      return MS_SUCCESS;
+  }
+
+  msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByFilter()"); 
+  return MS_FAILURE;
+
+ query_error:
+  msCopyExpression(&lp->filter, &old_filter); /* restore old filter */
+  freeExpression(&old_filter);
+  msLayerClose(lp);
+  return MS_FAILURE;
+}
+
 int msQueryByRect(mapObj *map) 
 {
   int l; /* counters */

Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h	2011-01-03 05:54:54 UTC (rev 10827)
+++ trunk/mapserver/mapserver.h	2011-01-03 05:55:07 UTC (rev 10828)
@@ -443,7 +443,7 @@
 #define MS_MULTIPLE 1
 
 enum MS_QUERY_MODE {MS_QUERY_SINGLE, MS_QUERY_MULTIPLE};
-enum MS_QUERY_TYPE {MS_QUERY_IS_NULL, MS_QUERY_BY_POINT, MS_QUERY_BY_RECT, MS_QUERY_BY_SHAPE, MS_QUERY_BY_ATTRIBUTE, MS_QUERY_BY_INDEX, MS_QUERY_BY_OPERATOR};
+enum MS_QUERY_TYPE {MS_QUERY_IS_NULL, MS_QUERY_BY_POINT, MS_QUERY_BY_RECT, MS_QUERY_BY_SHAPE, MS_QUERY_BY_ATTRIBUTE, MS_QUERY_BY_INDEX, MS_QUERY_BY_OPERATOR, MS_QUERY_BY_FILTER};
 
 enum MS_ALIGN_VALUE {MS_ALIGN_LEFT, MS_ALIGN_CENTER, MS_ALIGN_RIGHT}; 
 
@@ -733,6 +733,8 @@
   char *item; /* by attribute */
   char *str;
 
+  expressionObj *filter; /* by filter */
+
   int op; /* by GEOS operator */
 
   int slayer; /* selection layer, used for msQueryByFeatures() (note this is not a query mode per se) */
@@ -1682,8 +1684,8 @@
 /* Use this next, thread safe wrapper, function everywhere else */
 MS_DLL_EXPORT int msLoadExpressionString(expressionObj *exp, char *value);
 MS_DLL_EXPORT char *msGetExpressionString(expressionObj *exp);
+MS_DLL_EXPORT void initExpression(expressionObj *exp);
 MS_DLL_EXPORT void freeExpression(expressionObj *exp);
-MS_DLL_EXPORT char *msGetExpressionString(expressionObj *exp);
 
 MS_DLL_EXPORT void msLayerSubstituteString(layerObj *layer, const char *from, const char *to);
 MS_DLL_EXPORT void msApplyDefaultSubstitutions(mapObj *map);



More information about the mapserver-commits mailing list