Skip to content

Commit 2c773a7

Browse files
committed
Improve filtering by schema for postgres connections in browser
Results in much faster display and refresh of postgres tables Also: - ensure browser correctly respects postgres connection settings - add schema comment tooltip and refresh context menu item - make postgres connections less noisy in debug logs
1 parent 4e4e161 commit 2c773a7

File tree

4 files changed

+130
-47
lines changed

4 files changed

+130
-47
lines changed

src/providers/postgres/qgspostgresconn.cpp

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ void QgsPostgresConn::addColumnInfo( QgsPostgresLayerProperty& layerProperty, co
302302
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')" )
303303
.arg( quotedIdentifier( schemaName ) )
304304
.arg( quotedIdentifier( viewName ) );
305-
QgsDebugMsg( sql );
305+
//QgsDebugMsg( sql );
306306
QgsPostgresResult colRes = PQexec( sql );
307307

308308
layerProperty.pkCols.clear();
@@ -314,7 +314,7 @@ void QgsPostgresConn::addColumnInfo( QgsPostgresLayerProperty& layerProperty, co
314314
{
315315
if ( fetchPkCandidates )
316316
{
317-
QgsDebugMsg( colRes.PQgetvalue( i, 0 ) );
317+
//QgsDebugMsg( colRes.PQgetvalue( i, 0 ) );
318318
layerProperty.pkCols << colRes.PQgetvalue( i, 0 );
319319
}
320320

@@ -331,14 +331,14 @@ void QgsPostgresConn::addColumnInfo( QgsPostgresLayerProperty& layerProperty, co
331331

332332
}
333333

334-
bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables )
334+
bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables, const QString schema )
335335
{
336336
int nColumns = 0;
337337
int foundInTables = 0;
338338
QgsPostgresResult result;
339339
QgsPostgresLayerProperty layerProperty;
340340

341-
QgsDebugMsg( "Entering." );
341+
//QgsDebugMsg( "Entering." );
342342

343343
mLayersSupported.clear();
344344

@@ -401,9 +401,12 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
401401
if ( searchPublicOnly )
402402
sql += " AND n.nspname='public'";
403403

404+
if ( !schema.isEmpty() )
405+
sql += QString( " AND %1='%2'" ).arg( schemaName ).arg( schema );
406+
404407
sql += QString( " ORDER BY n.nspname,c.relname,%1" ).arg( columnName );
405408

406-
QgsDebugMsg( "getting table info: " + sql );
409+
//QgsDebugMsg( "getting table info: " + sql );
407410
result = PQexec( sql, i == 0 );
408411
if ( result.PQresultStatus() != PGRES_TUPLES_OK )
409412
{
@@ -429,13 +432,13 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
429432
srid = INT_MIN;
430433
}
431434

432-
QgsDebugMsg( QString( "%1 : %2.%3.%4: %5 %6 %7 %8" )
435+
/*QgsDebugMsg( QString( "%1 : %2.%3.%4: %5 %6 %7 %8" )
433436
.arg( gtableName )
434437
.arg( schemaName ).arg( tableName ).arg( column )
435438
.arg( type )
436439
.arg( srid )
437440
.arg( relkind )
438-
.arg( dim ) );
441+
.arg( dim ) );*/
439442

440443
layerProperty.schemaName = schemaName;
441444
layerProperty.tableName = tableName;
@@ -449,7 +452,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
449452

450453
if ( isView && layerProperty.pkCols.empty() )
451454
{
452-
QgsDebugMsg( "no key columns found." );
455+
//QgsDebugMsg( "no key columns found." );
453456
continue;
454457
}
455458

@@ -460,11 +463,6 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
460463
foundInTables |= 1 << i;
461464
}
462465

463-
if ( nColumns == 0 )
464-
{
465-
QgsMessageLog::logMessage( tr( "Database connection was successful, but the accessible tables could not be determined." ), tr( "PostGIS" ) );
466-
}
467-
468466
//search for geometry columns in tables that are not in the geometry_columns metatable
469467
if ( !searchGeometryColumnsOnly )
470468
{
@@ -489,6 +487,9 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
489487
if ( searchPublicOnly )
490488
sql += " AND n.nspname='public'";
491489

490+
if ( !schema.isEmpty() )
491+
sql += QString( " AND n.nspname='%2'" ).arg( schema );
492+
492493
// skip columns of which we already derived information from the metadata tables
493494
if ( nColumns > 0 )
494495
{
@@ -508,7 +509,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
508509
}
509510
}
510511

511-
QgsDebugMsg( "sql: " + sql );
512+
//QgsDebugMsg( "sql: " + sql );
512513

513514
result = PQexec( sql );
514515

@@ -537,7 +538,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
537538
QString coltype = result.PQgetvalue( i, 4 ); // column type
538539
bool isView = relkind == "v" || relkind == "m";
539540

540-
QgsDebugMsg( QString( "%1.%2.%3: %4" ).arg( schemaName ).arg( tableName ).arg( column ).arg( relkind ) );
541+
//QgsDebugMsg( QString( "%1.%2.%3: %4" ).arg( schemaName ).arg( tableName ).arg( column ).arg( relkind ) );
541542

542543
layerProperty.types.clear();
543544
layerProperty.srids.clear();
@@ -564,7 +565,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
564565
addColumnInfo( layerProperty, schemaName, tableName, isView );
565566
if ( isView && layerProperty.pkCols.empty() )
566567
{
567-
QgsDebugMsg( "no key columns found." );
568+
//QgsDebugMsg( "no key columns found." );
568569
continue;
569570
}
570571

@@ -593,7 +594,10 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
593594
if ( searchPublicOnly )
594595
sql += " AND pg_namespace.nspname='public'";
595596

596-
QgsDebugMsg( "sql: " + sql );
597+
if ( !schema.isEmpty() )
598+
sql += QString( " AND pg_namespace.nspname='%2'" ).arg( schema );
599+
600+
//QgsDebugMsg( "sql: " + sql );
597601

598602
result = PQexec( sql );
599603

@@ -612,14 +616,29 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
612616
QString relkind = result.PQgetvalue( i, 2 ); // relation kind
613617
bool isView = relkind == "v" || relkind == "m";
614618

615-
QgsDebugMsg( QString( "%1.%2: %3" ).arg( schema ).arg( table ).arg( relkind ) );
619+
//QgsDebugMsg( QString( "%1.%2: %3" ).arg( schema ).arg( table ).arg( relkind ) );
616620

617621
layerProperty.types = QList<QGis::WkbType>() << QGis::WKBNoGeometry;
618622
layerProperty.srids = QList<int>() << INT_MIN;
619623
layerProperty.schemaName = schema;
620624
layerProperty.tableName = table;
621625
layerProperty.geometryColName = QString::null;
622626
layerProperty.geometryColType = sctNone;
627+
628+
//check if we've already added this layer in some form
629+
bool alreadyFound = false;
630+
foreach ( QgsPostgresLayerProperty foundLayer, mLayersSupported )
631+
{
632+
if ( foundLayer.schemaName == schema && foundLayer.tableName == table )
633+
{
634+
//already found this table
635+
alreadyFound = true;
636+
break;
637+
}
638+
}
639+
if ( alreadyFound )
640+
continue;
641+
623642
addColumnInfo( layerProperty, schema, table, isView );
624643
layerProperty.sql = "";
625644

@@ -628,27 +647,52 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
628647
}
629648
}
630649

