Index: src/core/qgsdatasourceuri.cpp =================================================================== --- src/core/qgsdatasourceuri.cpp (revision 10147) +++ src/core/qgsdatasourceuri.cpp (working copy) @@ -136,6 +136,10 @@ { mPort = pval; } + else if ( pname == "key" ) + { + mKey = pval; + } else if ( pname == "tty" ) { QgsDebugMsg( "backend debug tty ignored" ); @@ -189,6 +193,11 @@ return mGeometryColumn; } +QString QgsDataSourceURI::key() const +{ + return mKey; +} + void QgsDataSourceURI::setSql( QString sql ) { mSql = sql; @@ -298,11 +307,14 @@ QString QgsDataSourceURI::uri() const { - return connectionInfo() - + QString( " table=%1 (%2) sql=%3" ) + QString r(connectionInfo()); + if (!mKey.isEmpty()) + r += QString( " key=%1" ).arg(mKey); + r += QString( " table=%1 (%2) sql=%3" ) .arg( quotedTablename() ) .arg( mGeometryColumn ) .arg( mSql ); + return r; } QString QgsDataSourceURI::quotedTablename() const @@ -329,10 +341,12 @@ void QgsDataSourceURI::setDataSource( const QString &schema, const QString &table, const QString &geometryColumn, - const QString &sql ) + const QString &sql, + const QString &key ) { mSchema = schema; mTable = table; mGeometryColumn = geometryColumn; mSql = sql; + mKey = key; } Index: src/core/qgsdatasourceuri.h =================================================================== --- src/core/qgsdatasourceuri.h (revision 10147) +++ src/core/qgsdatasourceuri.h (working copy) @@ -58,13 +58,15 @@ void setDataSource( const QString& aSchema, const QString& aTable, const QString& aGeometryColumn, - const QString& aSql = QString() ); + const QString& aSql = QString(), + const QString& aKey = QString() ); QString username() const; QString schema() const; QString table() const; QString sql() const; QString geometryColumn() const; + QString key() const; void clearSchema(); void setSql( QString sql ); @@ -87,6 +89,8 @@ QString mTable; //! geometry column QString mGeometryColumn; + //! primary key column + QString mKey; //! SQL where clause used to limit features returned from the layer QString mSql; //! username Index: src/providers/postgres/qgspostgresprovider.cpp =================================================================== --- src/providers/postgres/qgspostgresprovider.cpp (revision 10147) +++ src/providers/postgres/qgspostgresprovider.cpp (working copy) @@ -74,6 +74,7 @@ mTableName = mUri.table(); geometryColumn = mUri.geometryColumn(); sqlWhereClause = mUri.sql(); + primaryKey = mUri.key(); // Keep a schema qualified table name for convenience later on. mSchemaTableName = mUri.quotedTablename(); @@ -85,6 +86,8 @@ QgsDebugMsg( "Geometry column is: " + geometryColumn ); QgsDebugMsg( "Schema is: " + mSchemaName ); QgsDebugMsg( "Table name is: " + mTableName ); + if (!primaryKey.isEmpty()) + QgsDebugMsg( "User-suggested primary key is: " + primaryKey ); connectionRW = NULL; connectionRO = Conn::connectDb( mUri.connectionInfo(), true ); @@ -190,7 +193,7 @@ loadFields(); // set the primary key - getPrimaryKey(); + getPrimaryKey(primaryKey); // Set the postgresql message level so that we don't get the // 'there is no transaction in progress' warning. @@ -860,13 +863,46 @@ } } -QString QgsPostgresProvider::getPrimaryKey() +QString QgsPostgresProvider::getPrimaryKey(const QString& suggestedKey) { + QStringList log; + QString sql; + + // if the user has suggested a key to use, do some verification to + // ensure it is satisfactory + if (!suggestedKey.isEmpty()) + { + // Get the column data type + sql = QString( "select pg_type.typname from pg_attribute,pg_type where atttypid=pg_type.oid and attname=%1 and attrelid=regclass(%2)" ) + .arg( quotedValue( suggestedKey ) ) + .arg( quotedValue( mSchemaTableName ) ); + Result types = connectionRO->PQexec( sql ); + + if ( PQntuples( types ) > 0 ) + { + QString columnType = QString::fromUtf8( PQgetvalue( types, 0, 0 ) ); + + if ( columnType != "int4" ) + log.append( tr( "The user suggested column '%1' is unsuitable because Qgis does not currently " + "support non-int4 type columns as a key into the table.\n" ).arg( suggestedKey ) ); + else + { + primaryKey = suggestedKey; + primaryKeyType = columnType; + return primaryKey; + } + } + else + { + QgsDebugMsg( QString("User-suggested key column %1.%2(%3) not found.").arg(mSchemaName).arg(mTables).arg(suggestedKey) ); + } + } + // check to see if there is an unique index on the relation, which // can be used as a key into the table. Primary keys are always // unique indices, so we catch them as well. - QString sql = QString( "select indkey from pg_index where indisunique='t' and indrelid=regclass(%1)::oid" ) + sql = QString( "select indkey from pg_index where indisunique='t' and indrelid=regclass(%1)::oid" ) .arg( quotedValue( mSchemaTableName ) ); QgsDebugMsg( "Getting unique index using '" + sql + "'" ); @@ -875,8 +911,6 @@ QgsDebugMsg( "Got " + QString::number( PQntuples( pk ) ) + " rows." ); - QStringList log; - // if we got no tuples we ain't got no unique index :) if ( PQntuples( pk ) == 0 ) { Index: src/providers/postgres/qgspostgresprovider.h =================================================================== --- src/providers/postgres/qgspostgresprovider.h (revision 10147) +++ src/providers/postgres/qgspostgresprovider.h (working copy) @@ -159,7 +159,7 @@ /** * Get the name of the primary key for the layer */ - QString getPrimaryKey(); + QString getPrimaryKey(const QString& suggestedKey = QString()); /** * Get the field information for the layer