Permalink
Browse files

Implement getNumFeatures for some drivers (#5586)

  • Loading branch information...
szekerest committed Apr 30, 2018
1 parent 2fda5dc commit 2fec0326bd880ab27f766fa76427bd7c79077a9c
Showing with 296 additions and 12 deletions.
  1. +57 −8 maplayer.c
  2. +65 −2 mapmssql2008.c
  3. +40 −1 mapogr.cpp
  4. +134 −1 mappostgis.c
@@ -1120,12 +1120,26 @@ Returns the number of inline feature of a layer
*/
int msLayerGetNumFeatures(layerObj *layer)
{
if ( ! layer->vtable) {
int rv = msInitializeVirtualTable(layer);
if (rv != MS_SUCCESS)
return rv;
}
return layer->vtable->LayerGetNumFeatures(layer);
int need_to_close = MS_FALSE, result = -1;
if (!msLayerIsOpen(layer)) {
if (msLayerOpen(layer) != MS_SUCCESS)
return result;
need_to_close = MS_TRUE;
}
if (!layer->vtable) {
int rv = msInitializeVirtualTable(layer);
if (rv != MS_SUCCESS)
return result;
}
result = layer->vtable->LayerGetNumFeatures(layer);
if (need_to_close)
msLayerClose(layer);
return(result);
}
void
@@ -1781,8 +1795,43 @@ int LayerDefaultCreateItems(layerObj *layer, const int nt)
int LayerDefaultGetNumFeatures(layerObj *layer)
{
msSetError(MS_SHPERR, "Not an inline layer", "msLayerGetNumFeatures()");
return MS_FAILURE;
rectObj extent;
int status;
int result;
shapeObj shape;
/* calculate layer extent */
if (!MS_VALID_EXTENT(layer->extent)) {
if (msLayerGetExtent(layer, &extent) != MS_SUCCESS) {
msSetError(MS_MISCERR, "Unable to get layer extent", "LayerDefaultGetNumFeatures()");
return -1;
}
}
else
extent = layer->extent;
/* Cleanup any previous item selection */
msLayerFreeItemInfo(layer);
if (layer->items) {
msFreeCharArray(layer->items, layer->numitems);
layer->items = NULL;
layer->numitems = 0;
}
status = msLayerWhichShapes(layer, extent, MS_FALSE);
if (status == MS_DONE) { /* no overlap */
return 0;
}
else if (status != MS_SUCCESS) {
return -1;
}
result = 0;
while ((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) {
++result;
}
return result;
}
int LayerDefaultAutoProjection(layerObj *layer, projectionObj* projection)
@@ -904,6 +904,63 @@ int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent)
return MS_SUCCESS;
}
/* Get the layer feature count */
int msMSSQL2008LayerGetNumFeatures(layerObj *layer)
{
msMSSQL2008LayerInfo *layerinfo;
char query_string_temp[10000]; /* Should be big enough */
SQLLEN retLen;
SQLRETURN rc;
if (layer->debug) {
msDebug("msMSSQL2008LayerGetNumFeatures called\n");
}
layerinfo = getMSSQL2008LayerInfo(layer);
if (!layerinfo) {
msSetError(MS_QUERYERR, "GetNumFeatures called with layerinfo = NULL", "msMSSQL2008LayerGetNumFeatures()");
return -1;
}
/* set up statement */
if (layer->filter.native_string) {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT count(*) from %s WHERE (%s)", layerinfo->geom_table, layer->filter.native_string);
}
else if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") == NULL) {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT count(*) from %s", layerinfo->geom_table);
}
else {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT count(*) from %s WHERE (%s)", layerinfo->geom_table, msLayerGetProcessingKey(layer, "NATIVE_FILTER"));
}
if (!executeSQL(layerinfo->conn, query_string_temp)) {
return -1;
}
rc = SQLFetch(layerinfo->conn->hstmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
if (layer->debug) {
msDebug("msMSSQL2008LayerGetNumFeatures: No results found.\n");
}
return -1;
}
rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_CHAR, query_string_temp, sizeof(query_string_temp), &retLen);
if (rc == SQL_ERROR) {
msSetError(MS_QUERYERR, "Failed to get feature count", "msMSSQL2008LayerGetNumFeatures()");
return -1;
}
query_string_temp[retLen] = 0;
return atoi(query_string_temp);
}
/* Prepare and execute the SQL statement for this layer */
static int prepare_database(layerObj *layer, rectObj rect, char **query_string)
{
@@ -2964,6 +3021,12 @@ int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent)
return MS_FAILURE;
}
int msMSSQL2008LayerGetNumFeatures(layerObj *layer)
{
msSetError(MS_QUERYERR, "msMSSQL2008LayerGetNumFeatures called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetNumFeatures()");
return -1;
}
int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *record)
{
msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShapeRandom called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetShapeRandom()");
@@ -3028,7 +3091,7 @@ MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj
vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
/* vtable->LayerCreateItems, use default */
/* vtable->LayerGetNumFeatures, use default */
vtable->LayerGetNumFeatures = msMSSQL2008LayerGetNumFeatures;
/* layer->vtable->LayerGetAutoProjection, use defaut*/
return MS_SUCCESS;
@@ -3067,7 +3130,7 @@ msMSSQL2008LayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
/* layer->vtable->LayerCreateItems, use default */
/* layer->vtable->LayerGetNumFeatures, use default */
layer->vtable->LayerGetNumFeatures = msMSSQL2008LayerGetNumFeatures;
return MS_SUCCESS;
@@ -4640,6 +4640,45 @@ int msOGRLayerGetExtent(layerObj *layer, rectObj *extent)
#endif /* USE_OGR */
}
/**********************************************************************
* msOGRLayerGetNumFeatures()
*
* Returns the layer feature count.
*
* Returns the number of features on success, -1 on error
**********************************************************************/
int msOGRLayerGetNumFeatures(layerObj *layer)
{
#ifdef USE_OGR
msOGRFileInfo *psInfo = (msOGRFileInfo*)layer->layerinfo;
int result;
if (psInfo == NULL || psInfo->hLayer == NULL) {
msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!",
"msOGRLayerGetNumFeatures()");
return -1;
}
/* ------------------------------------------------------------------
* Call OGR's GetFeatureCount()... note that for some formats this will
* result in a scan of the whole layer and can be an expensive call.
* ------------------------------------------------------------------ */
ACQUIRE_OGR_LOCK;
result = (int)OGR_L_GetFeatureCount(psInfo->hLayer, TRUE);
RELEASE_OGR_LOCK;
return result;
#else
/* ------------------------------------------------------------------
* OGR Support not included...
* ------------------------------------------------------------------ */
msSetError(MS_MISCERR, "OGR support is not available.",
"msOGRLayerGetNumFeatures()");
return -1;
#endif /* USE_OGR */
}
/**********************************************************************
* msOGRGetSymbolId()
@@ -5602,7 +5641,7 @@ int msOGRLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer;
layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
/* layer->vtable->LayerCreateItems, use default */
/* layer->vtable->LayerGetNumFeatures, use default */
layer->vtable->LayerGetNumFeatures = msOGRLayerGetNumFeatures;
/* layer->vtable->LayerGetAutoProjection, use defaut*/
layer->vtable->LayerEscapeSQLParam = msOGREscapeSQLParam;
@@ -3520,6 +3520,139 @@ int msPostGISLayerGetExtent(layerObj *layer, rectObj *extent)
#endif
}
/*
** msPostGISLayerGetNumFeatures()
**
** Registered vtable->LayerGetNumFeatures function. Query the database for
** the feature count of the requested layer.
*/
int msPostGISLayerGetNumFeatures(layerObj *layer)
{
#ifdef USE_POSTGIS
msPostGISLayerInfo *layerinfo = NULL;
char *strSQL = NULL;
char *strFilter1 = 0, *strFilter2 = 0;
char *f_table_name;
static char *sqlNumFeaturesTemplate = "SELECT count(*) FROM %s";
size_t buffer_len;
size_t strFilterLength1 = 0, strFilterLength2 = 0;
PGresult *pgresult = NULL;
int result;
char *tmp;
if (layer->debug) {
msDebug("msPostGISLayerGetNumFeatures called.\n");
}
assert(layer->layerinfo != NULL);
layerinfo = (msPostGISLayerInfo *)layer->layerinfo;
if (msPostGISParseData(layer) != MS_SUCCESS) {
return -1;
}
/* if we have !BOX! substitution then we use just the table name */
if (strstr(layerinfo->fromsource, BOXTOKEN))
f_table_name = msPostGISFindTableName(layerinfo->fromsource);
else
f_table_name = msStrdup(layerinfo->fromsource);
if (!f_table_name) {
msSetError(MS_MISCERR, "Failed to get table name.", "msPostGISLayerGetExtent()");
return -1;
}
/* Handle a translated filter (RFC91). */
if (layer->filter.native_string) {
static char *strFilterTemplate = "(%s)";
strFilter1 = (char *)msSmallMalloc(strlen(strFilterTemplate) + strlen(layer->filter.native_string) + 1);
sprintf(strFilter1, strFilterTemplate, layer->filter.native_string);
strFilterLength1 = strlen(strFilter1) + 7;
}
/* Handle a native filter set as a PROCESSING option (#5001). */
if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) {
static char *strFilterTemplate = "(%s)";
char *native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER");
strFilter2 = (char *)msSmallMalloc(strlen(strFilterTemplate) + strlen(native_filter) + 1);
sprintf(strFilter2, strFilterTemplate, native_filter);
strFilterLength2 = strlen(strFilter2) + 7;
}
buffer_len = strlen(f_table_name) + strlen(sqlNumFeaturesTemplate)
+ strFilterLength1 + strFilterLength2;
strSQL = (char*)msSmallMalloc(buffer_len + 1); /* add space for terminating NULL */
snprintf(strSQL, buffer_len, sqlNumFeaturesTemplate, f_table_name);
msFree(f_table_name);
if (strFilter1) {
strlcat(strSQL, " where ", buffer_len);
strlcat(strSQL, strFilter1, buffer_len);
msFree(strFilter1);
if (strFilter2) {
strlcat(strSQL, " and ", buffer_len);
strlcat(strSQL, strFilter2, buffer_len);
msFree(strFilter2);
}
}
else if (strFilter2) {
strlcat(strSQL, " where ", buffer_len);
strlcat(strSQL, strFilter2, buffer_len);
msFree(strFilter2);
}
if (layer->debug) {
msDebug("msPostGISLayerGetNumFeatures executing SQL: %s\n", strSQL);
}
/* executing the query */
pgresult = PQexecParams(layerinfo->pgconn, strSQL, 0, NULL, NULL, NULL, NULL, 0);
msFree(strSQL);
if ((!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK)) {
msDebug("Error executing SQL: (%s) in msPostGISLayerGetNumFeatures()", PQerrorMessage(layerinfo->pgconn));
msSetError(MS_MISCERR, "Error executing SQL. Check server logs.", "msPostGISLayerGetNumFeatures()");
if (pgresult)
PQclear(pgresult);
return -1;
}
/* process results */
if (PQntuples(pgresult) < 1) {
msSetError(MS_MISCERR, "msPostGISLayerGetNumFeatures: No results found.",
"msPostGISLayerGetNumFeatures()");
PQclear(pgresult);
return -1;
}
if (PQgetisnull(pgresult, 0, 0)) {
msSetError(MS_MISCERR, "msPostGISLayerGetNumFeatures: Null result returned.",
"msPostGISLayerGetNumFeatures()");
PQclear(pgresult);
return -1;
}
tmp = PQgetvalue(pgresult, 0, 0);
if (tmp) {
result = strtol(tmp, NULL, 10);
}
else {
result = 0;
}
/* cleanup */
PQclear(pgresult);
return result;
#else
msSetError(MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetNumFeatures()");
return -1;
#endif
}
/*
* make sure that the timestring is complete and acceptable
* to the date_trunc function :
@@ -4098,7 +4231,7 @@ int msPostGISLayerInitializeVirtualTable(layerObj *layer)
// layer->vtable->LayerSetTimeFilter = msPostGISLayerSetTimeFilter;
layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
/* layer->vtable->LayerCreateItems, use default */
/* layer->vtable->LayerGetNumFeatures, use default */
layer->vtable->LayerGetNumFeatures = msPostGISLayerGetNumFeatures;
/* layer->vtable->LayerGetAutoProjection, use defaut*/

0 comments on commit 2fec032

Please sign in to comment.