Commit a0ae54df authored by Robert Haas's avatar Robert Haas

libpq: Fix another bug in 721f7bd3.

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.
parent 2f4193c3
...@@ -1762,6 +1762,39 @@ connectDBComplete(PGconn *conn) ...@@ -1762,6 +1762,39 @@ connectDBComplete(PGconn *conn)
} }
} }
/*
* This subroutine saves conn->errorMessage, which will be restored back by
* restoreErrorMessage subroutine.
*/
static bool
saveErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
{
initPQExpBuffer(savedMessage);
if (PQExpBufferBroken(savedMessage))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
appendPQExpBufferStr(savedMessage,
conn->errorMessage.data);
resetPQExpBuffer(&conn->errorMessage);
return true;
}
/*
* Restores saved error messages back to conn->errorMessage.
*/
static void
restoreErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
{
appendPQExpBufferStr(savedMessage, conn->errorMessage.data);
resetPQExpBuffer(&conn->errorMessage);
appendPQExpBufferStr(&conn->errorMessage, savedMessage->data);
termPQExpBuffer(savedMessage);
}
/* ---------------- /* ----------------
* PQconnectPoll * PQconnectPoll
* *
...@@ -1795,6 +1828,7 @@ PQconnectPoll(PGconn *conn) ...@@ -1795,6 +1828,7 @@ PQconnectPoll(PGconn *conn)
PGresult *res; PGresult *res;
char sebuf[256]; char sebuf[256];
int optval; int optval;
PQExpBufferData savedMessage;
if (conn == NULL) if (conn == NULL)
return PGRES_POLLING_FAILED; return PGRES_POLLING_FAILED;
...@@ -2792,11 +2826,26 @@ keep_going: /* We will come back to here until there is ...@@ -2792,11 +2826,26 @@ keep_going: /* We will come back to here until there is
if (conn->target_session_attrs != NULL && if (conn->target_session_attrs != NULL &&
strcmp(conn->target_session_attrs, "read-write") == 0) strcmp(conn->target_session_attrs, "read-write") == 0)
{ {
/*
* We are yet to make a connection. Save all existing error
* messages until we make a successful connection state.
* This is important because PQsendQuery is going to reset
* conn->errorMessage and we will loose error messages
* related to previous hosts we have tried to connect and
* failed.
*/
if (!saveErrorMessage(conn, &savedMessage))
goto error_return;
conn->status = CONNECTION_OK; conn->status = CONNECTION_OK;
if (!PQsendQuery(conn, if (!PQsendQuery(conn,
"show transaction_read_only")) "show transaction_read_only"))
{
restoreErrorMessage(conn, &savedMessage);
goto error_return; goto error_return;
}
conn->status = CONNECTION_CHECK_WRITABLE; conn->status = CONNECTION_CHECK_WRITABLE;
restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING; return PGRES_POLLING_READING;
} }
...@@ -2841,11 +2890,18 @@ keep_going: /* We will come back to here until there is ...@@ -2841,11 +2890,18 @@ keep_going: /* We will come back to here until there is
if (conn->target_session_attrs != NULL && if (conn->target_session_attrs != NULL &&
strcmp(conn->target_session_attrs, "read-write") == 0) strcmp(conn->target_session_attrs, "read-write") == 0)
{ {
if (!saveErrorMessage(conn, &savedMessage))
goto error_return;
conn->status = CONNECTION_OK; conn->status = CONNECTION_OK;
if (!PQsendQuery(conn, if (!PQsendQuery(conn,
"show transaction_read_only")) "show transaction_read_only"))
{
restoreErrorMessage(conn, &savedMessage);
goto error_return; goto error_return;
}
conn->status = CONNECTION_CHECK_WRITABLE; conn->status = CONNECTION_CHECK_WRITABLE;
restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING; return PGRES_POLLING_READING;
} }
...@@ -2858,13 +2914,20 @@ keep_going: /* We will come back to here until there is ...@@ -2858,13 +2914,20 @@ keep_going: /* We will come back to here until there is
case CONNECTION_CHECK_WRITABLE: case CONNECTION_CHECK_WRITABLE:
{ {
if (!saveErrorMessage(conn, &savedMessage))
goto error_return;
conn->status = CONNECTION_OK; conn->status = CONNECTION_OK;
if (!PQconsumeInput(conn)) if (!PQconsumeInput(conn))
{
restoreErrorMessage(conn, &savedMessage);
goto error_return; goto error_return;
}
if (PQisBusy(conn)) if (PQisBusy(conn))
{ {
conn->status = CONNECTION_CHECK_WRITABLE; conn->status = CONNECTION_CHECK_WRITABLE;
restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING; return PGRES_POLLING_READING;
} }
...@@ -2878,6 +2941,7 @@ keep_going: /* We will come back to here until there is ...@@ -2878,6 +2941,7 @@ keep_going: /* We will come back to here until there is
if (strncmp(val, "on", 2) == 0) if (strncmp(val, "on", 2) == 0)
{ {
PQclear(res); PQclear(res);
restoreErrorMessage(conn, &savedMessage);
/* Not writable; close connection. */ /* Not writable; close connection. */
appendPQExpBuffer(&conn->errorMessage, appendPQExpBuffer(&conn->errorMessage,
...@@ -2902,6 +2966,7 @@ keep_going: /* We will come back to here until there is ...@@ -2902,6 +2966,7 @@ keep_going: /* We will come back to here until there is
goto error_return; goto error_return;
} }
PQclear(res); PQclear(res);
termPQExpBuffer(&savedMessage);
/* We can release the address lists now. */ /* We can release the address lists now. */
release_all_addrinfo(conn); release_all_addrinfo(conn);
...@@ -2917,6 +2982,7 @@ keep_going: /* We will come back to here until there is ...@@ -2917,6 +2982,7 @@ keep_going: /* We will come back to here until there is
*/ */
if (res) if (res)
PQclear(res); PQclear(res);
restoreErrorMessage(conn, &savedMessage);
appendPQExpBuffer(&conn->errorMessage, appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("test \"show transaction_read_only\" failed " libpq_gettext("test \"show transaction_read_only\" failed "
" on \"%s:%s\" \n"), " on \"%s:%s\" \n"),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment