[QGIS Commit] r12418 - trunk/qgis/src/providers/postgres

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Dec 12 08:18:39 EST 2009


Author: jef
Date: 2009-12-12 08:18:38 -0500 (Sat, 12 Dec 2009)
New Revision: 12418

Modified:
   trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.h
Log:
better fix for #2137

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2009-12-12 11:32:11 UTC (rev 12417)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2009-12-12 13:18:38 UTC (rev 12418)
@@ -24,8 +24,6 @@
 #include <netinet/in.h>
 #endif
 
-#include <cassert>
-
 #include <qgis.h>
 #include <qgsapplication.h>
 #include <qgsfeature.h>
@@ -191,12 +189,12 @@
   calculateExtents();
   getFeatureCount();
 
+  // set the primary key
+  getPrimaryKey();
+
   // load the field list
   loadFields();
 
-  // set the primary key
-  getPrimaryKey();
-
   // Set the postgresql message level so that we don't get the
   // 'there is no transaction in progress' warning.
 #ifndef QGISDEBUG
@@ -870,6 +868,9 @@
   for ( int i = 0; i < PQnfields( result ); i++ )
   {
     QString fieldName = QString::fromUtf8( PQfname( result, i ) );
+    if ( fieldName == geometryColumn )
+      continue;
+
     int fldtyp = PQftype( result, i );
     QString typOid = QString().setNum( fldtyp );
     int fieldModifier = PQfmod( result, i );
@@ -899,79 +900,76 @@
     if ( PQntuples( tresult ) > 0 )
       fieldComment = QString::fromUtf8( PQgetvalue( tresult, 0, 0 ) );
 
-    if ( fieldName != geometryColumn )
+    QVariant::Type fieldType;
+
+    if ( fieldTType == "b" )
     {
-      QVariant::Type fieldType;
+      bool isArray = fieldTypeName.startsWith( "_" );
 
-      if ( fieldTType == "b" )
+      if ( isArray )
+        fieldTypeName = fieldTypeName.mid( 1 );
+
+      if ( fieldTypeName == "int8" )
       {
-        bool isArray = fieldTypeName.startsWith( "_" );
-
-        if ( isArray )
-          fieldTypeName = fieldTypeName.mid( 1 );
-
-        if ( fieldTypeName == "int8" )
-        {
-          fieldType = QVariant::LongLong;
-          fieldSize = -1;
-        }
-        else if ( fieldTypeName.startsWith( "int" ) ||
-                  fieldTypeName == "serial" )
-        {
-          fieldType = QVariant::Int;
-          fieldSize = -1;
-        }
-        else if ( fieldTypeName == "real" ||
-                  fieldTypeName == "double precision" ||
-                  fieldTypeName.startsWith( "float" ) ||
-                  fieldTypeName == "numeric" )
-        {
-          fieldType = QVariant::Double;
-          fieldSize = -1;
-        }
-        else if ( fieldTypeName == "text" ||
-                  fieldTypeName == "bpchar" ||
-                  fieldTypeName == "varchar" ||
-                  fieldTypeName == "bool" ||
-                  fieldTypeName == "geometry" ||
-                  fieldTypeName == "money" ||
-                  fieldTypeName.startsWith( "time" ) ||
-                  fieldTypeName.startsWith( "date" ) )
-        {
-          fieldType = QVariant::String;
-          fieldSize = -1;
-        }
-        else if ( fieldTypeName == "char" )
-        {
-          fieldType = QVariant::String;
-        }
-        else
-        {
-          QgsDebugMsg( "Field " + fieldName + " ignored, because of unsupported type " + fieldTypeName );
-          continue;
-        }
-
-        if ( isArray )
-        {
-          fieldTypeName = "_" + fieldTypeName;
-          fieldType = QVariant::String;
-          fieldSize = -1;
-        }
+        fieldType = QVariant::LongLong;
+        fieldSize = -1;
       }
-      else if ( fieldTType == "e" )
+      else if ( fieldTypeName.startsWith( "int" ) ||
+                fieldTypeName == "serial" )
       {
-        // enum
+        fieldType = QVariant::Int;
+        fieldSize = -1;
+      }
+      else if ( fieldTypeName == "real" ||
+                fieldTypeName == "double precision" ||
+                fieldTypeName.startsWith( "float" ) ||
+                fieldTypeName == "numeric" )
+      {
+        fieldType = QVariant::Double;
+        fieldSize = -1;
+      }
+      else if ( fieldTypeName == "text" ||
+                fieldTypeName == "bpchar" ||
+                fieldTypeName == "varchar" ||
+                fieldTypeName == "bool" ||
+                fieldTypeName == "geometry" ||
+                fieldTypeName == "money" ||
+                fieldTypeName.startsWith( "time" ) ||
+                fieldTypeName.startsWith( "date" ) )
+      {
         fieldType = QVariant::String;
         fieldSize = -1;
       }
+      else if ( fieldTypeName == "char" )
+      {
+        fieldType = QVariant::String;
+      }
       else
       {
-        QgsDebugMsg( "Field " + fieldName + " ignored, because of unsupported type type " + fieldTType );
+        QgsDebugMsg( "Field " + fieldName + " ignored, because of unsupported type " + fieldTypeName );
         continue;
       }
 
-      attributeFields.insert( i, QgsField( fieldName, fieldType, fieldTypeName, fieldSize, fieldModifier, fieldComment ) );
+      if ( isArray )
+      {
+        fieldTypeName = "_" + fieldTypeName;
+        fieldType = QVariant::String;
+        fieldSize = -1;
+      }
     }
+    else if ( fieldTType == "e" )
+    {
+      // enum
+      fieldType = QVariant::String;
+      fieldSize = -1;
+    }
+    else
+    {
+      QgsDebugMsg( "Field " + fieldName + " ignored, because of unsupported type type " + fieldTType );
+      continue;
+    }
+
+    attributeFields.insert( i, QgsField( fieldName, fieldType, fieldTypeName, fieldSize, fieldModifier, fieldComment ) );
   }
 }
 
