diff --git a/src/providers/postgres/qgspostgresproviderconnection.cpp b/src/providers/postgres/qgspostgresproviderconnection.cpp index 41b38b890ac..421279a7681 100644 --- a/src/providers/postgres/qgspostgresproviderconnection.cpp +++ b/src/providers/postgres/qgspostgresproviderconnection.cpp @@ -656,3 +656,48 @@ QList QgsPostgresProviderConnection::nativeTy } return types; } + + +QgsFields QgsPostgresProviderConnection::fields( const QString &schema, const QString &tableName ) const +{ + // Try the base implementation first and fall back to a more complex approch for the + // few PG-specific corner cases that do not work with the base implementation. + try + { + return QgsAbstractDatabaseProviderConnection::fields( schema, tableName ); + } + catch ( QgsProviderConnectionException &ex ) + { + // This table might expose multiple geometry columns (different geom type or SRID) + // but we are only interested in fields here, so let's pick the first one. + TableProperty tableInfo { table( schema, tableName ) }; + if ( tableInfo.geometryColumnTypes().count( ) > 1 ) + { + try + { + QgsDataSourceUri tUri { tableUri( schema, tableName ) }; + TableProperty::GeometryColumnType geomCol { tableInfo.geometryColumnTypes().first() }; + tUri.setGeometryColumn( tableInfo.geometryColumn() ); + tUri.setWkbType( geomCol.wkbType ); + tUri.setSrid( QString::number( geomCol.crs.postgisSrid() ) ); + if ( tableInfo.primaryKeyColumns().count() > 0 ) + { + tUri.setKeyColumn( tableInfo.primaryKeyColumns().first() ); + } + tUri.setParam( QStringLiteral( "checkPrimaryKeyUnicity" ), QLatin1String( "0" ) ); + QgsVectorLayer::LayerOptions options { true, true }; + options.skipCrsValidation = true; + QgsVectorLayer vl { tUri.uri(), QStringLiteral( "temp_layer" ), mProviderKey, options }; + if ( vl.isValid() ) + { + return vl.fields(); + } + } + catch ( QgsProviderConnectionException & ) + { + // fall-through + } + } + throw ex; + } +} diff --git a/src/providers/postgres/qgspostgresproviderconnection.h b/src/providers/postgres/qgspostgresproviderconnection.h index 6945486ca5e..b7426ac6071 100644 --- a/src/providers/postgres/qgspostgresproviderconnection.h +++ b/src/providers/postgres/qgspostgresproviderconnection.h @@ -38,6 +38,7 @@ class QgsPostgresProviderConnection : public QgsAbstractDatabaseProviderConnecti const QMap *options ) const override; QString tableUri( const QString &schema, const QString &name ) const override; + QgsFields fields( const QString &schema, const QString &table ) const override; void dropVectorTable( const QString &schema, const QString &name ) const override; void dropRasterTable( const QString &schema, const QString &name ) const override; void renameVectorTable( const QString &schema, const QString &name, const QString &newName ) const override; @@ -65,9 +66,7 @@ class QgsPostgresProviderConnection : public QgsAbstractDatabaseProviderConnecti void dropTablePrivate( const QString &schema, const QString &name ) const; void renameTablePrivate( const QString &schema, const QString &name, const QString &newName ) const; - }; - #endif // QGSPOSTGRESPROVIDERCONNECTION_H diff --git a/tests/src/python/test_qgsproviderconnection_postgres.py b/tests/src/python/test_qgsproviderconnection_postgres.py index 4db4a4a2d36..df6ef0267fa 100644 --- a/tests/src/python/test_qgsproviderconnection_postgres.py +++ b/tests/src/python/test_qgsproviderconnection_postgres.py @@ -329,6 +329,30 @@ IMPORT FOREIGN SCHEMA qgis_test LIMIT TO ( "someData" ) fields = conn.fields('qgis_test', 'someData') self.assertEqual(fields.names(), ['pk', 'cnt', 'name', 'name2', 'num_char', 'dt', 'date', 'time', 'geom']) + def test_fields_no_pk(self): + """Test issue: no fields are exposed for raster_columns""" + + md = QgsProviderRegistry.instance().providerMetadata('postgres') + conn = md.createConnection(self.uri, {}) + fields = conn.fields("public", "raster_columns") + self.assertEqual(fields.names(), [ + 'r_table_catalog', + 'r_table_schema', + 'r_table_name', + 'r_raster_column', + 'srid', + 'scale_x', + 'scale_y', + 'blocksize_x', + 'blocksize_y', + 'same_alignment', + 'regular_blocking', + 'num_bands', + 'pixel_types', + 'nodata_values', + 'out_db', + 'spatial_index']) + if __name__ == '__main__': unittest.main()