Skip to content

Commit 55aa7a8

Browse files
committed
[OGR provider] Improve performance of subLayers(), particularly on FileGDB with the proprietary driver (fixes #18342)
1 parent 79ba0ee commit 55aa7a8

File tree

2 files changed

+41
-24
lines changed

2 files changed

+41
-24
lines changed

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,11 @@ void QgsOgrProvider::repack()
198198
QString errCause;
199199
if ( mLayerName.isNull() )
200200
{
201-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerIndex, errCause );
201+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerIndex, errCause, true );
202202
}
203203
else
204204
{
205-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerName, errCause );
205+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerName, errCause, true );
206206
}
207207
208208
if ( !mOgrOrigLayer )
@@ -837,18 +837,30 @@ QStringList QgsOgrProvider::subLayers() const
837837
}
838838
else
839839
{
840+
// In case there is no free opened dataset in the cache, keep the first
841+
// layer alive while we iterate over the other layers, so that we can
842+
// reuse the same dataset. Can help in a particular with a FileGDB with
843+
// the FileGDB driver
844+
QgsOgrLayerUniquePtr firstLayer;
840845
for ( unsigned int i = 0; i < layerCount() ; i++ )
841846
{
842847
QString errCause;
843848
QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( mOgrOrigLayer->datasetName(),
844849
mOgrOrigLayer->updateMode(),
845850
mOgrOrigLayer->options(),
846851
i,
847-
errCause );
852+
errCause,
853+
// do not check timestamp beyond the first
854+
// layer
855+
firstLayer == nullptr );
848856
if ( !layer )
849857
continue;
850858

851859
addSubLayerDetailsToSubLayerList( i, layer.get() );
860+
if ( firstLayer == nullptr )
861+
{
862+
firstLayer = std::move( layer );
863+
}
852864
}
853865
}
854866
return mSubLayerList;
@@ -4020,11 +4032,11 @@ void QgsOgrProvider::open( OpenMode mode )
40204032
// has precedence over the layerid if both are given.
40214033
if ( !mLayerName.isNull() )
40224034
{
4023-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerName, errCause );
4035+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerName, errCause, true );
40244036
}
40254037
else
40264038
{
4027-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerIndex, errCause );
4039+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerIndex, errCause, true );
40284040
}
40294041
}
40304042

@@ -4045,11 +4057,11 @@ void QgsOgrProvider::open( OpenMode mode )
40454057
// try to open read-only
40464058
if ( !mLayerName.isNull() )
40474059
{
4048-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause );
4060+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause, true );
40494061
}
40504062
else
40514063
{
4052-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause );
4064+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause, true );
40534065
}
40544066
}
40554067

@@ -4120,11 +4132,11 @@ void QgsOgrProvider::open( OpenMode mode )
41204132
// try to open read-only
41214133
if ( !mLayerName.isNull() )
41224134
{
4123-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause );
4135+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause, true );
41244136
}
41254137
else
41264138
{
4127-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause );
4139+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause, true );
41284140
}
41294141

41304142
mWriteAccess = false;
@@ -4346,18 +4358,19 @@ QgsOgrLayerUniquePtr QgsOgrProviderUtils::getLayer( const QString &dsName,
43464358
errCause = QObject::tr( "Cannot find layer %1." ).arg( layerIndex );
43474359
return nullptr;
43484360
}
4349-
return getLayer( dsName, iter.key().updateMode, iter.key().options, layerName, errCause );
4361+
return getLayer( dsName, iter.key().updateMode, iter.key().options, layerName, errCause, true );
43504362
}
43514363
}
43524364
}
4353-
return getLayer( dsName, false, QStringList(), layerIndex, errCause );
4365+
return getLayer( dsName, false, QStringList(), layerIndex, errCause, true );
43544366
}
43554367

43564368
QgsOgrLayerUniquePtr QgsOgrProviderUtils::getLayer( const QString &dsName,
43574369
bool updateMode,
43584370
const QStringList &options,
43594371
int layerIndex,
4360-
QString &errCause )
4372+
QString &errCause,
4373+
bool checkModificationDateAgainstCache )
43614374
{
43624375
QMutexLocker locker( &sGlobalMutex );
43634376

@@ -4398,7 +4411,8 @@ QgsOgrLayerUniquePtr QgsOgrProviderUtils::getLayer( const QString &dsName,
43984411
errCause = QObject::tr( "Cannot find layer %1." ).arg( layerIndex );
43994412
return nullptr;
44004413
}
4401-
return getLayer( dsName, updateMode, options, layerName, errCause );
4414+
return getLayer( dsName, updateMode, options, layerName, errCause,
4415+
checkModificationDateAgainstCache );
44024416
}
44034417
}
44044418

