[mapserver-commits] r9668 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Tue Jan 5 09:54:35 EST 2010


Author: assefa
Date: 2010-01-05 09:54:33 -0500 (Tue, 05 Jan 2010)
New Revision: 9668

Modified:
   trunk/mapserver/mapfile.c
   trunk/mapserver/maplayer.c
   trunk/mapserver/maporaclespatial.c
   trunk/mapserver/mapserver.h
   trunk/mapserver/mapwfs.c
Log:
wfs pagination support #2799

Modified: trunk/mapserver/mapfile.c
===================================================================
--- trunk/mapserver/mapfile.c	2010-01-05 11:56:00 UTC (rev 9667)
+++ trunk/mapserver/mapfile.c	2010-01-05 14:54:33 UTC (rev 9668)
@@ -2795,6 +2795,7 @@
   layer->sizeunits = MS_PIXELS;
 
   layer->maxfeatures = -1; /* no quota */
+  layer->startindex = -1; /*used for pagination*/
   
   layer->template = layer->header = layer->footer = NULL;
 

Modified: trunk/mapserver/maplayer.c
===================================================================
--- trunk/mapserver/maplayer.c	2010-01-05 11:56:00 UTC (rev 9667)
+++ trunk/mapserver/maplayer.c	2010-01-05 14:54:33 UTC (rev 9668)
@@ -977,6 +977,14 @@
 #endif
 }
 
+int msLayerSupportsPaging(layerObj *layer)
+{
+    if (layer && layer->connectiontype == MS_ORACLESPATIAL)
+      return MS_TRUE;
+
+    return MS_FALSE;
+}
+
 int 
 msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, 
                                int iLayerIndex, int bOnlySpatialFilter)

Modified: trunk/mapserver/maporaclespatial.c
===================================================================
--- trunk/mapserver/maporaclespatial.c	2010-01-05 11:56:00 UTC (rev 9667)
+++ trunk/mapserver/maporaclespatial.c	2010-01-05 14:54:33 UTC (rev 9668)
@@ -1019,18 +1019,8 @@
 
     sprintf( query_str2 + strlen(query_str2), " %s FROM %s", geom_column_name, table_name);
 
-    osFilteritem(layer, FUNCTION_NONE, query_str2, 1);
+    osFilteritem(layer, FUNCTION_NONE, query_str2, 1);    
 
-    if (layer->maxfeatures > 0)
-    {
-        if(layer->filter.string != NULL)
-           sprintf (query_str2 + strlen(query_str2), " AND ");
-        else
-           sprintf (query_str2 + strlen(query_str2), " WHERE ");
-
-        sprintf( query_str2 + strlen(query_str2), " ROWNUM <= %d ", layer->maxfeatures);
-    }
-
     sprintf( query_str, "SELECT SDO_AGGR_MBR(%s) AS GEOM from %s)", geom_column_name, query_str2);
 
      if (layer->debug)
@@ -1049,17 +1039,8 @@
     sprintf( query_str2 + strlen(query_str2), " %s FROM %s", geom_column_name, table_name);
 
     osFilteritem(layer, FUNCTION_NONE, query_str2, 1);
-    if (layer->maxfeatures > 0)
-    {
-        if(layer->filter.string != NULL)
-           sprintf (query_str2 + strlen(query_str2), " AND ");
-        else
-          sprintf (query_str2 + strlen(query_str2), " WHERE ");
-
-        sprintf( query_str2 + strlen(query_str2), " ROWNUM <= %d ", layer->maxfeatures);
-            
-    }
     
+    
     sprintf( query_str, "SELECT SDO_GEOM.SDO_CONVEXHULL(%s, %f) AS GEOM from %s)", geom_column_name, TOLERANCE, query_str2);
 }
 
@@ -1920,6 +1901,8 @@
     int version = 0;
     int existunique = MS_FALSE;
     char query_str[6000];
+    char query_str2[256];
+    char *tmp_str=NULL, *tmp1_str=NULL;
     char *table_name;
     char geom_column_name[100], unique[100], srid[100];
     OCIDefine *adtp = NULL;
@@ -1977,6 +1960,7 @@
     if (strcmp(srid,"NULL") == 0)
         strcpy(srid,"-1");
 
+
     /* Check if the unique field is already in the items list */
     for( i=0; i < layer->numitems; ++i ) {
         if (strcmp(unique, layer->items[i])==0) {
@@ -1984,11 +1968,22 @@
             break;
         }
     }
-        
+       
+     /*always select rownum to allow paging*/
     if (existunique)
