Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Correctly handle edit buffer when using request with limit (fix #15505)
(cherry-picked from 2665eb5)
  • Loading branch information
nyalldawson committed Oct 12, 2016
1 parent 4603075 commit e79f2b9
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/core/qgsvectorlayerfeatureiterator.cpp
Expand Up @@ -175,6 +175,28 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
changedIds << attIt.key();
}
mChangedFeaturesRequest.setFilterFids( changedIds );

if ( mChangedFeaturesRequest.limit() > 0 )
{
int providerLimit = mProviderRequest.limit();

// features may be deleted in buffer, so increase limit sent to provider
providerLimit += mSource->mDeletedFeatureIds.size();

if ( mProviderRequest.filterType() == QgsFeatureRequest::FilterExpression )
{
// attribute changes may mean some features no longer match expression, so increase limit sent to provider
providerLimit += mSource->mChangedAttributeValues.size();
}

if ( mProviderRequest.filterType() == QgsFeatureRequest::FilterExpression || mProviderRequest.filterType() == QgsFeatureRequest::FilterRect )
{
// geometry changes may mean some features no longer match expression or rect, so increase limit sent to provider
providerLimit += mSource->mChangedGeometries.size();
}

mProviderRequest.setLimit( providerLimit );
}
}

if ( request.filterType() == QgsFeatureRequest::FilterFid )
Expand Down
41 changes: 41 additions & 0 deletions tests/src/python/test_qgsvectorlayer.py
Expand Up @@ -1465,6 +1465,47 @@ def test_setRendererV2(self):
self.assertTrue(self.rendererChanged)
self.assertEqual(layer.rendererV2(), r)

def testGetFeatureLimitWithEdits(self):
""" test getting features with a limit, when edits are present """
layer = createLayerWithOnePoint()
# now has one feature with id 0

pr = layer.dataProvider()

f1 = QgsFeature(1)
f1.setAttributes(["test", 3])
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
f2 = QgsFeature(2)
f2.setAttributes(["test", 3])
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
f3 = QgsFeature(3)
f3.setAttributes(["test", 3])
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
self.assertTrue(pr.addFeatures([f1, f2, f3]))

req = QgsFeatureRequest().setLimit(2)
self.assertEqual(len(list(layer.getFeatures(req))), 2)

# now delete feature f1
layer.startEditing()
self.assertTrue(layer.deleteFeature(1))
req = QgsFeatureRequest().setLimit(2)
self.assertEqual(len(list(layer.getFeatures(req))), 2)
layer.rollBack()

# change an attribute value required by filter
layer.startEditing()
req = QgsFeatureRequest().setFilterExpression('fldint=3').setLimit(2)
self.assertTrue(layer.changeAttributeValue(2, 1, 4))
self.assertEqual(len(list(layer.getFeatures(req))), 2)
layer.rollBack()

layer.startEditing()
req = QgsFeatureRequest().setFilterRect(QgsRectangle(50, 100, 150, 300)).setLimit(2)
self.assertTrue(layer.changeGeometry(2, QgsGeometry.fromPoint(QgsPoint(500, 600))))
self.assertEqual(len(list(layer.getFeatures(req))), 2)
layer.rollBack()

# TODO:
# - fetch rect: feat with changed geometry: 1. in rect, 2. out of rect
# - more join tests
Expand Down

0 comments on commit e79f2b9

Please sign in to comment.