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

svn_qgis at osgeo.org svn_qgis at osgeo.org
Wed Mar 26 20:44:22 EDT 2008


Author: jef
Date: 2008-03-26 20:44:22 -0400 (Wed, 26 Mar 2008)
New Revision: 8285

Modified:
   trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.h
Log:
More work on the postgres provider:

- put common code from select/getNextFeature and getFeatureById methods 
  to new declareCursor and getFeature methods
- unify type handling and support bool, arrays and time types
  (fixes #1009)
- ignore columns not explicitly supported (might apply to columns
  previously supported implicitly; please file a bug if you run into
  one)
- fixes a unreported problem with getFeatureById returning only NULL
  attributes.

Please test!


Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2008-03-26 21:07:02 UTC (rev 8284)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2008-03-27 00:44:22 UTC (rev 8285)
@@ -65,7 +65,8 @@
 : QgsVectorDataProvider(uri),
   geomType(QGis::WKBUnknown),
   mFeatureQueueSize(200),
-  gotPostgisVersion(FALSE)
+  gotPostgisVersion(false),
+  mFetching(false)
 {
   // assume this is a valid layer until we determine otherwise
   valid = true;
@@ -366,388 +367,294 @@
   return "PostgreSQL database with PostGIS extension";
 }
 
-bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
+void QgsPostgresProvider::declareCursor(const QString &cursorName,
+                                        const QgsAttributeList &fetchAttributes,
+                                        bool fetchGeometry,
+                                        QString whereClause,
+                                        QStringList &attributeNames)
 {
-  assert(mFetching);
+  QString declare = QString("declare %1 binary cursor with hold for select %2")
+                      .arg(cursorName).arg(quotedIdentifier(primaryKey));
 
-  if (valid)
+  if(fetchGeometry)
   {
+    declare += QString(",asbinary(%1,'%2') as qgs_feature_geometry")
+                 .arg( quotedIdentifier(geometryColumn) )
+                 .arg( endianString() ); 
+  }
 
-    // Top up our queue if it is empty
-    if (mFeatureQueue.empty())
+  QgsFieldMap attributeMap = fields();
+  for (QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it)
+  {
+    QgsFieldMap::const_iterator fieldIt = attributeMap.find(*it);
+    if(fieldIt != attributeMap.end())
     {
-      QString fetch = QString("fetch forward %1 from qgisf%2")
-                        .arg(mFeatureQueueSize)
-                        .arg(providerId);
+      const QString &fieldname = fieldIt.value().name();
 
-      if(mFirstFetch)
+      if( fieldname != primaryKey ) 
       {
-        if(PQsendQuery(connection, fetch.toUtf8()) == 0) //fetch features in asynchronously
+        if( fieldIt.value().typeName() == "money" || fieldIt.value().typeName().startsWith("_") )
         {
-          qWarning("PQsendQuery failed (1)");
+          // money and arrays don't support cast to text, but return text
+          // TODO: check other types
+          declare += "," + quotedIdentifier( fieldname );
         }
+        else if( fieldIt.value().typeName() == "bool" )
+        {
+          // bool doesn't support cast to text either and even doesn't return text.
+          // (even text() doesn't work with binary cursors)
+          declare += QString(",CASE WHEN %1 THEN 't' WHEN NOT %1 THEN 'f' ELSE NULL END AS %1")
+                       .arg( quotedIdentifier(fieldname) );
+        }
+        else
+        {
+          declare += "," + quotedIdentifier( fieldname ) + "::text";
+        }
       }
-      mFirstFetch = false;
-      queryResult = PQgetResult(connection);
-      PQgetResult(connection); //just to get the 0 pointer...  
 
-      int rows = PQntuples(queryResult);
+      attributeNames << fieldname;
+    }
+  }
 
-      if (rows == 0)
-      {
-        QgsDebugMsg("End of features");
+  declare += " from " + mSchemaTableName;
+  
+  if( !whereClause.isEmpty() )
+    declare += QString(" where %1").arg(whereClause);
 
-        PQclear(queryResult);
+  QgsDebugMsg("Binary cursor: " + declare);
 
-        return false;
-      }
+  PQexecNR(connection, declare.toUtf8());
+}
 
-      for (int row = 0; row < rows; row++)
-      {
-        int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,quotedIdentifier(primaryKey).toUtf8()));
+void QgsPostgresProvider::getFeature(PGresult *queryResult, int row, bool fetchGeometry,
+                                     QgsFeature &feature,
+                                     const QStringList &attributeNames,
+                                     const QgsAttributeList &fetchAttributes)
+{  
+  int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,quotedIdentifier(primaryKey).toUtf8()));
+  if (swapEndian)
+    oid = ntohl(oid); // convert oid to opposite endian
 
