[QGIS Commit] r13922 - in trunk/qgis/src: app/postgres providers/postgres

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Jul 17 07:22:30 EDT 2010


Author: jef
Date: 2010-07-17 11:22:30 +0000 (Sat, 17 Jul 2010)
New Revision: 13922

Modified:
   trunk/qgis/src/app/postgres/qgspgsourceselect.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.h
Log:
apply #2730

Modified: trunk/qgis/src/app/postgres/qgspgsourceselect.cpp
===================================================================
--- trunk/qgis/src/app/postgres/qgspgsourceselect.cpp	2010-07-17 11:19:04 UTC (rev 13921)
+++ trunk/qgis/src/app/postgres/qgspgsourceselect.cpp	2010-07-17 11:22:30 UTC (rev 13922)
@@ -606,66 +606,105 @@
 
 bool QgsPgSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly )
 {
-  int n = 0;
+  int nColumns = 0;
+  int nGTables = 0;
   QApplication::setOverrideCursor( Qt::WaitCursor );
 
-  // The following query returns only tables that exist and the user has SELECT privilege on.
-  // Can't use regclass here because table must exist, else error occurs.
-  QString sql = "select "
-                "f_table_name,"
-                "f_table_schema,"
-                "f_geometry_column,"
-                "type,"
-                "pg_class.relkind"
-                " from "
-                "geometry_columns,"
-                "pg_class,"
-                "pg_namespace"
-                " where "
-                "relname=f_table_name"
-                " and f_table_schema=nspname"
-                " and pg_namespace.oid=pg_class.relnamespace"
-                " and has_schema_privilege(pg_namespace.nspname,'usage')"
-                " and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')" // user has select privilege
-                " order by "
-                "f_table_schema,f_table_name,f_geometry_column";
+  PGresult *result = 0;
 
-  PGresult *result = PQexec( pg, sql.toUtf8() );
-  if ( result )
+  for ( int i = 0; i < 2; i++ )
   {
-    if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
+    QString gtableName, columnName;
+
+    if ( i == 0 )
     {
-      QMessageBox::warning( this,
-                            tr( "Accessible tables could not be determined" ),
-                            tr( "Database connection was successful, but the accessible tables could not be determined.\n\n"
-                                "The error message from the database was:\n%1\n" )
-                            .arg( QString::fromUtf8( PQresultErrorMessage( result ) ) ) );
-      n = -1;
+      gtableName = "geometry_columns";
+      columnName = "f_geometry_column";
     }
-    else if ( PQntuples( result ) > 0 )
+    else if ( i == 1 )
     {
-      for ( int idx = 0; idx < PQntuples( result ); idx++ )
+      gtableName = "geography_columns";
+      columnName = "f_geography_column";
+    }
+
+    // The following query returns only tables that exist and the user has SELECT privilege on.
+    // Can't use regclass here because table must exist, else error occurs.
+    QString sql = QString( "select "
+                           "f_table_name,"
+                           "f_table_schema,"
+                           "%2,"
+                           "upper(type),"
+                           "pg_class.relkind"
+                           " from "
+                           "%1,"
+                           "pg_class,"
+                           "pg_namespace"
+                           " where "
+                           "relname=f_table_name"
+                           " and f_table_schema=nspname"
+                           " and pg_namespace.oid=pg_class.relnamespace"
+                           " and has_schema_privilege(pg_namespace.nspname,'usage')"
+                           " and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')" // user has select privilege
+                           " order by "
+                           "f_table_schema,f_table_name,%2" ).arg( gtableName ).arg( columnName );
+
+    QgsDebugMsg( "sql: " + sql );
+
+    result = PQexec( pg, sql.toUtf8() );
+    if ( result )
+    {
+      if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
       {
-        QString tableName = QString::fromUtf8( PQgetvalue( result, idx, 0 ) );
-        QString schemaName = QString::fromUtf8( PQgetvalue( result, idx, 1 ) );
-        QString column = QString::fromUtf8( PQgetvalue( result, idx, 2 ) );
-        QString type = QString::fromUtf8( PQgetvalue( result, idx, 3 ) );
-        QString relkind = QString::fromUtf8( PQgetvalue( result, idx, 4 ) );
+        PGresult *r = PQexec( pg, "COMMIT" );
+        if ( r )
+          PQclear( r );
+      }
+      else
+      {
+        nGTables++;
 
-        QString as = "";
-        if ( type == "GEOMETRY" && !searchGeometryColumnsOnly )
+        if ( PQntuples( result ) > 0 )
         {
-          addSearchGeometryColumn( schemaName, tableName,  column );
-          as = type = "WAITING";
+
+          for ( int idx = 0; idx < PQntuples( result ); idx++ )
+          {
+            QString tableName = QString::fromUtf8( PQgetvalue( result, idx, 0 ) );
+            QString schemaName = QString::fromUtf8( PQgetvalue( result, idx, 1 ) );
+            QString column = QString::fromUtf8( PQgetvalue( result, idx, 2 ) );
+            QString type = QString::fromUtf8( PQgetvalue( result, idx, 3 ) );
+            QString relkind = QString::fromUtf8( PQgetvalue( result, idx, 4 ) );
+
+            QgsDebugMsg( QString( "%1 %2.%3.%4: %5 %6" )
+                         .arg( gtableName )
+                         .arg( schemaName ).arg( tableName ).arg( column )
+                         .arg( type )
+                         .arg( relkind ) );
+
+            QString as = "";
+            if ( type == "GEOMETRY" && !searchGeometryColumnsOnly )
+            {
+              addSearchGeometryColumn( schemaName, tableName,  column );
+              as = type = "WAITING";
+            }
+
+            mTableModel.addTableEntry( type, schemaName, tableName, column, relkind == "v" ? pkCandidates( pg, schemaName, tableName ) : QStringList(), "" );
+            nColumns++;
+          }
         }
-
-        mTableModel.addTableEntry( type, schemaName, tableName, column, relkind == "v" ? pkCandidates( pg, schemaName, tableName ) : QStringList(), "" );
-        n++;
       }
     }
+
+    PQclear( result );
+    result = 0;
   }
 
-  PQclear( result );
+  if ( nColumns == 0 )
+  {
+    QMessageBox::warning( this,
+                          tr( "Accessible tables could not be determined" ),
+                          tr( "Database connection was successful, but the accessible tables could not be determined." ) );
+    nColumns = -1;
+  }
 
   //search for geometry columns in tables that are not in the geometry_columns metatable
   QApplication::restoreOverrideCursor();
@@ -676,39 +715,47 @@
     // geometry_columns table. This code is specific to postgresql,
     // but an equivalent query should be possible in other
     // databases.
-    sql = "select "
-          "pg_class.relname,"
-          "pg_namespace.nspname,"
-          "pg_attribute.attname,"
-          "pg_class.relkind"
-          " from "
-          "pg_attribute,"
-          "pg_class,"
-          "pg_namespace"
-          " where "
-          "pg_namespace.oid = pg_class.relnamespace"
-          " and pg_attribute.attrelid = pg_class.oid "
-          " and ("
-          "pg_attribute.atttypid = regtype('geometry')"
-          " or pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype=regtype('geometry'))"
-          ")"
-          " and has_schema_privilege(pg_namespace.nspname,'usage')"
-          " and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')";
+    QString sql = "select "
+                  "pg_class.relname"
+                  ",pg_namespace.nspname"
+                  ",pg_attribute.attname"
+                  ",pg_class.relkind"
+                  " from "
+                  "pg_attribute"
+                  ",pg_class"
+                  ",pg_namespace"
+                  " where "
+                  "pg_namespace.oid=pg_class.relnamespace"
+                  " and pg_attribute.attrelid = pg_class.oid"
+                  " and ("
+                  "pg_attribute.atttypid::regtype::text IN ('geometry','geography')"
+                  " or pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype::regtype::text IN ('geometry','geography'))"
+                  ")"
+                  " and has_schema_privilege( pg_namespace.nspname, 'usage' )"
+                  " and has_table_privilege( '\"' || pg_namespace.nspname || '\".\"' || pg_class.relname || '\"', 'select' )";
+
     // user has select privilege
     if ( searchPublicOnly )
       sql += " and pg_namespace.nspname = 'public'";
 
-    if ( n > 0 )
+    if ( nColumns > 0 )
     {
       sql += " and not exists (select * from geometry_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name)";
+
+      if ( nGTables > 1 )
+      {
+        sql += " and not exists (select * from geography_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name)";
+      }
     }
     else
     {
-      n = 0;
+      nColumns = 0;
     }
 
-    sql += " and pg_class.relkind in ('v', 'r')"; // only from views and relations (tables)
+    sql += " and pg_class.relkind in( 'v', 'r' )"; // only from views and relations (tables)
 
+    QgsDebugMsg( "sql: " + sql );
+
     result = PQexec( pg, sql.toUtf8() );
 
     if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
@@ -718,8 +765,8 @@
                             tr( "Database connection was successful, but the accessible tables could not be determined.\n\n"
                                 "The error message from the database was:\n%1\n" )
                             .arg( QString::fromUtf8( PQresultErrorMessage( result ) ) ) );
