Skip to content
Permalink
Browse files
[postgres] Only fetch type info of used fields. Fixes #38114
  • Loading branch information
borysiasty committed Aug 5, 2020
1 parent 97915e3 commit d313902c3d33032031ba85d55c24b5286f825430
Showing with 44 additions and 18 deletions.
  1. +44 −18 src/providers/postgres/qgspostgresprovider.cpp
@@ -789,12 +789,15 @@ bool QgsPostgresProvider::loadFields()
// Clear cached information about enum values support
mShared->clearSupportsEnumValuesCache();

QString sql;
QString attroidsFilter;

if ( !mIsQuery )
{
QgsDebugMsgLevel( QStringLiteral( "Loading fields for table %1" ).arg( mTableName ), 2 );

// Get the relation oid for use in later queries
QString sql = QStringLiteral( "SELECT regclass(%1)::oid" ).arg( quotedValue( mQuery ) );
sql = QStringLiteral( "SELECT regclass(%1)::oid" ).arg( quotedValue( mQuery ) );
QgsPostgresResult tresult( connectionRO()->PQexec( sql ) );
QString tableoid = tresult.PQgetvalue( 0, 0 );

@@ -808,23 +811,6 @@ bool QgsPostgresProvider::loadFields()
}
}

// Collect type info
QString sql = QStringLiteral( "SELECT oid,typname,typtype,typelem,typlen FROM pg_type" );
QgsPostgresResult typeResult( connectionRO()->PQexec( sql ) );

QMap<Oid, PGTypeInfo> typeMap;
for ( int i = 0; i < typeResult.PQntuples(); ++i )
{
PGTypeInfo typeInfo =
{
/* typeName = */ typeResult.PQgetvalue( i, 1 ),
/* typeType = */ typeResult.PQgetvalue( i, 2 ),
/* typeElem = */ typeResult.PQgetvalue( i, 3 ),
/* typeLen = */ typeResult.PQgetvalue( i, 4 ).toInt()
};
typeMap.insert( typeResult.PQgetvalue( i, 0 ).toUInt(), typeInfo );
}

// Populate the field vector for this layer. The field vector contains
// field name, type, length, and precision (if numeric)
sql = QStringLiteral( "SELECT * FROM %1 LIMIT 0" ).arg( mQuery );
@@ -836,6 +822,14 @@ bool QgsPostgresProvider::loadFields()
QMap<Oid, QMap<int, bool> > notNullMap, uniqueMap;
if ( result.PQnfields() > 0 )
{
// Collect attribiute oids
QSet<Oid> attroids;
for ( int i = 0; i < result.PQnfields(); i++ )
{
Oid attroid = result.PQftype( i );
attroids.insert( attroid );
}

// Collect table oids
QSet<Oid> tableoids;
for ( int i = 0; i < result.PQnfields(); i++ )
@@ -900,10 +894,42 @@ bool QgsPostgresProvider::loadFields()
uniqueMap[attrelid][attnum] = uniqueConstraint;
identityMap[attrelid][attnum] = attIdentity.isEmpty() ? " " : attIdentity;
generatedMap[attrelid][attnum] = attGenerated.isEmpty() ? "" : defVal;

// Also include atttype oid from pg_attribute, because PQnfields only returns basic type for for domains
attroids.insert( attType );
}
}

// Prepare filter for fetching pg_type info
if ( !attroids.isEmpty() )
{
QStringList attroidsList;
const auto constAttroids = attroids;
for ( Oid attroid : constAttroids )
{
attroidsList.append( QString::number( attroid ) );
}
attroidsFilter = QStringLiteral( "WHERE oid in (" ) + attroidsList.join( QStringLiteral( "," ) ) + QStringLiteral( ")" );
}
}

// Collect type info
sql = QStringLiteral( "SELECT oid,typname,typtype,typelem,typlen FROM pg_type %1" ).arg( attroidsFilter );
QgsPostgresResult typeResult( connectionRO()->PQexec( sql ) );

QMap<Oid, PGTypeInfo> typeMap;
for ( int i = 0; i < typeResult.PQntuples(); ++i )
{
PGTypeInfo typeInfo =
{
/* typeName = */ typeResult.PQgetvalue( i, 1 ),
/* typeType = */ typeResult.PQgetvalue( i, 2 ),
/* typeElem = */ typeResult.PQgetvalue( i, 3 ),
/* typeLen = */ typeResult.PQgetvalue( i, 4 ).toInt()
};
typeMap.insert( typeResult.PQgetvalue( i, 0 ).toUInt(), typeInfo );
}

QSet<QString> fields;
mAttributeFields.clear();
mIdentityFields.clear();

0 comments on commit d313902

Please sign in to comment.