Skip to content

Commit df08e5b

Browse files
committed
WFS: implements SortBy
1 parent 8131096 commit df08e5b

File tree

8 files changed

+520
-240
lines changed

8 files changed

+520
-240
lines changed

mapfile.c

+7
Original file line numberDiff line numberDiff line change
@@ -3805,6 +3805,9 @@ int initLayer(layerObj *layer, mapObj *map)
38053805
layer->utfitemindex = -1;
38063806

38073807
layer->encoding = NULL;
3808+
3809+
layer->sortBy.nProperties = 0;
3810+
layer->sortBy.properties = NULL;
38083811

38093812
return(0);
38103813
}
@@ -3923,6 +3926,10 @@ int freeLayer(layerObj *layer)
39233926

39243927
freeExpression(&(layer->utfdata));
39253928
msFree(layer->utfitem);
3929+
3930+
for(i=0;i<layer->sortBy.nProperties;i++)
3931+
msFree(layer->sortBy.properties[i].item);
3932+
msFree(layer->sortBy.properties);
39263933

39273934
return MS_SUCCESS;
39283935
}

maplayer.c

+60
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,66 @@ int msLayerSupportsPaging(layerObj *layer)
14121412
return MS_FALSE;
14131413
}
14141414

1415+
/*
1416+
* msLayerSupportsSorting()
1417+
*
1418+
* Returns MS_TRUE if the layer supports sorting/ordering.
1419+
*/
1420+
int msLayerSupportsSorting(layerObj *layer)
1421+
{
1422+
if (layer &&
1423+
((layer->connectiontype == MS_OGR) ||
1424+
(layer->connectiontype == MS_POSTGIS)) )
1425+
return MS_TRUE;
1426+
1427+
return MS_FALSE;
1428+
}
1429+
1430+
/*
1431+
* msLayerSetSort()
1432+
*
1433+
* Copy the sortBy clause passed as an argument into the layer sortBy member.
1434+
*/
1435+
void msLayerSetSort(layerObj *layer, const sortByClause* sortBy)
1436+
{
1437+
int i;
1438+
for(i=0;i<layer->sortBy.nProperties;i++)
1439+
msFree(layer->sortBy.properties[i].item);
1440+
msFree(layer->sortBy.properties);
1441+
1442+
layer->sortBy.nProperties = sortBy->nProperties;
1443+
layer->sortBy.properties = (sortByProperties*) msSmallMalloc(
1444+
sortBy->nProperties * sizeof(sortByProperties) );
1445+
for(i=0;i<layer->sortBy.nProperties;i++) {
1446+
layer->sortBy.properties[i].item = msStrdup(sortBy->properties[i].item);
1447+
layer->sortBy.properties[i].sortOrder = sortBy->properties[i].sortOrder;
1448+
}
1449+
}
1450+
1451+
/*
1452+
* msLayerBuildSQLOrderBy()
1453+
*
1454+
* Returns the content of a SQL ORDER BY clause from the sortBy member of
1455+
* the layer. The string does not contain the "ORDER BY" keywords itself.
1456+
*/
1457+
char* msLayerBuildSQLOrderBy(layerObj *layer)
1458+
{
1459+
char* strOrderBy = NULL;
1460+
if( layer->sortBy.nProperties > 0 ) {
1461+
int i;
1462+
for(i=0;i<layer->sortBy.nProperties;i++) {
1463+
char* escaped = msLayerEscapePropertyName(layer, layer->sortBy.properties[i].item);
1464+
if( i > 0 )
1465+
strOrderBy = msStringConcatenate(strOrderBy, ", ");
1466+
strOrderBy = msStringConcatenate(strOrderBy, escaped);
1467+
if( layer->sortBy.properties[i].sortOrder == SORT_DESC )
1468+
strOrderBy = msStringConcatenate(strOrderBy, " DESC");
1469+
msFree(escaped);
1470+
}
1471+
}
1472+
return strOrderBy;
1473+
}
1474+
14151475
int
14161476
msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map,
14171477
int iLayerIndex)

mapogr.cpp

