Add support for SQLSTATE error codes

Postgres can report detailed information about an error using error codes.
See http://www.postgresql.org/docs/8.1/static/errcodes-appendix.html .
The current driver doesn't report the error, nor is it supported by the
QSqlError object.
The patch appends the error to the error message, helping applications to:
- handle different errors in a specific way
- show correct, translated error messages, independently on the language of the postgres installation

Change-Id: Ica3530ac33d3aaa9985e06f6c1f302ece9891033
Reviewed-by: Mark Brand <mabrand@mabrand.nl>
bb10
Andras Mantia 2012-07-01 17:11:00 +03:00 committed by Qt by Nokia
parent f128c1f6d3
commit 8ccab9b029
2 changed files with 23 additions and 12 deletions

5
dist/changes-5.0.0 vendored
View File

@ -567,6 +567,11 @@ sqlite
'true' and 'false'. Sqlite does not have a boolean column type and it is
customary to use integer. QTBUG-23895
postgres
--------
* the error message returned in QSqlError::text() has the SQLSTATE error code
appended in parantheses.
****************************************************************************
* Platform Specific Changes *
****************************************************************************

View File

@ -195,10 +195,14 @@ public:
};
static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
const QPSQLDriverPrivate *p)
const QPSQLDriverPrivate *p, PGresult* result = 0)
{
const char *s = PQerrorMessage(p->connection);
QString msg = p->isUtf8 ? QString::fromUtf8(s) : QString::fromLocal8Bit(s);
if (result) {
const char *sCode = PQresultErrorField(result, PG_DIAG_SQLSTATE);
msg += QString::fromLatin1("(%1)").arg(QString::fromLatin1(sCode));
}
return QSqlError(QLatin1String("QPSQL: ") + err, msg, type);
}
@ -220,7 +224,7 @@ bool QPSQLResultPrivate::processResults()
return true;
}
q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
"Unable to create query"), QSqlError::StatementError, driver));
"Unable to create query"), QSqlError::StatementError, driver, result));
return false;
}
@ -586,7 +590,7 @@ bool QPSQLResult::prepare(const QString &query)
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
"Unable to prepare statement"), QSqlError::StatementError, d->driver));
"Unable to prepare statement"), QSqlError::StatementError, d->driver, result));
PQclear(result);
d->preparedStmtId.clear();
return false;
@ -881,9 +885,9 @@ bool QPSQLDriver::beginTransaction()
}
PGresult* res = d->exec("BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
PQclear(res);
setLastError(qMakeError(tr("Could not begin transaction"),
QSqlError::TransactionError, d));
QSqlError::TransactionError, d, res));
PQclear(res);
return false;
}
PQclear(res);
@ -914,9 +918,9 @@ bool QPSQLDriver::commitTransaction()
}
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK || transaction_failed) {
PQclear(res);
setLastError(qMakeError(tr("Could not commit transaction"),
QSqlError::TransactionError, d));
QSqlError::TransactionError, d, res));
PQclear(res);
return false;
}
PQclear(res);
@ -932,7 +936,7 @@ bool QPSQLDriver::rollbackTransaction()
PGresult* res = d->exec("ROLLBACK");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Could not rollback transaction"),
QSqlError::TransactionError, d));
QSqlError::TransactionError, d, res));
PQclear(res);
return false;
}
@ -1316,8 +1320,9 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
// to check for notifications immediately after executing the LISTEN
d->seid << name;
QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
if (PQresultStatus(d->exec(query)) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to subscribe"), QSqlError::StatementError, d));
PGresult *result = d->exec(query);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to subscribe"), QSqlError::StatementError, d, result));
return false;
}
@ -1347,8 +1352,9 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
}
QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
if (PQresultStatus(d->exec(query)) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to unsubscribe"), QSqlError::StatementError, d));
PGresult *result = d->exec(query);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to unsubscribe"), QSqlError::StatementError, d, result));
return false;
}