631-
if ( nColumns == 0 )
650+
if ( nColumns == 0 && schema.isEmpty() )
632651
{
633-
QgsMessageLog::logMessage( tr( "Database connection was successful, but no accessible tables were found. Please verify that you have SELECT privilege on a table carrying PostGIS geometry." ), tr( "PostGIS" ) );
652+
QgsMessageLog::logMessage( tr( "Database connection was successful, but the accessible tables could not be determined." ), tr( "PostGIS" ) );
634653
}
635654

636655
return true;
637656
}
638657

639-
bool QgsPostgresConn::supportedLayers( QVector<QgsPostgresLayerProperty> &layers, bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables )
658+
bool QgsPostgresConn::supportedLayers( QVector<QgsPostgresLayerProperty> &layers, bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables, const QString schema )
640659
{
641660
// Get the list of supported tables
642-
if ( !getTableInfo( searchGeometryColumnsOnly, searchPublicOnly, allowGeometrylessTables ) )
661+
if ( !getTableInfo( searchGeometryColumnsOnly, searchPublicOnly, allowGeometrylessTables, schema ) )
643662
{
644663
QgsMessageLog::logMessage( tr( "Unable to get list of spatially enabled tables from the database" ), tr( "PostGIS" ) );
645664
return false;
646665
}
647666

648667
layers = mLayersSupported;
649668

650-
QgsDebugMsg( "Exiting." );
669+
//QgsDebugMsg( "Exiting." );
670+
671+
return true;
672+
}
673+
674+
bool QgsPostgresConn::getSchemas( QList<QgsPostgresSchemaProperty> &schemas )
675+
{
676+
schemas.clear();
677+
QgsPostgresResult result;
678+
679+
QString sql = QString( "SELECT nspname, pg_get_userbyid(nspowner), pg_catalog.obj_description(oid) FROM pg_namespace WHERE nspname !~ '^pg_' AND nspname != 'information_schema' ORDER BY nspname" );
651680

681+
result = PQexec( sql, true );
682+
if ( result.PQresultStatus() != PGRES_TUPLES_OK )
683+
{
684+
PQexecNR( "COMMIT" );
685+
return false;
686+
}
687+
688+
for ( int idx = 0; idx < result.PQntuples(); idx++ )
689+
{
690+
QgsPostgresSchemaProperty schema;
691+
schema.name = result.PQgetvalue( idx, 0 );
692+
schema.owner = result.PQgetvalue( idx, 1 );
693+
schema.description = result.PQgetvalue( idx, 2 );
694+
schemas << schema;
695+
}
652696
return true;
653697
}
654698