-      if ( n == 0 )
-        n = -1;
+      if ( nColumns == 0 )
+        nColumns = -1;
     }
     else if ( PQntuples( result ) > 0 )
     {
@@ -737,17 +784,20 @@
         QString column = QString::fromUtf8( PQgetvalue( result, i, 2 ) ); // attname
         QString relkind = QString::fromUtf8( PQgetvalue( result, i, 3 ) ); // relation kind
 
+        QgsDebugMsg( QString( "%1.%2.%3: %4" ).arg( schema ).arg( table ).arg( column ).arg( relkind ) );
+
         addSearchGeometryColumn( schema, table, column );
         //details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
-        mTableModel.addTableEntry( "Waiting", schema, table, column, relkind == "v" ? pkCandidates( pg, schema, table ) : QStringList(), "" );
-        n++;
+        mTableModel.addTableEntry( tr( "Waiting" ), schema, table, column, relkind == "v" ? pkCandidates( pg, schema, table ) : QStringList(), "" );
+        nColumns++;
       }
     }
 
     PQclear( result );
+    result = 0;
   }
 
-  if ( n == 0 )
+  if ( nColumns == 0 )
   {
     QMessageBox::warning( this,
                           tr( "No accessible tables found" ),
@@ -756,7 +806,7 @@
                               "geometry." ) );
   }
 
