Skip to content
Permalink
Browse files

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 38f05b597421975ed2b86b662ab21106cc3fd474
Showing with 173 additions and 1 deletion.
  1. +8 −0 src/providers/wfs/qgswfsfeatureiterator.cpp
  2. +165 −1 tests/src/python/test_provider_wfs.py
@@ -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 )
{
@@ -33,7 +33,10 @@
QgsVectorDataProvider,
QgsFeatureRequest,
QgsApplication,
QgsSettings
QgsSettings,
QgsExpression,
QgsExpressionContextUtils,
QgsExpressionContext,
)
from qgis.testing import (start_app,
unittest
@@ -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.
You can’t perform that action at this time.