Skip to content

Commit

Permalink
Fix feature request containing a filter expression which needs
Browse files Browse the repository at this point in the history
both geometry and the magic all attributes flag

(cherry picked from commit 33aa63b)
  • Loading branch information
nyalldawson committed Feb 20, 2019
1 parent 86b0bd8 commit 6d71053
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/core/qgsvectorlayerfeatureiterator.cpp
Expand Up @@ -199,6 +199,7 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat

if ( mProviderRequest.filterType() == QgsFeatureRequest::FilterExpression )
{
const bool needsGeom = mProviderRequest.filterExpression()->needsGeometry();
Q_FOREACH ( const QString &field, mProviderRequest.filterExpression()->referencedColumns() )
{
int idx = source->mFields.lookupField( field );
Expand All @@ -210,6 +211,12 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
mProviderRequest.disableFilter();
// can't limit at provider side
mProviderRequest.setLimit( -1 );
if ( needsGeom )
{
// have to get geometry from provider in order to evaluate expression on client
mProviderRequest.setFlags( mProviderRequest.flags() & ~QgsFeatureRequest::NoGeometry );
}
break;
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions tests/src/python/featuresourcetestbase.py
Expand Up @@ -528,6 +528,22 @@ def testRectAndExpression(self):
for f in self.source.getFeatures():
self.assertEqual(request.acceptFeature(f), f['pk'] in expected)

def testGeomAndAllAttributes(self):
"""
Test combination of a filter which requires geometry and all attributes
"""
request = QgsFeatureRequest().setFilterExpression('attribute($currentfeature,\'cnt\')>200 and $x>=-70 and $x<=-60').setSubsetOfAttributes([]).setFlags(QgsFeatureRequest.NoGeometry)
result = set([f['pk'] for f in self.source.getFeatures(request)])
all_valid = (all(f.isValid() for f in self.source.getFeatures(request)))
self.assertEqual(result, {4})
self.assertTrue(all_valid)

request = QgsFeatureRequest().setFilterExpression('attribute($currentfeature,\'cnt\')>200 and $x>=-70 and $x<=-60')
result = set([f['pk'] for f in self.source.getFeatures(request)])
all_valid = (all(f.isValid() for f in self.source.getFeatures(request)))
self.assertEqual(result, {4})
self.assertTrue(all_valid)

def testRectAndFids(self):
"""
Test the combination of a filter rect along with filterfids
Expand Down
3 changes: 3 additions & 0 deletions tests/src/python/test_provider_wfs.py
Expand Up @@ -3857,6 +3857,9 @@ def test_NullValues_regression_20961(self):
self.assertEqual(str(got_f2[1]['elevation']), 'NULL')
self.assertEqual(str(got_f2[1]['name']), 'sdf')

def testGeomAndAllAttributes(self):
pass # skip this feature source test -- provider is not affected

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

Expand Down
21 changes: 21 additions & 0 deletions tests/src/python/test_qgsvectorlayer.py
Expand Up @@ -66,6 +66,8 @@
from featuresourcetestbase import FeatureSourceTestCase
from utilities import unitTestDataPath

TEST_DATA_DIR = unitTestDataPath()

start_app()


Expand Down Expand Up @@ -184,6 +186,25 @@ def dumpEditBuffer(layer):
print(("%d | %s" % (f.id(), f.geometry().asWkt())))


class TestQgsVectorLayerShapefile(unittest.TestCase, FeatureSourceTestCase):

"""
Tests a vector layer against the feature source tests, using a real layer source (not a memory layer)
"""
@classmethod
def getSource(cls):
vl = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'provider', 'shapefile.shp'), 'test')
assert (vl.isValid())
return vl

@classmethod
def setUpClass(cls):
"""Run before all tests"""
QgsGui.editorWidgetRegistry().initEditors()
# Create test layer for FeatureSourceTestCase
cls.source = cls.getSource()


class TestQgsVectorLayer(unittest.TestCase, FeatureSourceTestCase):

@classmethod
Expand Down

0 comments on commit 6d71053

Please sign in to comment.