Обсуждение: Is there public API to fetch errcode?
Hi Postgres hackers, ereport() can accept an error code. For example: ereport(FATAL, (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)", max_wal_senders))); In this case the error happens during connection initialization, outside of an SQL query. I.e. PGresult is not available. I suspect that the error code is available on the client as PGconn->last_sqlstate however it is private and I can't find any public API to fetch it. Does libpq have an API to extract this code? --- Sergey
Sergey Fukanchik <s.fukanchik@postgrespro.ru> writes: > Does libpq have an API to extract this code? PQresultErrorField(res, PG_DIAG_SQLSTATE) should do, no? regards, tom lane
On Sun, Oct 12, 2025 at 1:27 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Sergey Fukanchik <s.fukanchik@postgrespro.ru> writes:
> Does libpq have an API to extract this code?
PQresultErrorField(res, PG_DIAG_SQLSTATE) should do, no?
I believe the call flow is the following - no "res"/result is ever constructed:
PGconn *PQconnectdb(const char *conninfo);
ConnStatusType PQstatus(const PGconn *conn);
// Connection_Bad
char *PQerrorMessage(const PGconn *conn);
// Obtains the error message; but there seems to be no equivalent of PQresultErrorField (e.g. PQconnErrorField) to obtain the SQLState field component thereof
David J.
"David G. Johnston" <david.g.johnston@gmail.com> writes: > On Sun, Oct 12, 2025 at 1:27 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: >> PQresultErrorField(res, PG_DIAG_SQLSTATE) should do, no? > I believe the call flow is the following - no "res"/result is ever > constructed: Hmm ... no, we do construct a PGresult containing the error (including SQLSTATE), because pqGetErrorNotice3 is what's used to read the server's error response. But it looks like for a connection-time failure, PQconnectPoll clears it before returning. In principle maybe we could keep that around, allowing the application to do PQgetResult from the failed connection object. Seems like it'd be a bit of a mess though. Also, given all the logic that's there to retry different server addresses etc, it's not clear which failure result to preserve. We sidestep that question so far as the textual PQerrorMessage output is concerned by concatenating all the failures, but that's not workable for PGresults. regards, tom lane
sqlstate is saved into conn->last_sqlstate along with the error message in pqGetErrorNotice3: if (id == PG_DIAG_SQLSTATE) strlcpy(conn->last_sqlstate, workBuf.data, sizeof(conn->last_sqlstate)); is this usable? Can it be extracted somehow? --- Sergey
Sergey Fukanchik <s.fukanchik@postgrespro.ru> writes: > sqlstate is saved into conn->last_sqlstate along with the error message > in pqGetErrorNotice3: > if (id == PG_DIAG_SQLSTATE) > strlcpy(conn->last_sqlstate, workBuf.data, > sizeof(conn->last_sqlstate)); > is this usable? Can it be extracted somehow? It is not exposed, and if it were you'd have the same problem of lack of context: you don't know which connection attempt set the value, nor whether that's the most interesting failure. If we wanted to up our game in this area, I'd envision making it possible to extract a PGresult or PGresult-like structure for each connection attempt that libpq made. It'd need to carry the connection details (server address, encryption options, etc) as well as the failure info. Not a trivial project, but doubtless do-able if someone cared to put in the effort. Of course, that just begs the question of what an application would do with this data if it had it. regards, tom lane
So the difference between conn->errorMessage and conn->last_sqlstate is that erorrMessage is appended and last_sqstate is overwritten. And it seems that changing this is not easy. As to why I want this - there are several reasons for connection to be rejected, like ERRCODE_CANNOT_CONNECT_NOW, ERRCODE_TOO_MANY_CONNECTIONS, ERRCODE_INSUFFICIENT_PRIVILEGE, ERRCODE_DATA_CORRUPTED etc I would like my client to behave differently based on a particular errcode - sometimes wait and retry, sometimes choose another server, sometimes just fail. It would be perfect if I could simply configure libpq to do such reactions automatically for me, but designing this properly seems to be even harder than exposing connection sqlstate. SQLSTATE codes are locale independent and it would help a lot if I could use them instead of relying on localized messages. --- Sergey