aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-connect.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2016-12-05 14:09:54 -0500
committerRobert Haas <rhaas@postgresql.org>2016-12-05 14:11:52 -0500
commita0ae54df9b153256a9d0afe45732853cb5ccae09 (patch)
treee8c6dc29e547b1fd78181781750f6d408c93b83a /src/interfaces/libpq/fe-connect.c
parent2f4193c3509a822c55cc0eae77e7788806d9b022 (diff)
downloadpostgresql-a0ae54df9b153256a9d0afe45732853cb5ccae09.tar.gz
postgresql-a0ae54df9b153256a9d0afe45732853cb5ccae09.zip
libpq: Fix another bug in 721f7bd3cbccaf8c07cad2707826b83f84694832.
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.
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r--src/interfaces/libpq/fe-connect.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 3b9b263a394..101cce8673f 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -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
*
@@ -1795,6 +1828,7 @@ PQconnectPoll(PGconn *conn)
PGresult *res;
char sebuf[256];
int optval;
+ PQExpBufferData savedMessage;
if (conn == NULL)
return PGRES_POLLING_FAILED;
@@ -2792,11 +2826,26 @@ keep_going: /* We will come back to here until there is
if (conn->target_session_attrs != NULL &&
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;
if (!PQsendQuery(conn,
"show transaction_read_only"))
+ {
+ restoreErrorMessage(conn, &savedMessage);
goto error_return;
+ }
conn->status = CONNECTION_CHECK_WRITABLE;
+ restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
@@ -2841,11 +2890,18 @@ keep_going: /* We will come back to here until there is
if (conn->target_session_attrs != NULL &&
strcmp(conn->target_session_attrs, "read-write") == 0)
{
+ if (!saveErrorMessage(conn, &savedMessage))
+ goto error_return;
+
conn->status = CONNECTION_OK;
if (!PQsendQuery(conn,
"show transaction_read_only"))
+ {
+ restoreErrorMessage(conn, &savedMessage);
goto error_return;
+ }
conn->status = CONNECTION_CHECK_WRITABLE;
+ restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
@@ -2858,13 +2914,20 @@ keep_going: /* We will come back to here until there is
case CONNECTION_CHECK_WRITABLE:
{
+ if (!saveErrorMessage(conn, &savedMessage))
+ goto error_return;
+
conn->status = CONNECTION_OK;
if (!PQconsumeInput(conn))
+ {
+ restoreErrorMessage(conn, &savedMessage);
goto error_return;
+ }
if (PQisBusy(conn))
{
conn->status = CONNECTION_CHECK_WRITABLE;
+ restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
@@ -2878,6 +2941,7 @@ keep_going: /* We will come back to here until there is
if (strncmp(val, "on", 2) == 0)
{
PQclear(res);
+ restoreErrorMessage(conn, &savedMessage);
/* Not writable; close connection. */
appendPQExpBuffer(&conn->errorMessage,
@@ -2902,6 +2966,7 @@ keep_going: /* We will come back to here until there is
goto error_return;
}
PQclear(res);
+ termPQExpBuffer(&savedMessage);
/* We can release the address lists now. */
release_all_addrinfo(conn);
@@ -2917,6 +2982,7 @@ keep_going: /* We will come back to here until there is
*/
if (res)
PQclear(res);
+ restoreErrorMessage(conn, &savedMessage);
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("test \"show transaction_read_only\" failed "
" on \"%s:%s\" \n"),