@@ -4475,7 +4489,7 @@ QgsOgrLayerUniquePtr QgsOgrProviderUtils::getLayer( const QString &dsName,
44754489
}
44764490
}
44774491
}
4478-
return getLayer( dsName, false, QStringList(), layerName, errCause );
4492+
return getLayer( dsName, false, QStringList(), layerName, errCause, true );
44794493
}
44804494

44814495
static QDateTime getLastModified( const QString &dsName )
@@ -4817,7 +4831,8 @@ QgsOgrLayerUniquePtr QgsOgrProviderUtils::getLayer( const QString &dsName,
48174831
bool updateMode,
48184832
const QStringList &options,
48194833
const QString &layerName,
4820-
QString &errCause )
4834+
QString &errCause,
4835+
bool checkModificationDateAgainstCache )
48214836
{
48224837
QMutexLocker locker( &sGlobalMutex );
48234838

@@ -4835,7 +4850,7 @@ QgsOgrLayerUniquePtr QgsOgrProviderUtils::getLayer( const QString &dsName,
48354850
auto iter = sMapSharedDS.find( ident );
48364851
if ( iter != sMapSharedDS.end() )
48374852
{
4838-
if ( !canUseOpenedDatasets( dsName ) )
4853+
if ( checkModificationDateAgainstCache && !canUseOpenedDatasets( dsName ) )
48394854
{
48404855
QgsDebugMsg( QString( "Cannot reuse existing opened dataset(s) on %1 since it has been modified" ).arg( dsName ) );
48414856
invalidateCachedDatasets( dsName );
@@ -5311,11 +5326,11 @@ QgsOgrLayerUniquePtr LoadDataSourceAndLayer( const QString &uri,
53115326

53125327
if ( !layerName.isEmpty() )
53135328
{
5314-
return QgsOgrProviderUtils::getLayer( filePath, true, QStringList(), layerName, errCause );
5329+
return QgsOgrProviderUtils::getLayer( filePath, true, QStringList(), layerName, errCause, true );
53155330
}
53165331
else
53175332
{
5318-
return QgsOgrProviderUtils::getLayer( filePath, true, QStringList(), layerIndex, errCause );
5333+
return QgsOgrProviderUtils::getLayer( filePath, true, QStringList(), layerIndex, errCause, true );
53195334
}
53205335
}
53215336

src/providers/ogr/qgsogrprovider.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -387,30 +387,32 @@ class QgsOgrProviderUtils
387387
//! Wrapper for GDALClose()
388388
static void GDALCloseWrapper( GDALDatasetH mhDS );
389389

390-
//! Open a layer given by name, potentially reusing an existing GDALDatasetH if it doesn't already use that layer. release() should be called when done with the object
390+
//! Open a layer given by name, potentially reusing an existing GDALDatasetH if it doesn't already use that layer.
391391
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
392392
const QString &layerName,
393393
QString &errCause );
394394

395395

396-
//! Open a layer given by name, potentially reusing an existing GDALDatasetH if it has been opened with the same (updateMode, options) tuple and doesn't already use that layer. release() should be called when done with the object
396+
//! Open a layer given by name, potentially reusing an existing GDALDatasetH if it has been opened with the same (updateMode, options) tuple and doesn't already use that layer.
397397
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
398398
bool updateMode,
399399
const QStringList &options,
400400
const QString &layerName,
401-
QString &errCause );
401+
QString &errCause,
402+
bool checkModificationDateAgainstCache );
402403

403-
//! Open a layer given by index, potentially reusing an existing GDALDatasetH if it doesn't already use that layer. release() should be called when done with the object
404+
//! Open a layer given by index, potentially reusing an existing GDALDatasetH if it doesn't already use that layer.
404405
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
405406
int layerIndex,
406407
QString &errCause );
407408

408-
//! Open a layer given by index, potentially reusing an existing GDALDatasetH if it has been opened with the same (updateMode, options) tuple and doesn't already use that layer. release() should be called when done with the object
409+
//! Open a layer given by index, potentially reusing an existing GDALDatasetH if it has been opened with the same (updateMode, options) tuple and doesn't already use that layer.
409410
static QgsOgrLayerUniquePtr getLayer( const QString &dsName,
410411
bool updateMode,
411412
const QStringList &options,
412413
int layerIndex,
413-
QString &errCause );
414+
QString &errCause,
415+
bool checkModificationDateAgainstCache );
414416

415417
//! Returns a QgsOgrLayer* with a SQL result layer
416418
static QgsOgrLayerUniquePtr getSqlLayer( QgsOgrLayer *baseLayer, OGRLayerH hSqlLayer, const QString &sql );

0 commit comments

Comments
 (0)