mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-17 00:09:36 -04:00
parent
25da5f8810
commit
6b18c7fb1d
@ -15,4 +15,5 @@ QgsProviderMetadata.ProviderMetadataCapabilities = lambda flags=0: QgsProviderMe
|
||||
QgsProviderMetadata.FileBasedUris = QgsProviderMetadata.ProviderCapability.FileBasedUris
|
||||
QgsProviderMetadata.SaveLayerMetadata = QgsProviderMetadata.ProviderCapability.SaveLayerMetadata
|
||||
QgsProviderMetadata.ParallelCreateProvider = QgsProviderMetadata.ProviderCapability.ParallelCreateProvider
|
||||
QgsProviderMetadata.LoadLayerMetadata = QgsProviderMetadata.ProviderCapability.LoadLayerMetadata
|
||||
QgsProviderMetadata.ProviderCapabilities = lambda flags=0: QgsProviderMetadata.ProviderCapability(flags)
|
||||
|
@ -158,6 +158,7 @@ library object.
|
||||
FileBasedUris,
|
||||
SaveLayerMetadata,
|
||||
ParallelCreateProvider,
|
||||
LoadLayerMetadata,
|
||||
};
|
||||
typedef QFlags<QgsProviderMetadata::ProviderCapability> ProviderCapabilities;
|
||||
|
||||
@ -680,6 +681,21 @@ Saves ``metadata`` to the layer corresponding to the specified ``uri``.
|
||||
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
virtual QgsLayerMetadata loadLayerMetadata( const QString &layerUri, bool &found /Out/ ) throw( QgsNotSupportedException );
|
||||
%Docstring
|
||||
Loads layer metadata for the specified ``layerUri``.
|
||||
|
||||
:param layerUri: uri of layer to load metadata for
|
||||
|
||||
:return: - layer metadata
|
||||
- found: set to ``True`` if metadata was found, ``False`` otherwise
|
||||
|
||||
:raises QgsNotSupportedException: if the provider does not support loading layer metadata for the
|
||||
specified ``layerUri``.
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
virtual bool createDb( const QString &dbPath, QString &errCause );
|
||||
|
@ -324,6 +324,25 @@ Saves ``metadata`` to the layer corresponding to the specified ``uri``.
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
QgsLayerMetadata loadLayerMetadata( const QString &providerKey, const QString &uri, bool &found /Out/ ) throw( QgsNotSupportedException );
|
||||
%Docstring
|
||||
Loads metadata for the layer corresponding to the specified ``uri``.
|
||||
|
||||
:param providerKey: identifier of the provider
|
||||
:param uri: uri of layer to load metadata for
|
||||
|
||||
:return: - The layer metadata or empty metadata if not found.
|
||||
- found: will be set to ``True`` if metadata was found, or ``False`` if no metadata was found
|
||||
|
||||
|
||||
:raises QgsNotSupportedException: if the provider does not support loading layer metadata for the
|
||||
specified ``uri``.
|
||||
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
|
||||
bool createDb( const QString &providerKey, const QString &dbPath, QString &errCause );
|
||||
%Docstring
|
||||
Creates database by the provider on the path
|
||||
|
@ -158,6 +158,7 @@ library object.
|
||||
FileBasedUris,
|
||||
SaveLayerMetadata,
|
||||
ParallelCreateProvider,
|
||||
LoadLayerMetadata,
|
||||
};
|
||||
typedef QFlags<QgsProviderMetadata::ProviderCapability> ProviderCapabilities;
|
||||
|
||||
@ -680,6 +681,21 @@ Saves ``metadata`` to the layer corresponding to the specified ``uri``.
|
||||
|
||||
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
virtual QgsLayerMetadata loadLayerMetadata( const QString &layerUri, bool &found /Out/ ) throw( QgsNotSupportedException );
|
||||
%Docstring
|
||||
Loads layer metadata for the specified ``layerUri``.
|
||||
|
||||
:param layerUri: uri of layer to load metadata for
|
||||
|
||||
:return: - layer metadata
|
||||
- found: set to ``True`` if metadata was found, ``False`` otherwise
|
||||
|
||||
:raises QgsNotSupportedException: if the provider does not support loading layer metadata for the
|
||||
specified ``layerUri``.
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
virtual bool createDb( const QString &dbPath, QString &errCause );
|
||||
|
@ -324,6 +324,25 @@ Saves ``metadata`` to the layer corresponding to the specified ``uri``.
|
||||
.. versionadded:: 3.20
|
||||
%End
|
||||
|
||||
QgsLayerMetadata loadLayerMetadata( const QString &providerKey, const QString &uri, bool &found /Out/ ) throw( QgsNotSupportedException );
|
||||
%Docstring
|
||||
Loads metadata for the layer corresponding to the specified ``uri``.
|
||||
|
||||
:param providerKey: identifier of the provider
|
||||
:param uri: uri of layer to load metadata for
|
||||
|
||||
:return: - The layer metadata or empty metadata if not found.
|
||||
- found: will be set to ``True`` if metadata was found, or ``False`` if no metadata was found
|
||||
|
||||
|
||||
:raises QgsNotSupportedException: if the provider does not support loading layer metadata for the
|
||||
specified ``uri``.
|
||||
|
||||
|
||||
.. versionadded:: 3.36
|
||||
%End
|
||||
|
||||
|
||||
bool createDb( const QString &providerKey, const QString &dbPath, QString &errCause );
|
||||
%Docstring
|
||||
Creates database by the provider on the path
|
||||
|
@ -32,6 +32,7 @@ email : nyall dot dawson at gmail dot com
|
||||
#include "qgsgdalutils.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsvectorfilewriter.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include <gdal.h>
|
||||
#include <QFileInfo>
|
||||
@ -654,6 +655,117 @@ bool QgsOgrProviderMetadata::saveLayerMetadata( const QString &uri, const QgsLay
|
||||
throw QgsNotSupportedException( QObject::tr( "Storing metadata for the specified uri is not supported" ) );
|
||||
}
|
||||
|
||||
QgsLayerMetadata QgsOgrProviderMetadata::loadLayerMetadata( const QString &layerUri, bool &found )
|
||||
{
|
||||
QgsLayerMetadata metadata;
|
||||
found = false;
|
||||
const QVariantMap parts = decodeUri( layerUri );
|
||||
const QString path = parts.value( QStringLiteral( "path" ) ).toString();
|
||||
QString errorMessage;
|
||||
|
||||
if ( !path.isEmpty() && QFileInfo::exists( path ) )
|
||||
{
|
||||
const QFileInfo fi( path );
|
||||
// if it is a gpkg, try reading metadata
|
||||
if ( fi.suffix().compare( QLatin1String( "gpkg" ), Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
const QString layerName = parts.value( QStringLiteral( "layerName" ) ).toString();
|
||||
QgsOgrLayerUniquePtr userLayer;
|
||||
userLayer = QgsOgrProviderUtils::getLayer( path, true, QStringList(), layerName, errorMessage, true );
|
||||
if ( userLayer )
|
||||
{
|
||||
// try to read metadata from gpkg_metadata table
|
||||
QString sql = QStringLiteral( "SELECT metadata FROM gpkg_metadata LEFT JOIN gpkg_metadata_reference ON "
|
||||
"(gpkg_metadata_reference.table_name = %1 AND gpkg_metadata.id = gpkg_metadata_reference.md_file_id) "
|
||||
"WHERE md_standard_uri = %2 and reference_scope = %3" ).arg(
|
||||
QgsSqliteUtils::quotedString( layerName ),
|
||||
QgsSqliteUtils::quotedString( QStringLiteral( "http://mrcc.com/qgis.dtd" ) ),
|
||||
QgsSqliteUtils::quotedString( QStringLiteral( "table" ) ) );
|
||||
if ( QgsOgrLayerUniquePtr l = userLayer->ExecuteSQL( sql.toUtf8().constData() ) )
|
||||
{
|
||||
// retrieve row id
|
||||
gdal::ogr_feature_unique_ptr f( l->GetNextFeature() );
|
||||
if ( f )
|
||||
{
|
||||
bool ok = false;
|
||||
QVariant res = QgsOgrUtils::getOgrFeatureAttribute( f.get(), QgsField( QString(), QVariant::String ), 0, nullptr, &ok );
|
||||
if ( ok )
|
||||
{
|
||||
QDomDocument document;
|
||||
QString metadataXml = res.toString();
|
||||
if ( document.setContent( metadataXml ) )
|
||||
{
|
||||
if ( !metadata.readMetadataXml( document.documentElement() ) )
|
||||
{
|
||||
found = false;
|
||||
return metadata;
|
||||
}
|
||||
found = true;
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read from gpkg_contents but do not override whatever was set in the previous step
|
||||
// (this is to support old geopackages which do not have metadata in gpkg_metadata)
|
||||
|
||||
if ( metadata.title().isEmpty() || metadata.abstract().isEmpty() )
|
||||
{
|
||||
QRecursiveMutex *mutex = nullptr;
|
||||
// Returns native OGRLayerH object with the mutex to lock when using it
|
||||
OGRLayerH hLayer = userLayer->getHandleAndMutex( mutex );
|
||||
QMutexLocker locker( mutex );
|
||||
|
||||
// These are special keys which get stored into the gpkg_contents table
|
||||
if ( metadata.abstract().isEmpty() )
|
||||
{
|
||||
const char *description = GDALGetMetadataItem( hLayer, "DESCRIPTION", nullptr );
|
||||
if ( description )
|
||||
{
|
||||
metadata.setAbstract( QString( description ) );
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if ( metadata.title().isEmpty() )
|
||||
{
|
||||
const char *identifier = GDALGetMetadataItem( hLayer, "IDENTIFIER", nullptr );
|
||||
if ( identifier )
|
||||
{
|
||||
found = true;
|
||||
metadata.setIdentifier( QString( identifier ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
// try to read metadata from .qmd sidecar file
|
||||
const QFileInfo fi( path );
|
||||
const QString qmdFileName = fi.dir().filePath( fi.completeBaseName() + QStringLiteral( ".qmd" ) );
|
||||
QFile qmdFile( qmdFileName );
|
||||
if ( qmdFile.open( QFile::ReadOnly ) )
|
||||
{
|
||||
QDomDocument document;
|
||||
if ( document.setContent( &qmdFile ) )
|
||||
{
|
||||
if ( !metadata.readMetadataXml( document.documentElement() ) )
|
||||
{
|
||||
found = false;
|
||||
return metadata;
|
||||
}
|
||||
found = true;
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
throw QgsNotSupportedException( QObject::tr( "Loading metadata for the specified uri is not supported" ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
QgsTransaction *QgsOgrProviderMetadata::createTransaction( const QString &connString )
|
||||
{
|
||||
@ -1201,7 +1313,7 @@ void QgsOgrProviderMetadata::saveConnection( const QgsAbstractProviderConnection
|
||||
|
||||
QgsProviderMetadata::ProviderCapabilities QgsOgrProviderMetadata::providerCapabilities() const
|
||||
{
|
||||
return FileBasedUris | SaveLayerMetadata;
|
||||
return FileBasedUris | SaveLayerMetadata | LoadLayerMetadata;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
@ -73,6 +73,7 @@ class QgsOgrProviderMetadata final: public QgsProviderMetadata
|
||||
QStringList &descriptions, QString &errCause ) override;
|
||||
QString getStyleById( const QString &uri, const QString &styleId, QString &errCause ) override;
|
||||
bool saveLayerMetadata( const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage ) final;
|
||||
QgsLayerMetadata loadLayerMetadata( const QString &layerUri, bool &found ) override;
|
||||
|
||||
// -----
|
||||
QgsTransaction *createTransaction( const QString &connString ) override;
|
||||
@ -85,9 +86,9 @@ class QgsOgrProviderMetadata final: public QgsProviderMetadata
|
||||
void saveConnection( const QgsAbstractProviderConnection *connection, const QString &name ) override;
|
||||
|
||||
protected:
|
||||
|
||||
QgsAbstractProviderConnection *createConnection( const QString &uri, const QVariantMap &configuration ) override;
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
|
@ -297,6 +297,11 @@ bool QgsProviderMetadata::saveLayerMetadata( const QString &, const QgsLayerMeta
|
||||
throw QgsNotSupportedException( QObject::tr( "Provider %1 does not support writing layer metadata" ).arg( key() ) );
|
||||
}
|
||||
|
||||
QgsLayerMetadata QgsProviderMetadata::loadLayerMetadata( const QString &, bool & )
|
||||
{
|
||||
throw QgsNotSupportedException( QObject::tr( "Provider %1 does not support reading layer metadata" ).arg( key() ) );
|
||||
}
|
||||
|
||||
bool QgsProviderMetadata::createDb( const QString &, QString &errCause )
|
||||
{
|
||||
errCause = QObject::tr( "Provider %1 has no %2 method" ).arg( key(), QStringLiteral( "createDb" ) );
|
||||
|
@ -203,6 +203,7 @@ class CORE_EXPORT QgsProviderMetadata : public QObject
|
||||
FileBasedUris = 1 << 0, //!< Indicates that the provider can utilize URIs which are based on paths to files (as opposed to database or internet paths)
|
||||
SaveLayerMetadata = 1 << 1, //!< Indicates that the provider supports saving native layer metadata (since QGIS 3.20)
|
||||
ParallelCreateProvider = 1 << 2, //!< Indicates that the provider supports parallel creation, that is, can be created on another thread than the main thread (since QGIS 3.32)
|
||||
LoadLayerMetadata = 1 << 3, //!< Indicates that the provider supports loading native layer metadata (since QGIS 3.36)
|
||||
};
|
||||
Q_DECLARE_FLAGS( ProviderCapabilities, ProviderCapability )
|
||||
|
||||
@ -703,6 +704,17 @@ class CORE_EXPORT QgsProviderMetadata : public QObject
|
||||
*/
|
||||
virtual bool saveLayerMetadata( const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage SIP_OUT ) SIP_THROW( QgsNotSupportedException );
|
||||
|
||||
/**
|
||||
* Loads layer metadata for the specified \a layerUri.
|
||||
* \param layerUri uri of layer to load metadata for
|
||||
* \param found set to TRUE if metadata was found, FALSE otherwise
|
||||
* \returns layer metadata
|
||||
* \throws QgsNotSupportedException if the provider does not support loading layer metadata for the
|
||||
* specified \a layerUri.
|
||||
* \since QGIS 3.36
|
||||
*/
|
||||
virtual QgsLayerMetadata loadLayerMetadata( const QString &layerUri, bool &found SIP_OUT ) SIP_THROW( QgsNotSupportedException );
|
||||
|
||||
/**
|
||||
* Creates database by the provider on the path
|
||||
* \since QGIS 3.10
|
||||
|
@ -840,6 +840,16 @@ bool QgsProviderRegistry::saveLayerMetadata( const QString &providerKey, const Q
|
||||
}
|
||||
}
|
||||
|
||||
QgsLayerMetadata QgsProviderRegistry::loadLayerMetadata( const QString &providerKey, const QString &uri, bool &found )
|
||||
{
|
||||
if ( QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey ) )
|
||||
return meta->loadLayerMetadata( uri, found );
|
||||
else
|
||||
{
|
||||
throw QgsNotSupportedException( QObject::tr( "Unable to load %1 provider" ).arg( providerKey ) );
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsProviderRegistry::createDb( const QString &providerKey, const QString &dbPath, QString &errCause )
|
||||
{
|
||||
QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
|
||||
|
@ -335,6 +335,23 @@ class CORE_EXPORT QgsProviderRegistry
|
||||
*/
|
||||
bool saveLayerMetadata( const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage SIP_OUT ) SIP_THROW( QgsNotSupportedException );
|
||||
|
||||
/**
|
||||
* Loads metadata for the layer corresponding to the specified \a uri.
|
||||
*
|
||||
* \param providerKey identifier of the provider
|
||||
* \param uri uri of layer to load metadata for
|
||||
* \param found will be set to TRUE if metadata was found, or FALSE if no metadata was found
|
||||
*
|
||||
* \returns The layer metadata or empty metadata if not found.
|
||||
*
|
||||
* \throws QgsNotSupportedException if the provider does not support loading layer metadata for the
|
||||
* specified \a uri.
|
||||
*
|
||||
* \since QGIS 3.36
|
||||
*/
|
||||
QgsLayerMetadata loadLayerMetadata( const QString &providerKey, const QString &uri, bool &found SIP_OUT ) SIP_THROW( QgsNotSupportedException );
|
||||
|
||||
|
||||
/**
|
||||
* Creates database by the provider on the path
|
||||
* \since QGIS 3.10
|
||||
|
@ -1301,6 +1301,28 @@ QString QgsMapLayer::loadDefaultMetadata( bool &resultFlag )
|
||||
{
|
||||
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
|
||||
|
||||
|
||||
if ( const QgsProviderMetadata *metadata = QgsProviderRegistry::instance()->providerMetadata( providerType() ) )
|
||||
{
|
||||
if ( metadata->providerCapabilities() & QgsProviderMetadata::ProviderCapability::LoadLayerMetadata )
|
||||
{
|
||||
try
|
||||
{
|
||||
const QgsLayerMetadata metadata { QgsProviderRegistry::instance()->loadLayerMetadata( providerType(), mDataSource, resultFlag ) };
|
||||
if ( resultFlag )
|
||||
{
|
||||
mMetadata = metadata;
|
||||
return tr( "Successfully loaded default layer metadata" );
|
||||
}
|
||||
}
|
||||
catch ( QgsNotSupportedException &e )
|
||||
{
|
||||
resultFlag = false;
|
||||
return e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loadNamedMetadata( metadataUri(), resultFlag );
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ void QgsLayerPropertiesDialog::loadDefaultMetadata()
|
||||
return;
|
||||
|
||||
bool defaultLoadedFlag = false;
|
||||
const QString message = mLayer->loadNamedMetadata( mLayer->metadataUri(), defaultLoadedFlag );
|
||||
const QString message = mLayer->loadDefaultMetadata( defaultLoadedFlag );
|
||||
//reset if the default metadata was loaded OK only
|
||||
if ( defaultLoadedFlag )
|
||||
{
|
||||
|
@ -215,36 +215,14 @@ QgsPostgresProvider::QgsPostgresProvider( QString const &uri, const ProviderOpti
|
||||
|
||||
mLayerExtent.setNull();
|
||||
|
||||
// Try to load metadata
|
||||
const QString schemaQuery = QStringLiteral( "SELECT table_schema FROM information_schema.tables WHERE table_name = 'qgis_layer_metadata'" );
|
||||
QgsPostgresResult res( mConnectionRO->LoggedPQexec( "QgsPostgresProvider", schemaQuery ) );
|
||||
if ( res.PQntuples( ) > 0 )
|
||||
{
|
||||
const QString schemaName = res.PQgetvalue( 0, 0 );
|
||||
// TODO: also filter CRS?
|
||||
const QString selectQuery = QStringLiteral( R"SQL(
|
||||
SELECT
|
||||
qmd
|
||||
FROM %4.qgis_layer_metadata
|
||||
WHERE
|
||||
f_table_schema=%1
|
||||
AND f_table_name=%2
|
||||
AND f_geometry_column %3
|
||||
AND layer_type='vector'
|
||||
)SQL" )
|
||||
.arg( QgsPostgresConn::quotedValue( mUri.schema() ) )
|
||||
.arg( QgsPostgresConn::quotedValue( mUri.table() ) )
|
||||
.arg( mUri.geometryColumn().isEmpty() ? QStringLiteral( "IS NULL" ) : QStringLiteral( "=%1" ).arg( QgsPostgresConn::quotedValue( mUri.geometryColumn() ) ) )
|
||||
.arg( QgsPostgresConn::quotedIdentifier( schemaName ) );
|
||||
// Try to load metadata from DB
|
||||
bool metadataLoadedFromDb = false;
|
||||
QgsLayerMetadata metadataFromDb { QgsPostgresProviderMetadataUtils::loadLayerMetadata( Qgis::LayerType::Vector, uri, metadataLoadedFromDb ) };
|
||||
|
||||
QgsPostgresResult res( mConnectionRO->LoggedPQexec( "QgsPostgresProvider", selectQuery ) );
|
||||
if ( res.PQntuples() > 0 )
|
||||
{
|
||||
QgsLayerMetadata metadata;
|
||||
QDomDocument doc;
|
||||
doc.setContent( res.PQgetvalue( 0, 0 ) );
|
||||
mLayerMetadata.readMetadataXml( doc.documentElement() );
|
||||
}
|
||||
if ( metadataLoadedFromDb )
|
||||
{
|
||||
mLayerMetadata = metadataFromDb;
|
||||
QgsMessageLog::logMessage( tr( "PostgreSQL layer metadata loaded from DB." ), tr( "PostGIS" ) );
|
||||
}
|
||||
|
||||
// set the primary key
|
||||
@ -6095,8 +6073,13 @@ bool QgsPostgresProviderMetadata::saveLayerMetadata( const QString &uri, const Q
|
||||
return QgsPostgresProviderMetadataUtils::saveLayerMetadata( Qgis::LayerType::Vector, uri, metadata, errorMessage );
|
||||
}
|
||||
|
||||
QgsLayerMetadata QgsPostgresProviderMetadata::loadLayerMetadata( const QString &layerUri, bool &found )
|
||||
{
|
||||
return QgsPostgresProviderMetadataUtils::loadLayerMetadata( Qgis::LayerType::Vector, layerUri, found );
|
||||
}
|
||||
|
||||
|
||||
QgsProviderMetadata::ProviderCapabilities QgsPostgresProviderMetadata::providerCapabilities() const
|
||||
{
|
||||
return QgsProviderMetadata::ProviderCapability::SaveLayerMetadata | QgsProviderMetadata::ProviderCapability::ParallelCreateProvider;
|
||||
return QgsProviderMetadata::ProviderCapability::SaveLayerMetadata | QgsProviderMetadata::ProviderCapability::LoadLayerMetadata | QgsProviderMetadata::ProviderCapability::ParallelCreateProvider;
|
||||
}
|
||||
|
@ -607,6 +607,7 @@ class QgsPostgresProviderMetadata final: public QgsProviderMetadata
|
||||
QString encodeUri( const QVariantMap &parts ) const override;
|
||||
QList< Qgis::LayerType > supportedLayerTypes() const override;
|
||||
bool saveLayerMetadata( const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage ) override;
|
||||
QgsLayerMetadata loadLayerMetadata( const QString &layerUri, bool &found ) override;
|
||||
QgsProviderMetadata::ProviderCapabilities providerCapabilities() const override;
|
||||
};
|
||||
|
||||
|
@ -337,3 +337,79 @@ bool QgsPostgresProviderMetadataUtils::saveLayerMetadata( const Qgis::LayerType
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
QgsLayerMetadata QgsPostgresProviderMetadataUtils::loadLayerMetadata( const Qgis::LayerType &layerType, const QString &layerUri, bool &found )
|
||||
{
|
||||
|
||||
found = false;
|
||||
|
||||
QgsLayerMetadata metadata;
|
||||
|
||||
QgsDataSourceUri dsUri( layerUri );
|
||||
|
||||
QString layerTypeString;
|
||||
|
||||
if ( layerType == Qgis::LayerType::Vector )
|
||||
{
|
||||
layerTypeString = QStringLiteral( "vector" );
|
||||
}
|
||||
else if ( layerType == Qgis::LayerType::Raster )
|
||||
{
|
||||
layerTypeString = QStringLiteral( "raster" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsupported!
|
||||
return metadata;
|
||||
}
|
||||
|
||||
QgsPostgresConn *conn = QgsPostgresConn::connectDb( dsUri, false );
|
||||
if ( !conn )
|
||||
{
|
||||
return metadata;
|
||||
}
|
||||
|
||||
if ( dsUri.database().isEmpty() ) // typically when a service file is used
|
||||
{
|
||||
dsUri.setDatabase( conn->currentDatabase() );
|
||||
}
|
||||
|
||||
// Try to load metadata
|
||||
QString schemaName { dsUri.schema().isEmpty() ? QStringLiteral( "public" ) : dsUri.schema() };
|
||||
const QString schemaQuery = QStringLiteral( "SELECT table_schema FROM information_schema.tables WHERE table_name = 'qgis_layer_metadata'" );
|
||||
QgsPostgresResult res( conn->LoggedPQexec( "QgsPostgresProviderMetadataUtils", schemaQuery ) );
|
||||
const bool metadataTableFound { res.PQntuples( ) > 0 };
|
||||
if ( metadataTableFound )
|
||||
{
|
||||
schemaName = res.PQgetvalue( 0, 0 ) ;
|
||||
const QString schemaName = res.PQgetvalue( 0, 0 );
|
||||
// TODO: also filter CRS?
|
||||
const QString selectQuery = QStringLiteral( R"SQL(
|
||||
SELECT
|
||||
qmd
|
||||
FROM %4.qgis_layer_metadata
|
||||
WHERE
|
||||
f_table_schema=%1
|
||||
AND f_table_name=%2
|
||||
AND f_geometry_column %3
|
||||
AND layer_type='%5'
|
||||
)SQL" )
|
||||
.arg( QgsPostgresConn::quotedValue( dsUri.schema() ) )
|
||||
.arg( QgsPostgresConn::quotedValue( dsUri.table() ) )
|
||||
.arg( dsUri.geometryColumn().isEmpty() ? QStringLiteral( "IS NULL" ) : QStringLiteral( "=%1" ).arg( QgsPostgresConn::quotedValue( dsUri.geometryColumn() ) ) )
|
||||
.arg( QgsPostgresConn::quotedIdentifier( schemaName ) )
|
||||
.arg( layerType == Qgis::LayerType::Raster ? QStringLiteral( "raster" ) : QStringLiteral( "vector" ) );
|
||||
|
||||
QgsPostgresResult res( conn->LoggedPQexec( "QgsPostgresProvider", selectQuery ) );
|
||||
if ( res.PQntuples() > 0 )
|
||||
{
|
||||
QDomDocument doc;
|
||||
doc.setContent( res.PQgetvalue( 0, 0 ) );
|
||||
metadata.readMetadataXml( doc.documentElement() );
|
||||
}
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
@ -32,6 +32,11 @@ class QgsPostgresProviderMetadataUtils
|
||||
|
||||
static QList<QgsLayerMetadataProviderResult> searchLayerMetadata( const QgsMetadataSearchContext &searchContext, const QString &uri, const QString &searchString, const QgsRectangle &geographicExtent, QgsFeedback *feedback );
|
||||
static bool saveLayerMetadata( const Qgis::LayerType &layerType, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage );
|
||||
|
||||
// Load metadata for a layer
|
||||
static QgsLayerMetadata loadLayerMetadata( const Qgis::LayerType &layerType, const QString &layerUri, bool &found );
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSPOSTGRESPROVIDERMETADATAUTILS_H
|
||||
|
@ -117,39 +117,26 @@ QgsPostgresRasterProvider::QgsPostgresRasterProvider( const QString &uri, const
|
||||
QStringLiteral( "PostGIS" ), Qgis::MessageLevel::Warning );
|
||||
}
|
||||
|
||||
// Try to load metadata
|
||||
const QString schemaQuery = QStringLiteral( "SELECT table_schema FROM information_schema.tables WHERE table_name = 'qgis_layer_metadata'" );
|
||||
QgsPostgresResult res( mConnectionRO->LoggedPQexec( "QgsPostgresRasterProvider", schemaQuery ) );
|
||||
if ( res.PQntuples( ) > 0 )
|
||||
{
|
||||
const QString schemaName = res.PQgetvalue( 0, 0 );
|
||||
// TODO: also filter CRS?
|
||||
const QString selectQuery = QStringLiteral( R"SQL(
|
||||
SELECT
|
||||
qmd
|
||||
FROM %4.qgis_layer_metadata
|
||||
WHERE
|
||||
f_table_schema=%1
|
||||
AND f_table_name=%2
|
||||
AND f_geometry_column %3
|
||||
AND layer_type='raster'
|
||||
)SQL" )
|
||||
.arg( QgsPostgresConn::quotedValue( mUri.schema() ) )
|
||||
.arg( QgsPostgresConn::quotedValue( mUri.table() ) )
|
||||
.arg( mUri.geometryColumn().isEmpty() ? QStringLiteral( "IS NULL" ) : QStringLiteral( "=%1" ).arg( QgsPostgresConn::quotedValue( mUri.geometryColumn() ) ) )
|
||||
.arg( QgsPostgresConn::quotedIdentifier( schemaName ) );
|
||||
// Try to load metadata from DB
|
||||
bool metadataLoadedFromDb = false;
|
||||
QgsLayerMetadata metadataFromDb { QgsPostgresProviderMetadataUtils::loadLayerMetadata( Qgis::LayerType::Raster, uri, metadataLoadedFromDb ) };
|
||||
|
||||
QgsPostgresResult res( mConnectionRO->LoggedPQexec( "QgsPostgresRasterProvider", selectQuery ) );
|
||||
if ( res.PQntuples() > 0 )
|
||||
{
|
||||
QgsLayerMetadata metadata;
|
||||
QDomDocument doc;
|
||||
doc.setContent( res.PQgetvalue( 0, 0 ) );
|
||||
mLayerMetadata.readMetadataXml( doc.documentElement() );
|
||||
QgsMessageLog::logMessage( tr( "PostgreSQL raster layer metadata loaded from the database." ), tr( "PostGIS" ) );
|
||||
}
|
||||
if ( metadataLoadedFromDb )
|
||||
{
|
||||
mLayerMetadata = metadataFromDb;
|
||||
QgsMessageLog::logMessage( tr( "PostgreSQL layer metadata loaded from DB." ), tr( "PostGIS" ) );
|
||||
}
|
||||
|
||||
// set the primary key
|
||||
if ( !determinePrimaryKey() )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "PostgreSQL layer has no primary key." ), tr( "PostGIS" ) );
|
||||
mValid = false;
|
||||
disconnectDb();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mLayerMetadata.setType( QStringLiteral( "dataset" ) );
|
||||
mLayerMetadata.setCrs( crs() );
|
||||
|
||||
@ -734,9 +721,14 @@ bool QgsPostgresRasterProviderMetadata::saveLayerMetadata( const QString &uri, c
|
||||
return QgsPostgresProviderMetadataUtils::saveLayerMetadata( Qgis::LayerType::Raster, uri, metadata, errorMessage );
|
||||
}
|
||||
|
||||
QgsLayerMetadata QgsPostgresRasterProviderMetadata::loadLayerMetadata( const QString &layerUri, bool &found )
|
||||
{
|
||||
return QgsPostgresProviderMetadataUtils::loadLayerMetadata( Qgis::LayerType::Raster, layerUri, found );
|
||||
}
|
||||
|
||||
QgsProviderMetadata::ProviderCapabilities QgsPostgresRasterProviderMetadata::providerCapabilities() const
|
||||
{
|
||||
return QgsProviderMetadata::ProviderCapability::SaveLayerMetadata;
|
||||
return QgsProviderMetadata::ProviderCapability::SaveLayerMetadata | QgsProviderMetadata::ProviderCapability::LoadLayerMetadata;
|
||||
}
|
||||
|
||||
QgsPostgresRasterProvider *QgsPostgresRasterProviderMetadata::createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
|
||||
|
@ -267,6 +267,7 @@ class QgsPostgresRasterProviderMetadata: public QgsProviderMetadata
|
||||
QString encodeUri( const QVariantMap &parts ) const override;
|
||||
QList< Qgis::LayerType > supportedLayerTypes() const override;
|
||||
bool saveLayerMetadata( const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage ) override;
|
||||
QgsLayerMetadata loadLayerMetadata( const QString &layerUri, bool &found ) override;
|
||||
QgsProviderMetadata::ProviderCapabilities providerCapabilities() const override;
|
||||
};
|
||||
|
||||
|
@ -135,3 +135,12 @@ class LayerMetadataProviderTestBase():
|
||||
self.assertEqual(len(results.metadata()), 1)
|
||||
results = md_provider.search(QgsMetadataSearchContext(), 'cat2')
|
||||
self.assertEqual(len(results.metadata()), 1)
|
||||
|
||||
# Test load from DB (used by restore from default)
|
||||
self.test_layer = self.getLayer()
|
||||
self.assertTrue(self.test_layer.isValid())
|
||||
|
||||
self.assertTrue(bool(md.providerCapabilities() & QgsProviderMetadata.ProviderCapability.LoadLayerMetadata))
|
||||
m2, found = md.loadLayerMetadata(layer_uri)
|
||||
self.assertTrue(found)
|
||||
self.assertEqual(m2, m)
|
||||
|
Loading…
x
Reference in New Issue
Block a user