-        if (swapEndian)
-          oid = ntohl(oid); // convert oid to opposite endian
- 
-        mFeatureQueue.push(QgsFeature());
+  feature.setFeatureId(oid);
 
-        // set ID
-        mFeatureQueue.back().setFeatureId(oid);
+  // fetch attributes
+  QgsAttributeList::const_iterator it = fetchAttributes.constBegin();
+  for(QStringList::const_iterator namesIt = attributeNames.begin(); namesIt != attributeNames.end(); ++namesIt, ++it)
+  {
+    QString val;
 
-        // fetch attributes
-        std::list<QString>::const_iterator name_it = mFetchAttributeNames.begin();
-        QgsAttributeList::const_iterator index_it = mAttributesToFetch.constBegin();
+    if( (*namesIt) == primaryKey)
+    {
+      val = QString::number(oid);
+    }
+    else
+    {
+      int fn = PQfnumber(queryResult,quotedIdentifier(*namesIt).toUtf8());
 
-        for(; name_it != mFetchAttributeNames.end(); ++name_it, ++index_it)
-        {
-          QString val;
-
-          if( (*name_it) == primaryKey)
-          {
-            val = QString::number(oid);
-          }
-          else
-          {
-            int fn = PQfnumber(queryResult,quotedIdentifier(*name_it).toUtf8());
-
-            if( !PQgetisnull(queryResult, row, fn) )
-              val = QString::fromUtf8(PQgetvalue(queryResult, row, fn));
-            else
-              val = QString::null;
-          }
-
-          if( val.isNull() )
-          {
-            mFeatureQueue.back().addAttribute(*index_it, val);
-          }
-          else
-          {
-            switch (attributeFields[*index_it].type())
-            {
-            case QVariant::LongLong:
-              mFeatureQueue.back().addAttribute(*index_it, val.toLongLong());
-              break;
-            case QVariant::Int:
-              mFeatureQueue.back().addAttribute(*index_it, val.toInt());
-              break;
-            case QVariant::Double:
-              mFeatureQueue.back().addAttribute(*index_it, val.toDouble());
-              break;
-            case QVariant::String:
-              mFeatureQueue.back().addAttribute(*index_it, val);
-              break;
-            default:
-              assert(0 && "unsupported field type");
-            }
-          }
-        }
-
-        //fetch geometry
-        if (mFetchGeom)
-        {
-          int returnedLength = PQgetlength(queryResult, row, PQfnumber(queryResult,"qgs_feature_geometry")); 
-          if(returnedLength > 0)
-          {
-            unsigned char *featureGeom = new unsigned char[returnedLength + 1];
-            memset(featureGeom, '\0', returnedLength + 1);
-            memcpy(featureGeom, PQgetvalue(queryResult, row, PQfnumber(queryResult,QString("qgs_feature_geometry").toUtf8())), returnedLength); 
-            mFeatureQueue.back().setGeometryAndOwnership(featureGeom, returnedLength + 1);
-          }
-          else
-          {
-            mFeatureQueue.back().setGeometryAndOwnership(0, 0);
-            QgsDebugMsg("Couldn't get the feature geometry in binary form");
-          }
-        } 
-      } // for each row in queue
-
-      PQclear(queryResult);
-
-      if(PQsendQuery(connection, fetch.toUtf8()) == 0) //already fetch the next couple of features asynchronously
+      if( !PQgetisnull(queryResult, row, fn) )
       {
-        qWarning("PQsendQuery failed (2)");
+        val = QString::fromUtf8(PQgetvalue(queryResult, row, fn));
       }
+      else
+      {
+        val = QString::null;
+      }
+    }
 
