[QGIS Commit] r14248 - in trunk/qgis/src: app/postgres core providers/postgres ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Sep 18 14:20:24 EDT 2010


Author: jef
Date: 2010-09-18 18:20:24 +0000 (Sat, 18 Sep 2010)
New Revision: 14248

Modified:
   trunk/qgis/src/app/postgres/qgspgnewconnection.cpp
   trunk/qgis/src/app/postgres/qgspgsourceselect.cpp
   trunk/qgis/src/app/postgres/qgspgsourceselect.h
   trunk/qgis/src/core/qgsdatasourceuri.cpp
   trunk/qgis/src/core/qgsvectorlayer.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
   trunk/qgis/src/ui/qgspgnewconnectionbase.ui
Log:
[FEATURE] allow adding geometryless layers from postgres

Modified: trunk/qgis/src/app/postgres/qgspgnewconnection.cpp
===================================================================
--- trunk/qgis/src/app/postgres/qgspgnewconnection.cpp	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/app/postgres/qgspgnewconnection.cpp	2010-09-18 18:20:24 UTC (rev 14248)
@@ -58,7 +58,8 @@
     txtPort->setText( port );
     cb_publicSchemaOnly->setChecked( settings.value( key + "/publicOnly", false ).toBool() );
     cb_geometryColumnsOnly->setChecked( settings.value( key + "/geometrycolumnsOnly", false ).toBool() );
-    // Ensure that cb_plublicSchemaOnly is set correctly
+    cb_allowGeometrylessTables->setChecked( settings.value( key + "/allowGeometrylessTables", true ).toBool() );
+    // Ensure that cb_publicSchemaOnly is set correctly
     on_cb_geometryColumnsOnly_clicked();
 
     cb_useEstimatedMetadata->setChecked( settings.value( key + "/estimatedMetadata", false ).toBool() );
@@ -125,6 +126,7 @@
   settings.setValue( baseKey + "/password", chkStorePassword->isChecked() ? txtPassword->text() : "" );
   settings.setValue( baseKey + "/publicOnly", cb_publicSchemaOnly->isChecked() );
   settings.setValue( baseKey + "/geometryColumnsOnly", cb_geometryColumnsOnly->isChecked() );
+  settings.setValue( baseKey + "/allowGeometrylessTables", cb_allowGeometrylessTables->isChecked() );
   settings.setValue( baseKey + "/sslmode", cbxSSLmode->itemData( cbxSSLmode->currentIndex() ).toInt() );
   settings.setValue( baseKey + "/saveUsername", chkStoreUsername->isChecked() ? "true" : "false" );
   settings.setValue( baseKey + "/savePassword", chkStorePassword->isChecked() ? "true" : "false" );

Modified: trunk/qgis/src/app/postgres/qgspgsourceselect.cpp
===================================================================
--- trunk/qgis/src/app/postgres/qgspgsourceselect.cpp	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/app/postgres/qgspgsourceselect.cpp	2010-09-18 18:20:24 UTC (rev 14248)
@@ -362,9 +362,9 @@
     uri += QString( " estimatedmetadata=true" );
   }
 
-  uri += QString( " table=\"%1\".\"%2\" (%3) sql=%4" )
+  uri += QString( " table=\"%1\".\"%2\"%3 sql=%4" )
          .arg( schemaName ).arg( tableName )
-         .arg( geomColumnName )
+         .arg( geomColumnName.isEmpty() ? QString() : QString( " (%1)" ).arg( geomColumnName ) )
          .arg( sql );
 
   return uri;
@@ -429,6 +429,7 @@
 
   bool searchPublicOnly = settings.value( key + "/publicOnly" ).toBool();
   bool searchGeometryColumnsOnly = settings.value( key + "/geometryColumnsOnly" ).toBool();
+  bool allowGeometrylessTables = settings.value( key + "/allowGeometrylessTables", true ).toBool();
   mUseEstimatedMetadata = settings.value( key + "/estimatedMetadata" ).toBool();
   // Need to escape the password to allow for single quotes and backslashes
 