-        sprintf( query_str, "SELECT ");
+    {
+        if (strcasecmp(unique, "rownum") == 0)
+          sprintf( query_str, "SELECT");
+        else
+          sprintf( query_str, "SELECT %s,", "rownum");
+    }
     else
-        sprintf( query_str, "SELECT %s, ", unique );
+    {
+        if (strcasecmp(unique, "rownum") == 0)
+          sprintf( query_str, "SELECT %s,", unique );
+        else
+          sprintf( query_str, "SELECT %s, %s,", "rownum", unique );
+    }
 
     /* allocate enough space for items */
     if (layer->numitems >= 0)
@@ -2013,14 +2008,17 @@
 
     /* define SQL query */
     for( i=0; i < layer->numitems; ++i )
+    {
         sprintf( query_str + strlen(query_str), "%s, ", layer->items[i] );
-
+    }
     sprintf( query_str + strlen(query_str), "%s FROM %s", geom_column_name, table_name );
 
     osFilteritem(layer, function, query_str, 1);
 
-    if (layer->maxfeatures > 0)
+    if (layer->maxfeatures > 0 && layer->startindex < 0)
     {
+       if (function == FUNCTION_NONE)
+         sprintf( query_str + strlen(query_str), "%s"," WHERE ");
         sprintf( query_str + strlen(query_str), " ROWNUM<=%d ", layer->maxfeatures);
         if (function != FUNCTION_NONE)
           sprintf (query_str + strlen(query_str), " AND ");
@@ -2032,6 +2030,34 @@
     else
         osNoGeodeticData(function, version, query_str, geom_column_name, srid, rect);
 
+
+    /*assuming startindex starts at 1*/
+    if (layer->startindex > 0)
+     {
+       tmp1_str = strdup("SELECT * from (SELECT atmp.*, ROWNUM rnum from (");
+       tmp_str = msStringConcatenate(tmp_str,  tmp1_str);
+       msFree(tmp1_str);
+       tmp_str = msStringConcatenate(tmp_str, query_str);
+       /*oder by rowid does not seem to work with function using the spatial filter, at least
+         on layers loaded using ogr in a 11g database*/
+       if (function == FUNCTION_NONE  || function == FUNCTION_RELATE || function == FUNCTION_GEOMRELATE)
+         tmp1_str = strdup( "order by rowid");
+       else
+         tmp1_str = strdup("");
+
+       if (layer->maxfeatures > 0)
+         sprintf(query_str2,  " %s) atmp where ROWNUM<=%d) where rnum >=%d",   tmp1_str, 
+                 layer->maxfeatures+layer->startindex-1,  layer->startindex);
+       else
+         sprintf( query_str2,  " %s) atmp) where rnum >=%d",  tmp1_str, layer->startindex);
+       msFree(tmp1_str);
+       
+       tmp_str = msStringConcatenate(tmp_str,  query_str2);
+       sprintf (query_str, "%s", tmp_str);
+       msFree(tmp_str);
+     } 
+    
+    
     if (layer->debug)
         msDebug("msOracleSpatialLayerWhichShapes. Using this Sql to retrieve the data: %s\n", query_str);
         
@@ -2069,7 +2095,7 @@
         
   /* do the actual binding */      
 
- if (success) {
+ if (success && function != FUNCTION_NONE) {
      success = TRY( hand,
             /* bind in srid */
             OCIBindByName( sthand->stmthp, &bnd2p,  hand->errhp, (text *) ":srid", strlen(":srid"),(ub1 *) srid,  strlen(srid)+1, SQLT_STR, 

Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h	2010-01-05 11:56:00 UTC (rev 9667)
+++ trunk/mapserver/mapserver.h	2010-01-05 14:54:33 UTC (rev 9668)
@@ -1229,7 +1229,8 @@
 
   int sizeunits; /* applies to all classes */
 
-  int maxfeatures;
+  int maxfeatures;      
+  int startindex;
 
   colorObj offsite; /* transparent pixel value for raster images */
 
@@ -1958,6 +1959,8 @@
 /* maplayer.c */
 MS_DLL_EXPORT int msLayerGetNumFeatures(layerObj *layer);
 
+MS_DLL_EXPORT int msLayerSupportsPaging(layerObj *layer);
+
 /* These are special because SWF is using these */
 int msOGRLayerNextShape(layerObj *layer, shapeObj *shape);
 int msOGRLayerGetItems(layerObj *layer);

Modified: trunk/mapserver/mapwfs.c
===================================================================
--- trunk/mapserver/mapwfs.c	2010-01-05 11:56:00 UTC (rev 9667)
+++ trunk/mapserver/mapwfs.c	2010-01-05 14:54:33 UTC (rev 9668)
@@ -1026,6 +1026,8 @@
   char **papszPropertyName = NULL;
   int nPropertyNames = 0;
   const char *pszMapSRS = NULL;
+  int nQueriedLayers=0;
+  layerObj *lpQueried=NULL;
 
   /* Default filter is map extents */
   bbox = map->extent;
@@ -1297,38 +1299,65 @@
       maxfeatures = paramsObj->nMaxFeatures;
   }
 
-  if (paramsObj->nStartIndex >= 0)
+  nQueriedLayers=0;
+  for(j=0; j<map->numlayers; j++) 
+  {
+      layerObj *lp;
+      lp = GET_LAYER(map, j);
+      if (lp->status == MS_ON)
+      {
+          lpQueried = GET_LAYER(map, j);
+          nQueriedLayers++;
+      }
+  }
+  
+  if (paramsObj->nStartIndex > 0)
     startindex = paramsObj->nStartIndex;
 
-  /* set the max features to each layer that is available. Note that maxfeatures is
-     the total number of features that is returned and setting this for each layer
-     is not entirely exact (it is only exact if we query one layer) but overall it
-     should be better */
-  if (maxfeatures > 0)
+
+  /*maxfeatures set but no startindex*/
+  if (maxfeatures > 0 && startindex < 0)
   {
-      /*if startindex is specified, do not set the maxfeatures on the layers. What we want is to retreive all
-        features that meet the criteria and then filter it when writing the gml (msGMLWriteWFSQuery)*/
-      if (startindex < 0)
+      for(j=0; j<map->numlayers; j++) 
       {
-          for(j=0; j<map->numlayers; j++) 
+          layerObj *lp;
+          lp = GET_LAYER(map, j);
+          if (lp->status == MS_ON)
           {
-              layerObj *lp;
-              lp = GET_LAYER(map, j);
-              if (lp->status == MS_ON)
-              {
-                  /*over-ride the value only if it is unset or wfs maxfeattures is
-                    lower that what is currently set*/
-		if (lp->maxfeatures <=0 || (lp->maxfeatures > 0 && maxfeatures < lp->maxfeatures))
-                    lp->maxfeatures = maxfeatures;
-              }
+              /*over-ride the value only if it is unset or wfs maxfeattures is
+                lower that what is currently set*/
+              if (lp->maxfeatures <=0 || (lp->maxfeatures > 0 && maxfeatures < lp->maxfeatures))
+                lp->maxfeatures = maxfeatures;
           }
       }
   }
+  
+  /*no maxfeatures set but startindex set*/
+  if (maxfeatures <=0 && startindex > 0)
+  {
+      if (nQueriedLayers == 1 && msLayerSupportsPaging(lpQueried))
+      {
+          lpQueried->startindex = startindex;
+          startindex = -1;
+      }
+  }
 
-  /* if (strcasecmp(names[i], "FEATUREID") == 0) */
-  /* { */
-  /*  */
-  /* } */
+  /*maxfeatures set and startindex set*/
+  if (maxfeatures >0 && startindex > 0)
+  {
+      if (nQueriedLayers == 1 && msLayerSupportsPaging(lpQueried))
+      {
+          lpQueried->startindex = startindex;
+          if (lpQueried->maxfeatures <=0 || 
+              (lpQueried->maxfeatures > 0 && maxfeatures < lpQueried->maxfeatures))
+            lpQueried->maxfeatures = maxfeatures;
+          
+          startindex = -1;
+          maxfeatures = -1;
+      }
+  }
+
+
   
   if (paramsObj->pszFilter) {
     bFilterSet = 1;
@@ -1859,7 +1888,7 @@
 
     /*some validations on startindex, it should not be > that the total elements
      TODO: should we send an exception?*/
-    if (startindex >=0 && startindex >=iNumberOfFeatures)
+    if (startindex >0 && startindex >=iNumberOfFeatures)
     {   
         msIO_printf("   <gml:boundedBy>\n"); 
         msIO_printf("      <gml:null>missing</gml:null>\n");
@@ -1868,8 +1897,9 @@
     else
     {
         /* handle case of maxfeatures = 0 */
+        /*internally use a start index that start with with 0 as the first index*/
         if(maxfeatures != 0 && iResultTypeHits == 0)
-          msGMLWriteWFSQuery(map, stdout, startindex, maxfeatures, pszNameSpace, outputformat);
+          msGMLWriteWFSQuery(map, stdout, startindex-1, maxfeatures, pszNameSpace, outputformat);
 
         if (((iNumberOfFeatures==0) || (maxfeatures == 0)) && iResultTypeHits == 0) {
           msIO_printf("   <gml:boundedBy>\n"); 



More information about the mapserver-commits mailing list