Skip to content

Commit

Permalink
Implement msPostGISLayerGetExtent (#3585)
Browse files Browse the repository at this point in the history
  • Loading branch information
szekerest committed Dec 14, 2013
1 parent 7244360 commit ebae992
Showing 1 changed file with 137 additions and 32 deletions.
169 changes: 137 additions & 32 deletions mappostgis.c
Original file line number Diff line number Diff line change
Expand Up @@ -1701,6 +1701,44 @@ char *msPostGISBuildSQLItems(layerObj *layer)
return strItems;
}


/*
** msPostGISFindTableName()
**
** Returns malloc'ed char* that must be freed by caller.
*/
char *msPostGISFindTableName(char* fromsource)
{
char *f_table_name = NULL;
char *pos = strstr(fromsource, " ");

if ( ! pos ) {
/* target table is one word */
f_table_name = msStrdup(fromsource);
} else {
/* target table is hiding in sub-select clause */
pos = strcasestr(fromsource, " from ");
if ( pos ) {
char *pos_paren;
char *pos_space;
pos += 6; /* should be start of table name */
pos_paren = strstr(pos, ")"); /* first ) after table name */
pos_space = strstr(pos, " "); /* first space after table name */
if ( pos_space < pos_paren ) {
/* found space first */
f_table_name = (char*)msSmallMalloc(pos_space - pos + 1);
strlcpy(f_table_name, pos, pos_space - pos+1);
} else {
/* found ) first */
f_table_name = (char*)msSmallMalloc(pos_paren - pos + 1);
strlcpy(f_table_name, pos, pos_paren - pos+1);
}
}
}
return f_table_name;
}


/*
** msPostGISBuildSQLSRID()
**
Expand Down Expand Up @@ -1733,42 +1771,15 @@ char *msPostGISBuildSQLSRID(layerObj *layer)
** or "(select ... from thetable where ...)".
*/
else {
char *f_table_name;
char *f_table_name = msPostGISFindTableName(layerinfo->fromsource);
char *strSRIDTemplate = "find_srid('','%s','%s')";
char *pos = strstr(layerinfo->fromsource, " ");
if( layer->debug > 1 ) {
msDebug("msPostGISBuildSQLSRID: Building find_srid line.\n");
}

if ( ! pos ) {
/* target table is one word */
f_table_name = msStrdup(layerinfo->fromsource);
if( layer->debug > 1 ) {
msDebug("msPostGISBuildSQLSRID: Found table (%s)\n", f_table_name);
}
} else {
/* target table is hiding in sub-select clause */
pos = strcasestr(layerinfo->fromsource, " from ");
if ( pos ) {
char *pos_paren;
char *pos_space;
pos += 6; /* should be start of table name */
pos_paren = strstr(pos, ")"); /* first ) after table name */
pos_space = strstr(pos, " "); /* first space after table name */
if ( pos_space < pos_paren ) {
/* found space first */
f_table_name = (char*)msSmallMalloc(pos_space - pos + 1);
strlcpy(f_table_name, pos, pos_space - pos+1);
} else {
/* found ) first */
f_table_name = (char*)msSmallMalloc(pos_paren - pos + 1);
strlcpy(f_table_name, pos, pos_paren - pos+1);
}
} else {
/* should not happen */
return NULL;
}
}
if (!f_table_name)
return NULL; /* should not happen */

strSRID = msSmallMalloc(strlen(strSRIDTemplate) + strlen(f_table_name) + strlen(layerinfo->geomcolumn));
sprintf(strSRID, strSRIDTemplate, f_table_name, layerinfo->geomcolumn);
if ( f_table_name ) free(f_table_name);
Expand Down Expand Up @@ -3029,6 +3040,100 @@ int msPostGISLayerGetItems(layerObj *layer)
#endif
}

