[mapserver] 02/07: Imported Upstream version 7.0.5
Bas Couwenberg
sebastic at debian.org
Tue May 9 20:42:30 UTC 2017
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch experimental
in repository mapserver.
commit e8d579737239d45858950a293f037370a6e246ef
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Tue May 9 22:13:57 2017 +0200
Imported Upstream version 7.0.5
---
CMakeLists.txt | 2 +-
cmake/FindPHP5.cmake | 4 +
mapdraw.c | 1 +
mapgraticule.c | 131 ++++++-
maphash.c | 4 +
mapio.c | 120 +++++++
mapio.h | 4 +-
maplegend.c | 1 +
mapogcfilter.c | 3 +-
mapogcsld.c | 6 +-
mapogr.cpp | 825 ++++++++++++++++++++++++++++++++++++++++----
maporaclespatial.c | 3 +
mappostgis.c | 10 +-
mapproject.c | 34 ++
mapquery.c | 7 +-
mapresample.c | 83 ++++-
mapscript/python/pymodule.i | 40 +++
mapscript/swiginc/msio.i | 5 +
mapshape.c | 21 +-
mapwms.c | 2 +-
20 files changed, 1191 insertions(+), 115 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3e7304e..25bc2d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,7 +17,7 @@ include(CheckCSourceCompiles)
set (MapServer_VERSION_MAJOR 7)
set (MapServer_VERSION_MINOR 0)
-set (MapServer_VERSION_REVISION 4)
+set (MapServer_VERSION_REVISION 5)
set (MapServer_VERSION_SUFFIX "")
set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR})
diff --git a/cmake/FindPHP5.cmake b/cmake/FindPHP5.cmake
index 92261b8..4b77f44 100644
--- a/cmake/FindPHP5.cmake
+++ b/cmake/FindPHP5.cmake
@@ -86,6 +86,10 @@ IF(PHP5_CONFIG_EXECUTABLE)
MESSAGE(STATUS ${PHP5_MAIN_INCLUDE_DIR})
+ IF(NOT PHP5_INCLUDE_PATH)
+ set(PHP5_INCLUDE_PATH ${PHP5_INCLUDES})
+ ENDIF(NOT PHP5_INCLUDE_PATH)
+
IF(PHP5_VERSION LESS 5)
MESSAGE(FATAL_ERROR "PHP version is not 5 or later")
ENDIF(PHP5_VERSION LESS 5)
diff --git a/mapdraw.c b/mapdraw.c
index 1ccc0fe..9fdacda 100644
--- a/mapdraw.c
+++ b/mapdraw.c
@@ -55,6 +55,7 @@ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare)
return(NULL);
}
+ msFreeLabelCache(&(map->labelcache));
msInitLabelCache(&(map->labelcache)); /* this clears any previously allocated cache */
/* clear any previously created mask layer images */
diff --git a/mapgraticule.c b/mapgraticule.c
index 688b45b..eab39f8 100644
--- a/mapgraticule.c
+++ b/mapgraticule.c
@@ -187,6 +187,19 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
* These lines will be used when generating labels to get correct placement at arc/rect edge intersections.
*/
rectMapCoordinates = layer->map->extent;
+#ifdef USE_PROJ
+ layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
+ if( layer->project &&
+ strstr(layer->map->projection.args[0], "epsg:3857") &&
+ pj_is_latlong(layer->projection.proj) )
+ {
+ if( rectMapCoordinates.minx < -20037508)
+ rectMapCoordinates.minx = -20037508;
+ if( rectMapCoordinates.maxx > 20037508 )
+ rectMapCoordinates.maxx = 20037508;
+ }
+#endif
+
msFree(pInfo->pboundinglines);
pInfo->pboundinglines = (lineObj *) msSmallMalloc( sizeof( lineObj ) * 4 );
msFree(pInfo->pboundingpoints);
@@ -205,7 +218,6 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy;
#ifdef USE_PROJ
- layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
if(layer->project)
msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]);
#endif
@@ -287,7 +299,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
case 0:
if(!pInfo->blabelaxes) { /* Bottom */
pInfo->ilabelstate++;
- shape->numlines = 0;
+ msFreeShape(shape);
return MS_SUCCESS;
}
@@ -306,7 +318,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
_FormatLabel( layer, shape, shape->line->point[0].x );
if(_AdjustLabelPosition( layer, shape, posBottom ) != MS_SUCCESS)
- return MS_FAILURE;
+ {
+ msFreeShape(shape);
+ pInfo->ilabelstate++;
+ return MS_SUCCESS;
+ }
pInfo->ilabelstate++;
return MS_SUCCESS;
@@ -314,7 +330,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
case 1:
if(!pInfo->blabelaxes) { /* Top */
pInfo->ilabelstate++;
- shape->numlines = 0;
+ msFreeShape(shape);
return MS_SUCCESS;
}
@@ -333,7 +349,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
_FormatLabel( layer, shape, shape->line->point[0].x );
if(_AdjustLabelPosition( layer, shape, posTop ) != MS_SUCCESS)
- return MS_FAILURE;
+ {
+ msFreeShape(shape);
+ pInfo->ilabelstate++;
+ return MS_SUCCESS;
+ }
pInfo->ilabelstate++;
return MS_SUCCESS;
@@ -372,7 +392,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
case 0:
if(!pInfo->blabelaxes) { /* Left side */
pInfo->ilabelstate++;
- shape->numlines = 0;
+ msFreeShape(shape);
return MS_SUCCESS;
}
@@ -391,7 +411,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
_FormatLabel( layer, shape, shape->line->point[0].y );
if(_AdjustLabelPosition( layer, shape, posLeft ) != MS_SUCCESS)
- return MS_FAILURE;
+ {
+ msFreeShape(shape);
+ pInfo->ilabelstate++;
+ return MS_SUCCESS;
+ }
pInfo->ilabelstate++;
return MS_SUCCESS;
@@ -399,7 +423,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
case 1:
if(!pInfo->blabelaxes) { /* Right side */
pInfo->ilabelstate++;
- shape->numlines = 0;
+ msFreeShape(shape);
return MS_SUCCESS;
}
@@ -418,7 +442,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
_FormatLabel( layer, shape, shape->line->point[0].y );
if(_AdjustLabelPosition( layer, shape, posRight ) != MS_SUCCESS)
- return MS_FAILURE;
+ {
+ msFreeShape(shape);
+ pInfo->ilabelstate++;
+ return MS_SUCCESS;
+ }
pInfo->ilabelstate++;
return MS_SUCCESS;
@@ -1039,7 +1067,20 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
#ifdef USE_PROJ
if(pLayer->project)
+ {
msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape );
+
+ /* Poor man detection of reprojection failure */
+ if( pj_is_latlong(pLayer->projection.proj) !=
+ pj_is_latlong(pLayer->map->projection.proj) )
+ {
+ if( ptPoint.x == pShape->line->point[0].x &&
+ ptPoint.y == pShape->line->point[0].y )
+ {
+ return MS_FAILURE;
+ }
+ }
+ }
#endif
if(pLayer->transform) {
@@ -1067,8 +1108,8 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
pShape->line->point[0].y = fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5;
break;
case posLeft:
- pShape->line->point[1].x = 0;
- pShape->line->point[0].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5;
+ pShape->line->point[0].x = 0;
+ pShape->line->point[1].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5;
break;
case posRight:
pShape->line->point[1].x = pLayer->map->width;
@@ -1081,7 +1122,75 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
#ifdef USE_PROJ
if(pLayer->project)
+ {
+ /* Clamp coordinates into the validity area of the projection, in the */
+ /* particular case of EPSG:3857 (WebMercator) to longlat reprojection */
+ if( strstr(pLayer->map->projection.args[0], "epsg:3857") &&
+ pj_is_latlong(pLayer->projection.proj) )
+ {
+ if( !pLayer->map->projection.gt.need_geotransform &&
+ ePosition == posLeft && pShape->line->point[0].x < -20037508)
+ {
+ pShape->line->point[1].x = -20037508 + (pShape->line->point[1].x -
+ pShape->line->point[0].x);
+ pShape->line->point[0].x = -20037508;
+ }
+ else if( pLayer->map->projection.gt.need_geotransform &&
+ ePosition == posLeft &&
+ pLayer->map->projection.gt.geotransform[0] +
+ pShape->line->point[0].x *
+ pLayer->map->projection.gt.geotransform[1] +
+ pShape->line->point[0].y *
+ pLayer->map->projection.gt.geotransform[2] < -20037508)
+ {
+ double y_tmp;
+ double width = pShape->line->point[1].x - pShape->line->point[0].x;
+
+ y_tmp = pLayer->map->projection.gt.geotransform[3] +
+ pShape->line->point[0].x *
+ pLayer->map->projection.gt.geotransform[4] +
+ pShape->line->point[0].y *
+ pLayer->map->projection.gt.geotransform[5];
+ pShape->line->point[0].x =
+ pLayer->map->projection.gt.invgeotransform[0] +
+ -20037508 * pLayer->map->projection.gt.invgeotransform[1] +
+ y_tmp * pLayer->map->projection.gt.invgeotransform[2];
+ pShape->line->point[1].x = pShape->line->point[0].x + width;
+ }
+
+ if( !pLayer->map->projection.gt.need_geotransform &&
+ ePosition == posRight && pShape->line->point[1].x > 20037508)
+ {
+ pShape->line->point[0].x = 20037508 - (pShape->line->point[1].x -
+ pShape->line->point[0].x);
+ pShape->line->point[1].x = 20037508;
+ }
+ else if( pLayer->map->projection.gt.need_geotransform &&
+ ePosition == posRight &&
+ pLayer->map->projection.gt.geotransform[0] +
+ pShape->line->point[1].x *
+ pLayer->map->projection.gt.geotransform[1] +
+ pShape->line->point[1].y *
+ pLayer->map->projection.gt.geotransform[2] > 20037508)
+ {
+ double y_tmp;
+ double width = pShape->line->point[1].x - pShape->line->point[0].x;
+
+ y_tmp = pLayer->map->projection.gt.geotransform[3] +
+ pShape->line->point[1].x *
+ pLayer->map->projection.gt.geotransform[4] +
+ pShape->line->point[1].y *
+ pLayer->map->projection.gt.geotransform[5];
+ pShape->line->point[1].x =
+ pLayer->map->projection.gt.invgeotransform[0] +
+ 20037508 * pLayer->map->projection.gt.invgeotransform[1] +
+ y_tmp * pLayer->map->projection.gt.invgeotransform[2];
+ pShape->line->point[0].x = pShape->line->point[1].x - width;
+ }
+ }
+
msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape );
+ }
#endif
switch( ePosition ) {
diff --git a/maphash.c b/maphash.c
index c548602..1c27cc8 100644
--- a/maphash.c
+++ b/maphash.c
@@ -187,10 +187,14 @@ int msRemoveHashTable(hashTableObj *table, const char *key)
status = MS_SUCCESS;
if (prev_tp) {
prev_tp->next = tp->next;
+ msFree(tp->key);
+ msFree(tp->data);
free(tp);
break;
} else {
table->items[hash(key)] = tp->next;
+ msFree(tp->key);
+ msFree(tp->data);
free(tp);
break;
}
diff --git a/mapio.c b/mapio.c
index 7077e8d..10bbe49 100644
--- a/mapio.c
+++ b/mapio.c
@@ -758,6 +758,126 @@ void msIO_installStdinFromBuffer()
}
/************************************************************************/
+/* msIO_getAndStripStdoutBufferMimeHeaders() */
+/* */
+/************************************************************************/
+
+hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders()
+{
+ /* -------------------------------------------------------------------- */
+ /* Find stdout buffer. */
+ /* -------------------------------------------------------------------- */
+ msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" );
+ msIOBuffer *buf;
+ int start_of_mime_header, current_pos;
+ hashTableObj* hashTable;
+
+ if( ctx == NULL || ctx->write_channel == MS_FALSE
+ || strcmp(ctx->label,"buffer") != 0 ) {
+ msSetError( MS_MISCERR, "Can't identify msIO buffer.",
+ "msIO_getAndStripStdoutBufferMimeHeaders" );
+ return NULL;
+ }
+
+ buf = (msIOBuffer *) ctx->cbData;
+
+ hashTable = msCreateHashTable();
+
+ /* -------------------------------------------------------------------- */
+ /* Loop over all headers. */
+ /* -------------------------------------------------------------------- */
+ current_pos = 0;
+ while( TRUE ) {
+ int pos_of_column = -1;
+ char* key, *value;
+
+ start_of_mime_header = current_pos;
+ while( current_pos < buf->data_offset )
+ {
+ if( buf->data[current_pos] == '\r' )
+ {
+ if( current_pos + 1 == buf->data_offset ||
+ buf->data[current_pos + 1] != '\n' )
+ {
+ pos_of_column = -1;
+ break;
+ }
+ break;
+ }
+ if( buf->data[current_pos] == ':' )
+ {
+ pos_of_column = current_pos;
+ if( current_pos + 1 == buf->data_offset ||
+ buf->data[current_pos + 1] != ' ' )
+ {
+ pos_of_column = -1;
+ break;
+ }
+ }
+ current_pos++;
+ }
+
+ if( pos_of_column < 0 || current_pos == buf->data_offset ) {
+ msSetError( MS_MISCERR, "Corrupt mime headers.",
+ "msIO_getAndStripStdoutBufferMimeHeaders" );
+ msFreeHashTable(hashTable);
+ return NULL;
+ }
+
+ key = (char*) malloc( pos_of_column - start_of_mime_header + 1 );
+ memcpy( key, buf->data+start_of_mime_header, pos_of_column - start_of_mime_header);
+ key[pos_of_column - start_of_mime_header] = '\0';
+
+ value = (char*) malloc( current_pos - (pos_of_column+2) + 1 );
+ memcpy( value, buf->data+pos_of_column+2, current_pos - (pos_of_column+2));
+ value[current_pos - (pos_of_column+2)] = '\0';
+
+ msInsertHashTable( hashTable, key, value );
+
+ msFree( key );
+ msFree( value );
+
+ /* -------------------------------------------------------------------- */
+ /* Go to next line. */
+ /* -------------------------------------------------------------------- */
+ current_pos += 2;
+ if( current_pos == buf->data_offset )
+ {
+ msSetError( MS_MISCERR, "Corrupt mime headers.",
+ "msIO_getAndStripStdoutBufferMimeHeaders" );
+ msFreeHashTable(hashTable);
+ return NULL;
+ }
+
+ /* If next line is a '\r', this is the end of mime headers. */
+ if( buf->data[current_pos] == '\r' )
+ {
+ current_pos ++;
+ if( current_pos == buf->data_offset ||
+ buf->data[current_pos] != '\n' )
+ {
+ msSetError( MS_MISCERR, "Corrupt mime headers.",
+ "msIO_getAndStripStdoutBufferMimeHeaders" );
+ msFreeHashTable(hashTable);
+ return NULL;
+ }
+ current_pos ++;
+ break;
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Move data to front of buffer, and reset length. */
+ /* -------------------------------------------------------------------- */
+ memmove( buf->data, buf->data+current_pos,
+ buf->data_offset - current_pos );
+ buf->data[buf->data_offset - current_pos] = '\0';
+ buf->data_offset -= current_pos;
+
+ return hashTable;
+}
+
+/************************************************************************/
/* msIO_stripStdoutBufferContentType() */
/* */
/* Strip off Content-Type header from buffer, and return to */
diff --git a/mapio.h b/mapio.h
index f339839..cc676be 100644
--- a/mapio.h
+++ b/mapio.h
@@ -37,6 +37,7 @@
*/
#include <stdarg.h>
+#include "maphash.h"
#ifdef __cplusplus
extern "C" {
@@ -105,7 +106,8 @@ extern "C" {
void MS_DLL_EXPORT msIO_Cleanup(void);
char MS_DLL_EXPORT *msIO_stripStdoutBufferContentType(void);
void MS_DLL_EXPORT msIO_stripStdoutBufferContentHeaders(void);
-
+ hashTableObj MS_DLL_EXPORT *msIO_getAndStripStdoutBufferMimeHeaders(void);
+
msIOContext *msIO_pushStdoutToBufferAndGetOldContext(void);
void msIO_restoreOldStdoutContext(msIOContext *context_to_restore);
diff --git a/maplegend.c b/maplegend.c
index b02f12c..4c2d377 100644
--- a/maplegend.c
+++ b/maplegend.c
@@ -387,6 +387,7 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass,
initTextSymbol(&ts);
msPopulateTextSymbolForLabelAndString(&ts,theclass->labels[0],msStrdup("Az"),lp->scalefactor*image_draw->resolutionfactor,image_draw->resolutionfactor, duplicate_always);
ts.label->size = height - 1;
+ ts.rotation = 0;
ret = msComputeTextPath(map,&ts);
if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
textstartpt = get_metrics(&marker,MS_CC,ts.textpath,0,0,0,0,NULL);
diff --git a/mapogcfilter.c b/mapogcfilter.c
index 7da559a..f4a6dfe 100644
--- a/mapogcfilter.c
+++ b/mapogcfilter.c
@@ -164,7 +164,8 @@ char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char
if (paszElements && numelements > 0) {
if (forcecharcter)
bIscharacter = MS_TRUE;
- bIscharacter= !FLTIsNumeric(paszElements[0]);
+ else
+ bIscharacter= !FLTIsNumeric(paszElements[0]);
pszTmpExpression = msStringConcatenate(pszTmpExpression, "(");
for (i=0; i<numelements; i++) {
diff --git a/mapogcsld.c b/mapogcsld.c
index 8b76ea2..26122e3 100644
--- a/mapogcsld.c
+++ b/mapogcsld.c
@@ -3418,7 +3418,7 @@ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer,
}
} else
bGenerateDefaultSymbol =1;
- } else if (psSymbol->type == MS_SYMBOL_PIXMAP) {
+ } else if (psSymbol->type == MS_SYMBOL_PIXMAP || psSymbol->type == MS_SYMBOL_SVG) {
if (psSymbol->name) {
pszURL = msLookupHashTable(&(psLayer->metadata), "WMS_SLD_SYMBOL_URL");
if (!pszURL)
@@ -3455,8 +3455,8 @@ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer,
snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/png</%sFormat>\n",
sNameSpace, sNameSpace);
} else
- snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s</%sFormat>\n", "image/gif",
- sNameSpace, sNameSpace);
+ snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s</%sFormat>\n", sNameSpace,
+ (psSymbol->type ==MS_SYMBOL_SVG)?"image/svg+xml":"image/gif",sNameSpace);
pszSLD = msStringConcatenate(pszSLD, szTmp);
diff --git a/mapogr.cpp b/mapogr.cpp
index 7012f66..5460c33 100644
--- a/mapogr.cpp
+++ b/mapogr.cpp
@@ -33,6 +33,8 @@
#include "mapproject.h"
#include "mapthread.h"
#include "mapows.h"
+#include <string>
+#include <vector>
#if defined(USE_OGR) || defined(USE_GDAL)
# include "gdal_version.h"
@@ -77,6 +79,8 @@ typedef struct ms_ogr_file_info_t {
int bPaging;
+ char* pszWHERE;
+
} msOGRFileInfo;
static int msOGRLayerIsOpen(layerObj *layer);
@@ -1298,6 +1302,7 @@ msOGRFileOpen(layerObj *layer, const char *connection )
psInfo->bPaging = false;
psInfo->bHasSpatialIndex = false;
psInfo->pszTablePrefix = NULL;
+ psInfo->pszWHERE = NULL;
// GDAL 1.x API
OGRSFDriverH dr = OGR_DS_GetDriver(hDS);
@@ -1695,6 +1700,7 @@ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo )
msFree(psInfo->pszMainTableName);
msFree(psInfo->pszRowId);
msFree(psInfo->pszTablePrefix);
+ msFree(psInfo->pszWHERE);
CPLFree(psInfo);
@@ -2170,6 +2176,9 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
layer->filter.native_string ||
(psInfo->bPaging && layer->maxfeatures > 0)) ) {
+ const bool bHasGeometry =
+ OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone;
+
if( psInfo->nLayerIndex == -1 && select == NULL ) {
select = msStrdup(psInfo->pszLayerDef);
/* If nLayerIndex == -1 then the layer is an SQL result ... free it */
@@ -2325,18 +2334,23 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
bSpatialiteOrGPKGAddOrderByFID = true;
}
- if (psInfo->dialect) {
- if (EQUAL(psInfo->dialect, "Spatialite") ||
- EQUAL(psInfo->dialect, "GPKG") ||
- EQUAL(psInfo->dialect, "PostgreSQL")) {
- const char *sql = layer->filter.native_string;
- if (sql && *sql != '\0') {
- if (filter) filter = msStringConcatenate(filter, "AND ");
- filter = msStringConcatenate(filter, "(");
- filter = msStringConcatenate(filter, sql);
- filter = msStringConcatenate(filter, ")");
- }
- }
+ const char *sql = layer->filter.native_string;
+ if (psInfo->dialect && sql && *sql != '\0' &&
+ (EQUAL(psInfo->dialect, "Spatialite") ||
+ EQUAL(psInfo->dialect, "GPKG") ||
+ EQUAL(psInfo->dialect, "PostgreSQL")) )
+ {
+ if (filter) filter = msStringConcatenate(filter, " AND ");
+ filter = msStringConcatenate(filter, "(");
+ filter = msStringConcatenate(filter, sql);
+ filter = msStringConcatenate(filter, ")");
+ }
+ else if( psInfo->pszWHERE )
+ {
+ if (filter) filter = msStringConcatenate(filter, " AND ");
+ filter = msStringConcatenate(filter, "(");
+ filter = msStringConcatenate(filter, psInfo->pszWHERE);
+ filter = msStringConcatenate(filter, ")");
}
bool bOffsetAlreadyAdded = false;
@@ -2450,8 +2464,40 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
{
OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer );
}
- psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, NULL, NULL );
+
+ OGRGeometryH hGeom = NULL;
+ if( psInfo->dialect == NULL &&
+ bHasGeometry && bIsValidRect ) {
+ if (rect.minx == rect.maxx && rect.miny == rect.maxy) {
+ hGeom = OGR_G_CreateGeometry( wkbPoint );
+ OGR_G_SetPoint_2D( hGeom, 0, rect.minx, rect.miny );
+ } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) {
+ hGeom = OGR_G_CreateGeometry( wkbLineString );
+ OGR_G_AddPoint_2D( hGeom, rect.minx, rect.miny );
+ OGR_G_AddPoint_2D( hGeom, rect.maxx, rect.maxy );
+ } else {
+ hGeom = OGR_G_CreateGeometry( wkbPolygon );
+ OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
+
+ OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny);
+ OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny);
+ OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy);
+ OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy);
+ OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny);
+ OGR_G_AddGeometryDirectly( hGeom, hRing );
+ }
+
+ if (layer->debug >= MS_DEBUGLEVEL_VVV)
+ {
+ msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n",
+ rect.minx, rect.miny, rect.maxx, rect.maxy );
+ }
+ }
+
+ psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, hGeom, NULL );
psInfo->nLayerIndex = -1;
+ if( hGeom != NULL )
+ OGR_G_DestroyGeometry(hGeom);
if( psInfo->hLayer == NULL ) {
RELEASE_OGR_LOCK;
@@ -2475,6 +2521,20 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
}
+ if( psInfo->pszWHERE )
+ {
+ if( pszOGRFilter )
+ {
+ pszOGRFilter = msStringConcatenate(pszOGRFilter, " AND (");
+ pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE);
+ pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
+ }
+ else
+ {
+ pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE);
+ }
+ }
+
ACQUIRE_OGR_LOCK;
if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone && bIsValidRect ) {
@@ -2525,12 +2585,7 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
CPLErrorReset();
if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) {
- msSetError(MS_OGRERR, "SetAttributeFilter() failed on layer %s. Check logs.", "msOGRFileWhichShapes()", layer->name?layer->name:"(null)");
- msDebug("SetAttributeFilter(%s) failed on layer %s.\n%s\n", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
- RELEASE_OGR_LOCK;
- msFree(pszOGRFilter);
- msFree(select);
- return MS_FAILURE;
+ msDebug("SetAttributeFilter(%s) failed on layer %s.\n%s\n", pszOGRFilter, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
}
msFree(pszOGRFilter);
} else
@@ -3035,6 +3090,613 @@ NextFile:
return MS_SUCCESS;
}
+/************************************************************************/
+/* msExprNode */
+/************************************************************************/
+
+class msExprNode
+{
+ public:
+ std::vector<msExprNode*> m_aoChildren;
+ int m_nToken;
+ std::string m_osVal;
+ double m_dfVal;
+ struct tm m_tmVal;
+
+ msExprNode() : m_nToken(0), m_dfVal(0.0) {}
+ ~msExprNode();
+};
+
+msExprNode::~msExprNode()
+{
+ for(size_t i=0;i<m_aoChildren.size();++i)
+ delete m_aoChildren[i];
+}
+
+/************************************************************************/
+/* exprGetPriority() */
+/************************************************************************/
+
+static int exprGetPriority(int token)
+{
+ if (token == MS_TOKEN_LOGICAL_NOT)
+ return 9;
+ else if (token == '*' || token == '/' || token == '%' )
+ return 8;
+ else if (token == '+' || token == '-' )
+ return 7;
+ else if (token == MS_TOKEN_COMPARISON_GE ||
+ token == MS_TOKEN_COMPARISON_GT ||
+ token == MS_TOKEN_COMPARISON_LE ||
+ token == MS_TOKEN_COMPARISON_LT ||
+ token == MS_TOKEN_COMPARISON_IN)
+ return 6;
+ else if (token == MS_TOKEN_COMPARISON_EQ ||
+ token == MS_TOKEN_COMPARISON_IEQ ||
+ token == MS_TOKEN_COMPARISON_LIKE ||
+ token == MS_TOKEN_COMPARISON_RE ||
+ token == MS_TOKEN_COMPARISON_IRE ||
+ token == MS_TOKEN_COMPARISON_NE)
+ return 5;
+ else if (token == MS_TOKEN_LOGICAL_AND)
+ return 4;
+ else if (token == MS_TOKEN_LOGICAL_OR)
+ return 3;
+ else
+ return 0;
+}
+
+/************************************************************************/
+/* BuildExprTree() */
+/************************************************************************/
+
+static msExprNode* BuildExprTree(tokenListNodeObjPtr node,
+ tokenListNodeObjPtr* pNodeNext,
+ int nParenthesisLevel)
+{
+ msExprNode* poRet = NULL;
+ std::vector<msExprNode*> aoStackOp, aoStackVal;
+ while( node != NULL )
+ {
+ if( node->token == '(' )
+ {
+ msExprNode* subExpr = BuildExprTree(node->next, &node,
+ nParenthesisLevel + 1);
+ if( subExpr == NULL )
+ {
+ goto fail;
+ }
+ aoStackVal.push_back(subExpr);
+ continue;
+ }
+ else if( node->token == ')' )
+ {
+ if( nParenthesisLevel > 0 )
+ {
+ break;
+ }
+ goto fail;
+ }
+ else if( node->token == '+' ||
+ node->token == '-' ||
+ node->token == '*' ||
+ node->token == '/' ||
+ node->token == '%' ||
+ node->token == MS_TOKEN_LOGICAL_NOT ||
+ node->token == MS_TOKEN_LOGICAL_AND ||
+ node->token == MS_TOKEN_LOGICAL_OR ||
+ node->token == MS_TOKEN_COMPARISON_GE ||
+ node->token == MS_TOKEN_COMPARISON_GT ||
+ node->token == MS_TOKEN_COMPARISON_LE ||
+ node->token == MS_TOKEN_COMPARISON_LT ||
+ node->token == MS_TOKEN_COMPARISON_EQ ||
+ node->token == MS_TOKEN_COMPARISON_IEQ ||
+ node->token == MS_TOKEN_COMPARISON_LIKE ||
+ node->token == MS_TOKEN_COMPARISON_NE ||
+ node->token == MS_TOKEN_COMPARISON_RE ||
+ node->token == MS_TOKEN_COMPARISON_IRE ||
+ node->token == MS_TOKEN_COMPARISON_IN )
+ {
+ while( !aoStackOp.empty() &&
+ exprGetPriority(node->token) <=
+ exprGetPriority(aoStackOp.back()->m_nToken))
+ {
+ msExprNode* val1 = NULL;
+ msExprNode* val2 = NULL;
+ msExprNode* newNode = NULL;
+ if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT)
+ {
+ if( aoStackVal.empty() )
+ goto fail;
+ val2 = aoStackVal.back();
+ aoStackVal.pop_back();
+ }
+ if( aoStackVal.empty() )
+ goto fail;
+ val1 = aoStackVal.back();
+ aoStackVal.pop_back();
+
+ newNode = new msExprNode;
+ newNode->m_nToken = aoStackOp.back()->m_nToken;
+ newNode->m_aoChildren.push_back(val1);
+ if( val2 )
+ newNode->m_aoChildren.push_back(val2);
+ aoStackVal.push_back(newNode);
+ delete aoStackOp.back();
+ aoStackOp.pop_back();
+ }
+
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ aoStackOp.push_back(newNode);
+ }
+ else if( node->token == ',' )
+ {
+ }
+ else if( node->token == MS_TOKEN_COMPARISON_INTERSECTS ||
+ node->token == MS_TOKEN_COMPARISON_DISJOINT ||
+ node->token == MS_TOKEN_COMPARISON_TOUCHES ||
+ node->token == MS_TOKEN_COMPARISON_OVERLAPS ||
+ node->token == MS_TOKEN_COMPARISON_CROSSES ||
+ node->token == MS_TOKEN_COMPARISON_DWITHIN ||
+ node->token == MS_TOKEN_COMPARISON_BEYOND ||
+ node->token == MS_TOKEN_COMPARISON_WITHIN ||
+ node->token == MS_TOKEN_COMPARISON_CONTAINS ||
+ node->token == MS_TOKEN_COMPARISON_EQUALS ||
+ node->token == MS_TOKEN_FUNCTION_LENGTH ||
+ node->token == MS_TOKEN_FUNCTION_TOSTRING ||
+ node->token == MS_TOKEN_FUNCTION_COMMIFY ||
+ node->token == MS_TOKEN_FUNCTION_AREA ||
+ node->token == MS_TOKEN_FUNCTION_ROUND ||
+ node->token == MS_TOKEN_FUNCTION_FROMTEXT ||
+ node->token == MS_TOKEN_FUNCTION_BUFFER ||
+ node->token == MS_TOKEN_FUNCTION_DIFFERENCE ||
+ node->token == MS_TOKEN_FUNCTION_SIMPLIFY ||
+ node->token == MS_TOKEN_FUNCTION_SIMPLIFYPT ||
+ node->token == MS_TOKEN_FUNCTION_GENERALIZE ||
+ node->token == MS_TOKEN_FUNCTION_SMOOTHSIA ||
+ node->token == MS_TOKEN_FUNCTION_JAVASCRIPT ||
+ node->token == MS_TOKEN_FUNCTION_UPPER ||
+ node->token == MS_TOKEN_FUNCTION_LOWER ||
+ node->token == MS_TOKEN_FUNCTION_INITCAP ||
+ node->token == MS_TOKEN_FUNCTION_FIRSTCAP )
+ {
+ if( node->next && node->next->token == '(' )
+ {
+ msExprNode* subExpr = BuildExprTree(node->next->next, &node,
+ nParenthesisLevel + 1);
+ if( subExpr == NULL )
+ {
+ goto fail;
+ }
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ if( subExpr->m_nToken == 0 )
+ {
+ newNode->m_aoChildren = subExpr->m_aoChildren;
+ subExpr->m_aoChildren.clear();
+ delete subExpr;
+ }
+ else
+ {
+ newNode->m_aoChildren.push_back(subExpr);
+ }
+ aoStackVal.push_back(newNode);
+ continue;
+ }
+ else
+ goto fail;
+ }
+ else if( node->token == MS_TOKEN_LITERAL_NUMBER ||
+ node->token == MS_TOKEN_LITERAL_BOOLEAN )
+ {
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ newNode->m_dfVal = node->tokenval.dblval;
+ aoStackVal.push_back(newNode);
+ }
+ else if( node->token == MS_TOKEN_LITERAL_STRING )
+ {
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ newNode->m_osVal = node->tokenval.strval;
+ aoStackVal.push_back(newNode);
+ }
+ else if( node->token == MS_TOKEN_LITERAL_TIME )
+ {
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ newNode->m_tmVal = node->tokenval.tmval;
+ aoStackVal.push_back(newNode);
+ }
+ else if( node->token == MS_TOKEN_LITERAL_SHAPE )
+ {
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ char *wkt = msShapeToWKT(node->tokenval.shpval);
+ newNode->m_osVal = wkt;
+ msFree(wkt);
+ aoStackVal.push_back(newNode);
+ }
+ else if( node->token == MS_TOKEN_BINDING_DOUBLE ||
+ node->token == MS_TOKEN_BINDING_INTEGER ||
+ node->token == MS_TOKEN_BINDING_STRING ||
+ node->token == MS_TOKEN_BINDING_TIME )
+ {
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ newNode->m_osVal = node->tokenval.bindval.item;
+ aoStackVal.push_back(newNode);
+ }
+ else
+ {
+ msExprNode* newNode = new msExprNode;
+ newNode->m_nToken = node->token;
+ aoStackVal.push_back(newNode);
+ }
+
+ node = node->next;
+ }
+
+ while( !aoStackOp.empty() )
+ {
+ msExprNode* val1 = NULL;
+ msExprNode* val2 = NULL;
+ msExprNode* newNode = NULL;
+ if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT)
+ {
+ if( aoStackVal.empty() )
+ goto fail;
+ val2 = aoStackVal.back();
+ aoStackVal.pop_back();
+ }
+ if( aoStackVal.empty() )
+ goto fail;
+ val1 = aoStackVal.back();
+ aoStackVal.pop_back();
+
+ newNode = new msExprNode;
+ newNode->m_nToken = aoStackOp.back()->m_nToken;
+ newNode->m_aoChildren.push_back(val1);
+ if( val2 )
+ newNode->m_aoChildren.push_back(val2);
+ aoStackVal.push_back(newNode);
+ delete aoStackOp.back();
+ aoStackOp.pop_back();
+ }
+
+ if( aoStackVal.size() == 1 )
+ poRet = aoStackVal.back();
+ else if( aoStackVal.size() > 1 )
+ {
+ poRet = new msExprNode;
+ poRet->m_aoChildren = aoStackVal;
+ }
+
+ if( pNodeNext )
+ *pNodeNext = node ? node->next : NULL;
+
+ return poRet;
+
+fail:
+ for( size_t i=0; i<aoStackOp.size(); ++i )
+ delete aoStackOp[i];
+ for( size_t i=0; i<aoStackVal.size(); ++i )
+ delete aoStackVal[i];
+ return NULL;
+}
+
+/**********************************************************************
+ * msOGRExtractTopSpatialFilter()
+ **********************************************************************/
+static int msOGRExtractTopSpatialFilter( msOGRFileInfo *info,
+ const msExprNode* expr,
+ const msExprNode** pSpatialFilterNode )
+{
+ if( expr == NULL )
+ return MS_FALSE;
+
+ if( expr->m_nToken == MS_TOKEN_COMPARISON_INTERSECTS &&
+ expr->m_aoChildren.size() == 2 &&
+ expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_SHAPE )
+ {
+ if( info->rect_is_defined )
+ {
+ // Several intersects...
+ *pSpatialFilterNode = NULL;
+ info->rect_is_defined = MS_FALSE;
+ return MS_FALSE;
+ }
+ OGRGeometryH hSpatialFilter = NULL;
+ char* wkt = const_cast<char*>(expr->m_aoChildren[1]->m_osVal.c_str());
+ OGRErr e = OGR_G_CreateFromWkt(&wkt, NULL, &hSpatialFilter);
+ if (e == OGRERR_NONE) {
+ OGREnvelope env;
+ OGR_G_GetEnvelope(hSpatialFilter, &env);
+ info->rect.minx = env.MinX;
+ info->rect.miny = env.MinY;
+ info->rect.maxx = env.MaxX;
+ info->rect.maxy = env.MaxY;
+ info->rect_is_defined = true;
+ *pSpatialFilterNode = expr;
+ OGR_G_DestroyGeometry(hSpatialFilter);
+ return MS_TRUE;
+ }
+ return MS_FALSE;
+ }
+
+ if( expr->m_nToken == MS_TOKEN_LOGICAL_AND &&
+ expr->m_aoChildren.size() == 2 )
+ {
+ return msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[0],
+ pSpatialFilterNode) &&
+ msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[1],
+ pSpatialFilterNode);
+ }
+
+ return MS_TRUE;
+}
+
+/**********************************************************************
+ * msOGRTranslatePartialMSExpressionToOGRSQL()
+ *
+ * Tries to partially translate a mapserver expression to SQL
+ **********************************************************************/
+
+static std::string msOGRGetTokenText(int nToken)
+{
+ switch( nToken )
+ {
+ case '*':
+ case '+':
+ case '-':
+ case '/':
+ case '%':
+ return std::string(1, static_cast<char>(nToken));
+
+ case MS_TOKEN_COMPARISON_GE: return ">=";
+ case MS_TOKEN_COMPARISON_GT: return ">";
+ case MS_TOKEN_COMPARISON_LE: return "<=";
+ case MS_TOKEN_COMPARISON_LT: return "<";
+ case MS_TOKEN_COMPARISON_EQ: return "=";
+ case MS_TOKEN_COMPARISON_NE: return "!=";
+ case MS_TOKEN_COMPARISON_LIKE: return "LIKE";
+
+ default:
+ return std::string();
+ }
+}
+
+static std::string msOGRTranslatePartialInternal(layerObj* layer,
+ const msExprNode* expr,
+ const msExprNode* spatialFilterNode,
+ bool& bPartialFilter)
+{
+ switch( expr->m_nToken )
+ {
+ case MS_TOKEN_LOGICAL_NOT:
+ {
+ std::string osTmp(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+ if( osTmp.empty() )
+ return std::string();
+ return "(NOT " + osTmp + ")";
+ }
+
+ case MS_TOKEN_LOGICAL_AND:
+ {
+ // We can deal with partially translated children
+ std::string osTmp1(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+ std::string osTmp2(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter ));
+ if( !osTmp1.empty() && !osTmp2.empty() )
+ {
+ return "(" + osTmp1 + " AND " + osTmp2 + ")";
+ }
+ else if( !osTmp1.empty() )
+ return osTmp1;
+ else
+ return osTmp2;
+ }
+
+ case MS_TOKEN_LOGICAL_OR:
+ {
+ // We can NOT deal with partially translated children
+ std::string osTmp1(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+ std::string osTmp2(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter ));
+ if( !osTmp1.empty() && !osTmp2.empty() )
+ {
+ return "(" + osTmp1 + " OR " + osTmp2 + ")";
+ }
+ else
+ return std::string();
+ }
+
+ case '*':
+ case '+':
+ case '-':
+ case '/':
+ case '%':
+ case MS_TOKEN_COMPARISON_GE:
+ case MS_TOKEN_COMPARISON_GT:
+ case MS_TOKEN_COMPARISON_LE:
+ case MS_TOKEN_COMPARISON_LT:
+ case MS_TOKEN_COMPARISON_EQ:
+ case MS_TOKEN_COMPARISON_NE:
+ {
+ std::string osTmp1(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+ std::string osTmp2(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter ));
+ if( !osTmp1.empty() && !osTmp2.empty() )
+ {
+ if( expr->m_nToken == MS_TOKEN_COMPARISON_EQ &&
+ osTmp2 == "'_MAPSERVER_NULL_'" )
+ {
+ return "(" + osTmp1 + " IS NULL )";
+ }
+ if( expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_STRING )
+ {
+ char md_item_name[256];
+ snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type",
+ expr->m_aoChildren[0]->m_osVal.c_str() );
+ const char* type =
+ msLookupHashTable(&(layer->metadata), md_item_name);
+ // Cast if needed (or unsure)
+ if( type == NULL || !EQUAL(type, "Character") )
+ {
+ osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))";
+ }
+ }
+ return "(" + osTmp1 + " " + msOGRGetTokenText(expr->m_nToken) +
+ " " + osTmp2 + ")";
+ }
+ else
+ return std::string();
+ }
+
+ case MS_TOKEN_COMPARISON_RE:
+ {
+ std::string osTmp1(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+ if( expr->m_aoChildren[1]->m_nToken != MS_TOKEN_LITERAL_STRING )
+ {
+ return std::string();
+ }
+ std::string osRE("'");
+ const size_t nSize = expr->m_aoChildren[1]->m_osVal.size();
+ bool bHasUsedEscape = false;
+ for( size_t i=0; i<nSize;i++ )
+ {
+ if( i == 0 && expr->m_aoChildren[1]->m_osVal[i] == '^' )
+ continue;
+ if( expr->m_aoChildren[1]->m_osVal[i] == '.' )
+ {
+ if( i+1<nSize &&
+ expr->m_aoChildren[1]->m_osVal[i+1] == '*' )
+ {
+ osRE += "%";
+ i++;
+ }
+ else
+ {
+ osRE += "_";
+ }
+ }
+ else if( expr->m_aoChildren[1]->m_osVal[i] == '\\' &&
+ i+1<nSize )
+ {
+ bHasUsedEscape = true;
+ osRE += 'X';
+ osRE += expr->m_aoChildren[1]->m_osVal[i+1];
+ i++;
+ }
+ else if( expr->m_aoChildren[1]->m_osVal[i] == 'X' ||
+ expr->m_aoChildren[1]->m_osVal[i] == '%' ||
+ expr->m_aoChildren[1]->m_osVal[i] == '_' )
+ {
+ bHasUsedEscape = true;
+ osRE += 'X';
+ osRE += expr->m_aoChildren[1]->m_osVal[i];
+ }
+ else
+ {
+ osRE += expr->m_aoChildren[1]->m_osVal[i];
+ }
+ }
+ osRE += "'";
+ char md_item_name[256];
+ snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type",
+ expr->m_aoChildren[0]->m_osVal.c_str() );
+ const char* type =
+ msLookupHashTable(&(layer->metadata), md_item_name);
+ // Cast if needed (or unsure)
+ if( type == NULL || !EQUAL(type, "Character") )
+ {
+ osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))";
+ }
+ std::string osRet( "(" + osTmp1 + " LIKE " + osRE );
+ if( bHasUsedEscape )
+ osRet += " ESCAPE 'X'";
+ osRet += ")";
+ return osRet;
+ }
+
+ case MS_TOKEN_COMPARISON_IN:
+ {
+ std::string osTmp1(msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+ std::string osRet = "(" + osTmp1 + " IN (";
+ for( size_t i=0; i< expr->m_aoChildren[1]->m_aoChildren.size(); ++i )
+ {
+ if( i > 0 )
+ osRet += ", ";
+ osRet += msOGRTranslatePartialInternal(
+ layer, expr->m_aoChildren[1]->m_aoChildren[i],
+ spatialFilterNode, bPartialFilter );
+ }
+ osRet += ")";
+ return osRet;
+ }
+
+ case MS_TOKEN_LITERAL_NUMBER:
+ case MS_TOKEN_LITERAL_BOOLEAN:
+ {
+ return std::string(CPLSPrintf("%.18g", expr->m_dfVal));
+ }
+
+ case MS_TOKEN_LITERAL_STRING:
+ {
+ char *stresc = msOGREscapeSQLParam(layer, expr->m_osVal.c_str());
+ std::string osRet("'" + std::string(stresc) + "'");
+ msFree(stresc);
+ return osRet;
+ }
+
+ case MS_TOKEN_LITERAL_TIME:
+ {
+#ifdef notdef
+ // Breaks tests in msautotest/wxs/wfs_time_ogr.map
+ return std::string(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
+ expr->m_tmVal.tm_year+1900,
+ expr->m_tmVal.tm_mon+1,
+ expr->m_tmVal.tm_mday,
+ expr->m_tmVal.tm_hour,
+ expr->m_tmVal.tm_min,
+ expr->m_tmVal.tm_sec));
+#endif
+ return std::string();
+ }
+
+ case MS_TOKEN_BINDING_DOUBLE:
+ case MS_TOKEN_BINDING_INTEGER:
+ case MS_TOKEN_BINDING_STRING:
+ case MS_TOKEN_BINDING_TIME:
+ {
+ char* pszTmp = msOGRGetQuotedItem(layer, expr->m_osVal.c_str());
+ std::string osRet(pszTmp);
+ msFree(pszTmp);
+ return osRet;
+ }
+
+ case MS_TOKEN_COMPARISON_INTERSECTS:
+ {
+ if( expr != spatialFilterNode )
+ bPartialFilter = true;
+ return std::string();
+ }
+
+ default:
+ {
+ bPartialFilter = true;
+ return std::string();
+ }
+ }
+}
+
#endif /* def USE_OGR */
/* ==================================================================
@@ -3053,25 +3715,61 @@ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
#ifdef USE_OGR
msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo;
+ msFree(layer->filter.native_string);
+ layer->filter.native_string = NULL;
+
+ msFree(info->pszWHERE);
+ info->pszWHERE = NULL;
+
// reasons to not produce native string: not simple layer, or an explicit deny
char *do_this = msLayerGetProcessingKey(layer, "NATIVE_SQL"); // default is YES
if (do_this && strcmp(do_this, "NO") == 0) {
return MS_SUCCESS;
}
+ tokenListNodeObjPtr node = psFilter->tokens;
+ msExprNode* expr = BuildExprTree(node, NULL, 0);
+ info->rect_is_defined = MS_FALSE;
+ const msExprNode* spatialFilterNode = NULL;
+ if( expr )
+ msOGRExtractTopSpatialFilter( info, expr, &spatialFilterNode );
+
// more reasons to not produce native string: not a recognized driver
- if (!info->dialect) {
+ if (!info->dialect)
+ {
+ // in which case we might still want to try to get a partial WHERE clause
+ if( filteritem == NULL && expr )
+ {
+ bool bPartialFilter = false;
+ std::string osSQL( msOGRTranslatePartialInternal(layer, expr,
+ spatialFilterNode,
+ bPartialFilter) );
+ if( !osSQL.empty() )
+ {
+ info->pszWHERE = msStrdup(osSQL.c_str());
+ if( bPartialFilter )
+ {
+ msDebug("Full filter has only been partially "
+ "translated to OGR filter %s\n",
+ info->pszWHERE);
+ }
+ }
+ else if( bPartialFilter )
+ {
+ msDebug("Filter could not be translated to OGR filter\n");
+ }
+ }
+ delete expr;
return MS_SUCCESS;
}
char *sql = NULL;
- tokenListNodeObjPtr node = psFilter->tokens;
- // node may be NULL if layer->filter.string != NULL and layer->filteritem != NULL
+ // node may be NULL if layer->filter.string != NULL and filteritem != NULL
// this is simple filter but string is regex
- if (node == NULL && layer->filteritem != NULL && layer->filter.string != NULL) {
+ if (node == NULL && filteritem != NULL && layer->filter.string != NULL) {
sql = msStringConcatenate(sql, "\"");
- sql = msStringConcatenate(sql, layer->filteritem);
+ sql = msStringConcatenate(sql, filteritem);
sql = msStringConcatenate(sql, "\"");
if (EQUAL(info->dialect, "PostgreSQL") ) {
sql = msStringConcatenate(sql, " ~ ");
@@ -3082,54 +3780,7 @@ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
sql = msStringConcatenate(sql, layer->filter.string);
sql = msStringConcatenate(sql, "'");
}
- // test if there is a "top" level intersects (see FLTValidForBBoxFilter) for a bounding box
- if (node != NULL) {
- int is_top_level_and = 0;
- int has_bounding_box = 0;
- tokenListNodeObjPtr bounding_box_node = NULL;
- tokenListNodeObjPtr x = psFilter->tokens;
- int d = 0;
- while (x != NULL) {
- if (x->token == '(') d++;
- if (x->token == ')') d--;
- if (x->token == MS_TOKEN_COMPARISON_INTERSECTS && d == 0) {
- has_bounding_box = 1;
- bounding_box_node = x;
- }
- if (d == 1) {
- if (x->token == MS_TOKEN_COMPARISON_INTERSECTS)
- bounding_box_node = x;
- else if (x->token == MS_TOKEN_LOGICAL_AND)
- is_top_level_and = 1;
- }
- if (is_top_level_and && bounding_box_node)
- has_bounding_box = 1;
- x = x->next;
- }
- if (has_bounding_box) {
- x = bounding_box_node;
- x = x->next; // skip fct
- x = x->next; // skip (
- x = x->next; // skip field name
- x = x->next; // skip ,
- char *a = msOGRGetToken(layer, &x);
- // skip "ST_GeomFromText(' from a
- char *wkt = a+17;
- OGRGeometryH hSpatialFilter;
- OGRErr e = OGR_G_CreateFromWkt(&wkt, NULL, &hSpatialFilter);
- msFree(a);
- if (e == OGRERR_NONE) {
- OGREnvelope env;
- OGR_G_GetEnvelope(hSpatialFilter, &env);
- info->rect.minx = env.MinX;
- info->rect.miny = env.MinY;
- info->rect.maxx = env.MaxX;
- info->rect.maxy = env.MaxY;
- info->rect_is_defined = true;
- OGR_G_DestroyGeometry(hSpatialFilter);
- }
- }
- }
+
while (node != NULL) {
if (node->next && node->next->token == MS_TOKEN_COMPARISON_IEQ) {
@@ -3223,12 +3874,38 @@ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
}
layer->filter.native_string = sql;
+ delete expr;
return MS_SUCCESS;
fail:
// error producing native string
- fprintf(stderr, "Note: Error parsing token list, could produce only: %s\n", sql);
+ msDebug("Note: Error parsing token list, could produce only: %s. Trying in partial mode\n", sql);
msFree(sql);
- return MS_FAILURE;
+
+ // in which case we might still want to try to get a partial WHERE clause
+ if( expr )
+ {
+ bool bPartialFilter = false;
+ std::string osSQL( msOGRTranslatePartialInternal(layer, expr,
+ spatialFilterNode,
+ bPartialFilter) );
+ if( !osSQL.empty() )
+ {
+ info->pszWHERE = msStrdup(osSQL.c_str());
+ if( bPartialFilter )
+ {
+ msDebug("Full filter has only been partially "
+ "translated to OGR filter %s\n",
+ info->pszWHERE);
+ }
+ }
+ else if( bPartialFilter )
+ {
+ msDebug("Filter could not be translated to OGR filter\n");
+ }
+ }
+ delete expr;
+
+ return MS_SUCCESS;
#else
/* ------------------------------------------------------------------
* OGR Support not included...
diff --git a/maporaclespatial.c b/maporaclespatial.c
index afc679c..2f44ebc 100644
--- a/maporaclespatial.c
+++ b/maporaclespatial.c
@@ -38,6 +38,7 @@
#include "mapserver.h"
#include "maptime.h"
+#include "mapows.h"
#include <assert.h>
@@ -399,8 +400,10 @@ static int msSplitData( char *data, char **geometry_column_name, char **table_na
break; /* stop on spaces */
/* double the size of the table_name array if necessary */
if (i == table_name_size) {
+ size_t tgt_offset = tgt - *table_name;
table_name_size *= 2;
*table_name = (char *) realloc(*table_name,sizeof(char *) * table_name_size);
+ tgt = *table_name + tgt_offset;
}
*tgt = *src;
}
diff --git a/mappostgis.c b/mappostgis.c
index 4bec985..cc4edf8 100644
--- a/mappostgis.c
+++ b/mappostgis.c
@@ -3636,9 +3636,13 @@ int msPostGISLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *
native_string = msStringConcatenate(native_string, "FALSE");
break;
case MS_TOKEN_LITERAL_NUMBER:
- strtmpl = "%lf";
- snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16);
- sprintf(snippet, strtmpl, node->tokenval.dblval);
+ snippet = (char *) msSmallMalloc(32);
+ if( node->tokenval.dblval >= INT_MIN &&
+ node->tokenval.dblval <= INT_MAX &&
+ node->tokenval.dblval == (int)node->tokenval.dblval )
+ sprintf(snippet, "%d", (int)node->tokenval.dblval);
+ else
+ sprintf(snippet, "%.18g", node->tokenval.dblval);
native_string = msStringConcatenate(native_string, snippet);
msFree(snippet);
break;
diff --git a/mapproject.c b/mapproject.c
index 1a10390..c90cc54 100644
--- a/mapproject.c
+++ b/mapproject.c
@@ -954,6 +954,40 @@ int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect)
char *over = "+over";
int ret;
projectionObj in_over,out_over,*inp,*outp;
+
+#if USE_PROJ
+ /* Detect projecting from north polar stereographic to longlat */
+ if( in && !in->gt.need_geotransform &&
+ out && !out->gt.need_geotransform &&
+ !pj_is_latlong(in->proj) && pj_is_latlong(out->proj) )
+ {
+ pointObj p;
+ p.x = 0.0;
+ p.y = 0.0;
+ if( msProjectPoint(in, out, &p) == MS_SUCCESS &&
+ fabs(p.y - 90) < 1e-8 )
+ {
+ /* Is the pole in the rectangle ? */
+ if( 0 >= rect->minx && 0 >= rect->miny &&
+ 0 <= rect->maxx && 0 <= rect->maxy )
+ {
+ if( msProjectRectAsPolygon(in, out, rect ) == MS_SUCCESS )
+ {
+ rect->minx = -180.0;
+ rect->maxx = 180.0;
+ rect->maxy = 90.0;
+ return MS_SUCCESS;
+ }
+ }
+ /* Are we sure the dateline is not enclosed ? */
+ else if( rect->maxy < 0 || rect->maxx < 0 || rect->minx > 0 )
+ {
+ return msProjectRectAsPolygon(in, out, rect );
+ }
+ }
+ }
+#endif
+
/*
* Issue #4892: When projecting a rectangle we do not want proj to wrap resulting
* coordinates around the dateline, as in practice a requested bounding box of
diff --git a/mapquery.c b/mapquery.c
index 968354a..df0b2ee 100644
--- a/mapquery.c
+++ b/mapquery.c
@@ -673,6 +673,7 @@ int msQueryByFilter(mapObj *map)
const rectObj invalid_rect = MS_INIT_INVALID_RECT;
shapeObj shape;
+ int paging;
int nclasses = 0;
int *classgroup = NULL;
@@ -732,12 +733,14 @@ int msQueryByFilter(mapObj *map)
if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue;
}
+ paging = msLayerGetPaging(lp);
msLayerClose(lp); /* reset */
status = msLayerOpen(lp);
if(status != MS_SUCCESS) goto query_error;
+ msLayerEnablePaging(lp, paging);
/* disable driver paging */
- msLayerEnablePaging(lp, MS_FALSE);
+ // msLayerEnablePaging(lp, MS_FALSE);
old_filteritem = lp->filteritem; /* cache the existing filter/filteritem */
msInitExpression(&old_filter);
@@ -815,7 +818,7 @@ int msQueryByFilter(mapObj *map)
#endif
/* Should we skip this feature? */
- if (!msLayerGetPaging(lp) && map->query.startindex > 1) {
+ if (!paging && map->query.startindex > 1) {
--map->query.startindex;
msFreeShape(&shape);
continue;
diff --git a/mapresample.c b/mapresample.c
index c1a98b2..b0fa1c1 100644
--- a/mapresample.c
+++ b/mapresample.c
@@ -83,7 +83,8 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
imageObj *psDstImage, rasterBufferObj *dst_rb,
int *panCMap,
SimpleTransformer pfnTransform, void *pCBData,
- int debug, rasterBufferObj *mask_rb )
+ int debug, rasterBufferObj *mask_rb,
+ int bWrapAtLeftRight )
{
double *x, *y;
@@ -122,6 +123,9 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
nSrcX = (int) x[nDstX];
nSrcY = (int) y[nDstX];
+ if( bWrapAtLeftRight && nSrcX >= nSrcXSize && nSrcX < 2 * nSrcXSize )
+ nSrcX -= nSrcXSize;
+
/*
* We test the original floating point values to
* avoid errors related to asymmetric rounding around zero.
@@ -302,7 +306,8 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
imageObj *psDstImage, rasterBufferObj *dst_rb,
int *panCMap,
SimpleTransformer pfnTransform, void *pCBData,
- int debug, rasterBufferObj *mask_rb )
+ int debug, rasterBufferObj *mask_rb,
+ int bWrapAtLeftRight )
{
double *x, *y;
@@ -359,31 +364,32 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
dfRatioY2 = y[nDstX] - nSrcY;
/* If we are right off the source, skip this pixel */
- if( nSrcX2 < 0 || nSrcX >= nSrcXSize
+ if( nSrcX2 < 0 || (!bWrapAtLeftRight && nSrcX >= nSrcXSize)
|| nSrcY2 < 0 || nSrcY >= nSrcYSize )
continue;
/* Trim in stuff one pixel off the edge */
nSrcX = MS_MAX(nSrcX,0);
nSrcY = MS_MAX(nSrcY,0);
- nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1);
+ if( !bWrapAtLeftRight )
+ nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1);
nSrcY2 = MS_MIN(nSrcY2,nSrcYSize-1);
memset( padfPixelSum, 0, sizeof(double) * bandCount);
- msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY, padfPixelSum,
+ msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY, padfPixelSum,
(1.0 - dfRatioX2) * (1.0 - dfRatioY2),
&dfWeightSum );
- msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY, padfPixelSum,
+ msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY, padfPixelSum,
(dfRatioX2) * (1.0 - dfRatioY2),
&dfWeightSum );
- msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY2, padfPixelSum,
+ msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY2, padfPixelSum,
(1.0 - dfRatioX2) * (dfRatioY2),
&dfWeightSum );
- msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY2, padfPixelSum,
+ msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY2, padfPixelSum,
(dfRatioX2) * (dfRatioY2),
&dfWeightSum );
@@ -1200,8 +1206,17 @@ static int msTransformMapToSource( int nDstXSize, int nDstYSize,
+ (dfLonWrap-180)*adfInvSrcGeoTransform[4]
+ dfY*adfInvSrcGeoTransform[5];
- psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
- psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+ /* Does the raster cover a whole 360 deg range ? */
+ if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) )
+ {
+ psSrcExtent->minx = 0;
+ psSrcExtent->maxx = nSrcXSize;
+ }
+ else
+ {
+ psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
+ psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+ }
psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out);
psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out);
}
@@ -1216,8 +1231,17 @@ static int msTransformMapToSource( int nDstXSize, int nDstYSize,
+ (dfLonWrap+180)*adfInvSrcGeoTransform[4]
+ dfY*adfInvSrcGeoTransform[5];
- psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
- psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+ /* Does the raster cover a whole 360 deg range ? */
+ if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) )
+ {
+ psSrcExtent->minx = 0;
+ psSrcExtent->maxx = nSrcXSize;
+ }
+ else
+ {
+ psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
+ psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+ }
psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out);
psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out);
}
@@ -1282,6 +1306,7 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
double dfOversampleRatio;
rasterBufferObj src_rb, *psrc_rb = NULL, *mask_rb = NULL;
int bAddPixelMargin = MS_TRUE;
+ int bWrapAtLeftRight = MS_FALSE;
const char *resampleMode = CSLFetchNameValue( layer->processing,
@@ -1471,7 +1496,16 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
sqrt(adfSrcGeoTransform[1] * adfSrcGeoTransform[1]
+ adfSrcGeoTransform[2] * adfSrcGeoTransform[2]);
- if( (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize
+ /* Check first that the requested extent is not well beyond than the source */
+ /* raster. This might be the case for example if asking to visualize */
+ /* -180,-89,180,90 in EPSG:4326 from a raster in Arctic Polar Stereographic */
+ /* But restrict that to rasters of modest size, otherwise we may end up */
+ /* requesting very large dimensions in other legit reprojection cases */
+ /* See https://github.com/mapserver/mapserver/issues/5402 */
+ if( !(sOrigSrcExtent.minx <= -4 * nSrcXSize && sOrigSrcExtent.miny <= -4 * nSrcYSize &&
+ sOrigSrcExtent.maxx >= 5 * nSrcXSize && sOrigSrcExtent.maxy >= 5 * nSrcYSize &&
+ nSrcXSize < 4000 && nSrcYSize < 4000)
+ && (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize
&& !CSLFetchBoolean( layer->processing, "LOAD_FULL_RES_IMAGE", FALSE ))
sDummyMap.cellsize =
(dfNominalCellSize * (sOrigSrcExtent.maxx - sOrigSrcExtent.minx))
@@ -1509,6 +1543,18 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
adfSrcGeoTransform[4] *= (sDummyMap.cellsize / dfNominalCellSize);
adfSrcGeoTransform[5] *= (sDummyMap.cellsize / dfNominalCellSize);
+ /* In the non-rotated case, make sure that the geotransform exactly */
+ /* matches the sSrcExtent, even if that generates non-square pixels (#1715) */
+ /* The rotated case should ideally be dealt with, but not for now... */
+ if( adfSrcGeoTransform[2] == 0 && adfSrcGeoTransform[4] == 0 &&
+ adfSrcGeoTransform[5] < 0 )
+ {
+ adfSrcGeoTransform[1] = (sSrcExtent.maxx - sSrcExtent.minx) *
+ dfNominalCellSize / nLoadImgXSize;
+ adfSrcGeoTransform[5] = -(sSrcExtent.maxy - sSrcExtent.miny) *
+ dfNominalCellSize / nLoadImgYSize;
+ }
+
papszAlteredProcessing = CSLDuplicate( layer->processing );
papszAlteredProcessing =
CSLSetNameValue( papszAlteredProcessing, "RAW_WINDOW",
@@ -1629,6 +1675,13 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
/* -------------------------------------------------------------------- */
pACBData = msInitApproxTransformer( msProjTransformer, pTCBData, 0.333 );
+ if( pj_is_latlong(layer->projection.proj) )
+ {
+ /* Does the raster cover a whole 360 deg range ? */
+ if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) )
+ bWrapAtLeftRight = MS_TRUE;
+ }
+
/* -------------------------------------------------------------------- */
/* Perform the resampling. */
/* -------------------------------------------------------------------- */
@@ -1641,12 +1694,12 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
result =
msBilinearRasterResampler( srcImage, psrc_rb, image, rb,
anCMap, msApproxTransformer, pACBData,
- layer->debug, mask_rb );
+ layer->debug, mask_rb, bWrapAtLeftRight );
else
result =
msNearestRasterResampler( srcImage, psrc_rb, image, rb,
anCMap, msApproxTransformer, pACBData,
- layer->debug, mask_rb );
+ layer->debug, mask_rb, bWrapAtLeftRight );
/* -------------------------------------------------------------------- */
/* cleanup */
diff --git a/mapscript/python/pymodule.i b/mapscript/python/pymodule.i
index 08b7a6d..76b68ee 100644
--- a/mapscript/python/pymodule.i
+++ b/mapscript/python/pymodule.i
@@ -102,6 +102,46 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
$result = t_output_helper($result,r);
}
+
+/*
+ * Typemap hashTableObj* -> dict
+ */
+%typemap(out) hashTableObj*
+{
+ /* %typemap(out) hashTableObj* */
+ const char* key;
+ hashTableObj *hashTable = $1;
+ $result = PyDict_New();
+ key = msFirstKeyFromHashTable(hashTable);
+ while( key )
+ {
+ const char* val = msLookupHashTable(hashTable, key);
+ if( val )
+ {
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject *py_key = PyUnicode_FromString(key);
+ PyObject *py_val = PyUnicode_FromString(val);
+#else
+ PyObject *py_key = PyString_FromString(key);
+ PyObject *py_val = PyString_FromString(val);
+#endif
+
+ PyDict_SetItem($result, py_key, py_val );
+ Py_DECREF(py_key);
+ Py_DECREF(py_val);
+ }
+ key = msNextKeyFromHashTable(hashTable, key);
+ }
+}
+
+%typemap(freearg) hashTableObj*
+{
+ /* %typemap(freearg) hashTableObj* */
+ msFreeHashTable( $1 );
+}
+
+
+
/**************************************************************************
* MapServer Errors and Python Exceptions
**************************************************************************
diff --git a/mapscript/swiginc/msio.i b/mapscript/swiginc/msio.i
index 45fe745..3cee64d 100644
--- a/mapscript/swiginc/msio.i
+++ b/mapscript/swiginc/msio.i
@@ -45,6 +45,11 @@ void msIO_stripStdoutBufferContentHeaders(void);
const char *msIO_getStdoutBufferString(void);
gdBuffer msIO_getStdoutBufferBytes(void);
+#ifdef SWIGPYTHON
+%newobject msIO_getAndStripStdoutBufferMimeHeaders;
+hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders(void);
+#endif
+
%{
const char *msIO_getStdoutBufferString() {
diff --git a/mapshape.c b/mapshape.c
index f1f71a5..7b72020 100644
--- a/mapshape.c
+++ b/mapshape.c
@@ -1934,6 +1934,10 @@ int msTiledSHPOpenFile(layerObj *layer)
msTiledSHPLayerInfo *tSHP=NULL;
+ if (layer->layerinfo != NULL) {
+ return MS_SUCCESS; // Nothing to do... layer is already opened
+ }
+
if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE )
return MS_FAILURE;
@@ -2206,6 +2210,7 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
continue;
} else if(status != MS_SUCCESS) {
msShapefileClose(tSHP->shpfile);
+ tSHP->tileshpfile->lastshape = -1;
return(MS_FAILURE);
}
@@ -2214,7 +2219,10 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
break;
}
- if(status == MS_DONE) return(MS_DONE); /* no more tiles */
+ if(status == MS_DONE) {
+ tSHP->tileshpfile->lastshape = -1;
+ return(MS_DONE); /* no more tiles */
+ }
else {
msFreeShape(&tshape);
continue; /* we've got shapes */
@@ -2248,6 +2256,7 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
continue;
} else if(status != MS_SUCCESS) {
msShapefileClose(tSHP->shpfile);
+ tSHP->tileshpfile->lastshape = -1;
return(MS_FAILURE);
}
@@ -2256,7 +2265,10 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
}
} /* end for loop */
- if(i == tSHP->tileshpfile->numshapes) return(MS_DONE); /* no more tiles */
+ if(i == tSHP->tileshpfile->numshapes) {
+ tSHP->tileshpfile->lastshape = -1;
+ return(MS_DONE); /* no more tiles */
+ }
else continue; /* we've got shapes */
}
}
@@ -2304,6 +2316,8 @@ int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
return(MS_FAILURE);
}
+ msTileIndexAbsoluteDir(tiFileAbsDir, layer);
+
if((tileindex < 0) || (tileindex >= tSHP->tileshpfile->numshapes)) return(MS_FAILURE); /* invalid tile id */
if(tileindex != tSHP->tileshpfile->lastshape) { /* correct tile is not currenly open so open the correct tile */
@@ -2332,6 +2346,7 @@ int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
msSHPReadShape(tSHP->shpfile->hSHP, shapeindex, shape);
tSHP->shpfile->lastshape = shapeindex;
+ tSHP->tileshpfile->lastshape = tileindex;
if(layer->numitems > 0 && layer->iteminfo) {
shape->numvalues = layer->numitems;
@@ -2624,8 +2639,8 @@ int msSHPLayerOpen(layerObj *layer)
}
OSRDestroySpatialReference(hSRS);
}
+ fclose(fp);
}
- fclose(fp);
if( bOK != MS_TRUE )
{
diff --git a/mapwms.c b/mapwms.c
index 6dc4ebf..1b09109 100644
--- a/mapwms.c
+++ b/mapwms.c
@@ -791,7 +791,6 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
const char *wms_request, owsRequestObj *ows_request)
{
int i, adjust_extent = MS_FALSE, nonsquare_enabled = MS_FALSE;
- int nLayerOrder = 0;
int transparent = MS_NOOVERRIDE;
int bbox_pixel_is_point = MS_FALSE;
outputFormatObj *format = NULL;
@@ -870,6 +869,7 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
if (strcasecmp(names[i], "LAYERS") == 0) {
int j, k, iLayer, *layerOrder;
+ int nLayerOrder = 0;
char ***nestedGroups = NULL;
int *numNestedGroups = NULL;
int *isUsedInNestedGroup = NULL;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapserver.git
More information about the Pkg-grass-devel
mailing list