Permalink
Browse files

Implement LayerGetShapeCount()

  • Loading branch information...
rouault committed Feb 3, 2016
1 parent c8c461e commit 1bf85cfb53c16c2b6e00bdb483d64d4862991154
Showing with 202 additions and 13 deletions.
  1. +1 −0 mapcluster.c
  2. +1 −0 mapcontour.c
  3. +1 −0 mapgraticule.c
  4. +47 −0 maplayer.c
  5. +1 −0 mapmssql2008.c
  6. +1 −0 mapogr.cpp
  7. +1 −0 maporaclespatial.c
  8. +1 −0 mappluginlayer.c
  9. +123 −12 mappostgis.c
  10. +18 −0 mapquery.c
  11. +1 −0 maprasterquery.c
  12. +2 −0 mapserver.h
  13. +1 −0 mapshape.c
  14. +1 −1 mapunion.c
  15. +1 −0 mapuvraster.c
  16. +1 −0 mapwfslayer.c
@@ -1506,6 +1506,7 @@ void msClusterLayerCopyVirtualTable(layerVTableObj* vtable)
vtable->LayerWhichShapes = msClusterLayerWhichShapes;
vtable->LayerNextShape = msClusterLayerNextShape;
vtable->LayerGetShape = msClusterLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
vtable->LayerClose = msClusterLayerClose;
@@ -880,6 +880,7 @@ int msContourLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msContourLayerWhichShapes;
layer->vtable->LayerNextShape = msContourLayerNextShape;
layer->vtable->LayerGetShape = msContourLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msContourLayerClose;
layer->vtable->LayerGetItems = msContourLayerGetItems;
layer->vtable->LayerGetExtent = msContourLayerGetExtent;
@@ -973,6 +973,7 @@ int msGraticuleLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerNextShape = msGraticuleLayerNextShape;
/* layer->vtable->LayerResultsGetShape, use default */
layer->vtable->LayerGetShape = msGraticuleLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msGraticuleLayerClose;
layer->vtable->LayerGetItems = msGraticuleLayerGetItems;
layer->vtable->LayerGetExtent = msGraticuleLayerGetExtent;
@@ -407,6 +407,28 @@ int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
return rv;
}
/*
** Returns the number of shapes that match the potential filter and extent.
* This should be equivalent to calling msLayerWhichShapes() and counting the
* number of shapes returned by msLayerNextShape(), honouring layer->maxfeatures
* limitation if layer->maxfeatures>=0, and honouring layer->startindex if
* layer->startindex >= 1 and paging is enabled.
* Returns -1 in case of failure.
*/
int msLayerGetShapeCount(layerObj *layer, rectObj rect)
{
int rv;
if( ! layer->vtable) {
rv = msInitializeVirtualTable(layer);
if(rv != MS_SUCCESS)
return -1;
}
return layer->vtable->LayerGetShapeCount(layer, rect);
}
/*
** Closes resources used by a particular layer.
*/
@@ -1504,6 +1526,29 @@ int LayerDefaultGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
return MS_FAILURE;
}
int LayerDefaultGetShapeCount(layerObj *layer, rectObj rect)
{
int status;
shapeObj shape;
int nShapeCount = 0;
status = msLayerWhichShapes(layer, rect, MS_TRUE) ;
if( status == MS_FAILURE )
return -1;
if( status == MS_DONE )
return 0;
msInitShape(&shape);
while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) {
nShapeCount++ ;
msFreeShape(&shape);
if(layer->maxfeatures > 0 && layer->maxfeatures == nShapeCount)
break;
}
return nShapeCount;
}
int LayerDefaultClose(layerObj *layer)
{
return MS_SUCCESS;
@@ -1807,6 +1852,7 @@ static int populateVirtualTable(layerVTableObj *vtable)
vtable->LayerNextShape = LayerDefaultNextShape;
/* vtable->LayerResultsGetShape = LayerDefaultResultsGetShape; */
vtable->LayerGetShape = LayerDefaultGetShape;
vtable->LayerGetShapeCount = LayerDefaultGetShapeCount;
vtable->LayerClose = LayerDefaultClose;
vtable->LayerGetItems = LayerDefaultGetItems;
vtable->LayerGetExtent = LayerDefaultGetExtent;
@@ -2113,6 +2159,7 @@ msINLINELayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerIsOpen = msINLINELayerIsOpen;
layer->vtable->LayerWhichShapes = msINLINELayerWhichShapes;
layer->vtable->LayerNextShape = msINLINELayerNextShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerGetShape = msINLINELayerGetShape;
layer->vtable->LayerClose = msINLINELayerClose;
/* layer->vtable->LayerGetItems, use default */
@@ -2771,6 +2771,7 @@ msMSSQL2008LayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msMSSQL2008LayerWhichShapes;
layer->vtable->LayerNextShape = msMSSQL2008LayerNextShape;
layer->vtable->LayerGetShape = msMSSQL2008LayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msMSSQL2008LayerClose;
@@ -3646,6 +3646,7 @@ int msOGRLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msOGRLayerWhichShapes;
layer->vtable->LayerNextShape = msOGRLayerNextShape;
layer->vtable->LayerGetShape = msOGRLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msOGRLayerClose;
layer->vtable->LayerGetItems = msOGRLayerGetItems;
layer->vtable->LayerGetExtent = msOGRLayerGetExtent;
@@ -3998,6 +3998,7 @@ int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes;
layer->vtable->LayerNextShape = msOracleSpatialLayerNextShape;
layer->vtable->LayerGetShape = msOracleSpatialLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msOracleSpatialLayerClose;
layer->vtable->LayerGetItems = msOracleSpatialLayerGetItems;
layer->vtable->LayerGetExtent = msOracleSpatialLayerGetExtent;
@@ -164,6 +164,7 @@ copyVirtualTable(layerVTableObj *dest,
dest->LayerNextShape = src->LayerNextShape ? src->LayerNextShape : dest->LayerNextShape;
dest->LayerGetShape = src->LayerGetShape ? src->LayerGetShape : dest->LayerGetShape;
/* dest->LayerResultsGetShape = src->LayerResultsGetShape ? src->LayerResultsGetShape : dest->LayerResultsGetShape; */
dest->LayerGetShapeCount = src->LayerGetShapeCount ? src->LayerGetShapeCount : dest->LayerGetShapeCount;
dest->LayerClose = src->LayerClose ? src->LayerClose : dest->LayerClose;
dest->LayerGetItems = src->LayerGetItems ? src->LayerGetItems : dest->LayerGetItems;
dest->LayerGetExtent = src->LayerGetExtent ? src->LayerGetExtent : dest->LayerGetExtent;
@@ -2656,6 +2656,18 @@ int msPostGISLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
int num_bind_values = 0;
assert(layer != NULL);
assert(layer->layerinfo != NULL);
if (layer->debug) {
msDebug("msPostGISLayerWhichShapes called.\n");
}
/* Fill out layerinfo with our current DATA state. */
if ( msPostGISParseData(layer) != MS_SUCCESS) {
return MS_FAILURE;
}
/* try to get the first bind value */
bind_value = msLookupHashTable(&layer->bindvals, "1");
while(bind_value != NULL) {
@@ -2669,18 +2681,6 @@ int msPostGISLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
bind_value = msLookupHashTable(&layer->bindvals, bind_key);
}
assert(layer != NULL);
assert(layer->layerinfo != NULL);
if (layer->debug) {
msDebug("msPostGISLayerWhichShapes called.\n");
}
/* Fill out layerinfo with our current DATA state. */
if ( msPostGISParseData(layer) != MS_SUCCESS) {
return MS_FAILURE;
}
/*
** This comes *after* parsedata, because parsedata fills in
** layer->layerinfo.
@@ -2799,6 +2799,116 @@ int msPostGISLayerNextShape(layerObj *layer, shapeObj *shape)
#endif
}
/*
** msPostGISLayerGetShape()
**
*/
int msPostGISLayerGetShapeCount(layerObj *layer, rectObj rect)
{
#ifdef USE_POSTGIS
msPostGISLayerInfo *layerinfo = NULL;
char *strSQL = NULL;
char *strSQLCount = NULL;
PGresult *pgresult = NULL;
char** layer_bind_values = (char**)msSmallMalloc(sizeof(char*) * 1000);
char* bind_value;
char* bind_key = (char*)msSmallMalloc(3);
int num_bind_values = 0;
int nCount = 0;
assert(layer != NULL);
assert(layer->layerinfo != NULL);
if (layer->debug) {
msDebug("msPostGISLayerGetShapeCount called.\n");
}
/* Fill out layerinfo with our current DATA state. */
if ( msPostGISParseData(layer) != MS_SUCCESS) {
return -1;
}
/* try to get the first bind value */
bind_value = msLookupHashTable(&layer->bindvals, "1");
while(bind_value != NULL) {
/* put the bind value on the stack */
layer_bind_values[num_bind_values] = bind_value;
/* increment the counter */
num_bind_values++;
/* create a new lookup key */
sprintf(bind_key, "%d", num_bind_values+1);
/* get the bind_value */
bind_value = msLookupHashTable(&layer->bindvals, bind_key);
}
/*
** This comes *after* parsedata, because parsedata fills in
** layer->layerinfo.
*/
layerinfo = (msPostGISLayerInfo*) layer->layerinfo;
/* Build a SQL query based on our current state. */
strSQL = msPostGISBuildSQL(layer, &rect, NULL);
if ( ! strSQL ) {
msSetError(MS_QUERYERR, "Failed to build query SQL.", "msPostGISLayerGetShapeCount()");
return -1;
}
strSQLCount = NULL;
strSQLCount = msStringConcatenate(strSQLCount, "SELECT COUNT(*) FROM (");
strSQLCount = msStringConcatenate(strSQLCount, strSQL);
strSQLCount = msStringConcatenate(strSQLCount, ") msQuery");
msFree(strSQL);
if (layer->debug) {
msDebug("msPostGISLayerGetShapeCount query: %s\n", strSQLCount);
}
if(num_bind_values > 0) {
pgresult = PQexecParams(layerinfo->pgconn, strSQLCount, num_bind_values, NULL, (const char**)layer_bind_values, NULL, NULL, 1);
} else {
pgresult = PQexecParams(layerinfo->pgconn, strSQLCount,0, NULL, NULL, NULL, NULL, 0);
}
msFree(strSQLCount);
/* free bind values */
free(bind_key);
free(layer_bind_values);
if ( layer->debug > 1 ) {
msDebug("msPostGISLayerWhichShapes query status: %s (%d)\n", PQresStatus(PQresultStatus(pgresult)), PQresultStatus(pgresult));
}
/* Something went wrong. */
if (!pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) {
msDebug("msPostGISLayerGetShapeCount(): Error (%s) executing query: %s\n", PQerrorMessage(layerinfo->pgconn), strSQL);
msSetError(MS_QUERYERR, "Error executing query. Check server logs","msPostGISLayerGetShapeCount()");
free(strSQL);
if (pgresult) {
PQclear(pgresult);
}
return MS_FAILURE;
}
nCount = atoi(PQgetvalue(pgresult, 0, 0 ));
if ( layer->debug ) {
msDebug("msPostGISLayerWhichShapes return: %d.\n", nCount);
}
PQclear(pgresult);
return nCount;
#else
msSetError( MS_MISCERR,
"PostGIS support is not available.",
"msPostGISLayerGetShapeCount()");
return -1;
#endif
}
/*
** msPostGISLayerGetShape()
**
@@ -3823,6 +3933,7 @@ int msPostGISLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msPostGISLayerWhichShapes;
layer->vtable->LayerNextShape = msPostGISLayerNextShape;
layer->vtable->LayerGetShape = msPostGISLayerGetShape;
layer->vtable->LayerGetShapeCount = msPostGISLayerGetShapeCount;
layer->vtable->LayerClose = msPostGISLayerClose;
layer->vtable->LayerGetItems = msPostGISLayerGetItems;
layer->vtable->LayerGetExtent = msPostGISLayerGetExtent;
@@ -985,6 +985,24 @@ int msQueryByRect(mapObj *map)
lp->project = MS_FALSE;
#endif
if( map->query.only_cache_result_count )
{
int numFeatures = msLayerGetShapeCount(lp, searchrect);
if( numFeatures >= 0 )
{
lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */
MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE);
initResultCache( lp->resultcache);
lp->resultcache->numresults = numFeatures;
if (!paging && map->query.startindex > 1) {
lp->resultcache->numresults -= (map->query.startindex-1);
}
msFreeShape(&searchshape);
continue;
}
// Fallback in case of error (should not happen normally)
}
status = msLayerWhichShapes(lp, searchrect, MS_TRUE);
if(status == MS_DONE) { /* no overlap */
msLayerClose(lp);
@@ -1486,6 +1486,7 @@ msRASTERLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msRASTERLayerWhichShapes;
layer->vtable->LayerNextShape = msRASTERLayerNextShape;
layer->vtable->LayerGetShape = msRASTERLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msRASTERLayerClose;
layer->vtable->LayerGetItems = msRASTERLayerGetItems;
layer->vtable->LayerGetExtent = msRASTERLayerGetExtent;
@@ -1951,6 +1951,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
int (*LayerWhichShapes)(layerObj *layer, rectObj rect, int isQuery);
int (*LayerNextShape)(layerObj *layer, shapeObj *shape);
int (*LayerGetShape)(layerObj *layer, shapeObj *shape, resultObj *record);
int (*LayerGetShapeCount)(layerObj *layer, rectObj rect);
int (*LayerClose)(layerObj *layer);
int (*LayerGetItems)(layerObj *layer);
int (*LayerGetExtent)(layerObj *layer, rectObj *extent);
@@ -2420,6 +2421,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
MS_DLL_EXPORT int msLayerGetItems(layerObj *layer);
MS_DLL_EXPORT int msLayerSetItems(layerObj *layer, char **items, int numitems);
MS_DLL_EXPORT int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record);
MS_DLL_EXPORT int msLayerGetShapeCount(layerObj *layer, rectObj rect);
MS_DLL_EXPORT int msLayerGetExtent(layerObj *layer, rectObj *extent);
MS_DLL_EXPORT int msLayerSetExtent( layerObj *layer, double minx, double miny, double maxx, double maxy);
MS_DLL_EXPORT int msLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape);
@@ -2795,6 +2795,7 @@ int msSHPLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msSHPLayerWhichShapes;
layer->vtable->LayerNextShape = msSHPLayerNextShape;
layer->vtable->LayerGetShape = msSHPLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msSHPLayerClose;
layer->vtable->LayerGetItems = msSHPLayerGetItems;
layer->vtable->LayerGetExtent = msSHPLayerGetExtent;
@@ -714,7 +714,7 @@ int msUnionLayerCopyVirtualTable(layerVTableObj* vtable)
vtable->LayerWhichShapes = msUnionLayerWhichShapes;
vtable->LayerNextShape = msUnionLayerNextShape;
vtable->LayerGetShape = msUnionLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
vtable->LayerClose = msUnionLayerClose;
vtable->LayerGetItems = msUnionLayerGetItems;
@@ -760,6 +760,7 @@ msUVRASTERLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msUVRASTERLayerWhichShapes;
layer->vtable->LayerNextShape = msUVRASTERLayerNextShape;
layer->vtable->LayerGetShape = msUVRASTERLayerGetShape;
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerClose = msUVRASTERLayerClose;
layer->vtable->LayerGetItems = msUVRASTERLayerGetItems;
layer->vtable->LayerGetExtent = msUVRASTERLayerGetExtent;
@@ -1279,6 +1279,7 @@ msWFSLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerWhichShapes = msWFSLayerWhichShapes;
layer->vtable->LayerNextShape = msWFSLayerNextShape;
/* layer->vtable->LayerResultsGetShape = msWFSLayerResultGetShape; */
/* layer->vtable->LayerGetShapeCount, use default */
layer->vtable->LayerGetShape = msWFSLayerGetShape;
layer->vtable->LayerClose = msWFSLayerClose;
layer->vtable->LayerGetItems = msWFSLayerGetItems;

0 comments on commit 1bf85cf

Please sign in to comment.