Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix WFS context fields variable
because the fields in the (spatialite) cached
iterator are not the same as the main iterator.

Fix #21077 - Form Value relation based on WFS layer (nothing to do with
value relations)
  • Loading branch information
elpaso committed Jan 24, 2019
1 parent 861a8b7 commit 38f05b5
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/providers/wfs/qgswfsfeatureiterator.cpp
Expand Up @@ -991,7 +991,15 @@ QgsFeatureRequest QgsWFSFeatureIterator::buildRequestCache( int genCounter )
{
if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
{
// Transfer and transform context
requestCache.setFilterExpression( mRequest.filterExpression()->expression() );
QgsExpressionContext ctx { *mRequest.expressionContext( ) };
QgsExpressionContextScope *scope { ctx.activeScopeForVariable( QgsExpressionContext::EXPR_FIELDS ) };
if ( scope )
{
scope->setVariable( QgsExpressionContext::EXPR_FIELDS, mShared->mCacheDataProvider->fields() );
}
requestCache.setExpressionContext( ctx );
}
if ( genCounter >= 0 )
{
Expand Down
166 changes: 165 additions & 1 deletion tests/src/python/test_provider_wfs.py
Expand Up @@ -33,7 +33,10 @@
QgsVectorDataProvider,
QgsFeatureRequest,
QgsApplication,
QgsSettings
QgsSettings,
QgsExpression,
QgsExpressionContextUtils,
QgsExpressionContext,
)
from qgis.testing import (start_app,
unittest
Expand Down Expand Up @@ -3738,5 +3741,166 @@ def test_NullValues_regression_20961(self):
self.assertEqual(str(got_f2[1]['name']), 'sdf')


def testFilteredFeatureRequests(self):
"""Test https://issues.qgis.org/issues/21077 """

endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_filtered_feature_requests'

with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.1.0'), 'wb') as f:
f.write("""
<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">
<FeatureTypeList>
<FeatureType>
<Name>points</Name>
<Title>Title</Title>
<Abstract>Abstract</Abstract>
<DefaultCRS>urn:ogc:def:crs:OGC:1.3:CRS84</DefaultCRS>
<WGS84BoundingBox>
<LowerCorner>-98.6523 32.7233</LowerCorner>
<UpperCorner>23.2868 69.9882</UpperCorner>
</WGS84BoundingBox>
</FeatureType>
</FeatureTypeList>
</wfs:WFS_Capabilities>""".encode('UTF-8'))

with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=points'), 'wb') as f:
f.write("""
<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">
<import schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd" namespace="http://www.opengis.net/gml"/>
<element type="qgs:pointsType" name="points" substitutionGroup="gml:_Feature"/>
<complexType name="pointsType">
<complexContent>
<extension base="gml:AbstractFeatureType">
<sequence>
<element type="gml:MultiPointPropertyType" name="geometry" minOccurs="0" maxOccurs="1"/>
<element type="int" name="id"/>
<element type="string" name="name"/>
<element type="int" name="type" nillable="true"/>
<element type="decimal" name="elevation" nillable="true"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
""".encode('UTF-8'))

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">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:3857">
<gml:lowerCorner>-10981925.67093 3858635.0686243</gml:lowerCorner>
<gml:upperCorner>2592274.0488407 11064877.6393476</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<gml:featureMember>
<qgs:points gml:id="points.177">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:3857">
<gml:lowerCorner>1544231.80343599 5930698.04174612</gml:lowerCorner>
<gml:upperCorner>1544231.80343599 5930698.04174612</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<MultiPoint xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
<pointMember xmlns="http://www.opengis.net/gml">
<Point xmlns="http://www.opengis.net/gml">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">1544231.80343599 5930698.04174612</pos>
</Point>
</pointMember>
</MultiPoint>
</qgs:geometry>
<qgs:id>177</qgs:id>
<qgs:name>Xxx</qgs:name>
<qgs:elevation_source></qgs:elevation_source>
</qgs:points>
</gml:featureMember>
</wfs:FeatureCollection>
"""
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">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:3857">
<gml:lowerCorner>-10981925.67093 3858635.0686243</gml:lowerCorner>
<gml:upperCorner>2592274.0488407 11064877.6393476</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<gml:featureMember>
<qgs:points gml:id="points.177">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:3857">
<gml:lowerCorner>1544231.80343599 5930698.04174612</gml:lowerCorner>
<gml:upperCorner>1544231.80343599 5930698.04174612</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<MultiPoint xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
<pointMember xmlns="http://www.opengis.net/gml">
<Point xmlns="http://www.opengis.net/gml">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">1544231.80343599 5930698.04174612</pos>
</Point>
</pointMember>
</MultiPoint>
</qgs:geometry>
<qgs:id>177</qgs:id>
<qgs:name>Xxx</qgs:name>
<qgs:type xsi:nil="true"></qgs:type>
<qgs:elevation xsi:nil="true"></qgs:elevation>
</qgs:points>
</gml:featureMember>
<gml:featureMember>
<qgs:points gml:id="points.5">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:3857">
<gml:lowerCorner>-10977033.701121 3897159.3308746</gml:lowerCorner>
<gml:upperCorner>-10977033.701121 3897159.3308746</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<MultiPoint xmlns="http://www.opengis.net/gml" srsName="EPSG:3857">
<pointMember xmlns="http://www.opengis.net/gml">
<Point xmlns="http://www.opengis.net/gml">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">-10977033.701121 3897159.3308746</pos>
</Point>
</pointMember>
</MultiPoint>
</qgs:geometry>
<qgs:id>5</qgs:id>
<qgs:name>qgis</qgs:name>
<qgs:type>0</qgs:type>
<qgs:elevation xsi:nil="true"></qgs:elevation>
</qgs:points>
</gml:featureMember>
</wfs:FeatureCollection>"""

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:
f.write(get_feature_1.encode('UTF-8'))

with open(sanitize(endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=points&SRSNAME=urn:ogc:def:crs:EPSG::4326"""), 'wb') as f:
f.write(get_features.encode('UTF-8'))

vl = QgsVectorLayer("url='http://" + endpoint + "' typename='points' version='1.1.0'", 'test', 'WFS')
self.assertTrue(vl.isValid())

# Fill the cache
[f for f in vl.getFeatures()]

qgis_feat = next(vl.getFeatures(QgsFeatureRequest(QgsExpression('"name" = \'qgis\''))))
other_feat = next(vl.getFeatures(QgsFeatureRequest(QgsExpression('"name" != \'qgis\''))))
self.assertEqual(qgis_feat['name'], 'qgis')
self.assertEqual(other_feat['name'], 'Xxx')

form_scope = QgsExpressionContextUtils.formScope(qgis_feat)
form_exp = QgsExpression('current_value(\'name\') = "name"')
ctx = QgsExpressionContext()
ctx.appendScope(form_scope)
ctx.setFeature(qgis_feat)
self.assertEqual(form_exp.evaluate(ctx), 1)
ctx.setFeature(other_feat)
self.assertEqual(form_exp.evaluate(ctx), 0)

# For real now! (this failed in issue 21077)
req = QgsFeatureRequest(form_exp)
req.setExpressionContext(ctx)
qgis_feat = next(vl.getFeatures(req))


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

0 comments on commit 38f05b5

Please sign in to comment.