1 Attachment(s)
[patch] QPSQL: set an error code so QSqlError::number() gives a useful value
Problem: in my application (which makes use of PostgreSQL and Qt4) I
need to distinguish between different kinds of (SQL) errors, that is,
I need to check if the error is a foreign key violation, or uniqness
voilation, etc. This information is available via `native' PostgreSQL
API, the relevant function is
char *PQresultErrorField(const PGresult *res, int fieldcode)
However, QPSQL driver does not provide this information, i.e. QSqlError
returned by QPSQL always has number() == -1. Also, there's no (easy)
way to retrive PGresult* from the driver. Hence the patch below. With
this patch number() returns an error code (as described in the Appendix A
of the PostgreSQL manual). There's one quirk, though. PostgreSQLs error
codes are 5 character ASCII strings, but QSqlError expects an integer
instead. The patch treats error codes as integres in base 29. To get
back the original error code, one should convert that integer back.
Code:
Index: qt4-x11-4.4.3/src/sql/drivers/psql/qsql_psql.cpp
===================================================================
--- qt4-x11-4.4.3.orig/src/sql/drivers/psql/qsql_psql.cpp 2008-12-08 11:42:21.000000000 +0200
+++ qt4-x11-4.4.3/src/sql/drivers/psql/qsql_psql.cpp 2008-12-08 11:48:11.000000000 +0200
@@ -146,11 +146,28 @@
};
- const QPSQLDriverPrivate *p)
+ const QPSQLDriverPrivate *p,
+ const PGresult *res = 0)
{
const char *s = PQerrorMessage(p->connection);
+ int errnum = -1;
+ if (res) {
+ const char *sql_state_ = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+ if (sql_state_) {
+ bool ok;
+ // PQresultErrorField returns 5-character error code,
+ // see the appendix A (titled `PostgreSQL Error Codes')
+ // of the PostgreSQL manual. On the other hand, Qt
+ // expects an integer.
+ static const int latin_base = 29;
+ // Error code contains arbitrary alphanumeric characters
+ errnum
= QString::fromAscii(sql_state_
).
toInt(&ok, latin_base
);
+ if (!ok)
+ errnum = -1;
+ }
+ }
}
bool QPSQLResultPrivate::processResults()
@@ -171,7 +188,7 @@
return true;
}
- "Unable to create query"),
QSqlError::StatementError, driver
));
+ "Unable to create query"),
QSqlError::StatementError, driver, result
));
return false;
}
@@ -543,6 +560,7 @@
: stmt.toLocal8Bit().constData());
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
+ // XXX: do we need to setNumber() here?
"Unable to prepare statement"),
QSqlError::StatementError, d
->driver
));
PQclear(result);
@@ -1173,6 +1191,7 @@
d->isUtf8 ? query.toUtf8().constData()
: query.toLocal8Bit().constData())
) != PGRES_COMMAND_OK) {
+ // XXX: do we need to setNumber() here?
setLastError
(qMakeError
(tr
("Unable to subscribe"),
QSqlError::StatementError, d
));
return false;
}
@@ -1205,6 +1224,7 @@
d->isUtf8 ? query.toUtf8().constData()
: query.toLocal8Bit().constData())
) != PGRES_COMMAND_OK) {
+ // XXX: do we need to setNumber() here?
setLastError
(qMakeError
(tr
("Unable to unsubscribe"),
QSqlError::StatementError, d
));
return false;
}
Re: [patch] QPSQL: set an error code so QSqlError::number() gives a useful value
Try sending the patch to Trolls via Task-Tracker.
Re: [patch] QPSQL: set an error code so QSqlError::number() gives a useful value
The problem persist on Qt4.7.4, could you please guide me for apply this patch?