@@ -1193,7 +1237,7 @@ void QgsPostgresConn::retrieveLayerTypes( QgsPostgresLayerProperty &layerPropert
11931237

11941238
query += " FROM " + table;
11951239

1196-
QgsDebugMsg( "Retrieving geometry types: " + query );
1240+
//QgsDebugMsg( "Retrieving geometry types: " + query );
11971241

11981242
QgsPostgresResult gresult = PQexec( query );
11991243

src/providers/postgres/qgspostgresconn.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ enum QgsPostgresPrimaryKeyType
5050
pktFidMap
5151
};
5252

53+
/** Schema properties structure */
54+
struct QgsPostgresSchemaProperty
55+
{
56+
QString name;
57+
QString description;
58+
QString owner;
59+
};
60+
5361
/** Layer Property structure */
5462
// TODO: Fill to Postgres/PostGIS specifications
5563
struct QgsPostgresLayerProperty
@@ -230,16 +238,40 @@ class QgsPostgresConn : public QObject
230238
*/
231239
static QString quotedValue( QVariant value );
232240

233-
//! Get the list of supported layers
241+
/**Get the list of supported layers
242+
* @param layers list to store layers in
243+
* @param searchGeometryColumnsOnly only look for geometry columns which are
244+
* contained in the geometry_columns metatable
245+
* @param searchPublicOnly
246+
* @param allowGeometrylessTables
247+
* @param schema restrict layers to layers within specified schema
248+
* @returns true if layers were fetched successfully
249+
*/
234250
bool supportedLayers( QVector<QgsPostgresLayerProperty> &layers,
235251
bool searchGeometryColumnsOnly = true,
236252
bool searchPublicOnly = true,
237-
bool allowGeometrylessTables = false );
253+
bool allowGeometrylessTables = false,
254+
const QString schema = QString() );
255+
256+
/**Get the list of database schemas
257+
* @param schemas list to store schemas in
258+
* @returns true if schemas where fetched successfully
259+
* @note added in QGIS 2.7
260+
*/
261+
bool getSchemas( QList<QgsPostgresSchemaProperty> &schemas );
238262

239263
void retrieveLayerTypes( QgsPostgresLayerProperty &layerProperty, bool useEstimatedMetadata );
240264

241-
/** Gets information about the spatial tables */
242-
bool getTableInfo( bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables );
265+
/**Gets information about the spatial tables
266+
* @param searchGeometryColumnsOnly only look for geometry columns which are
267+
* contained in the geometry_columns metatable
268+
* @param searchPublicOnly
269+
* @param allowGeometrylessTables
270+
* @param schema restrict tables to those within specified schema
271+
* @returns true if tables were successfully queried
272+
*/
273+
bool getTableInfo( bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables,
274+
const QString schema = QString() );
243275

244276
qint64 getBinaryInt( QgsPostgresResult &queryResult, int row, int col );
245277

src/providers/postgres/qgspostgresdataitems.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,8 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
5656
return items;
5757
}
5858

59-
QVector<QgsPostgresLayerProperty> layerProperties;
60-
bool ok = conn->supportedLayers( layerProperties,
61-
QgsPostgresConn::geometryColumnsOnly( mName ),
62-
QgsPostgresConn::publicSchemaOnly( mName ),
63-
QgsPostgresConn::allowGeometrylessTables( mName ) );
59+
QList<QgsPostgresSchemaProperty> schemas;
60+
bool ok = conn->getSchemas( schemas );
6461

6562
QgsPostgresConnPool::instance()->releaseConnection( conn );
6663

