Skip to content

Commit

Permalink
create postgres RO connection in the thread where the provider live
Browse files Browse the repository at this point in the history
  • Loading branch information
vcloarec authored and github-actions[bot] committed Jul 19, 2023
1 parent e216ca2 commit 3cc21e1
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 3 deletions.
Expand Up @@ -79,6 +79,7 @@ Abstract base class for spatial data provider implementations.
SkipFullScan,
ForceReadOnly,
SkipCredentialsRequest,
ParallelThreadLoading,
};
typedef QFlags<QgsDataProvider::ReadFlag> ReadFlags;

Expand Down
2 changes: 2 additions & 0 deletions src/core/project/qgsproject.cpp
Expand Up @@ -1367,6 +1367,7 @@ void QgsProject::preloadProviders( const QVector<QDomNode> &parallelLayerNodes,

// Requesting credential from worker thread could lead to deadlocks because the main thread is waiting for worker thread to fininsh
layerToLoad.flags.setFlag( QgsDataProvider::SkipCredentialsRequest, true );
layerToLoad.flags.setFlag( QgsDataProvider::ParallelThreadLoading, true );

layersToLoad.insert( layerToLoad.layerId, layerToLoad );
}
Expand Down Expand Up @@ -1425,6 +1426,7 @@ void QgsProject::preloadProviders( const QVector<QDomNode> &parallelLayerNodes,
const LayerToLoad &lay = it.value();
QgsDataProvider::ReadFlags providerFlags = lay.flags;
providerFlags.setFlag( QgsDataProvider::SkipCredentialsRequest, false );
providerFlags.setFlag( QgsDataProvider::ParallelThreadLoading, false );
QgsScopedRuntimeProfile profile( "Create data providers/" + lay.layerId, QStringLiteral( "projectload" ) );
std::unique_ptr<QgsDataProvider> provider( QgsProviderRegistry::instance()->createProvider( lay.provider, lay.dataSource, lay.options, providerFlags ) );
i++;
Expand Down
1 change: 1 addition & 0 deletions src/core/providers/qgsdataprovider.h
Expand Up @@ -128,6 +128,7 @@ class CORE_EXPORT QgsDataProvider : public QObject
SkipFullScan = 1 << 4, //!< Skip expensive full scan on files (i.e. on delimited text) (since QGIS 3.24)
ForceReadOnly = 1 << 5, //!< Open layer in a read-only mode (since QGIS 3.28)
SkipCredentialsRequest = 1 << 6, //! Skip credentials if the provided one are not valid, let the provider be invalid, avoiding to block the thread creating the provider if it is not the main thread (since QGIS 3.32).
ParallelThreadLoading = 1 << 7, //! Provider is created in a parallel thread than the one where it will live (since QGIS 3.32.1).
};
Q_DECLARE_FLAGS( ReadFlags, ReadFlag )

Expand Down
15 changes: 13 additions & 2 deletions src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -303,6 +303,11 @@ QgsPostgresProvider::QgsPostgresProvider( QString const &uri, const ProviderOpti

mLayerMetadata.setType( QStringLiteral( "dataset" ) );
mLayerMetadata.setCrs( crs() );

// Constructor is called in another thread than the thread where the provider will live,
// so we disconnect the DB, connection will be done later in the provider thread when needed
if ( flags.testFlag( QgsDataProvider::ParallelThreadLoading ) )
disconnectDb();
}

QgsPostgresProvider::~QgsPostgresProvider()
Expand All @@ -320,7 +325,13 @@ QgsAbstractFeatureSource *QgsPostgresProvider::featureSource() const

QgsPostgresConn *QgsPostgresProvider::connectionRO() const
{
return mTransaction ? mTransaction->connection() : mConnectionRO;
if ( mTransaction )
return mTransaction->connection();

if ( !mConnectionRO )
mConnectionRO = QgsPostgresConn::connectDb( mUri, true, true, false, !mReadFlags.testFlag( QgsDataProvider::SkipCredentialsRequest ) );

return mConnectionRO;
}

void QgsPostgresProvider::setListening( bool isListening )
Expand Down Expand Up @@ -3887,7 +3898,7 @@ QgsRectangle QgsPostgresProvider::extent() const
quotedValue( mSchemaName ),
quotedValue( mTableName ),
quotedValue( mGeometryColumn ) );
result = mConnectionRO->LoggedPQexec( "QgsPostgresProvider", sql );
result = connectionRO()->LoggedPQexec( "QgsPostgresProvider", sql );
if ( result.PQresultStatus() == PGRES_TUPLES_OK && result.PQntuples() == 1 && !result.PQgetisnull( 0, 0 ) )
{
ext = result.PQgetvalue( 0, 0 );
Expand Down
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresprovider.h
Expand Up @@ -450,7 +450,7 @@ class QgsPostgresProvider final: public QgsVectorDataProvider

QString paramValue( const QString &fieldvalue, const QString &defaultValue ) const;

QgsPostgresConn *mConnectionRO = nullptr ; //!< Read-only database connection (initially)
mutable QgsPostgresConn *mConnectionRO = nullptr ; //!< Read-only database connection (initially)
QgsPostgresConn *mConnectionRW = nullptr ; //!< Read-write database connection (on update)

QgsPostgresConn *connectionRO() const;
Expand Down

0 comments on commit 3cc21e1

Please sign in to comment.