Skip to content

Commit

Permalink
Postgis: cache information about enum fields
Browse files Browse the repository at this point in the history
This is called several times and can slow down substantially
the opening of the attribute table.

Partially fixes #21303  (down from ~30 to ~6 seconds on a remote
connection)

The remaining ~4 seconds (compared to ~2 seconds in 2.18) are due
to the check for enums and provider-side  constraints, that were
not implemented in 2.18.

See: QgsEnumerationWidgetFactory::fieldScore and the call to
enumValues for details, fieldScore is called several times
because QgsAttributeTableModel::loadAttributes is also
called multiple times and it queries for widget configuration
all the times.
  • Loading branch information
elpaso committed Feb 20, 2019
1 parent e5a416e commit 4f30a44
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
41 changes: 34 additions & 7 deletions src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -1683,42 +1683,50 @@ QStringList QgsPostgresProvider::uniqueStringsMatching( int index, const QString

void QgsPostgresProvider::enumValues( int index, QStringList &enumList ) const
{
enumList.clear();

if ( index < 0 || index >= mAttributeFields.count() )
return;

if ( ! mShared->fieldSupportsEnumValuesIsSet( index ) )
{
mShared->setFieldSupportsEnumValues( index, true );
}
else if ( ! mShared->fieldSupportsEnumValues( index ) )
{
return;
}

//find out type of index
QString fieldName = mAttributeFields.at( index ).name();
const QString fieldName = mAttributeFields.at( index ).name();
QString typeName = mAttributeFields.at( index ).typeName();

// Remove schema extension from typeName
typeName.remove( QRegularExpression( "^([^.]+\\.)+" ) );

//is type an enum?
QString typeSql = QStringLiteral( "SELECT typtype FROM pg_type WHERE typname=%1" ).arg( quotedValue( typeName ) );
const QString typeSql = QStringLiteral( "SELECT typtype FROM pg_type WHERE typname=%1" ).arg( quotedValue( typeName ) );
QgsPostgresResult typeRes( connectionRO()->PQexec( typeSql ) );
if ( typeRes.PQresultStatus() != PGRES_TUPLES_OK || typeRes.PQntuples() < 1 )
{
mShared->setFieldSupportsEnumValues( index, false );
return;
}


QString typtype = typeRes.PQgetvalue( 0, 0 );
const QString typtype = typeRes.PQgetvalue( 0, 0 );
if ( typtype.compare( QLatin1String( "e" ), Qt::CaseInsensitive ) == 0 )
{
//try to read enum_range of attribute
if ( !parseEnumRange( enumList, fieldName ) )
{
enumList.clear();
mShared->setFieldSupportsEnumValues( index, false );
}
}
else
{
//is there a domain check constraint for the attribute?
if ( !parseDomainCheckConstraint( enumList, fieldName ) )
{
enumList.clear();
mShared->setFieldSupportsEnumValues( index, false );
}
}
}
Expand Down Expand Up @@ -5166,3 +5174,22 @@ void QgsPostgresSharedData::clear()
mFeaturesCounted = -1;
mFidCounter = 0;
}

bool QgsPostgresSharedData::fieldSupportsEnumValuesIsSet( int index )
{
QMutexLocker locker( &mMutex );
return mFieldSupportsEnumValues.contains( index );
}

bool QgsPostgresSharedData::fieldSupportsEnumValues( int index )
{
QMutexLocker locker( &mMutex );
return mFieldSupportsEnumValues.contains( index ) && mFieldSupportsEnumValues[ index ];
}

void QgsPostgresSharedData::setFieldSupportsEnumValues( int index, bool isSupported )
{
QMutexLocker locker( &mMutex );
mFieldSupportsEnumValues[ index ] = isSupported;
}

5 changes: 5 additions & 0 deletions src/providers/postgres/qgspostgresprovider.h
Expand Up @@ -522,6 +522,10 @@ class QgsPostgresSharedData
QVariantList lookupKey( QgsFeatureId featureId );
void clear();

bool fieldSupportsEnumValuesIsSet( int index );
bool fieldSupportsEnumValues( int index );
void setFieldSupportsEnumValues( int index, bool isSupported );

protected:
QMutex mMutex; //!< Access to all data members is guarded by the mutex

Expand All @@ -530,6 +534,7 @@ class QgsPostgresSharedData
QgsFeatureId mFidCounter = 0; // next feature id if map is used
QMap<QVariantList, QgsFeatureId> mKeyToFid; // map key values to feature id
QMap<QgsFeatureId, QVariantList> mFidToKey; // map feature id back to key values
QMap<int, bool> mFieldSupportsEnumValues; // map field index to bool flag supports enum values
};

// clazy:excludeall=qstring-allocations
Expand Down

0 comments on commit 4f30a44

Please sign in to comment.