Skip to content
Permalink
Browse files

[memory] Fix memory provider does not return correct min/max

values after adding or editing features

The cache was not cleared correctly in this case

Fix sponsored by LINZ
  • Loading branch information
nyalldawson committed May 14, 2018
1 parent 8f47691 commit 6b742687ab5297cab8fc319cb554e2cc9e2b37d6
@@ -402,6 +402,7 @@ bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist, Flags )
mNextFeatureId++;
}

clearMinMaxCache();
return result;
}

@@ -423,6 +424,7 @@ bool QgsMemoryProvider::deleteFeatures( const QgsFeatureIds &id )
}

updateExtents();
clearMinMaxCache();

return true;
}
@@ -504,6 +506,7 @@ bool QgsMemoryProvider::deleteAttributes( const QgsAttributeIds &attributes )
f.setAttributes( attr );
}
}
clearMinMaxCache();
return true;
}

@@ -519,6 +522,7 @@ bool QgsMemoryProvider::changeAttributeValues( const QgsChangedAttributesMap &at
for ( QgsAttributeMap::const_iterator it2 = attrs.constBegin(); it2 != attrs.constEnd(); ++it2 )
fit->setAttribute( it2.key(), it2.value() );
}
clearMinMaxCache();
return true;
}

@@ -471,6 +471,8 @@ QVariant QgsVectorDataProvider::aggregate( QgsAggregateCalculator::Aggregate agg
void QgsVectorDataProvider::clearMinMaxCache()
{
mCacheMinMaxDirty = true;
mCacheMinValues.clear();
mCacheMaxValues.clear();
}

void QgsVectorDataProvider::fillMinMaxCache() const
@@ -444,6 +444,71 @@ def testThreadSafetyWithIndex(self):
request = QgsFeatureRequest().setFilterRect(extent)
self.assertTrue(QgsTestUtils.testProviderIteratorThreadSafety(self.source, request))

def testMinMaxCache(self):
"""
Test that min/max cache is appropriately cleared
:return:
"""
vl = QgsVectorLayer(
'Point?crs=epsg:4326&field=f1:integer&field=f2:integer',
'test', 'memory')
self.assertTrue(vl.isValid())

f1 = QgsFeature()
f1.setAttributes([5, -200])
f2 = QgsFeature()
f2.setAttributes([3, 300])
f3 = QgsFeature()
f3.setAttributes([1, 100])
f4 = QgsFeature()
f4.setAttributes([2, 200])
f5 = QgsFeature()
f5.setAttributes([4, 400])
res, [f1, f2, f3, f4, f5] = vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])
self.assertTrue(res)

self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 5)
self.assertEqual(vl.dataProvider().maximumValue(1), 400)

# add feature
f6 = QgsFeature()
f6.setAttributes([15, 1400])
res, [f6] = vl.dataProvider().addFeatures([f6])
self.assertTrue(res)
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 15)
self.assertEqual(vl.dataProvider().maximumValue(1), 1400)
f7 = QgsFeature()
f7.setAttributes([-1, -1400])
res, [f7] = vl.dataProvider().addFeatures([f7])
self.assertTrue(res)
self.assertEqual(vl.dataProvider().minimumValue(0), -1)
self.assertEqual(vl.dataProvider().minimumValue(1), -1400)
self.assertEqual(vl.dataProvider().maximumValue(0), 15)
self.assertEqual(vl.dataProvider().maximumValue(1), 1400)

# change attribute values
self.assertTrue(vl.dataProvider().changeAttributeValues({f6.id(): {0: 3, 1: 150}, f7.id(): {0: 4, 1: -100}}))
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
self.assertEqual(vl.dataProvider().maximumValue(0), 5)
self.assertEqual(vl.dataProvider().maximumValue(1), 400)

# delete features
self.assertTrue(vl.dataProvider().deleteFeatures([f4.id(), f1.id()]))
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
self.assertEqual(vl.dataProvider().minimumValue(1), -100)
self.assertEqual(vl.dataProvider().maximumValue(0), 4)
self.assertEqual(vl.dataProvider().maximumValue(1), 400)

# delete attributes
self.assertTrue(vl.dataProvider().deleteAttributes([0]))
self.assertEqual(vl.dataProvider().minimumValue(0), -100)
self.assertEqual(vl.dataProvider().maximumValue(0), 400)


class TestPyQgsMemoryProviderIndexed(unittest.TestCase, ProviderTestCase):

0 comments on commit 6b74268

Please sign in to comment.
You can’t perform that action at this time.