Index: src/app/qgspgquerybuilder.cpp
===================================================================
--- src/app/qgspgquerybuilder.cpp (revision 8182)
+++ src/app/qgspgquerybuilder.cpp (working copy)
@@ -40,7 +40,7 @@
QgsDebugMsg("Attempting connect using: " + connInfo);
- mPgConnection = PQconnectdb(connInfo.toLocal8Bit().data());
+ mPgConnection = PQconnectdb(connInfo.toLocal8Bit().data()); // use what is set based on locale; after connecting, use Utf8
// check the connection status
if (PQstatus(mPgConnection) == CONNECTION_OK) {
QString datasource = QString(tr("Table %1 in database %2 on host %3, user %4"))
@@ -57,7 +57,7 @@
}
else
{
- QString err = PQerrorMessage(mPgConnection);
+ QString err = QString::fromLocal8Bit(PQerrorMessage(mPgConnection));
QMessageBox::critical(this, tr("Connection Failed"), tr("Connection to the database failed:") + "\n" + err);
}
}
@@ -96,22 +96,21 @@
// Populate the field vector for this layer. The field vector contains
// field name, type, length, and precision (if numeric)
QString sql = "select * from " + mUri->quotedTablename() + " limit 1";
- PGresult *result = PQexec(mPgConnection, (const char *) (sql.utf8()));
+ PGresult *result = PQexec(mPgConnection, sql.toUtf8());
QgsLogger::debug("Query executed: " + sql);
if (PQresultStatus(result) == PGRES_TUPLES_OK)
{
//--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
for (int i = 0; i < PQnfields(result); i++) {
- QString fieldName = PQfname(result, i);
+ QString fieldName = QString::fromUtf8(PQfname(result, i));
int fldtyp = PQftype(result, i);
QString typOid = QString().setNum(fldtyp);
QgsLogger::debug("typOid is: " + typOid);
//int fieldModifier = PQfmod(result, i);
QString sql = "select typelem from pg_type where typelem = " + typOid + " and typlen = -1";
// //--std::cout << sql << std::endl;
- PGresult *oidResult = PQexec(mPgConnection,
- (const char *) (sql.utf8()));
+ PGresult *oidResult = PQexec(mPgConnection, sql.toUtf8());
if (PQresultStatus(oidResult) == PGRES_TUPLES_OK)
QgsLogger::debug("Ok fetching typelem using\n" + sql);
@@ -123,7 +122,7 @@
PQclear(oidResult);
sql = "select typname, typlen from pg_type where oid = " + poid;
// //--std::cout << sql << std::endl;
- oidResult = PQexec(mPgConnection, (const char *) (sql.utf8()));
+ oidResult = PQexec(mPgConnection, sql.toUtf8());
if (PQresultStatus(oidResult) == PGRES_TUPLES_OK)
QgsLogger::debug("Ok fetching typenam,etc\n");
@@ -180,9 +179,9 @@
// determine the field type
QgsField field = mFieldMap[mModelFields->data(lstFields->currentIndex()).toString()];
- bool mActualFieldIsChar = field.typeName().find("char") > -1;
+ mActualFieldIsChar = field.typeName().find("char") > -1 || field.typeName().find("text") > -1 ; // really should be: field.type()==QVariant::String - but is not set correctly above
- PGresult *result = PQexec(mPgConnection, (const char *) (theSQL.utf8()));
+ PGresult *result = PQexec(mPgConnection, theSQL.toUtf8());
if (PQresultStatus(result) == PGRES_TUPLES_OK)
{
@@ -196,7 +195,7 @@
}
}else
{
- QMessageBox::warning(this, tr("Database error"), tr("
Failed to get sample of field values using SQL:
") + theSQL + "
Error message was: "+ QString(PQerrorMessage(mPgConnection)) + "
");
+ QMessageBox::warning(this, tr("Database error"), tr("Failed to get sample of field values using SQL:
") + theSQL + "
Error message was: "+ QString::fromUtf8(PQerrorMessage(mPgConnection)) + "
");
}
// free the result set
PQclear(result);
@@ -210,7 +209,6 @@
return;
QgsField field = mFieldMap[mModelFields->data(lstFields->currentIndex()).toString()];
- bool mActualFieldIsChar = field.typeName().find("char") > -1;
QString sql = "SELECT DISTINCT \"" + myFieldName + "\" " +
"FROM (SELECT \"" + myFieldName + "\" " +
@@ -268,7 +266,7 @@
QString numRows;
QString sql = "select count(*) from " + mUri->quotedTablename()
+ " where " + txtSQL->text();
- PGresult *result = PQexec(mPgConnection, (const char *)(sql.utf8()));
+ PGresult *result = PQexec(mPgConnection, sql.toUtf8());
if (PQresultStatus(result) == PGRES_TUPLES_OK)
{
numRows = QString::fromUtf8(PQgetvalue(result, 0, 0));
@@ -280,7 +278,7 @@
{
QMessageBox::warning(this, tr("Query Failed"),
tr("An error occurred when executing the query:")
- + "\n" + QString(PQresultErrorMessage(result)));
+ + "\n" + QString::fromUtf8(PQresultErrorMessage(result)));
}
// free the result set
PQclear(result);
@@ -294,7 +292,7 @@
QString sql = "select count(*) from " + mUri->quotedTablename() + " where " + where;
long numRows;
- PGresult *result = PQexec(mPgConnection, (const char *)(sql.utf8()));
+ PGresult *result = PQexec(mPgConnection, sql.toUtf8());
if (PQresultStatus(result) == PGRES_TUPLES_OK)
{
QString rowCount = QString::fromUtf8(PQgetvalue(result, 0, 0));
@@ -303,7 +301,7 @@
else
{
numRows = -1;
- mPgErrorMessage = PQresultErrorMessage(result);
+ mPgErrorMessage = QString::fromUtf8(PQresultErrorMessage(result));
}
// free the result set
Index: src/app/qgsnewconnection.cpp
===================================================================
--- src/app/qgsnewconnection.cpp (revision 8182)
+++ src/app/qgsnewconnection.cpp (working copy)
@@ -130,7 +130,14 @@
settings.writeEntry(baseKey + "/database", txtDatabase->text());
settings.writeEntry(baseKey + "/port", txtPort->text());
settings.writeEntry(baseKey + "/username", txtUsername->text());
- settings.writeEntry(baseKey + "/password", txtPassword->text());
+ if (chkStorePassword->isChecked())
+ {
+ settings.writeEntry(baseKey + "/password", txtPassword->text());
+ }
+ else
+ {
+ settings.writeEntry(baseKey + "/password", "");
+ }
settings.writeEntry(baseKey + "/publicOnly", cb_publicSchemaOnly->isChecked());
settings.writeEntry(baseKey + "/geometryColumnsOnly", cb_geometryColumnsOnly->isChecked());
if (chkStorePassword->isChecked())
Index: src/app/qgsdbsourceselect.cpp
===================================================================
--- src/app/qgsdbsourceselect.cpp (revision 8182)
+++ src/app/qgsdbsourceselect.cpp (working copy)
@@ -181,7 +181,7 @@
" when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
" when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
" end "
- "from \"%2\".\"%3\"").arg(column).arg(schema).arg(table);
+ "from \"%2\".\"%3\"").arg("\""+column+"\"").arg(schema).arg(table);
}
QgsDbSourceSelect::~QgsDbSourceSelect()
@@ -361,11 +361,11 @@
QString username = settings.readEntry(key + "/username");
QString password = settings.readEntry(key + "/password");
- if (password == QString::null)
+ if ( password.isEmpty() )
{
// get password from user
makeConnection = false;
- QString password = QInputDialog::getText(tr("Password for ") + username,
+ password = QInputDialog::getText(tr("Password for ") + username,
tr("Please enter your password:"),
QLineEdit::Password, QString::null, &makeConnection, this);
// allow null password entry in case its valid for the database
@@ -393,13 +393,13 @@
if (pd != 0)
PQfinish(pd);
- pd = PQconnectdb(m_connInfo.toLocal8Bit().data());
+ pd = PQconnectdb(m_connInfo.toLocal8Bit()); // use what is set based on locale; after connecting, use Utf8
// std::cout << pd->ErrorMessage();
if (PQstatus(pd) == CONNECTION_OK)
{
//qDebug("Connection succeeded");
// tell the DB that we want text encoded in UTF8
- PQsetClientEncoding(pd, "UNICODE");
+ PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
// get the list of suitable tables and columns and populate the UI
geomCol details;
@@ -434,7 +434,7 @@
QMessageBox::warning(this, tr("Connection failed"),
tr
("Connection to %1 on %2 failed. Either the database is down or your settings are incorrect.%3Check your username and password and try again.%4The database said:%5%6").
- arg(settings.readEntry(key + "/database")).arg(settings.readEntry(key + "/host")).arg("\n\n").arg("\n\n").arg("\n").arg(PQerrorMessage(pd)));
+ arg(settings.readEntry(key + "/database")).arg(settings.readEntry(key + "/host")).arg("\n\n").arg("\n\n").arg("\n").arg(QString::fromLocal8Bit(PQerrorMessage(pd))));
}
}
@@ -526,43 +526,33 @@
bool ok = false;
QApplication::setOverrideCursor(Qt::waitCursor);
- QString sql = "select * from geometry_columns";
- sql += " order by f_table_schema,f_table_name";
+ // 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 * 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_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')" // user has select privilege
+ "order by f_table_schema,f_table_name";
- PGresult *result = PQexec(pg, sql.toLocal8Bit().data());
+ PGresult *result = PQexec(pg, sql.toUtf8());
if (result)
{
for (int idx = 0; idx < PQntuples(result); idx++)
{
- // Be a bit paranoid and check that the table actually
- // exists. This is not done as a subquery in the query above
- // because I can't get it to work correctly when there are tables
- // with capital letters in the name.
+ QString tableName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("f_table_name").toUtf8())));
+ QString schemaName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("f_table_schema").toUtf8())));
- // Take care to deal with tables with the same name but in different schema.
- QString tableName = PQgetvalue(result, idx, PQfnumber(result, "f_table_name"));
- QString schemaName = PQgetvalue(result, idx, PQfnumber(result, "f_table_schema"));
- sql = "select oid from pg_class where relname = '" + tableName + "'";
- if (schemaName.length() > 0)
- sql +=" and relnamespace = (select oid from pg_namespace where nspname = '" +
- schemaName + "')";
+ QString column = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("f_geometry_column").toUtf8())));
+ QString type = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("type").toUtf8())));
- PGresult* exists = PQexec(pg, sql.toLocal8Bit().data());
- if (PQntuples(exists) == 1)
+ QString as = "";
+ if(type=="GEOMETRY" && !searchGeometryColumnsOnly)
{
- QString column = PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column"));
- QString type = PQgetvalue(result, idx, PQfnumber(result, "type"));
-
- QString as = "";
- if(type=="GEOMETRY" && !searchGeometryColumnsOnly)
- {
- addSearchGeometryColumn(schemaName, tableName, column);
- as=type="WAITING";
- }
-
- mTableModel.addTableEntry(type, schemaName, tableName, column, "");
+ addSearchGeometryColumn(schemaName, tableName, column);
+ as=type="WAITING";
}
- PQclear(exists);
+
+ mTableModel.addTableEntry(type, schemaName, tableName, column, "");
}
ok = true;
}
@@ -581,20 +571,21 @@
// 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_type, pg_namespace where pg_type.typname = 'geometry' and "
- "pg_attribute.atttypid = pg_type.oid and pg_attribute.attrelid = pg_class.oid ";
-
+ 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.atttypid = regtype('geometry') "
+ "and pg_attribute.attrelid = pg_class.oid "
+ "and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select') ";
+ // user has select privilege
if (searchPublicOnly)
sql += "and pg_namespace.nspname = 'public' ";
- sql += "and cast(pg_class.relname as character varying) not in "
- "(select f_table_name from geometry_columns) "
- "and pg_namespace.oid = pg_class.relnamespace "
+ sql += "and pg_namespace.nspname||'.'||pg_class.relname not in " // needs to be table and schema
+ "(select f_table_schema||'.'||f_table_name from geometry_columns) "
"and pg_class.relkind in ('v', 'r')"; // only from views and relations (tables)
- result = PQexec(pg, sql.toLocal8Bit().data());
+ result = PQexec(pg, sql.toUtf8());
for (int i = 0; i < PQntuples(result); i++)
{
@@ -605,10 +596,10 @@
// Make the assumption that the geometry type for the first
// row is the same as for all other rows.
- QString table = PQgetvalue(result, i, 0); // relname
- QString schema = PQgetvalue(result, i, 1); // nspname
- QString column = PQgetvalue(result, i, 2); // attname
- QString relkind = PQgetvalue(result, i, 3); // relation kind
+ QString table = QString::fromUtf8(PQgetvalue(result, i, 0)); // relname
+ QString schema = QString::fromUtf8(PQgetvalue(result, i, 1)); // nspname
+ QString column = QString::fromUtf8(PQgetvalue(result, i, 2)); // attname
+ QString relkind = QString::fromUtf8(PQgetvalue(result, i, 3)); // relation kind
addSearchGeometryColumn(schema, table, column);
//details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
@@ -620,6 +611,7 @@
return ok;
}
+#if 0 // this function is never called - smizuno
bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg,
geomCol& details, bool searchGeometryColumnsOnly,
bool searchPublicOnly)
@@ -632,7 +624,7 @@
// where f_table_schema ='" + settings.readEntry(key + "/database") + "'";
sql += " order by f_table_schema,f_table_name";
//qDebug("Fetching tables using: " + sql);
- PGresult *result = PQexec(pg, sql.toLocal8Bit().data());
+ PGresult *result = PQexec(pg, sql.toUtf8());
if (result)
{
QString msg;
@@ -646,18 +638,18 @@
// with capital letters in the name.
// Take care to deal with tables with the same name but in different schema.
- QString tableName = PQgetvalue(result, idx, PQfnumber(result, "f_table_name"));
- QString schemaName = PQgetvalue(result, idx, PQfnumber(result, "f_table_schema"));
+ QString tableName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "f_table_name")));
+ QString schemaName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "f_table_schema")));
sql = "select oid from pg_class where relname = '" + tableName + "'";
if (schemaName.length() > 0)
sql +=" and relnamespace = (select oid from pg_namespace where nspname = '" +
schemaName + "')";
- PGresult* exists = PQexec(pg, sql.toLocal8Bit().data());
+ PGresult* exists = PQexec(pg, sql.toUtf8());
if (PQntuples(exists) == 1)
{
- QString column = PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column"));
- QString type = PQgetvalue(result, idx, PQfnumber(result, "type"));
+ QString column = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column")));
+ QString type = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "type")));
QString as = "";
if(type=="GEOMETRY" && !searchGeometryColumnsOnly) {
@@ -695,7 +687,7 @@
"and pg_namespace.oid = pg_class.relnamespace "
"and pg_class.relkind in ('v', 'r')"; // only from views and relations (tables)
- result = PQexec(pg, sql.toLocal8Bit().data());
+ result = PQexec(pg, sql.toUtf8());
for (int i = 0; i < PQntuples(result); i++)
{
@@ -706,10 +698,10 @@
// Make the assumption that the geometry type for the first
// row is the same as for all other rows.
- QString table = PQgetvalue(result, i, 0); // relname
- QString schema = PQgetvalue(result, i, 1); // nspname
- QString column = PQgetvalue(result, i, 2); // attname
- QString relkind = PQgetvalue(result, i, 3); // relation kind
+ QString table = QString::fromUtf8(PQgetvalue(result, i, 0)); // relname
+ QString schema = QString::fromUtf8(PQgetvalue(result, i, 1)); // nspname
+ QString column = QString::fromUtf8(PQgetvalue(result, i, 2)); // attname
+ QString relkind = QString::fromUtf8(PQgetvalue(result, i, 3)); // relation kind
addSearchGeometryColumn(schema, table, column);
details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
@@ -720,6 +712,7 @@
return ok;
}
+#endif
void QgsDbSourceSelect::showHelp()
{
@@ -800,23 +793,23 @@
{
mStopped=false;
- PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit().data());
+ PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit());
if (PQstatus(pd) == CONNECTION_OK)
{
- PQsetClientEncoding(pd, "UNICODE");
+ PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
for (uint i = 0; i connections;
Index: src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- src/providers/postgres/qgspostgresprovider.cpp (revision 8182)
+++ src/providers/postgres/qgspostgresprovider.cpp (working copy)
@@ -103,7 +103,7 @@
//pLog.open((const char *)logFile);
//QgsDebugMsg("Opened log file for " + mTableName);
- connection = connectDb( (const char *)mUri.connInfo() );
+ connection = connectDb( mUri.connInfo() );
if( connection==NULL ) {
valid = false;
return;
@@ -114,13 +114,13 @@
// Check that we can read from the table (i.e., we have
// select permission).
QString sql = "select * from " + mSchemaTableName + " limit 1";
- PGresult* testAccess = PQexec(connection, (const char*)(sql.utf8()));
+ PGresult* testAccess = PQexec(connection, sql.toUtf8());
if (PQresultStatus(testAccess) != PGRES_TUPLES_OK)
{
showMessageBox(tr("Unable to access relation"),
tr("Unable to access the ") + mSchemaTableName +
tr(" relation.\nThe error message from the database was:\n") +
- QString(PQresultErrorMessage(testAccess)) + ".\n" +
+ QString::fromUtf8(PQresultErrorMessage(testAccess)) + ".\n" +
"SQL: " + sql);
PQclear(testAccess);
valid = false;
@@ -129,10 +129,10 @@
}
PQclear(testAccess);
- PGresult *schema = PQexec(connection, "SELECT current_schema()");
+ PGresult *schema = PQexec(connection, QString("SELECT current_schema()").toUtf8());
if (PQresultStatus(schema) == PGRES_TUPLES_OK)
{
- mCurrentSchema = PQgetvalue(schema, 0, 0);
+ mCurrentSchema = QString::fromUtf8(PQgetvalue(schema, 0, 0));
if(mCurrentSchema==mSchemaName) {
mUri.clearSchema();
setDataSourceUri( mUri.uri() );
@@ -167,7 +167,7 @@
// Set the postgresql message level so that we don't get the
// 'there is no transaction in progress' warning.
#ifndef QGISDEBUG
- PQexec(connection, "set client_min_messages to error");
+ PQexec(connection, QString("set client_min_messages to error").toUtf8());
#endif
// Kick off the long running threads
@@ -241,7 +241,7 @@
//pLog.flush();
}
-PGconn *QgsPostgresProvider::connectDb(const char *conninfo)
+PGconn *QgsPostgresProvider::connectDb(const QString & conninfo)
{
if( connections.contains(conninfo) )
{
@@ -252,7 +252,7 @@
QgsDebugMsg(QString("New postgres connection for ") + conninfo);
- PGconn *pd = PQconnectdb(conninfo);
+ 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)
{
@@ -263,7 +263,7 @@
//set client encoding to unicode because QString uses UTF-8 anyway
QgsDebugMsg("setting client encoding to UNICODE");
- int errcode=PQsetClientEncoding(pd, "UNICODE");
+ int errcode=PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
if(errcode==0)
{
@@ -338,7 +338,7 @@
if(mFirstFetch)
{
- if(PQsendQuery(connection, (const char *)fetch) == 0) //fetch features in asynchronously
+ if(PQsendQuery(connection, fetch.toUtf8()) == 0) //fetch features in asynchronously
{
qWarning("PQsendQuery failed (1)");
}
@@ -353,15 +353,16 @@
{
QgsDebugMsg("End of features");
+ PQclear(queryResult);
if (ready)
- PQexec(connection, "end work");
+ PQexec(connection, QString("end work").toUtf8());
ready = false;
return false;
}
for (int row = 0; row < rows; row++)
{
- int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,"\""+primaryKey+"\""));
+ int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,quoteIdentifier(primaryKey).toUtf8()));
if (swapEndian)
oid = ntohl(oid); // convert oid to opposite endian
@@ -383,12 +384,14 @@
}
else
{
- char* attribute = PQgetvalue(queryResult, row, PQfnumber(queryResult,"\""+*name_it+"\""));
- val = QString::fromUtf8(attribute);
+ val = QString::fromUtf8(PQgetvalue(queryResult, row, PQfnumber(queryResult,quoteIdentifier(*name_it).toUtf8())));
}
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;
@@ -411,7 +414,7 @@
{
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
memset(featureGeom, '\0', returnedLength + 1);
- memcpy(featureGeom, PQgetvalue(queryResult, row, PQfnumber(queryResult,"qgs_feature_geometry")), returnedLength);
+ memcpy(featureGeom, PQgetvalue(queryResult, row, PQfnumber(queryResult,QString("qgs_feature_geometry").toUtf8())), returnedLength);
mFeatureQueue.back().setGeometryAndOwnership(featureGeom, returnedLength + 1);
}
else
@@ -424,7 +427,7 @@
PQclear(queryResult);
- if(PQsendQuery(connection, (const char *)fetch) == 0) //already fetch the next couple of features asynchronously
+ if(PQsendQuery(connection, fetch.toUtf8()) == 0) //already fetch the next couple of features asynchronously
{
qWarning("PQsendQuery failed (2)");
}
@@ -477,17 +480,17 @@
}
}
- QString declare = "declare qgisf" + providerId + " binary cursor for select \"" + primaryKey + "\"";
+ QString declare = "declare qgisf" + providerId + " binary cursor for select " + quoteIdentifier(primaryKey);
if(fetchGeometry)
{
- declare += QString(",asbinary(\"%1\",'%2') as qgs_feature_geometry").arg(geometryColumn).arg(endianString());
+ declare += QString(",asbinary(%1,'%2') as qgs_feature_geometry").arg(quoteIdentifier(geometryColumn)).arg(endianString());
}
for(std::list::const_iterator it = mFetchAttributeNames.begin(); it != mFetchAttributeNames.end(); ++it)
{
if( (*it) != primaryKey) //no need to fetch primary key again
{
- declare += ",\"" + *it + "\"::text";
+ declare += "," + quoteIdentifier(*it) + "::text";
}
}
@@ -504,12 +507,12 @@
{
// Contributed by #qgis irc "creeping"
// This version actually invokes PostGIS's use of spatial indexes
- declare += " where " + geometryColumn;
+ declare += " where " + quoteIdentifier(geometryColumn);
declare += " && setsrid('BOX3D(" + rect.asWKTCoords();
declare += ")'::box3d,";
declare += srid;
declare += ")";
- declare += " and intersects(" + geometryColumn;
+ declare += " and intersects(" + quoteIdentifier(geometryColumn);
declare += ", setsrid('BOX3D(" + rect.asWKTCoords();
declare += ")'::box3d,";
declare += srid;
@@ -517,7 +520,7 @@
}
else
{
- declare += " where " + geometryColumn;
+ declare += " where " + quoteIdentifier(geometryColumn);
declare += " && setsrid('BOX3D(" + rect.asWKTCoords();
declare += ")'::box3d,";
declare += srid;
@@ -540,11 +543,11 @@
// set up the cursor
if(ready){
- PQexec(connection, "end work");
+ PQexec(connection, QString("end work").toUtf8());
}
- PQexec(connection,"begin work");
+ PQexec(connection,QString("begin work").toUtf8());
ready = true;
- PQexec(connection, (const char *)(declare.utf8()));
+ PQexec(connection, declare.toUtf8());
while(!mFeatureQueue.empty())
{
@@ -558,7 +561,6 @@
bool fetchGeometry,
QgsAttributeList fetchAttributes)
{
-
std::list attributeNames;
QgsFieldMap fldMap = fields();
QgsFieldMap::const_iterator fieldIt;
@@ -574,43 +576,44 @@
}
}
- QString sql = "declare qgisfid" + providerId + " binary cursor for select \"" + primaryKey + "\"";
+ QString sql = "declare qgisfid" + providerId + " binary cursor for select " + quoteIdentifier(primaryKey);
if(fetchGeometry)
{
- sql += QString(",asbinary(\"%1\",'%2') as qgs_feature_geometry").arg(geometryColumn).arg(endianString());
+ sql += QString(",asbinary(%1,'%2') as qgs_feature_geometry").arg(quoteIdentifier(geometryColumn)).arg(endianString());
}
for(namesIt = attributeNames.begin(); namesIt != attributeNames.end(); ++namesIt)
{
if( (*namesIt) != primaryKey) //no need to fetch primary key again
{
- sql += ",\"" + *namesIt + "\"::text";
+ sql += "," + quoteIdentifier(*namesIt) + "::text";
}
}
sql += " " + QString("from %1").arg(mSchemaTableName);
- sql += " where " + primaryKey + " = " + QString::number(featureId);
+ sql += " where " + quoteIdentifier(primaryKey) + " = " + QString::number(featureId);
QgsDebugMsg("Selecting feature using: " + sql);
- PQexec(connection,"begin work");
+ PQexec(connection,QString("begin work").toUtf8());
// execute query
- PQexec(connection, (const char *)(sql.utf8()));
+ PQexec(connection, sql.toUtf8());
- PGresult *res = PQexec(connection, "fetch forward 1 from qgisfid" + providerId);
+ PGresult *res = PQexec(connection, ("fetch forward 1 from qgisfid" + providerId).toUtf8());
int rows = PQntuples(res);
if (rows == 0)
{
- PQexec(connection, "end work");
+ PQclear(res);
+ PQexec(connection, QString("end work").toUtf8());
QgsDebugMsg("feature " + QString::number(featureId) + " not found");
return FALSE;
}
// set ID
- int oid = *(int *)PQgetvalue(res, 0, PQfnumber(res,"\""+primaryKey+"\""));
+ int oid = *(int *)PQgetvalue(res, 0, PQfnumber(res,quoteIdentifier(primaryKey).toUtf8()));
if (swapEndian)
oid = ntohl(oid); // convert oid to opposite endian
feature.setFeatureId(oid);
@@ -627,12 +630,14 @@
}
else
{
- char* attribute = PQgetvalue(res, 0, PQfnumber(res,*namesIt));
- val = QString::fromUtf8(attribute);
+ val = QString::fromUtf8(PQgetvalue(res, 0, PQfnumber(res,quoteIdentifier(*namesIt).toUtf8())));
}
switch (attributeFields[*it].type())
{
+ case QVariant::LongLong:
+ feature.addAttribute(*it, val.toLongLong());
+ break;
case QVariant::Int:
feature.addAttribute(*it, val.toInt());
break;
@@ -655,12 +660,13 @@
{
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
memset(featureGeom, '\0', returnedLength + 1);
- memcpy(featureGeom, PQgetvalue(res, 0, PQfnumber(res,"qgs_feature_geometry")), returnedLength);
+ memcpy(featureGeom, PQgetvalue(res, 0, PQfnumber(res,QString("qgs_feature_geometry").toUtf8())), returnedLength);
feature.setGeometryAndOwnership(featureGeom, returnedLength + 1);
}
}
- PQexec(connection, "end work");
+ PQclear(res);
+ PQexec(connection, QString("end work").toUtf8());
return TRUE;
}
@@ -721,7 +727,7 @@
void QgsPostgresProvider::reset()
{
QString move = "move 0 in qgisf" + providerId; //move cursor to first record
- PQexec(connection, (const char *)(move.utf8()));
+ PQexec(connection, move.toUtf8());
mFeatureQueue.empty();
loadFields();
}
@@ -747,25 +753,24 @@
QgsDebugMsg("Loading fields for table " + mTableName);
// Get the relation oid for use in later queries
- QString sql = "SELECT oid FROM pg_class WHERE relname = '" + mTableName + "' AND relnamespace = ("
- "SELECT oid FROM pg_namespace WHERE nspname = '" + mSchemaName + "')";
- PGresult *tresult= PQexec(connection, (const char *)(sql.utf8()));
- QString tableoid = PQgetvalue(tresult, 0, 0);
+ QString sql = "SELECT regclass('" + mSchemaTableName + "')::oid";
+ PGresult *tresult= PQexec(connection, sql.toUtf8());
+ QString tableoid = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
PQclear(tresult);
// Get the table description
sql = "SELECT description FROM pg_description WHERE "
"objoid = " + tableoid + " AND objsubid = 0";
- tresult = PQexec(connection, (const char*) sql.utf8());
+ tresult = PQexec(connection, sql.toUtf8());
if (PQntuples(tresult) > 0)
- mDataComment = PQgetvalue(tresult, 0, 0);
+ mDataComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
PQclear(tresult);
// Populate the field vector for this layer. The field vector contains
// field name, type, length, and precision (if numeric)
sql = "select * from " + mSchemaTableName + " limit 0";
- PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
+ PGresult *result = PQexec(connection, sql.toUtf8());
//--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
// The queries inside this loop could possibly be combined into one
@@ -773,32 +778,33 @@
for (int i = 0; i < PQnfields(result); i++)
{
- QString fieldName = PQfname(result, i);
+ QString fieldName = QString::fromUtf8(PQfname(result, i));
int fldtyp = PQftype(result, i);
QString typOid = QString().setNum(fldtyp);
int fieldModifier = PQfmod(result, i);
QString fieldComment("");
- sql = "SELECT typname, typlen FROM pg_type WHERE "
- "oid = (SELECT typelem FROM pg_type WHERE "
- "typelem = " + typOid + " AND typlen = -1)";
+ sql = "SELECT typname, typlen FROM pg_type WHERE "
+ "oid="+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
+// "typelem = " + typOid + " AND typlen = -1)";
- PGresult* oidResult = PQexec(connection, (const char *) sql);
- QString fieldTypeName = PQgetvalue(oidResult, 0, 0);
- QString fieldSize = PQgetvalue(oidResult, 0, 1);
+ PGresult* oidResult = PQexec(connection, sql.toUtf8());
+ QString fieldTypeName = QString::fromUtf8(PQgetvalue(oidResult, 0, 0));
+ QString fieldSize = QString::fromUtf8(PQgetvalue(oidResult, 0, 1));
PQclear(oidResult);
sql = "SELECT attnum FROM pg_attribute WHERE "
"attrelid = " + tableoid + " AND attname = '" + fieldName + "'";
- PGresult *tresult = PQexec(connection, (const char *)(sql.utf8()));
- QString attnum = PQgetvalue(tresult, 0, 0);
+ PGresult *tresult = PQexec(connection, sql.toUtf8());
+ QString attnum = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
PQclear(tresult);
sql = "SELECT description FROM pg_description WHERE "
"objoid = " + tableoid + " AND objsubid = " + attnum;
- tresult = PQexec(connection, (const char*)(sql.utf8()));
+ tresult = PQexec(connection, sql.toUtf8());
if (PQntuples(tresult) > 0)
- fieldComment = PQgetvalue(tresult, 0, 0);
+ fieldComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
PQclear(tresult);
QgsDebugMsg("Field: " + attnum + " maps to " + QString::number(i) + " " + fieldName + ", "
@@ -807,7 +813,9 @@
if(fieldName!=geometryColumn)
{
QVariant::Type fieldType;
- if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
+ if (fieldTypeName.find("int8") != -1)
+ fieldType = QVariant::LongLong;
+ else if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
fieldType = QVariant::Int;
else if (fieldTypeName == "real" || fieldTypeName == "double precision" || \
fieldTypeName.find("float") != -1)
@@ -826,10 +834,8 @@
// can be used as a key into the table. Primary keys are always
// unique indices, so we catch them as well.
- QString sql = "select indkey from pg_index where indisunique = 't' and "
- "indrelid = (select oid from pg_class where relname = '"
- + mTableName + "' and relnamespace = (select oid from pg_namespace where "
- "nspname = '" + mSchemaName + "'))";
+ QString sql ="select indkey from pg_index where indisunique = 't' and "
+ "indrelid = regclass('" + mSchemaTableName + "')::oid"
QgsDebugMsg("Getting unique index using '" + sql + "'");
@@ -849,11 +855,10 @@
// If the relation is a view try to find a suitable column to use as
// the primary key.
- sql = "select relkind from pg_class where relname = '" + mTableName +
- "' and relnamespace = (select oid from pg_namespace where "
- "nspname = '" + mSchemaName + "')";
+ sql = "SELECT relkind FROM pg_class WHERE oid = regclass('" + mSchemaTableName +
+ "')::oid";
PGresult* tableType = executeDbCommand(connection, sql);
- QString type = PQgetvalue(tableType, 0, 0);
+ QString type = QString::fromUtf8(PQgetvalue(tableType, 0, 0));
PQclear(tableType);
primaryKey = "";
@@ -864,10 +869,9 @@
// If there is an oid on the table, use that instead,
// otherwise give up
- sql = "select attname from pg_attribute where attname = 'oid' and "
- "attrelid = (select oid from pg_class where relname = '" +
- mTableName + "' and relnamespace = (select oid from pg_namespace "
- "where nspname = '" + mSchemaName + "'))";
+ sql = "SELECT attname FROM pg_attribute WHERE attname = 'oid' AND "
+ "attrelid = regclass('" + mSchemaTableName + "')";
+
PGresult* oidCheck = executeDbCommand(connection, sql);
if (PQntuples(oidCheck) != 0)
@@ -909,22 +913,20 @@
std::vector > suitableKeyColumns;
for (int i = 0; i < PQntuples(pk); ++i)
{
- QString col = PQgetvalue(pk, i, 0);
+ QString col = QString::fromUtf8(PQgetvalue(pk, i, 0));
QStringList columns = QStringList::split(" ", col);
if (columns.count() == 1)
{
// Get the column name and data type
sql = "select attname, pg_type.typname from pg_attribute, pg_type where "
"atttypid = pg_type.oid and attnum = " +
- col + " and attrelid = (select oid from pg_class where " +
- "relname = '" + mTableName + "' and relnamespace = (select oid "
- "from pg_namespace where nspname = '" + mSchemaName + "'))";
+ col + " and attrelid = regclass('" + mSchemaTableName + "')";
PGresult* types = executeDbCommand(connection, sql);
if( PQntuples(types) > 0 )
{
- QString columnName = PQgetvalue(types, 0, 0);
- QString columnType = PQgetvalue(types, 0, 1);
+ QString columnName = QString::fromUtf8(PQgetvalue(types, 0, 0));
+ QString columnType = QString::fromUtf8(PQgetvalue(types, 0, 1));
if (columnType != "int4")
log.append(tr("The unique index on column") +
@@ -946,9 +948,7 @@
sql = "select attname from pg_attribute, pg_type where "
"atttypid = pg_type.oid and attnum in (" +
col.replace(" ", ",")
- + ") and attrelid = (select oid from pg_class where " +
- "relname = '" + mTableName + "' and relnamespace = (select oid "
- "from pg_namespace where nspname = '" + mSchemaName + "'))";
+ + ") and attrelid = regclass('" + mSchemaTableName + "')::oid";
PGresult* types = executeDbCommand(connection, sql);
QString colNames;
int numCols = PQntuples(types);
@@ -956,7 +956,7 @@
{
if (j == numCols-1)
colNames += tr("and ");
- colNames += "'" + QString(PQgetvalue(types, j, 0))
+ colNames += "'" + QString::fromUtf8(PQgetvalue(types, j, 0))
+ (j < numCols-2 ? "', " : "' ");
}
@@ -982,9 +982,7 @@
// If there is an oid on the table, use that instead,
// otherwise give up
sql = "select attname from pg_attribute where attname = 'oid' and "
- "attrelid = (select oid from pg_class where relname = '" +
- mTableName + "' and relnamespace = (select oid from pg_namespace "
- "where nspname = '" + mSchemaName + "'))";
+ "attrelid = regclass('" + mSchemaTableName + "')::oid";
PGresult* oidCheck = executeDbCommand(connection, sql);
if (PQntuples(oidCheck) != 0)
@@ -1051,10 +1049,8 @@
// Get the oid from pg_class for the given schema.relation for use
// in subsequent queries.
- sql = "select oid from pg_class where relname = '" + tableName +
- "' and relnamespace = (select oid from pg_namespace where "
- " nspname = '" + schemaName + "')";
- PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
+ sql = "select regclass('" + quoteIdentifier(schemaName) + "." + quoteIdentifier(tableName) + "')::oid";
+ PGresult* result = PQexec(connection, sql.toUtf8());
QString rel_oid;
if (PQntuples(result) == 1)
{
@@ -1086,7 +1082,7 @@
"and (contype = 'p' or contype = 'u') "
"and array_dims(conkey) = '[1:1]'";
- result = PQexec(connection, (const char*)(sql.utf8()));
+ result = PQexec(connection, sql.toUtf8());
if (PQntuples(result) == 1 && colType == "int4")
suitable[viewCol] = iter->second;
@@ -1145,7 +1141,7 @@
sql = "select * from pg_index where indrelid = " + rel_oid +
" and indkey[0] = (select attnum from pg_attribute where "
"attrelid = " + rel_oid + " and attname = '" + i->second.column + "')";
- PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
+ PGresult* result = PQexec(connection, sql.toUtf8());
if (PQntuples(result) > 0 && uniqueData(mSchemaName, mTableName, i->first))
{ // Got one. Use it.
@@ -1226,13 +1222,13 @@
bool isUnique = false;
- QString sql = "select count(distinct \"" + colName + "\") = count(\"" +
- colName + "\") from \"" + schemaName + "\".\"" + tableName + "\"";
+ QString sql = "select count(distinct " + quoteIdentifier(colName) + ") = count(" + quoteIdentifier(colName) + ") from " + quoteIdentifier(schemaName) + "." + quoteIdentifier(tableName);
- PGresult* unique = PQexec(connection, (const char*) (sql.utf8()));
+ PGresult* unique = PQexec(connection, sql.toUtf8());
if (PQntuples(unique) == 1)
- if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
+// if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
+ if (QString::fromUtf8(PQgetvalue(unique, 0, 0)).compare("t") == 0) //really should compare just first character as original did
isUnique = true;
PQclear(unique);
@@ -1243,12 +1239,12 @@
int QgsPostgresProvider::SRCFromViewColumn(const QString& ns, const QString& relname, const QString& attname_table, const QString& attname_view, const QString& viewDefinition, SRC& result) const
{
QString newViewDefSql = "SELECT definition FROM pg_views WHERE schemaname = '" + ns + "' AND viewname = '" + relname + "'";
- PGresult* newViewDefResult = PQexec(connection, (const char*)(newViewDefSql.utf8()));
+ PGresult* newViewDefResult = PQexec(connection, newViewDefSql.toUtf8());
int numEntries = PQntuples(newViewDefResult);
if(numEntries > 0) //relation is a view
{
- QString newViewDefinition(PQgetvalue(newViewDefResult, 0, 0));
+ QString newViewDefinition(QString::fromUtf8(PQgetvalue(newViewDefResult, 0, 0)));
QString newAttNameView = attname_table;
QString newAttNameTable = attname_table;
@@ -1263,12 +1259,15 @@
}
}
- QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM information_schema.view_column_usage WHERE view_schema = '" + ns + "' AND view_name = '" + relname + "' AND column_name = '" + newAttNameTable +"'";
- PGresult* viewColumnResult = PQexec(connection, (const char*)(viewColumnSql.utf8()));
+ QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM (SELECT DISTINCT current_database()::information_schema.sql_identifier AS view_catalog, nv.nspname::information_schema.sql_identifier AS view_schema, v.relname::information_schema.sql_identifier AS view_name, current_database()::information_schema.sql_identifier AS table_catalog, nt.nspname::information_schema.sql_identifier AS table_schema, t.relname::information_schema.sql_identifier AS table_name, a.attname::information_schema.sql_identifier AS column_name "
+" FROM pg_namespace nv, pg_class v, pg_depend dv, pg_depend dt, pg_class t, pg_namespace nt, pg_attribute a "
+" WHERE nv.oid = v.relnamespace AND v.relkind = 'v'::\"char\" AND v.oid = dv.refobjid AND dv.refclassid = 'pg_class'::regclass::oid AND dv.classid = 'pg_rewrite'::regclass::oid AND dv.deptype = 'i'::\"char\" AND dv.objid = dt.objid AND dv.refobjid <> dt.refobjid AND dt.classid = 'pg_rewrite'::regclass::oid AND dt.refclassid = 'pg_class'::regclass::oid AND dt.refobjid = t.oid AND t.relnamespace = nt.oid AND (t.relkind = ANY (ARRAY['r'::\"char\", 'v'::\"char\"])) AND t.oid = a.attrelid AND dt.refobjsubid = a.attnum "
+"ORDER BY current_database()::information_schema.sql_identifier, nv.nspname::information_schema.sql_identifier, v.relname::information_schema.sql_identifier, current_database()::information_schema.sql_identifier, nt.nspname::information_schema.sql_identifier, t.relname::information_schema.sql_identifier, a.attname::information_schema.sql_identifier) x WHERE view_schema = '" + ns + "' AND view_name = '" + relname + "' AND column_name = '" + newAttNameTable +"'";
+ PGresult* viewColumnResult = PQexec(connection, viewColumnSql.toUtf8());
if(PQntuples(viewColumnResult) > 0)
{
- QString newTableSchema = PQgetvalue(viewColumnResult, 0, 0);
- QString newTableName = PQgetvalue(viewColumnResult, 0, 1);
+ QString newTableSchema = QString::fromUtf8(PQgetvalue(viewColumnResult, 0, 0));
+ QString newTableName = QString::fromUtf8(PQgetvalue(viewColumnResult, 0, 1));
int retvalue = SRCFromViewColumn(newTableSchema, newTableName, newAttNameTable, newAttNameView, newViewDefinition, result);
PQclear(viewColumnResult);
return retvalue;
@@ -1288,12 +1287,12 @@
QgsDebugMsg("***********************************************************************************");
QgsDebugMsg(typeSql);
QgsDebugMsg("***********************************************************************************");
- PGresult* typeSqlResult = PQexec(connection, (const char*)(typeSql.utf8()));
+ PGresult* typeSqlResult = PQexec(connection, typeSql.toUtf8());
if(PQntuples(typeSqlResult) < 1)
{
return 1;
}
- QString type = PQgetvalue(typeSqlResult, 0, 0);
+ QString type = QString::fromUtf8(PQgetvalue(typeSqlResult, 0, 0));
PQclear(typeSqlResult);
result.schema=ns;
@@ -1309,18 +1308,21 @@
void QgsPostgresProvider::findColumns(tableCols& cols)
{
- QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM information_schema.view_column_usage WHERE view_schema = '" + mSchemaName + "' AND view_name = '" + mTableName + "'";
- PGresult* viewColumnResult = PQexec(connection, (const char*)(viewColumnSql.utf8()));
+ QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM (SELECT DISTINCT current_database() AS view_catalog, nv.nspname AS view_schema, v.relname AS view_name, current_database() AS table_catalog, nt.nspname AS table_schema, t.relname AS table_name, a.attname AS column_name "
+" FROM pg_namespace nv, pg_class v, pg_depend dv, pg_depend dt, pg_class t, pg_namespace nt, pg_attribute a "
+" WHERE nv.oid = v.relnamespace AND v.relkind = 'v'::\"char\" AND v.oid = dv.refobjid AND dv.refclassid = 'pg_class'::regclass::oid AND dv.classid = 'pg_rewrite'::regclass::oid AND dv.deptype = 'i'::\"char\" AND dv.objid = dt.objid AND dv.refobjid <> dt.refobjid AND dt.classid = 'pg_rewrite'::regclass::oid AND dt.refclassid = 'pg_class'::regclass::oid AND dt.refobjid = t.oid AND t.relnamespace = nt.oid AND (t.relkind = ANY (ARRAY['r'::\"char\", 'v'::\"char\"])) AND t.oid = a.attrelid AND dt.refobjsubid = a.attnum "
+"ORDER BY current_database(), nv.nspname, v.relname, current_database(), nt.nspname, t.relname, a.attname) x WHERE view_schema = '" + mSchemaName + "' AND view_name = '" + mTableName + "'";
+ PGresult* viewColumnResult = PQexec(connection, viewColumnSql.toUtf8());
//find out view definition
QString viewDefSql = "SELECT definition FROM pg_views WHERE schemaname = '" + mSchemaName + "' AND viewname = '" + mTableName + "'";
- PGresult* viewDefResult = PQexec(connection, (const char*)(viewDefSql.utf8()));
+ PGresult* viewDefResult = PQexec(connection, viewDefSql.toUtf8());
if(PQntuples(viewDefResult) < 1)
{
PQclear(viewDefResult);
return;
}
- QString viewDefinition(PQgetvalue(viewDefResult, 0, 0));
+ QString viewDefinition(QString::fromUtf8(PQgetvalue(viewDefResult, 0, 0)));
PQclear(viewDefResult);
QString ns, relname, attname_table, attname_view;
@@ -1328,9 +1330,9 @@
for(int i = 0; i < PQntuples(viewColumnResult); ++i)
{
- ns = PQgetvalue(viewColumnResult, i, 0);
- relname = PQgetvalue(viewColumnResult, i, 1);
- attname_table = PQgetvalue(viewColumnResult, i, 2);
+ ns = QString::fromUtf8(PQgetvalue(viewColumnResult, i, 0));
+ relname = QString::fromUtf8(PQgetvalue(viewColumnResult, i, 1));
+ attname_table = QString::fromUtf8(PQgetvalue(viewColumnResult, i, 2));
//find out original attribute name
attname_view = attname_table;
@@ -1574,14 +1576,14 @@
QString sql;
if(sqlWhereClause.isEmpty())
{
- sql = QString("select min(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName);
+ sql = QString("select min(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName);
}
else
{
- sql = QString("select min(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
+ sql = QString("select min(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName)+" where "+sqlWhereClause;
}
- PGresult *rmin = PQexec(connection,(const char *)(sql.utf8()));
- QString minValue = PQgetvalue(rmin,0,0);
+ PGresult *rmin = PQexec(connection, sql.toUtf8());
+ QString minValue = QString::fromUtf8(PQgetvalue(rmin,0,0));
PQclear(rmin);
return minValue.toDouble();
}
@@ -1595,14 +1597,14 @@
QString sql;
if(sqlWhereClause.isEmpty())
{
- sql = QString("select max(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName);
+ sql = QString("select max(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName);
}
else
{
- sql = QString("select max(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
+ sql = QString("select max(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName)+" where "+sqlWhereClause;
}
- PGresult *rmax = PQexec(connection,(const char *)(sql.utf8()));
- QString maxValue = PQgetvalue(rmax,0,0);
+ PGresult *rmax = PQexec(connection, sql.toUtf8());
+ QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
PQclear(rmax);
return maxValue.toDouble();
}
@@ -1612,12 +1614,12 @@
{
QString sql;
- sql = QString("select max(\"%1\") from %2")
- .arg(primaryKey)
+ sql = QString("select max(%1) from %2")
+ .arg(quoteIdentifier(primaryKey))
.arg(mSchemaTableName);
- PGresult *rmax = PQexec(connection,(const char *)(sql.utf8()));
- QString maxValue = PQgetvalue(rmax,0,0);
+ PGresult *rmax = PQexec(connection, sql.toUtf8());
+ QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
PQclear(rmax);
return maxValue.toInt();
@@ -1656,11 +1658,11 @@
insert+=" (";
// add the name of the geometry column to the insert statement
- insert += "\"" + geometryColumn;
+ insert += quoteIdentifier(geometryColumn);
// add the name of the primary key column to the insert statement
- insert += "\",\"";
- insert += primaryKey + "\"";
+ insert += ",";
+ insert += quoteIdentifier(primaryKey);
QgsDebugMsg("Constructing insert SQL, currently at: " + insert);
@@ -1685,8 +1687,8 @@
(!(it->isNull()))
)
{
- insert+=",\"";
- insert+=fieldname +"\"";
+ insert+=",";
+ insert+=quoteIdentifier(fieldname);
}
}
@@ -1777,8 +1779,6 @@
}
}
- // important: escape quotes in field value
- fieldvalue.replace("'", "''");
//request default value explicitly if fieldvalue is an empty string
if(fieldvalue.isEmpty())
@@ -1790,6 +1790,7 @@
// XXX isn't it better to always escape field value?
if(charactertype)
{
+ fieldvalue.replace("'", "''"); // escape quotes on text type fields; needs more work as other characters like '\' may need it as well; really should use PQescapeStringConn()
insert+="'";
}
@@ -1808,7 +1809,7 @@
qWarning("insert statement is: "+insert);
//send INSERT statement and do error handling
- PGresult* result=PQexec(connection, (const char *)(insert.utf8()));
+ PGresult* result=PQexec(connection, insert.toUtf8());
if(result==0)
{
showMessageBox(tr("INSERT error"),tr("An error occured during feature insertion"));
@@ -1817,7 +1818,7 @@
ExecStatusType message=PQresultStatus(result);
if(message==PGRES_FATAL_ERROR)
{
- showMessageBox(tr("INSERT error"),QString(PQresultErrorMessage(result)));
+ showMessageBox(tr("INSERT error"),QString::fromUtf8(PQresultErrorMessage(result)));
return false;
}
@@ -1844,10 +1845,10 @@
QString defaultValue("");
- PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
+ PGresult* result = PQexec(connection, sql.toUtf8());
if (PQntuples(result) == 1)
- defaultValue = PQgetvalue(result, 0, 0);
+ defaultValue = QString::fromUtf8(PQgetvalue(result, 0, 0));
PQclear(result);
@@ -1856,12 +1857,12 @@
bool QgsPostgresProvider::deleteFeature(int id)
{
- QString sql("DELETE FROM "+mSchemaTableName+" WHERE \""+primaryKey+"\" = "+QString::number(id));
+ QString sql("DELETE FROM "+mSchemaTableName+" WHERE "+quoteIdentifier(primaryKey)+" = "+QString::number(id));
QgsDebugMsg("delete sql: "+sql);
//send DELETE statement and do error handling
- PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
+ PGresult* result=PQexec(connection, sql.toUtf8());
if(result==0)
{
showMessageBox(tr("DELETE error"),tr("An error occured during deletion from disk"));
@@ -1870,7 +1871,7 @@
ExecStatusType message=PQresultStatus(result);
if(message==PGRES_FATAL_ERROR)
{
- showMessageBox(tr("DELETE error"),QString(PQresultErrorMessage(result)));
+ showMessageBox(tr("DELETE error"),QString::fromUtf8(PQresultErrorMessage(result)));
return false;
}
@@ -1890,8 +1891,8 @@
/* Functions for determining available features in postGIS */
QString QgsPostgresProvider::postgisVersion(PGconn *connection)
{
- PGresult *result = PQexec(connection, "select postgis_version()");
- postgisVersionInfo = PQgetvalue(result,0,0);
+ PGresult *result = PQexec(connection, QString("select postgis_version()").toUtf8());
+ postgisVersionInfo = QString::fromUtf8(PQgetvalue(result,0,0));
QgsDebugMsg("PostGIS version info: " + postgisVersionInfo);
@@ -1932,7 +1933,7 @@
bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
{
bool returnvalue=true;
- PQexec(connection,"BEGIN");
+ PQexec(connection,QString("BEGIN").toUtf8());
int primaryKeyHighWater = maxPrimaryKeyValue();
@@ -1945,7 +1946,7 @@
// TODO: exit loop here?
}
}
- PQexec(connection,"COMMIT");
+ PQexec(connection,QString("COMMIT").toUtf8());
reset();
return returnvalue;
}
@@ -1953,7 +1954,7 @@
bool QgsPostgresProvider::deleteFeatures(const QgsFeatureIds & id)
{
bool returnvalue=true;
- PQexec(connection,"BEGIN");
+ PQexec(connection,QString("BEGIN").toUtf8());
for(QgsFeatureIds::const_iterator it=id.begin();it!=id.end();++it)
{
if(!deleteFeature(*it))
@@ -1961,7 +1962,7 @@
returnvalue=false;
}
}
- PQexec(connection,"COMMIT");
+ PQexec(connection,QString("COMMIT").toUtf8());
reset();
return returnvalue;
}
@@ -1969,26 +1970,33 @@
bool QgsPostgresProvider::addAttributes(const QgsNewAttributesMap & name)
{
bool returnvalue=true;
- PQexec(connection,"BEGIN");
+ PQexec(connection,QString("BEGIN").toUtf8());
+
for(QgsNewAttributesMap::const_iterator iter=name.begin();iter!=name.end();++iter)
{
- QString sql="ALTER TABLE "+mSchemaTableName+" ADD COLUMN \""+iter.key()+"\" "+iter.value();
+ QString sql="ALTER TABLE "+mSchemaTableName+" ADD COLUMN "+quoteIdentifier(iter.key())+" " +iter.value();
QgsDebugMsg(sql);
//send sql statement and do error handling
- PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
+ PGresult* result=PQexec(connection, sql.toUtf8());
if(result==0)
{
+ // this condition is unlikely to occur; no message box is displayed
returnvalue=false;
+ }
+ else
+ {
ExecStatusType message=PQresultStatus(result);
if(message==PGRES_FATAL_ERROR)
{
- showMessageBox("ALTER TABLE error",QString(PQresultErrorMessage(result)));
+ showMessageBox("ALTER TABLE error",QString::fromUtf8(PQresultErrorMessage(result)));
+ returnvalue=false;
}
}
+ if (false==returnvalue) break; //break out of for loop on error
}
- PQexec(connection,"COMMIT");
+ PQexec(connection,QString("COMMIT").toUtf8());
reset();
return returnvalue;
}
@@ -1996,7 +2004,7 @@
bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
{
bool returnvalue=true;
- PQexec(connection,"BEGIN");
+ PQexec(connection,QString("BEGIN").toUtf8());
for(QgsAttributeIds::const_iterator iter=ids.begin();iter != ids.end();++iter)
{
@@ -2006,26 +2014,32 @@
continue;
}
QString column = field_it->name();
- QString sql="ALTER TABLE "+mSchemaTableName+" DROP COLUMN \""+column+"\"";
+ QString sql="ALTER TABLE "+mSchemaTableName+" DROP COLUMN "+quoteIdentifier(column);
//send sql statement and do error handling
- PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
+ PGresult* result=PQexec(connection, sql.toUtf8());
if(result==0)
{
+ // this condition is unlikely to occur; no message box is displayed
returnvalue=false;
+ }
+ else
+ {
ExecStatusType message=PQresultStatus(result);
if(message==PGRES_FATAL_ERROR)
{
- showMessageBox("ALTER TABLE error",QString(PQresultErrorMessage(result)));
+ showMessageBox("ALTER TABLE error",QString::fromUtf8(PQresultErrorMessage(result)));
+ returnvalue=false;
}
- }
- else
- {
+ else
+ {
//delete the attribute from attributeFields
attributeFields.remove(*iter);
+ }
}
+ if (false==returnvalue) break; //break out of for loop on error
}
- PQexec(connection,"COMMIT");
+ PQexec(connection,QString("COMMIT").toUtf8());
reset();
return returnvalue;
}
@@ -2033,7 +2047,7 @@
bool QgsPostgresProvider::changeAttributeValues(const QgsChangedAttributesMap & attr_map)
{
bool returnvalue=true;
- PQexec(connection,"BEGIN");
+ PQexec(connection,QString("BEGIN").toUtf8());
// cycle through the features
for(QgsChangedAttributesMap::const_iterator iter=attr_map.begin();iter!=attr_map.end();++iter)
@@ -2050,12 +2064,12 @@
// escape quotes
val.replace("'", "''");
- QString sql="UPDATE "+mSchemaTableName+" SET \""+fieldName+"\"='"+val+"' WHERE \"" +primaryKey+"\"="+QString::number(fid);
+ QString sql="UPDATE "+mSchemaTableName+" SET "+quoteIdentifier(fieldName)+"='"+val+"' WHERE " +quoteIdentifier(primaryKey)+"="+QString::number(fid);
QgsDebugMsg(sql);
// s end sql statement and do error handling
// TODO: Make all error handling like this one
- PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
+ PGresult* result=PQexec(connection, sql.toUtf8());
if (result==0)
{
showMessageBox(tr("PostGIS error"),
@@ -2066,14 +2080,14 @@
if(message==PGRES_FATAL_ERROR)
{
showMessageBox(tr("PostGIS error"),tr("The PostgreSQL database returned: ")
- + QString(PQresultErrorMessage(result))
+ + QString::fromUtf8(PQresultErrorMessage(result))
+ "\n" + tr("When trying: ") + sql);
return false;
}
}
}
- PQexec(connection,"COMMIT");
+ PQexec(connection,QString("COMMIT").toUtf8());
reset();
return returnvalue;
}
@@ -2104,7 +2118,7 @@
// Start the PostGIS transaction
- PQexec(connection,"BEGIN");
+ PQexec(connection,QString("BEGIN").toUtf8());
for(QgsGeometryMap::iterator iter = geometry_map.begin();
iter != geometry_map.end();
@@ -2117,8 +2131,8 @@
{
QgsDebugMsg("iterating over feature id " + QString::number(iter.key()));
- QString sql = "UPDATE "+ mSchemaTableName +" SET \"" +
- geometryColumn + "\"=";
+ QString sql = "UPDATE "+ mSchemaTableName +" SET " +
+ quoteIdentifier(geometryColumn) + "=";
sql += "GeomFromWKB('";
@@ -2169,13 +2183,13 @@
sql += "::bytea',"+srid+")";
}
- sql += " WHERE \"" +primaryKey+"\"="+QString::number(iter.key());
+ sql += " WHERE " +quoteIdentifier(primaryKey)+"="+QString::number(iter.key());
QgsDebugMsg("Updating with: " + sql);
// send sql statement and do error handling
// TODO: Make all error handling like this one
- PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
+ PGresult* result=PQexec(connection, sql.toUtf8());
if (result==0)
{
showMessageBox(tr("PostGIS error"), tr("An error occured contacting the PostgreSQL database"));
@@ -2185,7 +2199,7 @@
if(message==PGRES_FATAL_ERROR)
{
showMessageBox(tr("PostGIS error"), tr("The PostgreSQL database returned: ")
- + QString(PQresultErrorMessage(result))
+ + QString::fromUtf8(PQresultErrorMessage(result))
+ "\n" + tr("When trying: ") + sql);
return false;
}
@@ -2194,7 +2208,7 @@
} // for each feature
- PQexec(connection,"COMMIT");
+ PQexec(connection,QString("COMMIT").toUtf8());
// TODO: Reset Geometry dirty if commit was OK
@@ -2264,12 +2278,12 @@
}
#endif
- PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
+ PGresult *result = PQexec(connection, sql.toUtf8());
QgsDebugMsg("Approximate Number of features as text: " +
- QString(PQgetvalue(result, 0, 0)));
+ QString::fromUtf8(PQgetvalue(result, 0, 0)));
- numberFeatures = QString(PQgetvalue(result, 0, 0)).toLong();
+ numberFeatures = QString::fromUtf8(PQgetvalue(result, 0, 0)).toLong();
PQclear(result);
QgsDebugMsg("Approximate Number of features: " + QString::number(numberFeatures));
@@ -2285,7 +2299,7 @@
// get the approximate extent by retreiving the bounding box
// of the first few items with a geometry
- QString sql = "select box3d(" + geometryColumn + ") from "
+ QString sql = "select box3d(" + quoteIdentifier(geometryColumn) + ") from "
+ mSchemaTableName + " where ";
if(sqlWhereClause.length() > 0)
@@ -2293,20 +2307,20 @@
sql += "(" + sqlWhereClause + ") and ";
}
- sql += "not IsEmpty(" + geometryColumn + ") limit 5";
+ sql += "not IsEmpty(" + quoteIdentifier(geometryColumn) + ") limit 5";
#if WASTE_TIME
- sql = "select xmax(extent(\"" + geometryColumn + "\")) as xmax,"
- "xmin(extent(\"" + geometryColumn + "\")) as xmin,"
- "ymax(extent(\"" + geometryColumn + "\")) as ymax,"
- "ymin(extent(\"" + geometryColumn + "\")) as ymin"
+ sql = "select xmax(extent(" + quoteIdentifier(geometryColumn) + ")) as xmax,"
+ "xmin(extent(" + quoteIdentifier(geometryColumn) + ")) as xmin,"
+ "ymax(extent(" + quoteIdentifier(geometryColumn) + ")) as ymax,"
+ "ymin(extent(" + quoteIdentifier(geometryColumn) + ")) as ymin"
" from " + mSchemaTableName;
#endif
QgsDebugMsg("Getting approximate extent using: '" + sql + "'");
- PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
+ PGresult *result = PQexec(connection, sql.toUtf8());
// TODO: Guard against the result having no rows
@@ -2338,7 +2352,7 @@
// get the extents
- QString sql = "select extent(\"" + geometryColumn + "\") from " +
+ QString sql = "select extent(" + quoteIdentifier(geometryColumn) + ") from " +
mSchemaTableName;
if(sqlWhereClause.length() > 0)
{
@@ -2346,16 +2360,16 @@
}
#if WASTE_TIME
- sql = "select xmax(extent(\"" + geometryColumn + "\")) as xmax,"
- "xmin(extent(\"" + geometryColumn + "\")) as xmin,"
- "ymax(extent(\"" + geometryColumn + "\")) as ymax,"
- "ymin(extent(\"" + geometryColumn + "\")) as ymin"
+ sql = "select xmax(extent(" + quoteIdentifier(geometryColumn) + ")) as xmax,"
+ "xmin(extent(" + quoteIdentifier(geometryColumn) + ")) as xmin,"
+ "ymax(extent(" + quoteIdentifier(geometryColumn) + ")) as ymax,"
+ "ymin(extent(" + quoteIdentifier(geometryColumn) + ")) as ymin"
" from " + mSchemaTableName;
#endif
QgsDebugMsg("Getting extents using schema.table: " + sql);
- PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
+ PGresult *result = PQexec(connection, sql.toUtf8());
if(PQntuples(result)>0)
{
std::string box3d = PQgetvalue(result, 0, 0);
@@ -2473,28 +2487,26 @@
// version 7.4, binary cursors return data in XDR whereas previous versions
// return data in the endian of the server
- QString firstOid = "select oid from pg_class where relname = '" +
- mTableName + "' and relnamespace = (select oid from pg_namespace where nspname = '"
- + mSchemaName + "')";
- PGresult * oidResult = PQexec(connection, (const char*)(firstOid.utf8()));
+ QString firstOid = "select regclass('" + mSchemaTableName + "')::oid";
+ PGresult * oidResult = PQexec(connection, firstOid.toUtf8());
// get the int value from a "normal" select
- QString oidValue = PQgetvalue(oidResult,0,0);
+ QString oidValue = QString::fromUtf8(PQgetvalue(oidResult,0,0));
PQclear(oidResult);
QgsDebugMsg("Creating binary cursor");
// get the same value using a binary cursor
- PQexec(connection,"begin work");
- QString oidDeclare = QString("declare oidcursor binary cursor for select oid from pg_class where relname = '%1' and relnamespace = (select oid from pg_namespace where nspname = '%2')").arg(mTableName).arg(mSchemaName);
+ PQexec(connection,QString("begin work").toUtf8());
+ QString oidDeclare = "declare oidcursor binary cursor for select regclass('" + mSchemaTableName + "')::oid";
// set up the cursor
- PQexec(connection, (const char *)oidDeclare);
+ PQexec(connection, oidDeclare.toUtf8());
QString fetch = "fetch forward 1 from oidcursor";
QgsDebugMsg("Fetching a record and attempting to get check endian-ness");
- PGresult *fResult = PQexec(connection, (const char *)fetch);
- PQexec(connection, "end work");
+ PGresult *fResult = PQexec(connection, fetch.toUtf8());
+ PQexec(connection, QString("end work").toUtf8());
swapEndian = true;
if(PQntuples(fResult) > 0){
// get the oid value from the binary cursor
@@ -2531,8 +2543,8 @@
if (PQntuples(result) > 0)
{
- srid = PQgetvalue(result, 0, PQfnumber(result, "srid"));
- fType = PQgetvalue(result, 0, PQfnumber(result, "type"));
+ srid = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("srid").toUtf8())));
+ fType = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("type").toUtf8())));
PQclear(result);
}
else
@@ -2542,8 +2554,8 @@
// fail if there is no data in the relevant table.
PQclear(result); // for the query just before the if() statement
sql = "select "
- "srid(\"" + geometryColumn + "\"), "
- "geometrytype(\"" + geometryColumn + "\") from " +
+ "srid(" + quoteIdentifier(geometryColumn) + "), "
+ "geometrytype(" + quoteIdentifier(geometryColumn) + ") from " +
mSchemaTableName;
//it is possible that the where clause restricts the feature type
@@ -2559,8 +2571,8 @@
if (PQntuples(result) > 0)
{
- srid = PQgetvalue(result, 0, PQfnumber(result, "srid"));
- fType = PQgetvalue(result, 0, PQfnumber(result, "geometrytype"));
+ srid = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("srid").toUtf8())));
+ fType = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("geometrytype").toUtf8())));
}
PQclear(result);
}
@@ -2577,7 +2589,7 @@
" when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
" when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
" end "
- "from %2").arg(geometryColumn).arg(mSchemaTableName);
+ "from %2").arg(quoteIdentifier(geometryColumn)).arg(mSchemaTableName);
if(mUri.sql()!="")
sql += " where " + mUri.sql();
@@ -2585,7 +2597,7 @@
if (PQntuples(result)==1)
{
- fType = PQgetvalue(result, 0, 0);
+ fType = QString::fromUtf8(PQgetvalue(result, 0, 0));
}
PQclear(result);
}
@@ -2649,18 +2661,23 @@
PGresult* QgsPostgresProvider::executeDbCommand(PGconn* connection,
const QString& sql)
{
- PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
+ PGresult *result = PQexec(connection, sql.toUtf8());
QgsDebugMsg("Executed SQL: " + sql);
if (PQresultStatus(result) == PGRES_TUPLES_OK) {
QgsDebugMsg("Command was successful.");
} else {
QgsDebugMsg("Command was unsuccessful. The error message was: "
- + QString( PQresultErrorMessage(result) ) );
+ + QString::fromUtf8( PQresultErrorMessage(result) ) );
}
return result;
}
+QString QgsPostgresProvider::quoteIdentifier( const QString &ident )
+{
+ return QString( ident ).prepend("\"").append("\"");
+} // QgsPostgresProvider::quoteIdentifier( const QString &ident )
+
void QgsPostgresProvider::showMessageBox(const QString& title,
const QString& text)
{