-  return n > 0;
+  return nColumns > 0;
 }
 
 QString QgsPgSourceSelect::fullDescription( QString schema, QString table,
@@ -852,7 +902,9 @@
         query += "\"" + schemas[i] + "\".\"" + tables[i] + "\"";
       }
 
-      PGresult* gresult = PQexec( pd, query.toUtf8() );
+      QgsDebugMsg( "sql: " + query );
+
+      PGresult *gresult = PQexec( pd, query.toUtf8() );
       QString type;
       if ( PQresultStatus( gresult ) == PGRES_TUPLES_OK )
       {

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2010-07-17 11:19:04 UTC (rev 13921)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2010-07-17 11:22:30 UTC (rev 13922)
@@ -68,7 +68,6 @@
 
   providerId = providerIds++;
 
-  QgsDebugMsg( "Postgresql Layer Creation" );
   QgsDebugMsg( "URI: " + uri );
 
   mUri = QgsDataSourceURI( uri );
@@ -78,6 +77,7 @@
   mTableName = mUri.table();
   geometryColumn = mUri.geometryColumn();
   sqlWhereClause = mUri.sql();
+  isGeography = false;
 
   if ( mSchemaName.isEmpty() &&
        mTableName.startsWith( "(select", Qt::CaseInsensitive ) &&
@@ -374,6 +374,10 @@
   {
     return QString( "asewkt(%1)" ).arg( quotedIdentifier( fld.name() ) );
   }
+  else if ( type == "geography" )
+  {
+    return QString( "st_astext(%1)" ).arg( quotedIdentifier( fld.name() ) );
+  }
   else
   {
     return quotedIdentifier( fld.name() ) + "::text";
@@ -392,9 +396,16 @@
 
     if ( fetchGeometry )
     {
-      query += QString( ",asbinary(%1,'%2')" )
-               .arg( quotedIdentifier( geometryColumn ) )
-               .arg( endianString() );
+      if ( isGeography )
+      {
+        query += QString( ",st_asbinary(%1)" ).arg( quotedIdentifier( geometryColumn ) );
+      }
+      else
+      {
+        query += QString( ",asbinary(%1,'%2')" )
+                 .arg( quotedIdentifier( geometryColumn ) )
+                 .arg( endianString() );
+      }
     }
 
     for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
@@ -539,21 +550,32 @@
 
   if ( !rect.isEmpty() )
   {
-    if ( useIntersect )
+    if ( isGeography )
     {
-      // Contributed by #qgis irc "creeping"
-      // This version actually invokes PostGIS's use of spatial indexes
-      whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))" )
-                    .arg( quotedIdentifier( geometryColumn ) )
-                    .arg( rect.asWktCoordinates() )
-                    .arg( srid );
+      rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect );
+      if ( !rect.isFinite() )
+        whereClause = "false";
     }
-    else
+
+    if ( whereClause.isEmpty() )
     {
-      whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3)" )
-                    .arg( quotedIdentifier( geometryColumn ) )
-                    .arg( rect.asWktCoordinates() )
-                    .arg( srid );
+
+      if ( useIntersect )
+      {
+        // Contributed by #qgis irc "creeping"
+        // This version actually invokes PostGIS's use of spatial indexes
+        whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))" )
+                      .arg( quotedIdentifier( geometryColumn ) )
+                      .arg( rect.asWktCoordinates() )
+                      .arg( srid );
+      }
+      else
+      {
+        whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3)" )
+                      .arg( quotedIdentifier( geometryColumn ) )
+                      .arg( rect.asWktCoordinates() )
+                      .arg( srid );
+      }
     }
   }
 