-    } // if new queue is required
-
-    // Now return the next feature from the queue
-    if(mFetchGeom)
+    if( val.isNull() )
     {
-      QgsGeometry* featureGeom = mFeatureQueue.front().geometryAndOwnership();
-	    feature.setGeometry(featureGeom);
+      feature.addAttribute(*it, val);
     }
     else
     {
-	    feature.setGeometryAndOwnership(0, 0);
+      switch (attributeFields[*it].type())
+      {
+        case QVariant::LongLong:
+          feature.addAttribute(*it, val.toLongLong());
+          break;
+        case QVariant::Int:
+          feature.addAttribute(*it, val.toInt());
+          break;
+        case QVariant::Double:
+          feature.addAttribute(*it, val.toDouble());
+          break;
+        case QVariant::String:
+          feature.addAttribute(*it, val);
+          break;
+        default:
+          assert(0 && "unsupported field type");
+      }
     }
-    feature.setFeatureId(mFeatureQueue.front().featureId());
-    feature.setAttributeMap(mFeatureQueue.front().attributeMap());
-
-    mFeatureQueue.pop();
-
   }
-  else 
-  {
-    QgsDebugMsg("Read attempt on an invalid postgresql data source");
-    return false;
-  }
 
-  return true;
-}
-
-void QgsPostgresProvider::select(QgsAttributeList fetchAttributes,
-    QgsRect rect,
-    bool fetchGeometry,
-    bool useIntersect)
-{
-  mFetchGeom = fetchGeometry;
-  mAttributesToFetch = fetchAttributes;
-
-  mFetchAttributeNames.clear();
-  QgsFieldMap attributeMap = fields();
-  QgsFieldMap::const_iterator fieldIt;
-  for(QgsAttributeList::const_iterator it = mAttributesToFetch.constBegin();
-    it != mAttributesToFetch.constEnd(); ++it)
+  if (fetchGeometry)
   {
-    fieldIt = attributeMap.find(*it);
-    if(fieldIt != attributeMap.end())
+    int returnedLength = PQgetlength(queryResult, row, PQfnumber(queryResult,"qgs_feature_geometry")); 
+    if(returnedLength > 0)
     {
-      mFetchAttributeNames.push_back(fieldIt.value().name());
+      unsigned char *featureGeom = new unsigned char[returnedLength + 1];
+      memset(featureGeom, '\0', returnedLength + 1);
+      memcpy(featureGeom, PQgetvalue(queryResult, row, PQfnumber(queryResult,QString("qgs_feature_geometry").toUtf8())), returnedLength); 
+      feature.setGeometryAndOwnership(featureGeom, returnedLength + 1);
     }
-  }
+    else
+    {
+      feature.setGeometryAndOwnership(0, 0);
+      QgsDebugMsg("Couldn't get the feature geometry in binary form");
+    }
+  } 
+}
 
+void QgsPostgresProvider::select(QgsAttributeList fetchAttributes, QgsRect rect, bool fetchGeometry, bool useIntersect)
+{
+  QString cursorName = QString("qgisf%1").arg(providerId);
+  
   if(mFetching) 
   {
-    PQexecNR(connection, QString("CLOSE qgisf%1").arg(providerId).toUtf8() );
+    PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8() );
     mFetching=false;
-  }
-
-  QString declare = QString("declare qgisf%1 binary cursor with hold for select %2")
-                      .arg(providerId).arg(quotedIdentifier(primaryKey));
-
-  if(fetchGeometry)
-  {
-    declare += QString(",asbinary(%1,'%2') as qgs_feature_geometry")
-      .arg( quotedIdentifier(geometryColumn) )
-      .arg( endianString() ); 
-  }
-
-  for(std::list<QString>::const_iterator it = mFetchAttributeNames.begin(); it != mFetchAttributeNames.end(); ++it)
-  {
-    if( (*it) != primaryKey) //no need to fetch primary key again
+  
+    while(!mFeatureQueue.empty())
     {
-      declare += "," + quotedIdentifier(*it) + "::text";
+      mFeatureQueue.pop();
     }
   }
 