@@ -481,7 +482,7 @@
     // get the list of suitable tables and columns and populate the UI
     geomCol details;
 
-    if ( getTableInfo( pd, searchGeometryColumnsOnly, searchPublicOnly ) )
+    if ( getTableInfo( pd, searchGeometryColumnsOnly, searchPublicOnly, allowGeometrylessTables ) )
     {
       // Start the thread that gets the geometry type for relations that
       // may take a long time to return
@@ -604,7 +605,7 @@
   return cols;
 }
 
-bool QgsPgSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly )
+bool QgsPgSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables )
 {
   int nColumns = 0;
   int nGTables = 0;
@@ -797,6 +798,58 @@
     result = 0;
   }
 
+  if ( allowGeometrylessTables )
+  {
+    QString sql = "select "
+                  "pg_class.relname"
+                  ",pg_namespace.nspname"
+                  ",pg_class.relkind"
+                  " from "
+                  " pg_class"
+                  ",pg_namespace"
+                  " where "
+                  "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' )"
+                  " and pg_class.relkind in( 'v', 'r' )";
+
+    // user has select privilege
+    if ( searchPublicOnly )
+      sql += " and pg_namespace.nspname = 'public'";
+
+    QgsDebugMsg( "sql: " + sql );
+
+    result = PQexec( pg, sql.toUtf8() );
+
+    if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
+    {
+      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 ) ) ) );
+      if ( nColumns == 0 )
+        nColumns = -1;
+    }
+    else if ( PQntuples( result ) > 0 )
+    {
+      for ( int i = 0; i < PQntuples( result ); i++ )
+      {
+        QString table  = QString::fromUtf8( PQgetvalue( result, i, 0 ) ); // relname
+        QString schema = QString::fromUtf8( PQgetvalue( result, i, 1 ) ); // nspname
+        QString relkind = QString::fromUtf8( PQgetvalue( result, i, 2 ) ); // relation kind
+
+        QgsDebugMsg( QString( "%1.%2: %3" ).arg( schema ).arg( table ).arg( relkind ) );
+
+        mTableModel.addTableEntry( tr( "No geometry" ), schema, table, QString::null, relkind == "v" ? pkCandidates( pg, schema, table ) : QStringList(), "" );
+        nColumns++;
+      }
+    }
+
+    PQclear( result );
+    result = 0;
+  }
+
   if ( nColumns == 0 )
   {
     QMessageBox::warning( this,

Modified: trunk/qgis/src/app/postgres/qgspgsourceselect.h
===================================================================
--- trunk/qgis/src/app/postgres/qgspgsourceselect.h	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/app/postgres/qgspgsourceselect.h	2010-09-18 18:20:24 UTC (rev 14248)
@@ -155,7 +155,7 @@
     typedef QList<geomPair> geomCol;
 
     /**Inserts information about the spatial tables into mTableModel*/
-    bool getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly );
+    bool getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly, bool allowGeometrylessTables );
 
     /** get primary key candidates (all int4 columns) */
     QStringList pkCandidates( PGconn *pg, QString schemaName, QString viewName );

Modified: trunk/qgis/src/core/qgsdatasourceuri.cpp
===================================================================
--- trunk/qgis/src/core/qgsdatasourceuri.cpp	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/core/qgsdatasourceuri.cpp	2010-09-18 18:20:24 UTC (rev 14248)
@@ -103,6 +103,10 @@
 
           i++;
         }
+        else
+        {
+          mGeometryColumn = QString::null;
+        }
       }
       else if ( pname == "key" )
       {
@@ -439,9 +443,9 @@
     theUri += QString( " estimatedmetadata=true" );
   }
 
-  theUri += QString( " table=%1 (%2) sql=%3" )
+  theUri += QString( " table=%1%2 sql=%3" )
             .arg( quotedTablename() )
-            .arg( mGeometryColumn )
+            .arg( mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( mGeometryColumn ) )
             .arg( mSql );
 
   return theUri;

Modified: trunk/qgis/src/core/qgsvectorlayer.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.cpp	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/core/qgsvectorlayer.cpp	2010-09-18 18:20:24 UTC (rev 14248)
@@ -124,7 +124,7 @@
     setCoordinateSystem();
 
     QSettings settings;