@@ -1064,6 +1062,17 @@
                             "primary key), has a PostgreSQL oid column or has a ctid\n"
                             "column with a 16bit block number.\n" ) );
       }
+      else
+      {
+        primaryKeyDefault = defaultValue( primaryKey ).toString();
+        if ( primaryKeyDefault.isNull() )
+        {
+          primaryKeyDefault = QString( "max(%1)+1 from %2.%3" )
+                              .arg( quotedIdentifier( primaryKey ) )
+                              .arg( quotedIdentifier( mSchemaName ) )
+                              .arg( quotedIdentifier( mTableName ) );
+        }
+      }
     }
     else if ( type == "v" ) // the relation is a view
     {
@@ -1091,18 +1100,33 @@
         }
       }
 
+      // Have a poke around the view to see if any of the columns
+      // could be used as the primary key.
+      tableCols cols;
+
+      // Given a schema.view, populate the cols variable with the
+      // schema.table.column's that underly the view columns.
+      findColumns( cols );
+
       if ( primaryKey.isEmpty() )
       {
-        // Have a poke around the view to see if any of the columns
-        // could be used as the primary key.
-        tableCols cols;
-        // Given a schema.view, populate the cols variable with the
-        // schema.table.column's that underly the view columns.
-        findColumns( cols );
         // From the view columns, choose one for which the underlying
         // column is suitable for use as a key into the view.
         primaryKey = chooseViewColumn( cols );
       }
+
+      tableCols::const_iterator it = cols.find( primaryKey );
+      if ( it != cols.end() )
+      {
+        primaryKeyDefault = defaultValue( it->second.column, it->second.relation, it->second.schema ).toString();
+        if ( primaryKeyDefault.isNull() )
+        {
+          primaryKeyDefault = QString( "max(%1)+1 from %2.%3" )
+                              .arg( quotedIdentifier( it->second.column ) )
+                              .arg( quotedIdentifier( it->second.schema ) )
+                              .arg( quotedIdentifier( it->second.relation ) );
+        }
+      }
     }
     else
       QgsDebugMsg( "Unexpected relation type of '" + type + "'." );
@@ -1201,9 +1225,20 @@
       valid = false;
       showMessageBox( tr( "Unable to find a key column" ), log );
     }
+    else
+    {
+      primaryKeyDefault = defaultValue( primaryKey ).toString();
+      if ( primaryKeyDefault.isNull() )
+      {
+        primaryKeyDefault = QString( "max(%1)+1 from %2.%3" )
+                            .arg( quotedIdentifier( primaryKey ) )
+                            .arg( quotedIdentifier( mSchemaName ) )
+                            .arg( quotedIdentifier( mTableName ) );
+      }
+    }
   }
 
-  if ( primaryKey.length() > 0 )
+  if ( !primaryKey.isNull() )
   {
     QgsDebugMsg( "Qgis row key is " + primaryKey );
   }
@@ -1893,28 +1928,18 @@
 }
 
 
-int QgsPostgresProvider::maxPrimaryKeyValue()
-{
-  QString sql;
-
-  sql = QString( "select max(%1) from %2" )
-        .arg( quotedIdentifier( primaryKey ) )
-        .arg( mSchemaTableName );
-
-  Result rmax = connectionRO->PQexec( sql );
-  QString maxValue = QString::fromUtf8( PQgetvalue( rmax, 0, 0 ) );
-
-  return maxValue.toInt();
-}
-
-
 bool QgsPostgresProvider::isValid()
 {
   return valid;
 }
 
