Skip to content
Permalink
Browse files

Add mSpatialColType member in QgsPostgresProvider

This member tells us if a spatial column is of type Geometry,
Geography or TopoGeometry. The member is currently unused but
will eventually be used for specially handling TopoGeometry.
It could replace the mIsGeography bool, but replacement isn't
done by this commit.

Incidentally, this commit also adds SRID and type detection
for TopoGeometry columns
  • Loading branch information
Sandro Santilli
Sandro Santilli committed Oct 31, 2012
1 parent 6575448 commit b47b43997e71f0f042d89df898371512fe259512
Showing with 84 additions and 3 deletions.
  1. +79 −3 src/providers/postgres/qgspostgresprovider.cpp
  2. +5 −0 src/providers/postgres/qgspostgresprovider.h
@@ -39,11 +39,21 @@ const QString POSTGRES_DESCRIPTION = "PostgreSQL/PostGIS data provider";
int QgsPostgresProvider::sProviderIds = 0;
const int QgsPostgresProvider::sFeatureQueueSize = 2000;

namespace {
char *spatialColTypes[] = {
"UNKNOWN",
"Geometry",
"Geography",
"TopoGeometry"
};
}

QgsPostgresProvider::QgsPostgresProvider( QString const & uri )
: QgsVectorDataProvider( uri )
, mFetching( false )
, mValid( false )
, mPrimaryKeyType( pktUnknown )
, mSpatialColType( sctUnknown )
, mDetectedGeomType( QGis::WKBUnknown )
, mRequestedGeomType( QGis::WKBUnknown )
, mFeatureQueueSize( sFeatureQueueSize )
@@ -117,7 +127,7 @@ QgsPostgresProvider::QgsPostgresProvider( QString const & uri )
return;
}

if ( !getGeometryDetails() ) // gets srid and geometry type
if ( !getGeometryDetails() ) // gets srid, geometry and data type
{
// the table is not a geometry table
QgsMessageLog::logMessage( tr( "invalid PostgreSQL layer" ), tr( "PostGIS" ) );
@@ -2681,6 +2691,7 @@ bool QgsPostgresProvider::getGeometryDetails()
QString schemaName = mSchemaName;
QString tableName = mTableName;
QString geomCol = mGeometryColumn;
QString geomColType;

if ( mIsQuery )
{
@@ -2705,11 +2716,16 @@ bool QgsPostgresProvider::getGeometryDetails()
schemaName = result.PQgetvalue( 0, 0 );
tableName = result.PQgetvalue( 0, 1 );

sql = QString( "SELECT attname FROM pg_attribute WHERE attrelid=%1 AND attnum=%2" ).arg( tableoid ).arg( column );
sql = QString( "SELECT a.attname, t.typname FROM pg_attribute a, pg_type t WHERE a.attrelid=%1 AND a.attnum=%2 AND a.atttypid = t.oid" ).arg( tableoid ).arg( column );
result = mConnectionRO->PQexec( sql );
if ( PGRES_TUPLES_OK == result.PQresultStatus() && 1 == result.PQntuples() )
{
geomCol = result.PQgetvalue( 0, 0 );
geomColType = result.PQgetvalue( 0, 1 );
if ( geomColType == "geometry" ) mSpatialColType = sctGeometry;
else if ( geomColType == "geography" ) mSpatialColType = sctGeography;
else if ( geomColType == "topogeometry" ) mSpatialColType = sctTopoGeometry;
// else it's still unknown...
}
else
{
@@ -2750,6 +2766,7 @@ bool QgsPostgresProvider::getGeometryDetails()
{
detectedType = result.PQgetvalue( 0, 0 );
detectedSrid = result.PQgetvalue( 0, 1 );
mSpatialColType = sctGeometry;
}
else
{
@@ -2772,7 +2789,65 @@ bool QgsPostgresProvider::getGeometryDetails()
{
detectedType = result.PQgetvalue( 0, 0 );
detectedSrid = result.PQgetvalue( 0, 1 );
mIsGeography = true;
mIsGeography = true; // TODO: drop, use mSpatialColType instead
mSpatialColType = sctGeography;
}
else
{
mConnectionRO->PQexecNR( "COMMIT" );
}
}

if ( detectedType.isEmpty() && mConnectionRO->hasTopology() )
{
// check topology.layer
sql = QString( "SELECT CASE "
"WHEN l.feature_type = 1 THEN 'MULTIPOINT' "
"WHEN l.feature_type = 2 THEN 'MULTILINESTRING' "
"WHEN l.feature_type = 3 THEN 'MULTIPOLYGON' "
"WHEN l.feature_type = 4 THEN 'GEOMETRYCOLLECTION' "
"END AS type, t.srid FROM topology.layer l, topology.topology t "
"WHERE l.topology_id = t.id AND l.schema_name=%3 "
"AND l.table_name=%1 AND l.feature_column=%2" )
.arg( quotedValue( tableName ) )
.arg( quotedValue( geomCol ) )
.arg( quotedValue( schemaName ) );

QgsDebugMsg( QString( "Getting TopoGeometry column: %1" ).arg( sql ) );
result = mConnectionRO->PQexec( sql, false );
QgsDebugMsg( QString( "TopoGeometry column query returned %1" ).arg( result.PQntuples() ) );

if ( result.PQntuples() == 1 )
{
detectedType = result.PQgetvalue( 0, 0 );
detectedSrid = result.PQgetvalue( 0, 1 );
mSpatialColType = sctTopoGeometry;
}
else
{
mConnectionRO->PQexecNR( "COMMIT" );
}
}

if ( mSpatialColType == sctUnknown )
{
sql = QString( "SELECT t.typname FROM "
"pg_attribute a, pg_class c, pg_namespace n, pg_type t "
"WHERE a.attrelid=c.oid AND c.relnamespace=n.oid "
"AND a.atttypid=t.oid "
"AND n.nspname=%3 AND c.relname=%1 AND a.attname=%2" )
.arg( quotedValue( tableName ) )
.arg( quotedValue( geomCol ) )
.arg( quotedValue( schemaName ) );
QgsDebugMsg( QString( "Getting column datatype: %1" ).arg( sql ) );
result = mConnectionRO->PQexec( sql, false );
QgsDebugMsg( QString( "Column datatype query returned %1" ).arg( result.PQntuples() ) );
if ( result.PQntuples() == 1 )
{
geomColType = result.PQgetvalue( 0, 0 );
if ( geomColType == "geometry" ) mSpatialColType = sctGeometry;
else if ( geomColType == "geography" ) mSpatialColType = sctGeography;
else if ( geomColType == "topogeometry" ) mSpatialColType = sctTopoGeometry;
}
else
{
@@ -2888,6 +2963,7 @@ bool QgsPostgresProvider::getGeometryDetails()

QgsDebugMsg( QString( "Feature type name is %1" ).arg( QGis::qgisFeatureTypes[ geometryType()] ) );
QgsDebugMsg( QString( "Geometry is geography %1" ).arg( mIsGeography ) );
QgsDebugMsg( QString( "Spatial column type is %1" ).arg( spatialColTypes[mSpatialColType] ) );

return mValid;
}
@@ -412,6 +412,11 @@ class QgsPostgresProvider : public QgsVectorDataProvider
*/
enum { pktUnknown, pktInt, pktTid, pktOid, pktFidMap } mPrimaryKeyType;

/**
* Data type for the spatial column
*/
enum { sctUnknown, sctGeometry, sctGeography, sctTopoGeometry } mSpatialColType;

/**
* List of primary key attributes for fetching features.
*/

0 comments on commit b47b439

Please sign in to comment.
You can’t perform that action at this time.