Skip to content

Commit e7d15b6

Browse files
committed
[GDAL provider] Make sure that setEditable(true) invalides cached GDAL handles to get proper refresh (fixes #20104)
1 parent 0816a29 commit e7d15b6

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

src/providers/gdal/qgsgdalprovider.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,6 @@ QgsGdalProvider::~QgsGdalProvider()
490490
}
491491

492492

493-
// This was used by raster layer to reload data
494493
void QgsGdalProvider::closeDataset()
495494
{
496495
if ( !mValid )
@@ -504,6 +503,8 @@ void QgsGdalProvider::closeDataset()
504503

505504
GDALClose( mGdalDataset );
506505
mGdalDataset = nullptr;
506+
507+
closeCachedGdalHandlesFor( this );
507508
}
508509

509510
QString QgsGdalProvider::htmlMetadata()
@@ -2956,8 +2957,7 @@ bool QgsGdalProvider::remove()
29562957
if ( mGdalDataset )
29572958
{
29582959
GDALDriverH driver = GDALGetDatasetDriver( mGdalDataset );
2959-
GDALClose( mGdalDataset );
2960-
mGdalDataset = nullptr;
2960+
closeDataset();
29612961

29622962
CPLErrorReset();
29632963
CPLErr err = GDALDeleteDataset( driver, dataSourceUri( true ).toUtf8().constData() );

tests/src/providers/testqgsgdalprovider.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class TestQgsGdalProvider : public QObject
5454
void bandName(); // test band name based on `gtiff` tags (#7317)
5555
void bandNameNoDescription(); // test band name for when no description or tags available (#16047)
5656
void bandNameWithDescription(); // test band name for when description available (#16047)
57+
void interactionBetweenRasterChangeAndCache(); // test that updading a raster invalidates the GDAL dataset cache (#20104)
5758

5859
private:
5960
QString mTestDataDir;
@@ -275,5 +276,50 @@ void TestQgsGdalProvider::bandNameWithDescription()
275276
delete provider;
276277
}
277278

279+
void TestQgsGdalProvider::interactionBetweenRasterChangeAndCache()
280+
{
281+
double geoTransform[6] = { 0, 2, 0, 0, 0, -2};
282+
QgsCoordinateReferenceSystem crs;
283+
QString filename = QStringLiteral( "/vsimem/temp.tif" );
284+
285+
// Create a all-0 dataset
286+
auto provider = QgsRasterDataProvider::create(
287+
QStringLiteral( "gdal" ), filename, "GTiff", 1, Qgis::Byte, 1, 1, geoTransform, crs );
288+
delete provider;
289+
290+
// Open it
291+
provider = dynamic_cast< QgsRasterDataProvider * >(
292+
QgsProviderRegistry::instance()->createProvider(
293+
QStringLiteral( "gdal" ), filename, QgsDataProvider::ProviderOptions() ) );
294+
QVERIFY( provider );
295+
auto rp = dynamic_cast< QgsRasterDataProvider * >( provider );
296+
QVERIFY( rp );
297+
298+
// Create a first clone, and destroys it
299+
auto rpClone = dynamic_cast< QgsRasterDataProvider *>( rp->clone() );
300+
QVERIFY( rpClone );
301+
QCOMPARE( rpClone->sample( QgsPointXY( 0.5, -0.5 ), 1 ), 0.0 );
302+
delete rpClone;
303+
// Now the main provider should have a cached GDAL dataset corresponding
304+
// to the one that was used by rpClone
305+
306+
// Modify the raster
307+
rp->setEditable( true );
308+
auto rblock = new QgsRasterBlock( Qgis::Byte, 1, 1 );
309+
rblock->setValue( 0, 0, 255 );
310+
rp->writeBlock( rblock, 1, 0, 0 );
311+
delete rblock;
312+
rp->setEditable( false );
313+
314+
// Creates a new clone, and check that we get an updated sample value
315+
rpClone = dynamic_cast< QgsRasterDataProvider *>( rp->clone() );
316+
QVERIFY( rpClone );
317+
QCOMPARE( rpClone->sample( QgsPointXY( 0.5, -0.5 ), 1 ), 255.0 );
318+
delete rpClone;
319+
320+
provider->remove();
321+
delete provider;
322+
}
323+
278324
QGSTEST_MAIN( TestQgsGdalProvider )
279325
#include "testqgsgdalprovider.moc"

0 commit comments

Comments
 (0)