@@ -70,15 +67,13 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
7067
return items;
7168
}
7269

73-
QSet<QString> schemaNames;
74-
foreach ( QgsPostgresLayerProperty layerProperty, layerProperties )
70+
foreach ( QgsPostgresSchemaProperty schema, schemas )
7571
{
76-
schemaNames.insert( layerProperty.schemaName );
77-
}
78-
79-
foreach ( QString schemaName, schemaNames )
80-
{
81-
QgsPGSchemaItem * schemaItem = new QgsPGSchemaItem( this, mName, schemaName, mPath + "/" + schemaName );
72+
QgsPGSchemaItem * schemaItem = new QgsPGSchemaItem( this, mName, schema.name, mPath + "/" + schema.name );
73+
if ( !schema.description.isEmpty() )
74+
{
75+
schemaItem->setToolTip( schema.description );
76+
}
8277
items.append( schemaItem );
8378
}
8479

@@ -303,9 +298,9 @@ QVector<QgsDataItem*> QgsPGSchemaItem::createChildren()
303298

304299
QVector<QgsPostgresLayerProperty> layerProperties;
305300
bool ok = conn->supportedLayers( layerProperties,
306-
QgsPostgresConn::geometryColumnsOnly( mName ),
307-
QgsPostgresConn::publicSchemaOnly( mName ),
308-
QgsPostgresConn::allowGeometrylessTables( mName ) );
301+
QgsPostgresConn::geometryColumnsOnly( mConnectionName ),
302+
QgsPostgresConn::publicSchemaOnly( mConnectionName ),
303+
QgsPostgresConn::allowGeometrylessTables( mConnectionName ), mName );
309304

310305
if ( !ok )
311306
{
@@ -314,7 +309,7 @@ QVector<QgsDataItem*> QgsPGSchemaItem::createChildren()
314309
return items;
315310
}
316311

317-
bool dontResolveType = QgsPostgresConn::dontResolveType( mName );
312+
bool dontResolveType = QgsPostgresConn::dontResolveType( mConnectionName );
318313
foreach ( QgsPostgresLayerProperty layerProperty, layerProperties )
319314
{
320315
if ( layerProperty.schemaName != mName )
@@ -326,7 +321,7 @@ QVector<QgsDataItem*> QgsPGSchemaItem::createChildren()
326321
{
327322
if ( dontResolveType )
328323
{
329-
QgsDebugMsg( QString( "skipping column %1.%2 without type constraint" ).arg( layerProperty.schemaName ).arg( layerProperty.tableName ) );
324+
//QgsDebugMsg( QString( "skipping column %1.%2 without type constraint" ).arg( layerProperty.schemaName ).arg( layerProperty.tableName ) );
330325
continue;
331326
}
332327

@@ -345,9 +340,20 @@ QVector<QgsDataItem*> QgsPGSchemaItem::createChildren()
345340
return items;
346341
}
347342

343+
QList<QAction *> QgsPGSchemaItem::actions()
344+
{
345+
QList<QAction*> lst;
346+
347+
QAction* actionRefresh = new QAction( tr( "Refresh" ), this );
348+
connect( actionRefresh, SIGNAL( triggered() ), this, SLOT( refresh() ) );
349+
lst.append( actionRefresh );
350+
351+
return lst;
352+
}
353+
348354
QgsPGLayerItem *QgsPGSchemaItem::createLayer( QgsPostgresLayerProperty layerProperty )
349355
{
350-
QgsDebugMsg( "schemaName = " + layerProperty.schemaName + " tableName = " + layerProperty.tableName + " geometryColName = " + layerProperty.geometryColName );
356+
//QgsDebugMsg( "schemaName = " + layerProperty.schemaName + " tableName = " + layerProperty.tableName + " geometryColName = " + layerProperty.geometryColName );
351357
QGis::WkbType wkbType = layerProperty.types[0];
352358
QString tip = tr( "%1 as %2 in %3" ).arg( layerProperty.geometryColName ).arg( QgsPostgresConn::displayStringForWkbType( wkbType ) ).arg( layerProperty.srids[0] );
353359

src/providers/postgres/qgspostgresdataitems.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class QgsPGSchemaItem : public QgsDataCollectionItem
8484
~QgsPGSchemaItem();
8585

8686
QVector<QgsDataItem*> createChildren();
87+
virtual QList<QAction*> actions();
8788

8889
private:
8990
QgsPGLayerItem * createLayer( QgsPostgresLayerProperty layerProperty );

0 commit comments

Comments
 (0)