-  declare += QString(" from %1").arg(mSchemaTableName);
+  QString whereClause;
 
-  QgsDebugMsg("Binary cursor: " + declare);
-
-  bool hasWhere = FALSE;
-
   if(!rect.isEmpty())
   {
     if(useIntersect)
     { 
       // Contributed by #qgis irc "creeping"
       // This version actually invokes PostGIS's use of spatial indexes
-      declare += " where " + quotedIdentifier(geometryColumn);
-      declare += " && setsrid('BOX3D(" + rect.asWKTCoords();
-      declare += ")'::box3d,";
-      declare += srid;
-      declare += ")";
-      declare += " and intersects(" + quotedIdentifier(geometryColumn);
-      declare += ", setsrid('BOX3D(" + rect.asWKTCoords();
-      declare += ")'::box3d,";
-      declare += srid;
-      declare += "))";
+      whereClause = QString("%1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))")
+                      .arg( quotedIdentifier(geometryColumn) )
+                      .arg( rect.asWKTCoords() )
+                      .arg( srid );
     }
     else
     {
-      declare += " where " + quotedIdentifier(geometryColumn);
-      declare += " && setsrid('BOX3D(" + rect.asWKTCoords();
-      declare += ")'::box3d,";
-      declare += srid;
-      declare += ")";
+      whereClause = QString("%1 && setsrid('BOX3D(%2)'::box3d,%3)")
+                      .arg( quotedIdentifier(geometryColumn) )
+                      .arg( rect.asWKTCoords() )
+                      .arg( srid );
     }
-    hasWhere = TRUE;
   }
 
-  if(sqlWhereClause.length() > 0)
+  if( !sqlWhereClause.isEmpty() )
   {
-    if (hasWhere)
-      declare += " and ";
-    else
-      declare += " where ";
-    declare += "(" + sqlWhereClause + ")";
-    hasWhere = TRUE;
-  }
+    if (!whereClause.isEmpty())
+      whereClause += " and ";
 
-  QgsDebugMsg("Selecting features using: " + declare);
-
-  PQexecNR(connection, declare.toUtf8());
-  
-  while(!mFeatureQueue.empty())
-  {
-    mFeatureQueue.pop();
+    whereClause += "(" + sqlWhereClause + ")";
   }
 
+  mFetchGeom = fetchGeometry;
+  mAttributesToFetch = fetchAttributes;
+  declareCursor( cursorName, fetchAttributes, fetchGeometry, whereClause, mFetchAttributeNames );
+
   mFetching = true;
   mFirstFetch = true;
 }
 
