Add field name in layers from postgis relation with multiple spatial fields

NOTE: only works with browser, not with "Add PostGIS Layer" dialog
This commit is contained in:
Sandro Santilli 2013-05-31 14:22:27 +02:00
parent b72a79ad23
commit a2774a05cc
3 changed files with 44 additions and 30 deletions

View File

@ -270,22 +270,32 @@ void QgsPostgresConn::disconnect()
deleteLater();
}
QStringList QgsPostgresConn::pkCandidates( QString schemaName, QString viewName )
/* private */
void QgsPostgresConn::addColumnInfo( QgsPostgresLayerProperty& layerProperty, const QString& schemaName, const QString& viewName, bool fetchPkCandidates )
{
QStringList cols;
QString sql = QString( "SELECT attname FROM pg_attribute JOIN pg_type ON atttypid=pg_type.oid WHERE attrelid=regclass('%1.%2')" )
.arg( quotedIdentifier( schemaName ) )
.arg( quotedIdentifier( viewName ) );
// TODO: optimize this query when pk candidates aren't needed
// could use array_agg() and count()
// array output would look like this: "{One,tWo}"
QString sql = QString( "SELECT attname, CASE WHEN typname = ANY(ARRAY['geometry','geography','topogeometry']) THEN 1 ELSE null END AS isSpatial FROM pg_attribute JOIN pg_type ON atttypid=pg_type.oid WHERE attrelid=regclass('%1.%2')" )
.arg( quotedIdentifier( schemaName ) )
.arg( quotedIdentifier( viewName ) );
QgsDebugMsg( sql );
QgsPostgresResult colRes = PQexec( sql );
layerProperty.nSpCols = 0;
if ( colRes.PQresultStatus() == PGRES_TUPLES_OK )
{
for ( int i = 0; i < colRes.PQntuples(); i++ )
{
QgsDebugMsg( colRes.PQgetvalue( i, 0 ) );
cols << colRes.PQgetvalue( i, 0 );
if ( fetchPkCandidates ) {
QgsDebugMsg( colRes.PQgetvalue( i, 0 ) );
layerProperty.pkCols << colRes.PQgetvalue( i, 0 );
}
if ( colRes.PQgetisnull( i, 1 ) == 0 ) {
++layerProperty.nSpCols;
}
}
}
else
@ -293,7 +303,6 @@ QStringList QgsPostgresConn::pkCandidates( QString schemaName, QString viewName
QgsMessageLog::logMessage( tr( "SQL:%1\nresult:%2\nerror:%3\n" ).arg( sql ).arg( colRes.PQresultStatus() ).arg( colRes.PQresultErrorMessage() ), tr( "PostGIS" ) );
}
return cols;
}
bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables )
@ -404,15 +413,12 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
layerProperty.types = QList<QGis::WkbType>() << ( QgsPostgresConn::wkbTypeFromPostgis( type ) );
layerProperty.srids = QList<int>() << srid;
layerProperty.sql = "";
addColumnInfo( layerProperty, schemaName, tableName, relkind == "v" );
if ( relkind == "v" )
if ( relkind == "v" && layerProperty.pkCols.empty() )
{
layerProperty.pkCols = pkCandidates( schemaName, tableName );
if ( layerProperty.pkCols.isEmpty() )
{
QgsDebugMsg( "no key columns found." );
continue;
}
QgsDebugMsg( "no key columns found." );
continue;
}
mLayersSupported << layerProperty;
@ -522,14 +528,11 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
Q_ASSERT( !"Unknown geometry type" );
}
if ( relkind == "v" )
addColumnInfo( layerProperty, schemaName, tableName, relkind == "v" );
if ( relkind == "v" && layerProperty.pkCols.empty() )
{
layerProperty.pkCols = pkCandidates( schemaName, tableName );
if ( layerProperty.pkCols.isEmpty() )
{
QgsDebugMsg( "no key columns found." );
continue;
}
QgsDebugMsg( "no key columns found." );
continue;
}
layerProperty.sql = "";
@ -583,7 +586,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
layerProperty.tableName = table;
layerProperty.geometryColName = QString::null;
layerProperty.geometryColType = sctNone;
layerProperty.pkCols = relkind == "v" ? pkCandidates( schema, table ) : QStringList();
addColumnInfo( layerProperty, schema, table, relkind == "v" );
layerProperty.sql = "";
mLayersSupported << layerProperty;

View File

@ -53,10 +53,19 @@ struct QgsPostgresLayerProperty
QgsPostgresGeometryColumnType geometryColType;
QStringList pkCols;
QList<int> srids;
unsigned int nSpCols;
QString sql;
// TODO: rename this !
int size() const { Q_ASSERT( types.size() == srids.size() ); return types.size(); }
QString defaultName() const {
QString n = tableName;
if ( nSpCols > 1 ) n += "." + geometryColName;
return n;
}
QgsPostgresLayerProperty at( int i ) const
{
QgsPostgresLayerProperty property;
@ -70,6 +79,7 @@ struct QgsPostgresLayerProperty
property.geometryColName = geometryColName;
property.geometryColType = geometryColType;
property.pkCols = pkCols;
property.nSpCols = nSpCols;
property.sql = sql;
return property;
@ -93,14 +103,15 @@ struct QgsPostgresLayerProperty
sridString += QString::number( srid );
}
return QString( "%1.%2.%3 type=%4 srid=%5 pkCols=%6 sql=%7" )
return QString( "%1.%2.%3 type=%4 srid=%5 pkCols=%6 sql=%7 nSpCols=%8" )
.arg( schemaName )
.arg( tableName )
.arg( geometryColName )
.arg( typeString )
.arg( sridString )
.arg( pkCols.join( "|" ) )
.arg( sql );
.arg( sql )
.arg( nSpCols );
}
#endif
};
@ -215,9 +226,6 @@ class QgsPostgresConn : public QObject
/** Gets information about the spatial tables */
bool getTableInfo( bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables );
/** get primary key candidates (all int4 columns) */
QStringList pkCandidates( QString schemaName, QString viewName );
qint64 getBinaryInt( QgsPostgresResult &queryResult, int row, int col );
QString fieldExpression( const QgsField &fld );
@ -292,6 +300,9 @@ class QgsPostgresConn : public QObject
static QMap<QString, QgsPostgresConn *> sConnectionsRW;
static QMap<QString, QgsPostgresConn *> sConnectionsRO;
/** count number of spatial columns in a given relation */
void addColumnInfo( QgsPostgresLayerProperty& layerProperty, const QString& schemaName, const QString& viewName, bool fetchPkCandidates );
//! List of the supported layers
QVector<QgsPostgresLayerProperty> mLayersSupported;

View File

@ -375,7 +375,7 @@ void QgsPGSchemaItem::addLayer( QgsPostgresLayerProperty layerProperty )
tip = tr( "as geometryless table" );
}
QgsPGLayerItem *layerItem = new QgsPGLayerItem( this, layerProperty.tableName, mPath + "/" + layerProperty.tableName, layerType, layerProperty );
QgsPGLayerItem *layerItem = new QgsPGLayerItem( this, layerProperty.defaultName(), mPath + "/" + layerProperty.tableName, layerType, layerProperty );
layerItem->setToolTip( tip );
addChild( layerItem );
}