+50-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
typedef struct ms_ogr_file_info_t {
5353
char *pszFname;
54+
char *pszLayerDef;
5455
int nLayerIndex;
5556
OGRDataSourceH hDS;
5657
OGRLayerH hLayer;
@@ -1196,14 +1197,13 @@ msOGRFileOpen(layerObj *layer, const char *connection )
11961197
return NULL;
11971198
}
11981199

1199-
CPLFree( pszLayerDef );
1200-
12011200
/* ------------------------------------------------------------------
12021201
* OK... open succeded... alloc and fill msOGRFileInfo inside layer obj
12031202
* ------------------------------------------------------------------ */
12041203
msOGRFileInfo *psInfo =(msOGRFileInfo*)CPLCalloc(1,sizeof(msOGRFileInfo));
12051204

12061205
psInfo->pszFname = CPLStrdup(OGR_DS_GetName( hDS ));
1206+
psInfo->pszLayerDef = pszLayerDef;
12071207
psInfo->nLayerIndex = nLayerIndex;
12081208
psInfo->hDS = hDS;
12091209
psInfo->hLayer = hLayer;
@@ -1247,6 +1247,7 @@ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo )
12471247
psInfo->pszFname, psInfo->nLayerIndex);
12481248

12491249
CPLFree(psInfo->pszFname);
1250+
CPLFree(psInfo->pszLayerDef);
12501251

12511252
ACQUIRE_OGR_LOCK;
12521253
if (psInfo->hLastFeature)
@@ -1361,6 +1362,53 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect,
13611362
return(MS_FAILURE);
13621363
}
13631364

