[QGIS Commit] r9120 - trunk/qgis/src/providers/postgres
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Fri Aug 22 06:32:29 EDT 2008
Author: jef
Date: 2008-08-22 06:32:29 -0400 (Fri, 22 Aug 2008)
New Revision: 9120
Modified:
trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
Log:
fix #1237
Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp 2008-08-22 08:03:21 UTC (rev 9119)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp 2008-08-22 10:32:29 UTC (rev 9120)
@@ -103,7 +103,7 @@
showMessageBox(tr("No GEOS Support!"),
tr("Your PostGIS installation has no GEOS support.\n"
"Feature selection and identification will not "
- "work properly.\nPlease install PostGIS with "
+ "work properly.\nPlease install PostGIS with "
"GEOS support (http://geos.refractions.net)"));
}
@@ -116,9 +116,9 @@
if (PQresultStatus(testAccess) != PGRES_TUPLES_OK)
{
showMessageBox(tr("Unable to access relation"),
- tr("Unable to access the ") + mSchemaTableName +
+ tr("Unable to access the ") + mSchemaTableName +
tr(" relation.\nThe error message from the database was:\n") +
- QString::fromUtf8(PQresultErrorMessage(testAccess)) + ".\n" +
+ QString::fromUtf8(PQresultErrorMessage(testAccess)) + ".\n" +
"SQL: " + sql);
PQclear(testAccess);
valid = false;
@@ -137,9 +137,9 @@
testAccess = PQexec( connectionRO, sql.toUtf8() );
if( PQresultStatus(testAccess) != PGRES_TUPLES_OK ) {
showMessageBox(tr("Unable to access relation"),
- tr("Unable to determine table access privileges for the ") + mSchemaTableName +
+ tr("Unable to determine table access privileges for the ") + mSchemaTableName +
tr(" relation.\nThe error message from the database was:\n") +
- QString::fromUtf8(PQresultErrorMessage(testAccess)) + ".\n" +
+ QString::fromUtf8(PQresultErrorMessage(testAccess)) + ".\n" +
"SQL: " + sql);
PQclear(testAccess);
valid = false;
@@ -148,12 +148,12 @@
}
enabledCapabilities = QgsVectorDataProvider::SelectGeometryAtId;
-
+
if( QString::fromUtf8( PQgetvalue(testAccess, 0, 0) )=="t" ) {
// DELETE
enabledCapabilities |= QgsVectorDataProvider::DeleteFeatures;
}
-
+
if( QString::fromUtf8( PQgetvalue(testAccess, 0, 1) )=="t" ) {
// UPDATE
enabledCapabilities |= QgsVectorDataProvider::ChangeGeometries | QgsVectorDataProvider::ChangeAttributeValues;
@@ -295,9 +295,9 @@
QgsDebugMsg(QString("New postgres connection for ") + conninfo);
- PGconn *pd = PQconnectdb(conninfo.toLocal8Bit()); // use what is set based on locale; after connecting, use Utf8
+ PGconn *pd = PQconnectdb(conninfo.toLocal8Bit()); // use what is set based on locale; after connecting, use Utf8
// check the connection status
- if (PQstatus(pd) != CONNECTION_OK)
+ if (PQstatus(pd) != CONNECTION_OK)
{
QgsDebugMsg("Connection to database failed");
return NULL;
@@ -308,30 +308,36 @@
int errcode=PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
- if(errcode==0)
+ if(errcode==0)
{
QgsDebugMsg("encoding successfully set");
- }
- else if(errcode==-1)
+ }
+ else if(errcode==-1)
{
QgsDebugMsg("error in setting encoding");
- }
- else
+ }
+ else
{
QgsDebugMsg("undefined return value from encoding setting");
}
QgsDebugMsg("Connection to the database was successful");
-
+
Conn *conn = new Conn(pd);
connections.insert( conninfo, conn );
+ if(readonly)
+ {
+ QgsDebugMsg("Starting transaction for cursors");
+ PQexecNR( pd, QString("BEGIN").toUtf8() );
+ }
+
return pd;
}
void QgsPostgresProvider::disconnectDb()
{
- if(mFetching)
+ if(mFetching)
{
PQexecNR(connectionRO, QString("CLOSE qgisf%1").arg(providerId).toUtf8() );
mFetching=false;
@@ -390,7 +396,7 @@
{
declare += QString(",asbinary(%1,'%2')")
.arg( quotedIdentifier(geometryColumn) )
- .arg( endianString() );
+ .arg( endianString() );
}
for (QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it)
@@ -438,7 +444,7 @@
bool QgsPostgresProvider::getFeature(PGresult *queryResult, int row, bool fetchGeometry,
QgsFeature &feature,
const QgsAttributeList &fetchAttributes)
-{
+{
try
{
int oid = *(int *)PQgetvalue(queryResult, row, 0);
@@ -451,12 +457,12 @@
if (fetchGeometry)
{
- int returnedLength = PQgetlength(queryResult, row, 1);
+ int returnedLength = PQgetlength(queryResult, row, 1);
if(returnedLength > 0)
{
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
memset(featureGeom, '\0', returnedLength + 1);
- memcpy(featureGeom, PQgetvalue(queryResult, row, 1), returnedLength);
+ memcpy(featureGeom, PQgetvalue(queryResult, row, 1), returnedLength);
feature.setGeometryAndOwnership(featureGeom, returnedLength + 1);
}
else
@@ -530,12 +536,12 @@
void QgsPostgresProvider::select(QgsAttributeList fetchAttributes, QgsRect rect, bool fetchGeometry, bool useIntersect)
{
QString cursorName = QString("qgisf%1").arg(providerId);
-
- if(mFetching)
+
+ if(mFetching)
{
PQexecNR(connectionRO, QString("CLOSE %1").arg(cursorName).toUtf8() );
mFetching=false;
-
+
while(!mFeatureQueue.empty())
{
mFeatureQueue.pop();
@@ -547,7 +553,7 @@
if(!rect.isEmpty())
{
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))")
@@ -576,7 +582,7 @@
mAttributesToFetch = fetchAttributes;
if( !declareCursor( cursorName, fetchAttributes, fetchGeometry, whereClause ) )
return;
-
+
mFetching = true;
}
@@ -620,7 +626,7 @@
QgsDebugMsg("End of features");
return false;
}
-
+
// Now return the next feature from the queue
if(mFetchGeom)
{
@@ -691,7 +697,7 @@
return layerExtent; //extent_->MinX, extent_->MinY, extent_->MaxX, extent_->MaxY);
}
-/**
+/**
* Return the feature type
*/
QGis::WKBTYPE QgsPostgresProvider::geometryType() const
@@ -699,7 +705,7 @@
return geomType;
}
-/**
+/**
* Return the feature type
*/
long QgsPostgresProvider::featureCount() const
@@ -753,10 +759,10 @@
{
switch ( QgsApplication::endian() )
{
- case QgsApplication::NDR :
+ case QgsApplication::NDR:
return QString("NDR");
break;
- case QgsApplication::XDR :
+ case QgsApplication::XDR:
return QString("XDR");
break;
default :
@@ -802,7 +808,7 @@
sql = QString("SELECT typname,typlen FROM pg_type WHERE oid=%1").arg(typOid);
// just oid; needs more work to support array type
- // "oid = (SELECT Distinct typelem FROM pg_type WHERE " //needs DISTINCT to guard against 2 or more rows on int2
+ // "oid = (SELECT Distinct typelem FROM pg_type WHERE " //needs DISTINCT to guard against 2 or more rows on int2
// "typelem = " + typOid + " AND typlen = -1)";
PGresult* oidResult = PQexec(connectionRO, sql.toUtf8());
@@ -812,7 +818,7 @@
sql = QString("SELECT attnum FROM pg_attribute WHERE attrelid=%1 AND attname=%2")
.arg( tableoid ).arg( quotedValue(fieldName) );
-
+
PGresult *tresult = PQexec(connectionRO, sql.toUtf8());
QString attnum = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
PQclear(tresult);
@@ -829,7 +835,7 @@
{
QVariant::Type fieldType;
bool isArray = fieldTypeName.startsWith("_");
-
+
if(isArray)
fieldTypeName = fieldTypeName.mid(1);
@@ -839,9 +845,9 @@
fieldType = QVariant::Int;
else if (fieldTypeName == "real" || fieldTypeName == "double precision" || fieldTypeName.startsWith("float") || fieldTypeName == "numeric" )
fieldType = QVariant::Double;
- else if (fieldTypeName == "text" ||
+ else if (fieldTypeName == "text" ||
fieldTypeName == "char" ||
- fieldTypeName == "bpchar" ||
+ fieldTypeName == "bpchar" ||
fieldTypeName == "varchar" ||
fieldTypeName == "bool" ||
fieldTypeName == "money" ||
@@ -859,7 +865,7 @@
fieldTypeName = "_" + fieldTypeName;
fieldType = QVariant::String;
}
-
+
attributeFields.insert(i, QgsField(fieldName, fieldType, fieldTypeName, fieldSize.toInt(), fieldModifier, fieldComment));
}
}
@@ -966,7 +972,7 @@
QString columnType = QString::fromUtf8(PQgetvalue(types, 0, 1));
if (columnType != "int4")
- log.append(tr("The unique index on column") +
+ log.append(tr("The unique index on column") +
" '" + columnName + "' " +
tr("is unsuitable because Qgis does not currently support"
" non-int4 type columns as a key into the table.\n"));
@@ -998,7 +1004,7 @@
colNames+= ",";
}
- log.append(tr("The unique index based on columns ") + colNames +
+ log.append(tr("The unique index based on columns ") + colNames +
tr(" is unsuitable because Qgis does not currently support"
" multiple columns as a key into the table.\n"));
}
@@ -1105,7 +1111,7 @@
}
PQclear(result);
- // This sql returns one or more rows if the column 'tableCol' in
+ // This sql returns one or more rows if the column 'tableCol' in
// table 'tableName' and schema 'schemaName' has one or more
// columns that satisfy the following conditions:
// 1) the column has data type of int4.
@@ -1122,7 +1128,7 @@
if (PQntuples(result) == 1 && colType == "int4")
suitable[viewCol] = iter->second;
- QString details = "'" + viewCol + "'" + tr(" derives from ")
+ QString details = "'" + viewCol + "'" + tr(" derives from ")
+ "'" + schemaName + "." + tableName + "." + tableCol + "' ";
if (PQntuples(result) == 1 && colType == "int4")
@@ -1165,7 +1171,7 @@
//
// If there is more than one suitable column pick one that is
// indexed, else pick one called 'oid' if it exists, else
- // pick the first one. If there are none we return an empty string.
+ // pick the first one. If there are none we return an empty string.
// Search for one with an index
tableCols::const_iterator i = suitable.begin();
@@ -1193,7 +1199,7 @@
{
// If none have indices, choose one that is called 'oid' (if it
// exists). This is legacy support and could be removed in
- // future.
+ // future.
i = suitable.find("oid");
if (i != suitable.end() && uniqueData(mSchemaName, mTableName, i->first))
{
@@ -1251,14 +1257,14 @@
return key;
}
-bool QgsPostgresProvider::uniqueData(QString schemaName,
+bool QgsPostgresProvider::uniqueData(QString schemaName,
QString tableName, QString colName)
{
// Check to see if the given column contains unique data
bool isUnique = false;
- QString sql = QString("select count(distinct %1)=count(%1) from %2.%3")
+ QString sql = QString("select count(distinct %1)=count(%1) from %2.%3")
.arg( quotedIdentifier(colName) )
.arg( quotedIdentifier(schemaName) )
.arg( quotedIdentifier(tableName) );
@@ -1390,7 +1396,7 @@
.arg( quotedValue(relname ) )
.arg( quotedValue(ns) )
.arg( quotedValue(attname_table) );
-
+
PGresult* typeSqlResult = PQexec(connectionRO, typeSql.toUtf8());
if(PQntuples(typeSqlResult) < 1)
{
@@ -1406,7 +1412,7 @@
return 0;
}
-// This function will return in the cols variable the
+// This function will return in the cols variable the
// underlying view and columns for each column in
// mSchemaName.mTableName.
@@ -1525,7 +1531,7 @@
{
try
{
- // get the field name
+ // get the field name
const QgsField &fld = field(index);
QString sql;
if(sqlWhereClause.isEmpty())
@@ -1559,7 +1565,7 @@
try
{
- // get the field name
+ // get the field name
const QgsField &fld = field(index);
QString sql;
if(sqlWhereClause.isEmpty())
@@ -1585,7 +1591,7 @@
PQclear(res);
}
catch(PGFieldNotFound)
- {
+ {
}
}
@@ -1595,7 +1601,7 @@
{
try
{
- // get the field name
+ // get the field name
const QgsField &fld = field(index);
QString sql;
if(sqlWhereClause.isEmpty())
@@ -1610,7 +1616,7 @@
.arg(quotedIdentifier(fld.name()))
.arg(mSchemaTableName)
.arg(sqlWhereClause);
- }
+ }
PGresult *rmax = PQexec(connectionRO, sql.toUtf8());
QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
PQclear(rmax);
@@ -1716,7 +1722,7 @@
// parse out the capabilities and store them
QStringList geos = postgisParts.filter("GEOS");
if(geos.size() == 1) {
- geosAvailable = (geos[0].indexOf("=1") > -1);
+ geosAvailable = (geos[0].indexOf("=1") > -1);
}
QStringList gist = postgisParts.filter("STATS");
if(gist.size() == 1) {
@@ -1824,11 +1830,11 @@
values += "," + defVal;
}
}
- else
- {
+ else
+ {
values += "," + quotedValue( it->toString() );
}
- }
+ }
else
{
// value is not unique => add parameter
@@ -1920,7 +1926,7 @@
throw PGException(result);
PQclear(result);
}
-
+
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
} catch(PGException &e) {
e.showErrorMessage( tr("Error while deleting features") );
@@ -1982,7 +1988,7 @@
QgsFieldMap::const_iterator field_it = attributeFields.find(*iter);
if(field_it == attributeFields.constEnd())
continue;
-
+
QString column = field_it->name();
QString sql = QString("ALTER TABLE %1 DROP COLUMN %2")
.arg(mSchemaTableName)
@@ -2023,7 +2029,7 @@
for(QgsChangedAttributesMap::const_iterator iter=attr_map.begin();iter!=attr_map.end();++iter)
{
int fid = iter.key();
-
+
// skip added features
if(fid<0)
continue;
@@ -2057,11 +2063,11 @@
sql += QString(" WHERE %1=%2")
.arg( quotedIdentifier(primaryKey) )
.arg( fid );
-
+
PGresult* result=PQexec(connectionRW, sql.toUtf8());
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
throw PGException(result);
-
+
PQclear(result);
}
@@ -2202,7 +2208,7 @@
#ifdef POSTGRESQL_THREADS
QString sql = QString("select reltuples from pg_catalog.pg_class where relname=%1").arg( quotedValue(tableName) );
QgsDebugMsg("Running SQL: " + sql);
-#else
+#else
QString sql = QString("select count(*) from %1").arg( mSchemaTableName );
if(sqlWhereClause.length() > 0)
@@ -2248,7 +2254,7 @@
"xmax(extent(%1)) as xmax,"
"xmin(extent(%1)) as xmin,"
"ymax(extent(%1)) as ymax,"
- "ymin(extent(%1)) as ymin"
+ "ymin(extent(%1)) as ymin"
" from %2").arg( quotedIdentifier(geometryColumn).arg( mSchemaTableName );
#endif
@@ -2299,8 +2305,8 @@
sql = QString("select "
"xmax(extent(%1)) as xmax,"
"xmin(extent(%1)) as xmin,"
- "ymax(extent(%1)) as ymax,"
- "ymin(extent(%1)) as ymin"
+ "ymax(extent(%1)) as ymax,"
+ "ymin(extent(%1)) as ymin"
" from %2").arg( quotedIdentifier(geometryColumn) ).arg( mSchemaTableName );
#endif
@@ -2487,7 +2493,7 @@
else
{
// Didn't find what we need in the geometry_columns table, so
- // get stuff from the relevant column instead. This may (will?)
+ // get stuff from the relevant column instead. This may (will?)
// fail if there is no data in the relevant table.
PQclear(result); // for the query just before the if() statement
sql = QString("select srid(%1),geometrytype(%1) from %2" )
@@ -2562,7 +2568,7 @@
}
else
{
- showMessageBox(tr("Unknown geometry type"),
+ showMessageBox(tr("Unknown geometry type"),
tr("Column ") + geometryColumn + tr(" in ") +
mSchemaTableName + tr(" has a geometry type of ") +
fType + tr(", which Qgis does not currently support."));
@@ -2573,7 +2579,7 @@
{
log.prepend(tr("Qgis was unable to determine the type and srid of "
"column ") + geometryColumn + tr(" in ") +
- mSchemaTableName +
+ mSchemaTableName +
tr(". The database communication log was:\n"));
showMessageBox(tr("Unable to get feature type and srid"), log);
}
@@ -2593,7 +2599,7 @@
return valid;
}
-PGresult* QgsPostgresProvider::executeDbCommand(PGconn* connection,
+PGresult* QgsPostgresProvider::executeDbCommand(PGconn* connection,
const QString& sql)
{
PGresult *result = PQexec(connection, sql.toUtf8());
@@ -2618,7 +2624,7 @@
{
if( value.isNull() )
return "NULL";
-
+
// FIXME: use PQescapeStringConn
value.replace("'", "''");
return value.prepend("'").append("'");
@@ -2631,7 +2637,7 @@
#ifdef QGISDEBUG
if(res) {
int errorStatus = PQresultStatus(res);
- if( errorStatus!=PGRES_COMMAND_OK && errorStatus!=PGRES_TUPLES_OK )
+ if( errorStatus!=PGRES_COMMAND_OK && errorStatus!=PGRES_TUPLES_OK )
{
QString err = QString("Errornous query: %1 returned %2 [%3]")
.arg(query)
@@ -2652,7 +2658,7 @@
{
int errorStatus = PQresultStatus(res);
#ifdef QGISDEBUG
- if( errorStatus!=PGRES_COMMAND_OK )
+ if( errorStatus!=PGRES_COMMAND_OK )
{
QString err = QString("Query: %1 returned %2 [%3]")
.arg(query)
@@ -2679,7 +2685,7 @@
message->showMessage();
}
-void QgsPostgresProvider::showMessageBox(const QString& title,
+void QgsPostgresProvider::showMessageBox(const QString& title,
const QStringList& text)
{
showMessageBox(title, text.join("\n"));
@@ -2700,6 +2706,7 @@
PGconn * QgsPostgresProvider::pgConnection()
{
+ connectRW();
return connectionRW;
}
@@ -2732,7 +2739,7 @@
/**
- * Class factory to return a pointer to a newly created
+ * Class factory to return a pointer to a newly created
* QgsPostgresProvider object
*/
QGISEXTERN QgsPostgresProvider * classFactory(const QString *uri)
@@ -2746,12 +2753,12 @@
return POSTGRES_KEY;
}
/**
- * Required description function
+ * Required description function
*/
QGISEXTERN QString description()
{
return POSTGRES_DESCRIPTION;
-}
+}
/**
* Required isProvider function. Used to determine if this shared library
* is a data provider plugin
More information about the QGIS-commit
mailing list