-bool QgsPostgresProvider::getFeatureAtId(int featureId,
-    QgsFeature& feature,
-    bool fetchGeometry,
-    QgsAttributeList fetchAttributes)
+bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
 {
-  std::list<QString> attributeNames;
-  QgsFieldMap fldMap = fields();
-  QgsFieldMap::const_iterator fieldIt;
-  QgsAttributeList::const_iterator it;
-  std::list<QString>::const_iterator namesIt;
+  QString cursorName = QString("qgisf%1").arg(providerId);
 
-  for (it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it)
+  if (!valid)
   {
-    fieldIt = fldMap.find(*it);
-    if(fieldIt != fldMap.end())
-    {
-      attributeNames.push_back(fieldIt.value().name());
-    }
+    QgsDebugMsg("Read attempt on an invalid postgresql data source");
+    return false;
   }
 
-  QString declare = QString("declare qgisfid%1 binary cursor with hold for select %2")
-                      .arg(providerId).arg(quotedIdentifier(primaryKey));
-
-  if(fetchGeometry)
+  // Top up our queue if it is empty
+  if (mFeatureQueue.empty())
   {
-    declare += QString(",asbinary(%1,'%2') as qgs_feature_geometry")
-                 .arg( quotedIdentifier(geometryColumn) )
-                 .arg( endianString() ); 
-  }
+    QString fetch = QString("fetch forward %1 from %2").arg(mFeatureQueueSize).arg(cursorName);
+    if(mFirstFetch)
+    {
+      if(PQsendQuery(connection, fetch.toUtf8()) == 0) //fetch features in asynchronously
+      {
+        qWarning("PQsendQuery failed (1)");
+      }
+    }
+    mFirstFetch = false;
+    queryResult = PQgetResult(connection);
+    PQgetResult(connection); //just to get the 0 pointer...  
 
-  for(namesIt = attributeNames.begin(); namesIt != attributeNames.end(); ++namesIt)
-  {
-    if( (*namesIt) != primaryKey) //no need to fetch primary key again
+    int rows = PQntuples(queryResult);
+    if (rows == 0)
     {
-      declare += "," + quotedIdentifier(*namesIt) + "::text";
+      QgsDebugMsg("End of features");
+      PQclear(queryResult);
+      return false;
     }
-  }
 
-  declare += QString(" from %1 where %2=%3")
-               .arg(mSchemaTableName)
-               .arg(quotedIdentifier(primaryKey))
-               .arg(featureId);
+    for (int row = 0; row < rows; row++)
+    {
+      mFeatureQueue.push(QgsFeature());
+      getFeature(queryResult, row, mFetchGeom, mFeatureQueue.back(), mFetchAttributeNames, mAttributesToFetch);
+    } // for each row in queue
 
-  QgsDebugMsg("Selecting feature using: " + declare);
+    PQclear(queryResult);
 
-  // execute query
-  PQexecNR(connection, declare.toUtf8());
+    if(PQsendQuery(connection, fetch.toUtf8()) == 0) //already fetch the next couple of features asynchronously
+    {
+      qWarning("PQsendQuery failed (2)");
+    }
+  } // if new queue is required
 
-  PGresult *res = PQexec(connection, QString("fetch forward 1 from qgisfid%1").arg(providerId).toUtf8());
-
-  int rows = PQntuples(res);
-  if (rows == 0)
+  // Now return the next feature from the queue
+  if(mFetchGeom)
   {
-    PQclear(res);
-    PQexecNR(connection, QString("CLOSE qgisfid%1").arg(providerId).toUtf8());
-    QgsDebugMsg("feature " + QString::number(featureId) + " not found");
-    return FALSE;
+    QgsGeometry* featureGeom = mFeatureQueue.front().geometryAndOwnership();
+    feature.setGeometry(featureGeom);
   }
+  else
+  {
+    feature.setGeometryAndOwnership(0, 0);
+  }
+  feature.setFeatureId(mFeatureQueue.front().featureId());
+  feature.setAttributeMap(mFeatureQueue.front().attributeMap());
 
-  // set ID
-  int oid = *(int *)PQgetvalue(res, 0, PQfnumber(res,quotedIdentifier(primaryKey).toUtf8()));
-  if (swapEndian)
-    oid = ntohl(oid); // convert oid to opposite endian
-  feature.setFeatureId(oid);
+  mFeatureQueue.pop();
 
-  // fetch attributes
-  it = fetchAttributes.constBegin();
+  return true;
+}
 
