Skip to content

Commit ee0e0e1

Browse files
authored
Merge pull request #8970 from elpaso/bugfix-21077-value-relation-wfs
Fix WFS context fields variable
2 parents ab3adc6 + 4d134b3 commit ee0e0e1

File tree

2 files changed

+177
-6
lines changed

2 files changed

+177
-6
lines changed

src/providers/wfs/qgswfsfeatureiterator.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,15 @@ QgsFeatureRequest QgsWFSFeatureIterator::buildRequestCache( int genCounter )
991991
{
992992
if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
993993
{
994+
// Transfer and transform context
994995
requestCache.setFilterExpression( mRequest.filterExpression()->expression() );
996+
QgsExpressionContext ctx { *mRequest.expressionContext( ) };
997+
QgsExpressionContextScope *scope { ctx.activeScopeForVariable( QgsExpressionContext::EXPR_FIELDS ) };
998+
if ( scope )
999+
{
1000+
scope->setVariable( QgsExpressionContext::EXPR_FIELDS, mShared->mCacheDataProvider->fields() );
1001+
}
1002+
requestCache.setExpressionContext( ctx );
9951003
}
9961004
if ( genCounter >= 0 )
9971005
{

tests/src/python/test_provider_wfs.py

Lines changed: 169 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
QgsVectorDataProvider,
3434
QgsFeatureRequest,
3535
QgsApplication,
36-
QgsSettings
36+
QgsSettings,
37+
QgsExpression,
38+
QgsExpressionContextUtils,
39+
QgsExpressionContext,
3740
)
3841
from qgis.testing import (start_app,
3942
unittest
@@ -791,11 +794,11 @@ def testWFST10(self):
791794
self.assertTrue(vl.isValid())
792795

793796
self.assertEqual(vl.dataProvider().capabilities(),
794-
QgsVectorDataProvider.AddFeatures |
795-
QgsVectorDataProvider.ChangeAttributeValues |
796-
QgsVectorDataProvider.ChangeGeometries |
797-
QgsVectorDataProvider.DeleteFeatures |
798-
QgsVectorDataProvider.SelectAtId)
797+
QgsVectorDataProvider.AddFeatures
798+
| QgsVectorDataProvider.ChangeAttributeValues
799+
| QgsVectorDataProvider.ChangeGeometries
800+
| QgsVectorDataProvider.DeleteFeatures
801+
| QgsVectorDataProvider.SelectAtId)
799802

800803
(ret, _) = vl.dataProvider().addFeatures([QgsFeature()])
801804
self.assertFalse(ret)
@@ -3737,6 +3740,166 @@ def test_NullValues_regression_20961(self):
37373740
self.assertEqual(str(got_f2[1]['elevation']), 'NULL')
37383741
self.assertEqual(str(got_f2[1]['name']), 'sdf')
37393742

3743+
def testFilteredFeatureRequests(self):
3744+
"""Test https://issues.qgis.org/issues/21077 """
3745+
3746+
endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_filtered_feature_requests'
3747+
3748+
with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.1.0'), 'wb') as f:
3749+
f.write("""
3750+
<wfs:WFS_Capabilities version="1.1.0" xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:gml="http://schemas.opengis.net/gml">
3751+
<FeatureTypeList>
3752+
<FeatureType>
3753+
<Name>points</Name>
3754+
<Title>Title</Title>
3755+
<Abstract>Abstract</Abstract>
3756+
<DefaultCRS>urn:ogc:def:crs:OGC:1.3:CRS84</DefaultCRS>
3757+
<WGS84BoundingBox>
3758+
<LowerCorner>-98.6523 32.7233</LowerCorner>
3759+
<UpperCorner>23.2868 69.9882</UpperCorner>
3760+
</WGS84BoundingBox>
3761+
</FeatureType>
3762+
</FeatureTypeList>
3763+
</wfs:WFS_Capabilities>""".encode('UTF-8'))
3764+
3765+
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=points'), 'wb') as f:
3766+
f.write("""
3767+
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" version="1.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:qgs="http://www.qgis.org/gml" elementFormDefault="qualified" targetNamespace="http://www.qgis.org/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3768+
<import schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd" namespace="http://www.opengis.net/gml"/>
3769+
<element type="qgs:pointsType" name="points" substitutionGroup="gml:_Feature"/>
3770+
<complexType name="pointsType">
3771+
<complexContent>
3772+
<extension base="gml:AbstractFeatureType">
3773+
<sequence>
3774+
<element type="gml:MultiPointPropertyType" name="geometry" minOccurs="0" maxOccurs="1"/>
3775+
<element type="int" name="id"/>
3776+
<element type="string" name="name"/>
3777+
<element type="int" name="type" nillable="true"/>
3778+
<element type="decimal" name="elevation" nillable="true"/>
3779+
</sequence>
3780+
</extension>
3781+
</complexContent>
3782+
</complexType>
3783+
</schema>
3784+
""".encode('UTF-8'))
3785+
3786+
get_feature_1 = """<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml http://localhost:8000/ows/bug_20961_server?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0&amp;SERVICE=WFS&amp;VERSION=1.1.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=points&amp;OUTPUTFORMAT=text/xml; subtype%3Dgml/3.1.1">
3787+
<gml:boundedBy>
3788+
<gml:Envelope srsName="EPSG:3857">
3789+
<gml:lowerCorner>-10981925.67093 3858635.0686243</gml:lowerCorner>
3790+
<gml:upperCorner>2592274.0488407 11064877.6393476</gml:upperCorner>
3791+
</gml:Envelope>
3792+
</gml:boundedBy>
3793+
<gml:featureMember>
3794+
<qgs:points gml:id="points.177">
3795+
<gml:boundedBy>
3796+
<gml:Envelope srsName="EPSG:3857">
3797+
<gml:lowerCorner>1544231.80343599 5930698.04174612</gml:lowerCorner>
3798+
<gml:upperCorner>1544231.80343599 5930698.04174612</gml:upperCorner>
3799+
</gml:Envelope>
3800+
</gml:boundedBy>
3801+
<qgs:geometry>
3802+
<MultiPoint xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
3803+
<pointMember xmlns="http://www.opengis.net/gml">
3804+
<Point xmlns="http://www.opengis.net/gml">
3805+
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">1544231.80343599 5930698.04174612</pos>
3806+
</Point>
3807+
</pointMember>
3808+
</MultiPoint>
3809+
</qgs:geometry>
3810+
<qgs:id>177</qgs:id>
3811+
<qgs:name>Xxx</qgs:name>
3812+
<qgs:elevation_source></qgs:elevation_source>
3813+
</qgs:points>
3814+
</gml:featureMember>
3815+
</wfs:FeatureCollection>
3816+
"""
3817+
get_features = """<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml http://localhost:8000/ows/bug_20961_server?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0&amp;SERVICE=WFS&amp;VERSION=1.1.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=points&amp;OUTPUTFORMAT=text/xml; subtype%3Dgml/3.1.1">
3818+
<gml:boundedBy>
3819+
<gml:Envelope srsName="EPSG:3857">
3820+
<gml:lowerCorner>-10981925.67093 3858635.0686243</gml:lowerCorner>
3821+
<gml:upperCorner>2592274.0488407 11064877.6393476</gml:upperCorner>
3822+
</gml:Envelope>
3823+
</gml:boundedBy>
3824+
<gml:featureMember>
3825+
<qgs:points gml:id="points.177">
3826+
<gml:boundedBy>
3827+
<gml:Envelope srsName="EPSG:3857">
3828+
<gml:lowerCorner>1544231.80343599 5930698.04174612</gml:lowerCorner>
3829+
<gml:upperCorner>1544231.80343599 5930698.04174612</gml:upperCorner>
3830+
</gml:Envelope>
3831+
</gml:boundedBy>
3832+
<qgs:geometry>
3833+
<MultiPoint xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
3834+
<pointMember xmlns="http://www.opengis.net/gml">
3835+
<Point xmlns="http://www.opengis.net/gml">
3836+
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">1544231.80343599 5930698.04174612</pos>
3837+
</Point>
3838+
</pointMember>
3839+
</MultiPoint>
3840+
</qgs:geometry>
3841+
<qgs:id>177</qgs:id>
3842+
<qgs:name>Xxx</qgs:name>
3843+
<qgs:type xsi:nil="true"></qgs:type>
3844+
<qgs:elevation xsi:nil="true"></qgs:elevation>
3845+
</qgs:points>
3846+
</gml:featureMember>
3847+
<gml:featureMember>
3848+
<qgs:points gml:id="points.5">
3849+
<gml:boundedBy>
3850+
<gml:Envelope srsName="EPSG:3857">
3851+
<gml:lowerCorner>-10977033.701121 3897159.3308746</gml:lowerCorner>
3852+
<gml:upperCorner>-10977033.701121 3897159.3308746</gml:upperCorner>
3853+
</gml:Envelope>
3854+
</gml:boundedBy>
3855+
<qgs:geometry>
3856+
<MultiPoint xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
3857+
<pointMember xmlns="http://www.opengis.net/gml">
3858+
<Point xmlns="http://www.opengis.net/gml">
3859+
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">-10977033.701121 3897159.3308746</pos>
3860+
</Point>
3861+
</pointMember>
3862+
</MultiPoint>
3863+
</qgs:geometry>
3864+
<qgs:id>5</qgs:id>
3865+
<qgs:name>qgis</qgs:name>
3866+
<qgs:type>0</qgs:type>
3867+
<qgs:elevation xsi:nil="true"></qgs:elevation>
3868+
</qgs:points>
3869+
</gml:featureMember>
3870+
</wfs:FeatureCollection>"""
3871+
3872+
with open(sanitize(endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=points&MAXFEATURES=1&SRSNAME=urn:ogc:def:crs:EPSG::4326"""), 'wb') as f:
3873+
f.write(get_feature_1.encode('UTF-8'))
3874+
3875+
with open(sanitize(endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=points&SRSNAME=urn:ogc:def:crs:EPSG::4326"""), 'wb') as f:
3876+
f.write(get_features.encode('UTF-8'))
3877+
3878+
vl = QgsVectorLayer("url='http://" + endpoint + "' typename='points' version='1.1.0'", 'test', 'WFS')
3879+
self.assertTrue(vl.isValid())
3880+
3881+
# Fill the cache
3882+
[f for f in vl.getFeatures()]
3883+
3884+
qgis_feat = next(vl.getFeatures(QgsFeatureRequest(QgsExpression('"name" = \'qgis\''))))
3885+
other_feat = next(vl.getFeatures(QgsFeatureRequest(QgsExpression('"name" != \'qgis\''))))
3886+
self.assertEqual(qgis_feat['name'], 'qgis')
3887+
self.assertEqual(other_feat['name'], 'Xxx')
3888+
3889+
form_scope = QgsExpressionContextUtils.formScope(qgis_feat)
3890+
form_exp = QgsExpression('current_value(\'name\') = "name"')
3891+
ctx = QgsExpressionContext()
3892+
ctx.appendScope(form_scope)
3893+
ctx.setFeature(qgis_feat)
3894+
self.assertEqual(form_exp.evaluate(ctx), 1)
3895+
ctx.setFeature(other_feat)
3896+
self.assertEqual(form_exp.evaluate(ctx), 0)
3897+
3898+
# For real now! (this failed in issue 21077)
3899+
req = QgsFeatureRequest(form_exp)
3900+
req.setExpressionContext(ctx)
3901+
qgis_feat = next(vl.getFeatures(req))
3902+
37403903

37413904
if __name__ == '__main__':
37423905
unittest.main()

0 commit comments

Comments
 (0)