-    if ( settings.value( "/qgis/use_symbology_ng", false ).toBool() )
+    if ( settings.value( "/qgis/use_symbology_ng", false ).toBool() && geometryType() != QGis::NoGeometry )
     {
       // using symbology-ng!
       setUsingRendererV2( true );
@@ -139,7 +139,7 @@
     }
 
     // if the default style failed to load or was disabled use some very basic defaults
-    if ( !defaultLoadedFlag )
+    if ( !defaultLoadedFlag && geometryType() != QGis::NoGeometry )
     {
       // add single symbol renderer
       if ( mUsingRendererV2 )

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2010-09-18 18:20:24 UTC (rev 14248)
@@ -72,7 +72,7 @@
 
   mUri = QgsDataSourceURI( uri );
 
-  /* populate members from the uri structure */
+  // populate members from the uri structure
   mSchemaName = mUri.schema();
   mTableName = mUri.table();
   geometryColumn = mUri.geometryColumn();
@@ -390,6 +390,11 @@
   bool fetchGeometry,
   QString whereClause )
 {
+  if ( fetchGeometry && geometryColumn.isNull() )
+  {
+    return false;
+  }
+
   try
   {
     QString query = QString( "select %1" ).arg( quotedIdentifier( primaryKey ) );
@@ -548,7 +553,7 @@
 
   QString whereClause;
 
-  if ( !rect.isEmpty() )
+  if ( !rect.isEmpty() && !geometryColumn.isNull() )
   {
     if ( isGeography )
     {
@@ -983,10 +988,16 @@
       sql = QString( "SELECT "
                      "has_table_privilege(%1,'DELETE'),"
                      "has_any_column_privilege(%1,'UPDATE'),"
-                     "has_column_privilege(%1,%2,'UPDATE'),"
+                     "%2"
                      "has_table_privilege(%1,'INSERT'),"
                      "current_schema()" )
-            .arg( quotedValue( mQuery ) ).arg( quotedValue( geometryColumn ) );
+            .arg( quotedValue( mQuery ) )
+            .arg( geometryColumn.isNull()
+                  ? QString( "" )
+                  : QString( "has_column_privilege(%1,%2,'UPDATE')," )
+                  .arg( quotedValue( mQuery ) )
+                  .arg( quotedValue( geometryColumn ) )
+                );
     }
     else
     {
@@ -2254,18 +2265,28 @@
     connectionRW->PQexecNR( "BEGIN" );
 
     // Prepare the INSERT statement
-    QString insert = QString( "INSERT INTO %1(%2" )
-                     .arg( mQuery )
-                     .arg( quotedIdentifier( geometryColumn ) ),
-                     values = QString( ") VALUES (GeomFromWKB($1%1,%2)" )
-                              .arg( connectionRW->useWkbHex() ? "" : "::bytea" )
-                              .arg( srid );
+    QString insert = QString( "INSERT INTO %1(" ).arg( mQuery );
+    QString values;
+    QString delim = ",";
 
+    if ( !geometryColumn.isNull() )
+    {
+      insert += quotedIdentifier( geometryColumn );
+      values = QString( ") VALUES (GeomFromWKB($1%1,%2)" )
+               .arg( connectionRW->useWkbHex() ? "" : "::bytea" )
+               .arg( srid );
+      delim = ",";
+    }
+    else
+    {
+      delim = "";
+    }
+
     int offset;
     if ( primaryKeyType != "tid" && primaryKeyType != "oid" )
     {
-      insert += "," + quotedIdentifier( primaryKey );
-      values += ",$2";
+      insert += delim + quotedIdentifier( primaryKey );
+      values += delim + "$2";
       offset = 3;
     }
     else
@@ -2306,7 +2327,7 @@
           break;
       }
 
-      insert += "," + quotedIdentifier( fieldname );
+      insert += delim + quotedIdentifier( fieldname );
 
       QString defVal = defaultValue( it.key() ).toString();
 
@@ -2316,24 +2337,24 @@
         {
           if ( defVal.isNull() )
           {
-            values += ",NULL";
+            values += delim + "NULL";
           }
           else
           {
-            values += "," + defVal;
+            values += delim + defVal;
           }
         }
         else if ( fit->typeName() == "geometry" )
         {
-          values += QString( ",geomfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
+          values += QString( "%1geomfromewkt(%2)" ).arg( delim ).arg( quotedValue( it->toString() ) );
         }
         else if ( fit->typeName() == "geography" )
         {
-          values += QString( ",st_geographyfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
+          values += QString( "%1st_geographyfromewkt(%2)" ).arg( delim ).arg( quotedValue( it->toString() ) );
         }
         else
         {
-          values += "," + quotedValue( it->toString() );
+          values += delim + quotedValue( it->toString() );
         }
       }
       else
@@ -2341,19 +2362,21 @@
         // value is not unique => add parameter
         if ( fit->typeName() == "geometry" )
         {
-          values += QString( ",geomfromewkt($%1)" ).arg( defaultValues.size() + offset );
+          values += QString( "%1geomfromewkt($%2)" ).arg( delim ).arg( defaultValues.size() + offset );
         }
         else if ( fit->typeName() == "geography" )
         {
-          values += QString( ",st_geographyfromewkt($%1)" ).arg( defaultValues.size() + offset );
+          values += QString( "%1st_geographyfromewkt($%2)" ).arg( delim ).arg( defaultValues.size() + offset );
         }
         else
         {
-          values += QString( ",$%1" ).arg( defaultValues.size() + offset );
+          values += QString( "%1$%2" ).arg( delim ).arg( defaultValues.size() + offset );
         }
         defaultValues.append( defVal );
         fieldId.append( it.key() );
       }
+
+      delim = ",";
     }
 
     insert += values + ")";
@@ -2656,7 +2679,7 @@
 {
   QgsDebugMsg( "entering." );
 
-  if ( isQuery )
+  if ( isQuery || geometryColumn.isNull() )
     return false;
 
   if ( !connectRW() )
@@ -2811,6 +2834,9 @@
 
 QgsRectangle QgsPostgresProvider::extent()
 {
+  if ( geometryColumn.isNull() )
+    return QgsRectangle();
+
   if ( isGeography )
     return QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
 
@@ -2846,7 +2872,7 @@
             // dateline extent() returns -180 to 180 (which appears right), but
             // estimated_extent() returns eastern bound of data (>-180) and
             // 180 degrees.
-            if ( !ext.startsWith( "-180 ") && ext.contains( ",180 " ) )
+            if ( !ext.startsWith( "-180 " ) && ext.contains( ",180 " ) )
             {
               ext.clear();
             }
@@ -2974,6 +3000,13 @@
 
 bool QgsPostgresProvider::getGeometryDetails()
 {
+  if ( geometryColumn.isNull() )
+  {
+    geomType = QGis::WKBNoGeometry;
+    valid = true;
+    return true;
+  }
+
   QString fType( "" );
   srid = "";
   valid = false;

Modified: trunk/qgis/src/ui/qgspgnewconnectionbase.ui
===================================================================
--- trunk/qgis/src/ui/qgspgnewconnectionbase.ui	2010-09-18 15:31:31 UTC (rev 14247)
+++ trunk/qgis/src/ui/qgspgnewconnectionbase.ui	2010-09-18 18:20:24 UTC (rev 14248)
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>323</width>
-    <height>384</height>
+    <width>352</width>
+    <height>413</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -228,7 +228,7 @@
         </item>
        </layout>
       </item>
-      <item row="4" column="0">
+      <item row="5" column="0">
        <widget class="QCheckBox" name="cb_useEstimatedMetadata">
         <property name="toolTip">
          <string>Use estimated table statistics for the layer metadata.</string>
@@ -249,6 +249,16 @@
         </property>
        </widget>
       </item>
+      <item row="4" column="0">
+       <widget class="QCheckBox" name="cb_allowGeometrylessTables">
+        <property name="text">
+         <string>Allow geometryless tables</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>



More information about the QGIS-commit mailing list