Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 914611e

Browse files
committed
Fix missed cases in libpq's error handling.
Commit 618c167 invented an "error_result" flag in PGconn, which intends to represent the state that we have an error condition and need to build a PGRES_FATAL_ERROR PGresult from the message text in conn->errorMessage, but have not yet done so. (Postponing construction of the error object simplifies dealing with out-of-memory conditions and with concatenation of messages for multiple errors.) For nearly all purposes, this "virtual" PGresult object should act the same as if it were already materialized. But a couple of places in fe-protocol3.c didn't get that memo, and were only testing conn->result as they used to, without also checking conn->error_result. In hopes of reducing the probability of similar mistakes in future, I invented a pgHavePendingResult() macro that includes both tests. Per report from Peter Eisentraut. Discussion: https://postgr.es/m/b52277b9-fa66-b027-4a37-fb8989c73ff8@enterprisedb.com
1 parent 2cb1272 commit 914611e

File tree

3 files changed

+16
-7
lines changed

3 files changed

+16
-7
lines changed

src/interfaces/libpq/fe-exec.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,7 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
11961196
* Returns 1 if OK, 0 if error occurred.
11971197
*
11981198
* On error, *errmsgp can be set to an error string to be returned.
1199+
* (Such a string should already be translated via libpq_gettext().)
11991200
* If it is left NULL, the error is presumed to be "out of memory".
12001201
*
12011202
* In single-row mode, we create a new result holding just the current row,
@@ -1986,7 +1987,7 @@ PQsetSingleRowMode(PGconn *conn)
19861987
(conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE &&
19871988
conn->cmd_queue_head->queryclass != PGQUERY_EXTENDED))
19881989
return 0;
1989-
if (conn->result || conn->error_result)
1990+
if (pgHavePendingResult(conn))
19901991
return 0;
19911992

19921993
/* OK, set flag */
@@ -2941,7 +2942,7 @@ PQfn(PGconn *conn,
29412942
}
29422943

29432944
if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
2944-
conn->result || conn->error_result)
2945+
pgHavePendingResult(conn))
29452946
{
29462947
appendPQExpBufferStr(&conn->errorMessage,
29472948
libpq_gettext("connection in wrong state\n"));

src/interfaces/libpq/fe-protocol3.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ pqParseInput3(PGconn *conn)
209209
case 'C': /* command complete */
210210
if (pqGets(&conn->workBuffer, conn))
211211
return;
212-
if (conn->result == NULL)
212+
if (!pgHavePendingResult(conn))
213213
{
214214
conn->result = PQmakeEmptyPGresult(conn,
215215
PGRES_COMMAND_OK);
@@ -263,7 +263,7 @@ pqParseInput3(PGconn *conn)
263263
}
264264
break;
265265
case 'I': /* empty query */
266-
if (conn->result == NULL)
266+
if (!pgHavePendingResult(conn))
267267
{
268268
conn->result = PQmakeEmptyPGresult(conn,
269269
PGRES_EMPTY_QUERY);
@@ -281,7 +281,7 @@ pqParseInput3(PGconn *conn)
281281
if (conn->cmd_queue_head &&
282282
conn->cmd_queue_head->queryclass == PGQUERY_PREPARE)
283283
{
284-
if (conn->result == NULL)
284+
if (!pgHavePendingResult(conn))
285285
{
286286
conn->result = PQmakeEmptyPGresult(conn,
287287
PGRES_COMMAND_OK);
@@ -362,7 +362,7 @@ pqParseInput3(PGconn *conn)
362362
if (conn->cmd_queue_head &&
363363
conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)
364364
{
365-
if (conn->result == NULL)
365+
if (!pgHavePendingResult(conn))
366366
{
367367
conn->result = PQmakeEmptyPGresult(conn,
368368
PGRES_COMMAND_OK);
@@ -2133,7 +2133,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
21332133
* report COMMAND_OK. Otherwise, the backend violated the
21342134
* protocol, so complain.
21352135
*/
2136-
if (!(conn->result || conn->error_result))
2136+
if (!pgHavePendingResult(conn))
21372137
{
21382138
if (status == PGRES_COMMAND_OK)
21392139
{

src/interfaces/libpq/libpq-int.h

+8
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,14 @@ extern void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message);
852852
(resetPQExpBuffer(&(conn)->errorMessage), \
853853
(conn)->errorReported = 0)
854854

855+
/*
856+
* Check whether we have a PGresult pending to be returned --- either a
857+
* constructed one in conn->result, or a "virtual" error result that we
858+
* don't intend to materialize until the end of the query cycle.
859+
*/
860+
#define pgHavePendingResult(conn) \
861+
((conn)->result != NULL || (conn)->error_result)
862+
855863
/*
856864
* this is so that we can check if a connection is non-blocking internally
857865
* without the overhead of a function call

0 commit comments

Comments
 (0)