Skip to content

Commit dd0c4c7

Browse files
committed
[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 (cherry-picked from 6b74268)
1 parent 3716fa6 commit dd0c4c7

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

src/core/providers/memory/qgsmemoryprovider.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist, Flags )
402402
mNextFeatureId++;
403403
}
404404

405+
clearMinMaxCache();
405406
return result;
406407
}
407408

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

425426
updateExtents();
427+
clearMinMaxCache();
426428

427429
return true;
428430
}
@@ -504,6 +506,7 @@ bool QgsMemoryProvider::deleteAttributes( const QgsAttributeIds &attributes )
504506
f.setAttributes( attr );
505507
}
506508
}
509+
clearMinMaxCache();
507510
return true;
508511
}
509512

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

src/core/qgsvectordataprovider.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ QVariant QgsVectorDataProvider::aggregate( QgsAggregateCalculator::Aggregate agg
471471
void QgsVectorDataProvider::clearMinMaxCache()
472472
{
473473
mCacheMinMaxDirty = true;
474+
mCacheMinValues.clear();
475+
mCacheMaxValues.clear();
474476
}
475477

476478
void QgsVectorDataProvider::fillMinMaxCache() const

tests/src/python/test_provider_memory.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,71 @@ def testThreadSafetyWithIndex(self):
444444
request = QgsFeatureRequest().setFilterRect(extent)
445445
self.assertTrue(QgsTestUtils.testProviderIteratorThreadSafety(self.source, request))
446446

447+
def testMinMaxCache(self):
448+
"""
449+
Test that min/max cache is appropriately cleared
450+
:return:
451+
"""
452+
vl = QgsVectorLayer(
453+
'Point?crs=epsg:4326&field=f1:integer&field=f2:integer',
454+
'test', 'memory')
455+
self.assertTrue(vl.isValid())
456+
457+
f1 = QgsFeature()
458+
f1.setAttributes([5, -200])
459+
f2 = QgsFeature()
460+
f2.setAttributes([3, 300])
461+
f3 = QgsFeature()
462+
f3.setAttributes([1, 100])
463+
f4 = QgsFeature()
464+
f4.setAttributes([2, 200])
465+
f5 = QgsFeature()
466+
f5.setAttributes([4, 400])
467+
res, [f1, f2, f3, f4, f5] = vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])
468+
self.assertTrue(res)
469+
470+
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
471+
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
472+
self.assertEqual(vl.dataProvider().maximumValue(0), 5)
473+
self.assertEqual(vl.dataProvider().maximumValue(1), 400)
474+
475+
# add feature
476+
f6 = QgsFeature()
477+
f6.setAttributes([15, 1400])
478+
res, [f6] = vl.dataProvider().addFeatures([f6])
479+
self.assertTrue(res)
480+
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
481+
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
482+
self.assertEqual(vl.dataProvider().maximumValue(0), 15)
483+
self.assertEqual(vl.dataProvider().maximumValue(1), 1400)
484+
f7 = QgsFeature()
485+
f7.setAttributes([-1, -1400])
486+
res, [f7] = vl.dataProvider().addFeatures([f7])
487+
self.assertTrue(res)
488+
self.assertEqual(vl.dataProvider().minimumValue(0), -1)
489+
self.assertEqual(vl.dataProvider().minimumValue(1), -1400)
490+
self.assertEqual(vl.dataProvider().maximumValue(0), 15)
491+
self.assertEqual(vl.dataProvider().maximumValue(1), 1400)
492+
493+
# change attribute values
494+
self.assertTrue(vl.dataProvider().changeAttributeValues({f6.id(): {0: 3, 1: 150}, f7.id(): {0: 4, 1: -100}}))
495+
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
496+
self.assertEqual(vl.dataProvider().minimumValue(1), -200)
497+
self.assertEqual(vl.dataProvider().maximumValue(0), 5)
498+
self.assertEqual(vl.dataProvider().maximumValue(1), 400)
499+
500+
# delete features
501+
self.assertTrue(vl.dataProvider().deleteFeatures([f4.id(), f1.id()]))
502+
self.assertEqual(vl.dataProvider().minimumValue(0), 1)
503+
self.assertEqual(vl.dataProvider().minimumValue(1), -100)
504+
self.assertEqual(vl.dataProvider().maximumValue(0), 4)
505+
self.assertEqual(vl.dataProvider().maximumValue(1), 400)
506+
507+
# delete attributes
508+
self.assertTrue(vl.dataProvider().deleteAttributes([0]))
509+
self.assertEqual(vl.dataProvider().minimumValue(0), -100)
510+
self.assertEqual(vl.dataProvider().maximumValue(0), 400)
511+
447512

448513
class TestPyQgsMemoryProviderIndexed(unittest.TestCase, ProviderTestCase):
449514

0 commit comments

Comments
 (0)