-  for(namesIt = attributeNames.begin(); namesIt != attributeNames.end(); ++namesIt, ++it)
-  {
-    QString val;
+bool QgsPostgresProvider::getFeatureAtId(int featureId, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes)
+{
+  QStringList attributeNames;
+  QString cursorName = QString("qgisfid%1").arg(providerId);
+  declareCursor( cursorName, fetchAttributes, fetchGeometry, QString("%2=%3").arg(quotedIdentifier(primaryKey)).arg(featureId), attributeNames );
 
-    if( (*namesIt) == primaryKey)
-    {
-      val = QString::number(oid);
-    }
-    else
-    {
-      int fn = PQfnumber(res,quotedIdentifier(*namesIt).toUtf8());
+  PGresult *queryResult = PQexec(connection, QString("fetch forward 1 from %1").arg(cursorName).toUtf8());
+  if(queryResult==0)
+    return false;
 
-      if( PQgetisnull(res, 0, fn) )
-        val = QString::fromUtf8(PQgetvalue(res, 0, fn));
-      else
-        val = QString::null;
-    }
-
-    if( val.isNull() )
-    {
-      feature.addAttribute(*it, val);
-    }
-    else
-    {
-      switch (attributeFields[*it].type())
-      {
-      case QVariant::LongLong:
-        feature.addAttribute(*it, val.toLongLong());
-        break;
-      case QVariant::Int:
-        feature.addAttribute(*it, val.toInt());
-        break;
-      case QVariant::Double:
-        feature.addAttribute(*it, val.toDouble());
-        break;
-      case QVariant::String:
-        feature.addAttribute(*it, val);
-        break;
-      default:
-        assert(0 && "unsupported field type");
-      }
-    }
+  int rows = PQntuples(queryResult);
+  if (rows == 0)
+  {
+    QgsDebugMsg("feature " + QString::number(featureId) + " not found");
+    PQclear(queryResult);
+    PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8());
+    return false;
   }
-
-  // fetch geometry
-  if (fetchGeometry)
+  else if(rows != 1)
   {
-    int returnedLength = PQgetlength(res, 0, PQfnumber(res,"qgs_feature_geometry")); 
-    if(returnedLength > 0)
-    {
-      unsigned char *featureGeom = new unsigned char[returnedLength + 1];
-      memset(featureGeom, '\0', returnedLength + 1);
-      memcpy(featureGeom, PQgetvalue(res, 0, PQfnumber(res,QString("qgs_feature_geometry").toUtf8())), returnedLength); 
-      feature.setGeometryAndOwnership(featureGeom, returnedLength + 1);
-    }
+    QgsDebugMsg( QString("found %1 features instead of just one.").arg(rows) );
   }
 
-  PQclear(res);
-  PQexecNR(connection, QString("CLOSE qgisfid%1").arg(providerId).toUtf8());
+  getFeature(queryResult, 0, fetchGeometry, feature, attributeNames, fetchAttributes);
 
-  return TRUE;
+  PQclear(queryResult);
+
+  PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8());
+  return true;
 }
 
+
 QgsDataSourceURI& QgsPostgresProvider::getURI()
 {
   return mUri;
@@ -891,16 +798,38 @@
     if(fieldName!=geometryColumn)
     {
       QVariant::Type fieldType;
-      if (fieldTypeName.find("int8") != -1)
+      bool isArray = fieldTypeName.startsWith("_");
+ 
+      if(isArray)
+        fieldTypeName = fieldTypeName.mid(1);
+
+      if (fieldTypeName == "int8" )
         fieldType = QVariant::LongLong;
-      else if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
+      else if (fieldTypeName.startsWith("int") || fieldTypeName=="serial" )
         fieldType = QVariant::Int;
-      else if (fieldTypeName == "real" || fieldTypeName == "double precision" || fieldTypeName.find("float") != -1)
+      else if (fieldTypeName == "real" || fieldTypeName == "double precision" || fieldTypeName.startsWith("float") || fieldTypeName == "numeric" )
         fieldType = QVariant::Double;
-      else if (fieldTypeName == "bytea")
-        continue;
+      else if (fieldTypeName == "text" || 
+               fieldTypeName == "char" ||
+               fieldTypeName == "bpchar" || 
+               fieldTypeName == "varchar" ||
+               fieldTypeName == "bool" ||
+               fieldTypeName == "money" ||
+               fieldTypeName.startsWith("time") ||
+               fieldTypeName.startsWith("date") )
+        fieldType = QVariant::String;
       else
+      {
+        QgsDebugMsg( "Field " + fieldName + " ignored, because of unsupported type " + fieldTypeName);
+        continue;
+      }
+
+      if(isArray)
+      {
+        fieldTypeName = "_" + fieldTypeName;
         fieldType = QVariant::String;
+      }
+        
       attributeFields.insert(i, QgsField(fieldName, fieldType, fieldTypeName, fieldSize.toInt(), fieldModifier, fieldComment));
     }
   }