1365+
/* Apply sortBy */
1366+
if( layer->sortBy.nProperties > 0 ) {
1367+
char* strOrderBy;
1368+
char* pszLayerDef = NULL;
1369+
1370+
strOrderBy = msLayerBuildSQLOrderBy(layer);
1371+
1372+
if( psInfo->nLayerIndex == -1 )
1373+
{
1374+
pszLayerDef = msStrdup(psInfo->pszLayerDef);
1375+
if( strcasestr(psInfo->pszLayerDef, " ORDER BY ") == NULL )
1376+
pszLayerDef = msStringConcatenate(pszLayerDef, " ORDER BY ");
1377+
else
1378+
pszLayerDef = msStringConcatenate(pszLayerDef, ", ");
1379+
}
1380+
else
1381+
{
1382+
pszLayerDef = msStringConcatenate(pszLayerDef, "SELECT * FROM \"");
1383+
pszLayerDef = msStringConcatenate(pszLayerDef, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
1384+
pszLayerDef = msStringConcatenate(pszLayerDef, "\" ORDER BY ");
1385+
}
1386+
1387+
pszLayerDef = msStringConcatenate(pszLayerDef, strOrderBy);
1388+
msFree(strOrderBy);
1389+
strOrderBy = NULL;
1390+
1391+
if( layer->debug )
1392+
msDebug("msOGRFileWhichShapes: SQL = %s.\n", pszLayerDef);
1393+
1394+
/* If nLayerIndex == -1 then the layer is an SQL result ... free it */
1395+
if( psInfo->nLayerIndex == -1 )
1396+
OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer );
1397+
psInfo->nLayerIndex = -1;
1398+
1399+
ACQUIRE_OGR_LOCK;
1400+
psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszLayerDef, NULL, NULL );
1401+
msFree(pszLayerDef);
1402+
RELEASE_OGR_LOCK;
1403+
if( psInfo->hLayer == NULL ) {
1404+
msSetError(MS_OGRERR,
1405+
"ExecuteSQL(%s) failed.\n%s",
1406+
"msOGRFileWhichShapes()",
1407+
pszLayerDef, CPLGetLastErrorMsg() );
1408+
return MS_FAILURE;
1409+
}
1410+
}
1411+
13641412
/* ------------------------------------------------------------------
13651413
* Set Spatial filter... this may result in no features being returned
13661414
* if layer does not overlap current view.

mappostgis.c

+19-1
Original file line numberDiff line numberDiff line change
@@ -1870,11 +1870,13 @@ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid)
18701870
char *strFilter = 0;
18711871
char *strUid = 0;
18721872
char *strWhere = 0;
1873+
char *strOrderBy = 0;
18731874
char *strLimit = 0;
18741875
char *strOffset = 0;
18751876
size_t strRectLength = 0;
18761877
size_t strFilterLength = 0;
18771878
size_t strUidLength = 0;
1879+
size_t strOrderByLength = 0;
18781880
size_t strLimitLength = 0;
18791881
size_t strOffsetLength = 0;
18801882
size_t bufferSize = 0;
@@ -1954,8 +1956,17 @@ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid)
19541956
strUidLength = strlen(strUid);
19551957
}
19561958

1959+
/* Populate strOrderBy, if necessary */
1960+
if( layer->sortBy.nProperties > 0 ) {
1961+
char* pszTmp = msLayerBuildSQLOrderBy(layer);
1962+
strOrderBy = msStringConcatenate(strOrderBy, " ORDER BY ");
1963+
strOrderBy = msStringConcatenate(strOrderBy, pszTmp);
1964+
msFree(pszTmp);
1965+
strOrderByLength = strlen(strOrderBy);
1966+
}
1967+
19571968
bufferSize = strRectLength + 5 + strFilterLength + 5 + strUidLength
1958-
+ strLimitLength + strOffsetLength;
1969+
+ strLimitLength + strOffsetLength + strOrderByLength;
19591970
strWhere = (char*)msSmallMalloc(bufferSize);
19601971
*strWhere = '\0';
19611972
if ( strRect ) {
@@ -1979,6 +1990,12 @@ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid)
19791990
free(strUid);
19801991
insert_and++;
19811992
}
1993+
1994+
if ( strOrderBy ) {
1995+
strlcat(strWhere, strOrderBy, bufferSize);
1996+
free(strOrderBy);
1997+
}
1998+
19821999
if ( strLimit ) {
19832000
strlcat(strWhere, strLimit, bufferSize);
19842001
free(strLimit);
@@ -2046,6 +2063,7 @@ char *msPostGISBuildSQL(layerObj *layer, rectObj *rect, long *uid)
20462063

20472064
strSQL = msSmallMalloc(strlen(strSQLTemplate) + strlen(strFrom) + strlen(strItems) + strlen(strWhere));
20482065
sprintf(strSQL, strSQLTemplate, strItems, strFrom, strWhere);
2066+
20492067
if (strItems) free(strItems);
20502068
if (strFrom) free(strFrom);
20512069
if (strWhere) free(strWhere);

mapserver.h

+26-1
Original file line numberDiff line numberDiff line change
@@ -1487,7 +1487,24 @@ extern "C" {
14871487
int n_entries;
14881488
scaleTokenEntryObj *tokens;
14891489
} scaleTokenObj;
1490-
1490+
1491+
#ifndef SWIG
1492+
typedef enum {
1493+
SORT_ASC,
1494+
SORT_DESC
1495+
} sortOrderEnum;
1496+
1497+
typedef struct {
1498+
char* item;
1499+
sortOrderEnum sortOrder;
1500+
} sortByProperties;
1501+
1502+
typedef struct {
1503+
int nProperties;
1504+
sortByProperties* properties;
1505+
} sortByClause;
1506+
#endif
1507+
14911508
struct layerObj {
14921509

14931510
char *classitem; /* .DBF item to be used for symbol lookup */
@@ -1674,6 +1691,10 @@ extern "C" {
16741691
char *utfitem;
16751692
int utfitemindex;
16761693
expressionObj utfdata;
1694+
1695+
#ifndef SWIG
1696+
sortByClause sortBy;
1697+
#endif
16771698
};
16781699

16791700

@@ -2366,6 +2387,10 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
23662387
MS_DLL_EXPORT char *msLayerEscapeSQLParam(layerObj *layer, const char* pszString);
23672388
MS_DLL_EXPORT char *msLayerEscapePropertyName(layerObj *layer, const char* pszString);
23682389

2390+
int msLayerSupportsSorting(layerObj *layer);
2391+
void msLayerSetSort(layerObj *layer, const sortByClause* sortBy);
2392+
char* msLayerBuildSQLOrderBy(layerObj *layer);
2393+
23692394
/* These are special because SWF is using these */
23702395
int msOGRLayerNextShape(layerObj *layer, shapeObj *shape);
23712396
int msOGRLayerGetItems(layerObj *layer);

0 commit comments

Comments
 (0)