/*
** msPostGISLayerGetExtent()
**
** Registered vtable->LayerGetExtent function. Query the database for
** the extent of the requested layer.
*/
int msPostGISLayerGetExtent(layerObj *layer, rectObj *extent)
{
#ifdef USE_POSTGIS
msPostGISLayerInfo *layerinfo = NULL;
char *strSQL = NULL;
char *f_table_name;
static char *sqlExtentTemplate = "SELECT ST_Extent(%s) FROM %s";
size_t buffer_len;
PGresult *pgresult = NULL;

if (layer->debug) {
msDebug("msPostGISLayerGetExtent called.\n");
}

assert( layer->layerinfo != NULL);

layerinfo = (msPostGISLayerInfo *)layer->layerinfo;

if ( msPostGISParseData(layer) != MS_SUCCESS) {
return MS_FAILURE;
}

/* 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 MS_FAILURE;
}

buffer_len = strlen(layerinfo->geomcolumn) + strlen(f_table_name) + strlen(sqlExtentTemplate);
strSQL = (char*)msSmallMalloc(buffer_len+1); /* add space for terminating NULL */
snprintf(strSQL, buffer_len, sqlExtentTemplate, layerinfo->geomcolumn, f_table_name);
msFree(f_table_name);

if (layer->debug) {
msDebug("msPostGISLayerGetExtent 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) ) {
msSetError(MS_MISCERR, "Error executing SQL: %s", "msPostGISLayerGetExtent()", PQerrorMessage(layerinfo->pgconn));
if (pgresult)
PQclear(pgresult);

return MS_FAILURE;
}

/* process results */
if (PQntuples(pgresult) < 1) {
msSetError(MS_MISCERR, "msPostGISLayerGetExtent: No results found.",
"msPostGISLayerGetExtent()");
PQclear(pgresult);
return MS_FAILURE;
}

if (PQgetisnull(pgresult, 0, 0)) {
msSetError(MS_MISCERR, "msPostGISLayerGetExtent: Null result returned.",
"msPostGISLayerGetExtent()");
PQclear(pgresult);
return MS_FAILURE;
}

if (sscanf(PQgetvalue(pgresult, 0, 0), "BOX(%lf %lf,%lf %lf)",
&extent->minx, &extent->miny, &extent->maxx, &extent->maxy) != 4) {
msSetError(MS_MISCERR, "Failed to process result data.", "msPostGISLayerGetExtent()");
PQclear(pgresult);
return MS_FAILURE;
}

/* cleanup */
PQclear(pgresult);

return MS_SUCCESS;
#else
msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetExtent()");
return MS_FAILURE;
#endif
}


/*
* make sure that the timestring is complete and acceptable
* to the date_trunc function :
Expand Down Expand Up @@ -3399,7 +3504,7 @@ int msPostGISLayerInitializeVirtualTable(layerObj *layer)
layer->vtable->LayerGetShape = msPostGISLayerGetShape;
layer->vtable->LayerClose = msPostGISLayerClose;
layer->vtable->LayerGetItems = msPostGISLayerGetItems;
/* layer->vtable->LayerGetExtent = msPostGISLayerGetExtent; */
layer->vtable->LayerGetExtent = msPostGISLayerGetExtent;
layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer;
/* layer->vtable->LayerGetAutoStyle, not supported for this layer */
/* layer->vtable->LayerCloseConnection = msPostGISLayerClose; */
Expand Down

1 comment on commit ebae992

@pedros007
Copy link

@pedros007 pedros007 commented on ebae992 Jan 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As of Mapserver-7.0, my Postgres database logs ERROR: syntax error at or near "0" at character 29 STATEMENT: SELECT ST_Extent(geom) FROM 0 when rendering certain Postgis layers that worked fine with Mapserver-6.4. #3585 gave me the idea of setting ows_extent in my layer metadata, which prevents the error message. Looks like msPostGISLayerGetExtent was introduced to Mapserver in pull request #4825.

Please sign in to comment.