Skip to content

Commit 0e72384

Browse files
authored
Merge pull request #7078 from arnaud-morvan/server_proper_literal_convertion
[server] Proper convertion of literals in Filters
2 parents 370bac9 + b07c334 commit 0e72384

14 files changed

+126
-62
lines changed

python/core/auto_generated/qgsogcutils.sip.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Exports the rectangle to GML3 Envelope
128128
Parse XML with OGC fill into QColor
129129
%End
130130

131-
static QgsExpression *expressionFromOgcFilter( const QDomElement &element ) /Factory/;
131+
static QgsExpression *expressionFromOgcFilter( const QDomElement &element, QgsVectorLayer *layer = 0 ) /Factory/;
132132
%Docstring
133133
Parse XML with OGC filter into QGIS expression
134134
%End

src/core/qgsogcutils.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,7 +1598,7 @@ QColor QgsOgcUtils::colorFromOgcFill( const QDomElement &fillElement )
15981598
}
15991599

16001600

1601-
QgsExpression *QgsOgcUtils::expressionFromOgcFilter( const QDomElement &element )
1601+
QgsExpression *QgsOgcUtils::expressionFromOgcFilter( const QDomElement &element, QgsVectorLayer *layer )
16021602
{
16031603
if ( element.isNull() || !element.hasChildNodes() )
16041604
return nullptr;
@@ -1619,7 +1619,7 @@ QgsExpression *QgsOgcUtils::expressionFromOgcFilter( const QDomElement &element
16191619
while ( !childElem.isNull() )
16201620
{
16211621
QString errorMsg;
1622-
QgsExpressionNode *node = nodeFromOgcFilter( childElem, errorMsg );
1622+
QgsExpressionNode *node = nodeFromOgcFilter( childElem, errorMsg, layer );
16231623
if ( !node )
16241624
{
16251625
// invalid expression, parser error
@@ -1702,15 +1702,15 @@ static bool isSpatialOperator( const QString &tagName )
17021702

17031703

17041704

1705-
QgsExpressionNode *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString &errorMessage )
1705+
QgsExpressionNode *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString &errorMessage, QgsVectorLayer *layer )
17061706
{
17071707
if ( element.isNull() )
17081708
return nullptr;
17091709

17101710
// check for binary operators
17111711
if ( isBinaryOperator( element.tagName() ) )
17121712
{
1713-
return nodeBinaryOperatorFromOgcFilter( element, errorMessage );
1713+
return nodeBinaryOperatorFromOgcFilter( element, errorMessage, layer );
17141714
}
17151715

17161716
// check for spatial operators
@@ -1731,7 +1731,7 @@ QgsExpressionNode *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString
17311731
}
17321732
else if ( element.tagName() == QLatin1String( "Literal" ) )
17331733
{
1734-
return nodeLiteralFromOgcFilter( element, errorMessage );
1734+
return nodeLiteralFromOgcFilter( element, errorMessage, layer );
17351735
}
17361736
else if ( element.tagName() == QLatin1String( "Function" ) )
17371737
{
@@ -1752,7 +1752,7 @@ QgsExpressionNode *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString
17521752

17531753

17541754

1755-
QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage )
1755+
QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage, QgsVectorLayer *layer )
17561756
{
17571757
if ( element.isNull() )
17581758
return nullptr;
@@ -1771,7 +1771,7 @@ QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( Q
17711771
}
17721772

17731773
QDomElement operandElem = element.firstChildElement();
1774-
QgsExpressionNode *expr = nodeFromOgcFilter( operandElem, errorMessage ), *leftOp = expr;
1774+
QgsExpressionNode *expr = nodeFromOgcFilter( operandElem, errorMessage, layer ), *leftOp = expr;
17751775
if ( !expr )
17761776
{
17771777
if ( errorMessage.isEmpty() )
@@ -1781,7 +1781,7 @@ QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( Q
17811781

17821782
for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
17831783
{
1784-
QgsExpressionNode *opRight = nodeFromOgcFilter( operandElem, errorMessage );
1784+
QgsExpressionNode *opRight = nodeFromOgcFilter( operandElem, errorMessage, layer );
17851785
if ( !opRight )
17861786
{
17871787
if ( errorMessage.isEmpty() )
@@ -1960,7 +1960,7 @@ QgsExpressionNodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement &
19601960

19611961

19621962

1963-
QgsExpressionNode *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage )
1963+
QgsExpressionNode *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage, QgsVectorLayer *layer )
19641964
{
19651965
if ( element.isNull() || element.tagName() != QLatin1String( "Literal" ) )
19661966
{
@@ -1980,7 +1980,7 @@ QgsExpressionNode *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element,
19801980
{
19811981
// found a element node (e.g. PropertyName), convert it
19821982
QDomElement operandElem = childNode.toElement();
1983-
operand = nodeFromOgcFilter( operandElem, errorMessage );
1983+
operand = nodeFromOgcFilter( operandElem, errorMessage, layer );
19841984
if ( !operand )
19851985
{
19861986
delete root;
@@ -1994,12 +1994,36 @@ QgsExpressionNode *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element,
19941994
// probably a text/CDATA node
19951995
QVariant value = childNode.nodeValue();
19961996

1997-
// try to convert the node content to number if possible,
1998-
// otherwise let's use it as string
1999-
bool ok;
2000-
double d = value.toDouble( &ok );
2001-
if ( ok )
2002-
value = d;
1997+
bool converted = false;
1998+
1999+
// try to convert the node content to corresponding field type if possible
2000+
if ( layer != nullptr )
2001+
{
2002+
QDomElement propertyNameElement = element.previousSiblingElement( QLatin1String( "PropertyName" ) );
2003+
if ( propertyNameElement.isNull() || propertyNameElement.tagName() != QLatin1String( "PropertyName" ) )
2004+
{
2005+
propertyNameElement = element.nextSiblingElement( QLatin1String( "PropertyName" ) );
2006+
}
2007+
if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == QLatin1String( "PropertyName" ) )
2008+
{
2009+
int fieldIndex = layer->fields().indexOf( propertyNameElement.firstChild().nodeValue() );
2010+
if ( fieldIndex != -1 )
2011+
{
2012+
QgsField field = layer->fields().field( propertyNameElement.firstChild().nodeValue() );
2013+
field.convertCompatible( value );
2014+
converted = true;
2015+
}
2016+
}
2017+
}
2018+
if ( !converted )
2019+
{
2020+
// try to convert the node content to number if possible,
2021+
// otherwise let's use it as string
2022+
bool ok;
2023+
double d = value.toDouble( &ok );
2024+
if ( ok )
2025+
value = d;
2026+
}
20032027

20042028
operand = new QgsExpressionNodeLiteral( value );
20052029
if ( !operand )

src/core/qgsogcutils.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class QgsRectangle;
3737
#include "qgsexpressionnode.h"
3838
#include "qgsexpressionnodeimpl.h"
3939
#include "qgssqlstatement.h"
40+
#include "qgsvectorlayer.h"
4041

4142
/**
4243
* \ingroup core
@@ -140,7 +141,7 @@ class CORE_EXPORT QgsOgcUtils
140141
static QColor colorFromOgcFill( const QDomElement &fillElement );
141142

142143
//! Parse XML with OGC filter into QGIS expression
143-
static QgsExpression *expressionFromOgcFilter( const QDomElement &element ) SIP_FACTORY;
144+
static QgsExpression *expressionFromOgcFilter( const QDomElement &element, QgsVectorLayer *layer = nullptr ) SIP_FACTORY;
144145

145146
/**
146147
* Creates OGC filter XML element. Supports minimum standard filter
@@ -298,17 +299,17 @@ class CORE_EXPORT QgsOgcUtils
298299
static QDomElement createGMLPositions( const QgsPolylineXY &points, QDomDocument &doc );
299300

300301
//! handle a generic sub-expression
301-
static QgsExpressionNode *nodeFromOgcFilter( QDomElement &element, QString &errorMessage );
302+
static QgsExpressionNode *nodeFromOgcFilter( QDomElement &element, QString &errorMessage, QgsVectorLayer *layer = nullptr );
302303
//! handle a generic binary operator
303-
static QgsExpressionNodeBinaryOperator *nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage );
304+
static QgsExpressionNodeBinaryOperator *nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage, QgsVectorLayer *layer = nullptr );
304305
//! handles various spatial operation tags (\verbatim <Intersects> \endverbatim, \verbatim <Touches> \endverbatim etc.)
305306
static QgsExpressionNodeFunction *nodeSpatialOperatorFromOgcFilter( QDomElement &element, QString &errorMessage );
306307
//! handle \verbatim <Not> \endverbatim tag
307308
static QgsExpressionNodeUnaryOperator *nodeNotFromOgcFilter( QDomElement &element, QString &errorMessage );
308309
//! handles \verbatim <Function> \endverbatim tag
309310
static QgsExpressionNodeFunction *nodeFunctionFromOgcFilter( QDomElement &element, QString &errorMessage );
310311
//! handles \verbatim <Literal> \endverbatim tag
311-
static QgsExpressionNode *nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage );
312+
static QgsExpressionNode *nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage, QgsVectorLayer *layer = nullptr );
312313
//! handles \verbatim <PropertyName> \endverbatim tag
313314
static QgsExpressionNodeColumnRef *nodeColumnRefFromOgcFilter( QDomElement &element, QString &errorMessage );
314315
//! handles \verbatim <PropertyIsBetween> \endverbatim tag

src/server/qgsserverprojectutils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "qgis_server.h"
2222
#include "qgsproject.h"
23+
#include "qgsvectorlayer.h"
2324

2425
#ifdef SIP_RUN
2526
% ModuleHeaderCode

src/server/services/wfs/qgswfsdescribefeaturetype.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,7 @@ namespace QgsWfs
139139
continue;
140140
}
141141

142-
QString name = layer->name();
143-
if ( !layer->shortName().isEmpty() )
144-
name = layer->shortName();
145-
name = name.replace( ' ', '_' );
142+
QString name = layerTypeName( layer );
146143

147144
if ( !typeNameList.isEmpty() && !typeNameList.contains( name ) )
148145
{
@@ -180,10 +177,7 @@ namespace QgsWfs
180177
return;
181178
}
182179

183-
QString typeName = layer->name();
184-
if ( !layer->shortName().isEmpty() )
185-
typeName = layer->shortName();
186-
typeName = typeName.replace( ' ', '_' );
180+
QString typeName = layerTypeName( layer );
187181

188182
//xsd:element
189183
QDomElement elementElem = doc.createElement( QStringLiteral( "element" )/*xsd:element*/ );

src/server/services/wfs/qgswfsgetcapabilities.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -438,11 +438,7 @@ namespace QgsWfs
438438

439439
//create Name
440440
QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
441-
QString typeName = layer->name();
442-
if ( !layer->shortName().isEmpty() )
443-
typeName = layer->shortName();
444-
typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
445-
QDomText nameText = doc.createTextNode( typeName );
441+
QDomText nameText = doc.createTextNode( layerTypeName( layer ) );
446442
nameElem.appendChild( nameText );
447443
layerElem.appendChild( nameElem );
448444

src/server/services/wfs/qgswfsgetfeature.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ namespace QgsWfs
101101
if ( doc.setContent( mRequestParameters.value( QStringLiteral( "REQUEST_BODY" ) ), true, &errorMsg ) )
102102
{
103103
QDomElement docElem = doc.documentElement();
104-
aRequest = parseGetFeatureRequestBody( docElem );
104+
aRequest = parseGetFeatureRequestBody( docElem, project );
105105
}
106106
else
107107
{
108-
aRequest = parseGetFeatureParameters();
108+
aRequest = parseGetFeatureParameters( project );
109109
}
110110

111111
// store typeName
@@ -141,10 +141,7 @@ namespace QgsWfs
141141
continue;
142142
}
143143

144-
QString name = layer->name();
145-
if ( !layer->shortName().isEmpty() )
146-
name = layer->shortName();
147-
name = name.replace( ' ', '_' );
144+
QString name = layerTypeName( layer );
148145

149146
if ( typeNameList.contains( name ) )
150147
{
@@ -433,7 +430,7 @@ namespace QgsWfs
433430

434431
}
435432

436-
getFeatureRequest parseGetFeatureParameters()
433+
getFeatureRequest parseGetFeatureParameters( const QgsProject *project )
437434
{
438435
getFeatureRequest request;
439436
request.maxFeatures = mWfsParameters.maxFeaturesAsInt();;
@@ -767,7 +764,7 @@ namespace QgsWfs
767764
}
768765

769766
QDomElement filterElem = filter.firstChildElement();
770-
query.featureRequest = parseFilterElement( query.typeName, filterElem );
767+
query.featureRequest = parseFilterElement( query.typeName, filterElem, project );
771768

772769
if ( filterIt != filterList.constEnd() )
773770
{
@@ -821,7 +818,7 @@ namespace QgsWfs
821818
return request;
822819
}
823820

824-
getFeatureRequest parseGetFeatureRequestBody( QDomElement &docElem )
821+
getFeatureRequest parseGetFeatureRequestBody( QDomElement &docElem, const QgsProject *project )
825822
{
826823
getFeatureRequest request;
827824
request.maxFeatures = mWfsParameters.maxFeaturesAsInt();;
@@ -833,7 +830,7 @@ namespace QgsWfs
833830
for ( int i = 0; i < queryNodes.size(); i++ )
834831
{
835832
queryElem = queryNodes.at( i ).toElement();
836-
getFeatureQuery query = parseQueryElement( queryElem );
833+
getFeatureQuery query = parseQueryElement( queryElem, project );
837834
request.queries.append( query );
838835
}
839836
return request;
@@ -887,7 +884,7 @@ namespace QgsWfs
887884
}
888885
}
889886

890-
getFeatureQuery parseQueryElement( QDomElement &queryElem )
887+
getFeatureQuery parseQueryElement( QDomElement &queryElem, const QgsProject *project )
891888
{
892889
QString typeName = queryElem.attribute( QStringLiteral( "typeName" ), QLatin1String( "" ) );
893890
if ( typeName.contains( ':' ) )
@@ -923,7 +920,7 @@ namespace QgsWfs
923920
}
924921
else if ( queryChildElem.tagName() == QLatin1String( "Filter" ) )
925922
{
926-
featureRequest = parseFilterElement( typeName, queryChildElem );
923+
featureRequest = parseFilterElement( typeName, queryChildElem, project );
927924
}
928925
else if ( queryChildElem.tagName() == QLatin1String( "SortBy" ) )
929926
{

src/server/services/wfs/qgswfsgetfeature.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,17 @@ namespace QgsWfs
5858
/**
5959
* Transform Query element to getFeatureQuery
6060
*/
61-
getFeatureQuery parseQueryElement( QDomElement &queryElem );
61+
getFeatureQuery parseQueryElement( QDomElement &queryElem, const QgsProject *project = nullptr );
6262

6363
/**
6464
* Transform RequestBody root element to getFeatureRequest
6565
*/
66-
getFeatureRequest parseGetFeatureRequestBody( QDomElement &docElem );
66+
getFeatureRequest parseGetFeatureRequestBody( QDomElement &docElem, const QgsProject *project = nullptr );
6767

6868
/**
6969
* Transform parameters to getFeatureRequest
7070
*/
71-
getFeatureRequest parseGetFeatureParameters();
71+
getFeatureRequest parseGetFeatureParameters( const QgsProject *project = nullptr );
7272

7373
/**
7474
* Output WFS GetFeature response

src/server/services/wfs/qgswfstransaction.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,7 @@ namespace QgsWfs
259259
continue;
260260
}
261261

262-
QString name = layer->name();
263-
if ( !layer->shortName().isEmpty() )
264-
name = layer->shortName();
265-
name = name.replace( ' ', '_' );
262+
QString name = layerTypeName( layer );
266263

267264
if ( !typeNameList.contains( name ) )
268265
{

src/server/services/wfs/qgswfstransaction_1_0_0.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,7 @@ namespace QgsWfs
242242
continue;
243243
}
244244

245-
QString name = layer->name();
246-
if ( !layer->shortName().isEmpty() )
247-
name = layer->shortName();
248-
name = name.replace( ' ', '_' );
245+
QString name = layerTypeName( layer );
249246

250247
if ( !typeNameList.contains( name ) )
251248
{

0 commit comments

Comments
 (0)