Skip to content

Commit 307daf1

Browse files
committed
Clear existing cache when QgsVectorLayerCache is set to cache geom
Any features inside the cache must be cleared, because they won't necessarily have the feature's geometry cached On behalf of Faunalia, sponsored by ENEL (cherry-picked from 11c444)
1 parent 2a6bceb commit 307daf1

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

src/core/qgsvectorlayercache.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ int QgsVectorLayerCache::cacheSize()
5858

5959
void QgsVectorLayerCache::setCacheGeometry( bool cacheGeometry )
6060
{
61-
mCacheGeometry = cacheGeometry && mLayer->hasGeometryType();
61+
bool shouldCache = cacheGeometry && mLayer->hasGeometryType();
62+
bool mustInvalidate = shouldCache && !mCacheGeometry; // going from no geometry -> geometry, so have to clear existing cache entries
63+
mCacheGeometry = shouldCache;
6264
if ( cacheGeometry )
6365
{
6466
connect( mLayer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), SLOT( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
@@ -67,6 +69,10 @@ void QgsVectorLayerCache::setCacheGeometry( bool cacheGeometry )
6769
{
6870
disconnect( mLayer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
6971
}
72+
if ( mustInvalidate )
73+
{
74+
invalidate();
75+
}
7076
}
7177

7278
void QgsVectorLayerCache::setCacheSubsetOfAttributes( const QgsAttributeList& attributes )

tests/src/core/testqgsvectorlayercache.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class TestVectorLayerCache : public QObject
5454
void testFullCache();
5555
void testFullCacheThroughRequest();
5656
void testCanUseCacheForRequest();
57+
void testCacheGeom();
5758

5859
void onCommittedFeaturesAdded( const QString&, const QgsFeatureList& );
5960

@@ -330,6 +331,51 @@ void TestVectorLayerCache::testCanUseCacheForRequest()
330331
QVERIFY( cache.canUseCacheForRequest( QgsFeatureRequest().setFilterExpression( "$x<5" ), it ) );
331332
}
332333

334+
void TestVectorLayerCache::testCacheGeom()
335+
{
336+
QgsVectorLayerCache cache( mPointsLayer, 2 );
337+
// cache geometry
338+
cache.setCacheGeometry( true );
339+
340+
//first get some feature ids from layer
341+
QgsFeature f;
342+
QgsFeatureIterator it = mPointsLayer->getFeatures();
343+
it.nextFeature( f );
344+
QgsFeatureId id1 = f.id();
345+
it.nextFeature( f );
346+
QgsFeatureId id2 = f.id();
347+
348+
QgsFeatureRequest req;
349+
req.setFlags( QgsFeatureRequest::NoGeometry ); // should be ignored by cache
350+
req.setFilterFids( QgsFeatureIds() << id1 << id2 );
351+
352+
it = cache.getFeatures( req );
353+
while ( it.nextFeature( f ) )
354+
{
355+
QVERIFY( f.constGeometry() );
356+
}
357+
358+
// disabled geometry caching
359+
cache.setCacheGeometry( false );
360+
// we should still have cached features... no need to lose these!
361+
QCOMPARE( cache.cachedFeatureIds(), QgsFeatureIds() << id1 << id2 );
362+
it = cache.getFeatures( req );
363+
while ( it.nextFeature( f ) )
364+
{
365+
QVERIFY( f.constGeometry() );
366+
}
367+
368+
// now upgrade cache from no geometry -> geometry, should be cleared since we
369+
// cannot be confident that features existing in the cache have geometry
370+
cache.setCacheGeometry( true );
371+
QVERIFY( cache.cachedFeatureIds().isEmpty() );
372+
it = cache.getFeatures( req );
373+
while ( it.nextFeature( f ) )
374+
{
375+
QVERIFY( f.constGeometry() );
376+
}
377+
}
378+
333379
void TestVectorLayerCache::onCommittedFeaturesAdded( const QString& layerId, const QgsFeatureList& features )
334380
{
335381
Q_UNUSED( layerId )

0 commit comments

Comments
 (0)