@@ -1653,11 +1582,16 @@
   QString sql;
   if(sqlWhereClause.isEmpty())
   {
-    sql = QString("select min(%1) from %2").arg(quotedIdentifier(fld.name())).arg(mSchemaTableName);
+    sql = QString("select min(%1) from %2")
+            .arg(quotedIdentifier(fld.name()))
+            .arg(mSchemaTableName);
   }
   else
   {
-    sql = QString("select min(%1) from %2").arg(quotedIdentifier(fld.name())).arg(mSchemaTableName)+" where "+sqlWhereClause;
+    sql = QString("select min(%1) from %2 where %3")
+            .arg(quotedIdentifier(fld.name()))
+            .arg(mSchemaTableName)
+            .arg(sqlWhereClause);
   }
   PGresult *rmin = PQexec(connection, sql.toUtf8());
   QString minValue = QString::fromUtf8(PQgetvalue(rmin,0,0));
@@ -1705,11 +1639,16 @@
   QString sql;
   if(sqlWhereClause.isEmpty())
   {
-    sql = QString("select max(%1) from %2").arg(quotedIdentifier(fld.name())).arg(mSchemaTableName);
+    sql = QString("select max(%1) from %2")
+            .arg(quotedIdentifier(fld.name()))
+            .arg(mSchemaTableName);
   }
   else
   {
-    sql = QString("select max(%1) from %2").arg(quotedIdentifier(fld.name())).arg(mSchemaTableName)+" where "+sqlWhereClause;
+    sql = QString("select max(%1) from %2 where %3")
+            .arg(quotedIdentifier(fld.name()))
+            .arg(mSchemaTableName)
+            .arg(sqlWhereClause);
   } 
   PGresult *rmax = PQexec(connection, sql.toUtf8());
   QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
@@ -1818,7 +1757,7 @@
 
   useWkbHex = postgisVersionMajor < 1;
 
-  gotPostgisVersion = TRUE;
+  gotPostgisVersion = true;
 
   return postgisVersionInfo;
 }
@@ -1872,7 +1811,7 @@
     // e.g. for defaults
     for(QgsAttributeMap::const_iterator it = attributevec.begin(); it != attributevec.end(); it++)
     {
-      QgsFieldMap::const_iterator fit = attributeFields.find( it.key() );     
+      QgsFieldMap::const_iterator fit = attributeFields.find( it.key() );
       if (fit == attributeFields.end() )
         continue;
 
@@ -1897,7 +1836,7 @@
       }
 
       insert += "," + quotedIdentifier(fieldname);
-
+      
       QString defVal = getDefaultValue( it.key() ).toString();
 
       if( i==flist.size() )
@@ -2685,8 +2624,7 @@
   }
 }
 
-void QgsPostgresProvider::showMessageBox(const QString& title, 
-    const QString& text)
+void QgsPostgresProvider::showMessageBox(const QString& title, const QString& text)
 {
   QgsMessageOutput* message = QgsMessageOutput::createMessageOutput();
   message->setTitle(title);

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2008-03-26 21:07:02 UTC (rev 8284)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2008-03-27 00:44:22 UTC (rev 8285)
@@ -110,6 +110,16 @@
                                 bool fetchGeometry = true,
                                 QgsAttributeList fetchAttributes = QgsAttributeList());
 
+    void declareCursor(const QString &cursorName,
+                       const QgsAttributeList &fetchAttributes,
+                       bool fetchGeometry,
+                       QString whereClause,
+                       QStringList &attributeNames);
+
+    void getFeature(PGresult *queryResult, int row, bool fetchGeometry,
+                    QgsFeature &feature,
+                    const QStringList &attributeNames,
+                    const QgsAttributeList &fetchAttributes);
     
     /** Get the feature type. This corresponds to
      * WKBPoint,
@@ -444,7 +454,7 @@
     bool swapEndian;
 
     /**Stores the names of the attributes to fetch*/
-    std::list<QString> mFetchAttributeNames;
+    QStringList mFetchAttributeNames;
 
     bool deduceEndian();
     bool getGeometryDetails();



More information about the QGIS-commit mailing list