@@ -2305,6 +2327,10 @@
         {
           values += QString( ",geomfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
         }
+        else if ( fit->typeName() == "geography" )
+        {
+          values += QString( ",st_geographyfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
+        }
         else
         {
           values += "," + quotedValue( it->toString() );
@@ -2317,6 +2343,10 @@
         {
           values += QString( ",geomfromewkt($%1)" ).arg( defaultValues.size() + offset );
         }
+        else if ( fit->typeName() == "geography" )
+        {
+          values += QString( ",st_geographyfromewkt($%1)" ).arg( defaultValues.size() + offset );
+        }
         else
         {
           values += QString( ",$%1" ).arg( defaultValues.size() + offset );
@@ -2576,7 +2606,9 @@
           else
             first = false;
 
-          sql += QString( fld.typeName() != "geometry" ? "%1=%2" : "%1=geomfromewkt(%2)" )
+          sql += QString( fld.typeName() == "geometry" ? "%1=geomfromewkt(%2)" :
+                          fld.typeName() == "geography" ? "%1=st_geographyfromewkt(%2)" :
+                          "%1=%2" )
                  .arg( quotedIdentifier( fld.name() ) )
                  .arg( quotedValue( siter->toString() ) );
         }
@@ -2779,6 +2811,9 @@
 
 QgsRectangle QgsPostgresProvider::extent()
 {
+  if ( isGeography )
+    return QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
+
   if ( layerExtent.isEmpty() )
   {
     QString sql;
@@ -2986,7 +3021,6 @@
         .arg( quotedValue( schemaName ) );
 
   QgsDebugMsg( "Getting geometry column: " + sql );
-
   result = connectionRO->PQexec( sql );
 
   QgsDebugMsg( "geometry column query returned " + QString::number( PQntuples( result ) ) );
@@ -2999,6 +3033,28 @@
 
   if ( srid.isEmpty() || fType.isEmpty() )
   {
+    sql = QString( "select upper(type),srid from geography_columns"
+                   " where f_table_name=%1 and f_geography_column=%2 and f_table_schema=%3" )
+          .arg( quotedValue( tableName ) )
+          .arg( quotedValue( geomCol ) )
+          .arg( quotedValue( schemaName ) );
+
+    QgsDebugMsg( "Getting geography column: " + sql );
+    result = connectionRO->PQexec( sql );
+
+    QgsDebugMsg( "geography column query returned " + QString::number( PQntuples( result ) ) );
+
+    if ( PQntuples( result ) > 0 )
+    {
+      fType = QString::fromUtf8( PQgetvalue( result, 0, 0 ) );
+      srid = QString::fromUtf8( PQgetvalue( result, 0, 1 ) );
+
+      isGeography = true;
+    }
+  }
+
+  if ( srid.isEmpty() || fType.isEmpty() )
+  {
     // Didn't find what we need in the geometry_columns table, so
     // get stuff from the relevant column instead. This may (will?)
     // fail if there is no data in the relevant table.
@@ -3116,6 +3172,7 @@
     QgsDebugMsg( "type is " + fType );
     QgsDebugMsg( "Feature type is " + QString::number( geomType ) );
     QgsDebugMsg( "Feature type name is " + QString( QGis::qgisFeatureTypes[geomType] ) );
+    QgsDebugMsg( "Geometry is geography " + isGeography );
   }
   else
   {

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2010-07-17 11:19:04 UTC (rev 13921)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2010-07-17 11:22:30 UTC (rev 13922)
@@ -383,6 +383,11 @@
     bool isQuery;
 
     /**
+     * geometry is geography
+     */
+    bool isGeography;
+
+    /**
      * Name of the table with no schema
      */
     QString mTableName;



More information about the QGIS-commit mailing list