-QVariant QgsPostgresProvider::defaultValue( QString fieldName )
+QVariant QgsPostgresProvider::defaultValue( QString fieldName, QString tableName, QString schemaName )
 {
+  if ( schemaName.isNull() )
+    schemaName = mSchemaName;
+  if ( tableName.isNull() )
+    tableName = mTableName;
+
   // Get the default column value from the Postgres information
   // schema. If there is no default we return an empty string.
 
@@ -1924,8 +1949,8 @@
   QString sql( "SELECT column_default FROM"
                " information_schema.columns WHERE"
                " column_default IS NOT NULL"
-               " AND table_schema = " + quotedValue( mSchemaName ) +
-               " AND table_name = " + quotedValue( mTableName ) +
+               " AND table_schema = " + quotedValue( schemaName ) +
+               " AND table_name = " + quotedValue( tableName ) +
                " AND column_name = " + quotedValue( fieldName ) );
 
   QVariant defaultValue( QString::null );
@@ -1935,8 +1960,6 @@
   if ( PQntuples( result ) == 1 && !PQgetisnull( result, 0, 0 ) )
     defaultValue = QString::fromUtf8( PQgetvalue( result, 0, 0 ) );
 
-  // QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );
-
   return defaultValue;
 }
 
@@ -2084,7 +2107,6 @@
 
     QStringList defaultValues;
     QList<int> fieldId;
-    int primaryKeyId = -1;
 
     // look for unique attribute values to place in statement instead of passing as parameter
     // e.g. for defaults
@@ -2098,15 +2120,9 @@
 
       QgsDebugMsg( "Checking field against: " + fieldname );
 
-      if ( fieldname.isEmpty() || fieldname == geometryColumn )
+      if ( fieldname.isEmpty() || fieldname == geometryColumn || fieldname == primaryKey )
         continue;
 
-      if ( fieldname == primaryKey )
-      {
-        primaryKeyId = it.key();
-        continue;
-      }
-
       int i;
       for ( i = 1; i < flist.size(); i++ )
       {
@@ -2170,10 +2186,6 @@
       throw PGException( stmt );
     PQclear( stmt );
 
-    QString keyDefault = defaultValue( primaryKey ).toString();
-    int primaryKeyHighWater = -1;
-    if ( keyDefault.isNull() )
-      primaryKeyHighWater = maxPrimaryKeyValue();
     QList<int> newIds;
 
     for ( QgsFeatureList::iterator features = flist.begin(); features != flist.end(); features++ )
@@ -2188,19 +2200,9 @@
 
       if ( primaryKeyType != "tid" )
       {
-        QByteArray key = paramValue( primaryKeyId >= 0 ? attributevec[ primaryKeyId ].toString() : QString::null, keyDefault );
-
-        if ( key.isNull() )
-        {
-          ++primaryKeyHighWater;
-          params << QString::number( primaryKeyHighWater );
-          newIds << primaryKeyHighWater;
-        }
-        else
-        {
-          params << key;
-          newIds << key.toInt();
-        }
+        int id = paramValue( primaryKeyDefault, primaryKeyDefault ).toInt();
+        params << QString::number( id );
+        newIds << id;
       }
 
       for ( int i = 0; i < fieldId.size(); i++ )
@@ -3111,8 +3113,7 @@
   message->showMessage();
 }
 
-void QgsPostgresProvider::showMessageBox( const QString& title,
-    const QStringList& text )
+void QgsPostgresProvider::showMessageBox( const QString& title, const QStringList& text )
 {
   showMessageBox( title, text.join( "\n" ) );
 }

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2009-12-12 11:32:11 UTC (rev 12417)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2009-12-12 13:18:38 UTC (rev 12418)
@@ -205,7 +205,7 @@
     QgsAttributeList attributeIndexes();
 
     /**Returns the default value for field specified by @c fieldName */
-    QVariant defaultValue( QString fieldName );
+    QVariant defaultValue( QString fieldName, QString tableName = QString::null, QString schemaName = QString::null );
 
     /**Returns the default value for field specified by @c fieldId */
     QVariant defaultValue( int fieldId );
@@ -409,6 +409,10 @@
      */
     QString primaryKey;
     /**
+     * Default value for primary key
+     */
+    QString primaryKeyDefault;
+    /**
      * Data type for the primary key
      */
     QString primaryKeyType;
@@ -560,13 +564,6 @@
 
     int enabledCapabilities;
 
-    /**Returns the maximum value of the primary key attribute
-       @note  You should run this inside of a PostgreSQL transaction
-              so that you can safely increment the value returned for
-              use in newly added features.
-      */
-    int maxPrimaryKeyValue();
-
     //! Get the feature count based on the where clause
     long getFeatureCount();
 



More information about the QGIS-commit mailing list