Skip to content

Commit a0ae54d

Browse files
committed
libpq: Fix another bug in 721f7bd.
If we failed to connect to one or more hosts, and then afterwards we find one that fails to be read-write, the latter error message was clobbering any earlier ones. Repair. Mithun Cy, slightly revised by me.
1 parent 2f4193c commit a0ae54d

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

src/interfaces/libpq/fe-connect.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,39 @@ connectDBComplete(PGconn *conn)
17621762
}
17631763
}
17641764

1765+
/*
1766+
* This subroutine saves conn->errorMessage, which will be restored back by
1767+
* restoreErrorMessage subroutine.
1768+
*/
1769+
static bool
1770+
saveErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
1771+
{
1772+
initPQExpBuffer(savedMessage);
1773+
if (PQExpBufferBroken(savedMessage))
1774+
{
1775+
printfPQExpBuffer(&conn->errorMessage,
1776+
libpq_gettext("out of memory\n"));
1777+
return false;
1778+
}
1779+
1780+
appendPQExpBufferStr(savedMessage,
1781+
conn->errorMessage.data);
1782+
resetPQExpBuffer(&conn->errorMessage);
1783+
return true;
1784+
}
1785+
1786+
/*
1787+
* Restores saved error messages back to conn->errorMessage.
1788+
*/
1789+
static void
1790+
restoreErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
1791+
{
1792+
appendPQExpBufferStr(savedMessage, conn->errorMessage.data);
1793+
resetPQExpBuffer(&conn->errorMessage);
1794+
appendPQExpBufferStr(&conn->errorMessage, savedMessage->data);
1795+
termPQExpBuffer(savedMessage);
1796+
}
1797+
17651798
/* ----------------
17661799
* PQconnectPoll
17671800
*
@@ -1795,6 +1828,7 @@ PQconnectPoll(PGconn *conn)
17951828
PGresult *res;
17961829
char sebuf[256];
17971830
int optval;
1831+
PQExpBufferData savedMessage;
17981832

17991833
if (conn == NULL)
18001834
return PGRES_POLLING_FAILED;
@@ -2792,11 +2826,26 @@ PQconnectPoll(PGconn *conn)
27922826
if (conn->target_session_attrs != NULL &&
27932827
strcmp(conn->target_session_attrs, "read-write") == 0)
27942828
{
2829+
/*
2830+
* We are yet to make a connection. Save all existing error
2831+
* messages until we make a successful connection state.
2832+
* This is important because PQsendQuery is going to reset
2833+
* conn->errorMessage and we will loose error messages
2834+
* related to previous hosts we have tried to connect and
2835+
* failed.
2836+
*/
2837+
if (!saveErrorMessage(conn, &savedMessage))
2838+
goto error_return;
2839+
27952840
conn->status = CONNECTION_OK;
27962841
if (!PQsendQuery(conn,
27972842
"show transaction_read_only"))
2843+
{
2844+
restoreErrorMessage(conn, &savedMessage);
27982845
goto error_return;
2846+
}
27992847
conn->status = CONNECTION_CHECK_WRITABLE;
2848+
restoreErrorMessage(conn, &savedMessage);
28002849
return PGRES_POLLING_READING;
28012850
}
28022851

@@ -2841,11 +2890,18 @@ PQconnectPoll(PGconn *conn)
28412890
if (conn->target_session_attrs != NULL &&
28422891
strcmp(conn->target_session_attrs, "read-write") == 0)
28432892
{
2893+
if (!saveErrorMessage(conn, &savedMessage))
2894+
goto error_return;
2895+
28442896
conn->status = CONNECTION_OK;
28452897
if (!PQsendQuery(conn,
28462898
"show transaction_read_only"))
2899+
{
2900+
restoreErrorMessage(conn, &savedMessage);
28472901
goto error_return;
2902+
}
28482903
conn->status = CONNECTION_CHECK_WRITABLE;
2904+
restoreErrorMessage(conn, &savedMessage);
28492905
return PGRES_POLLING_READING;
28502906
}
28512907

@@ -2858,13 +2914,20 @@ PQconnectPoll(PGconn *conn)
28582914

28592915
case CONNECTION_CHECK_WRITABLE:
28602916
{
2917+
if (!saveErrorMessage(conn, &savedMessage))
2918+
goto error_return;
2919+
28612920
conn->status = CONNECTION_OK;
28622921
if (!PQconsumeInput(conn))
2922+
{
2923+
restoreErrorMessage(conn, &savedMessage);
28632924
goto error_return;
2925+
}
28642926

28652927
if (PQisBusy(conn))
28662928
{
28672929
conn->status = CONNECTION_CHECK_WRITABLE;
2930+
restoreErrorMessage(conn, &savedMessage);
28682931
return PGRES_POLLING_READING;
28692932
}
28702933

@@ -2878,6 +2941,7 @@ PQconnectPoll(PGconn *conn)
28782941
if (strncmp(val, "on", 2) == 0)
28792942
{
28802943
PQclear(res);
2944+
restoreErrorMessage(conn, &savedMessage);
28812945

28822946
/* Not writable; close connection. */
28832947
appendPQExpBuffer(&conn->errorMessage,
@@ -2902,6 +2966,7 @@ PQconnectPoll(PGconn *conn)
29022966
goto error_return;
29032967
}
29042968
PQclear(res);
2969+
termPQExpBuffer(&savedMessage);
29052970

29062971
/* We can release the address lists now. */
29072972
release_all_addrinfo(conn);
@@ -2917,6 +2982,7 @@ PQconnectPoll(PGconn *conn)
29172982
*/
29182983
if (res)
29192984
PQclear(res);
2985+
restoreErrorMessage(conn, &savedMessage);
29202986
appendPQExpBuffer(&conn->errorMessage,
29212987
libpq_gettext("test \"show transaction_read_only\" failed "
29222988
" on \"%s:%s\" \n"),

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy