On 23.09.22 04:45, Andres Freund wrote:
On 2022-09-22 19:27:27 -0700, Andres Freund wrote:
I just noticed it when trying to understand the linker failure - which I
still don't...
Heh, figured it out. It's inside #ifdef ENABLE_NLS. So it fails on all
platforms without NLS enabled.
Hah!
Here is an updated patch to get the CI clean. I'll look into the other
discussed issues later.
From de4cb33dcc98c7c71f21349eba650105a3385cbd Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Fri, 23 Sep 2022 16:26:16 -0400
Subject: [PATCH v2] WIP: libpq_append_error
Discussion:
https://www.postgresql.org/message-id/flat/7c0232ef-7b44-68db-599d-b327d0640...@enterprisedb.com
---
src/interfaces/libpq/fe-connect.c | 271 +++++++++++------------------
src/interfaces/libpq/fe-exec.c | 110 ++++--------
src/interfaces/libpq/fe-misc.c | 15 ++
src/interfaces/libpq/libpq-int.h | 2 +
src/interfaces/libpq/nls.mk | 4 +-
src/interfaces/libpq/pqexpbuffer.c | 27 ++-
src/interfaces/libpq/pqexpbuffer.h | 2 +
7 files changed, 186 insertions(+), 245 deletions(-)
diff --git a/src/interfaces/libpq/fe-connect.c
b/src/interfaces/libpq/fe-connect.c
index 746e9b4f1efc..b99c4549d08e 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -896,8 +896,7 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
*connmember = strdup(tmp);
if (*connmember == NULL)
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("out of memory\n"));
+ libpq_append_error(conn, "out of
memory");
return false;
}
}
@@ -1079,9 +1078,8 @@ connectOptions2(PGconn *conn)
if (more || i != conn->nconnhost)
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could
not match %d host names to %d hostaddr values\n"),
-
count_comma_separated_elems(conn->pghost), conn->nconnhost);
+ libpq_append_error(conn, "could not match %d host names
to %d hostaddr values",
+
count_comma_separated_elems(conn->pghost), conn->nconnhost);
return false;
}
}
@@ -1160,9 +1158,8 @@ connectOptions2(PGconn *conn)
else if (more || i != conn->nconnhost)
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could
not match %d port numbers to %d hosts\n"),
-
count_comma_separated_elems(conn->pgport), conn->nconnhost);
+ libpq_append_error(conn, "could not match %d port
numbers to %d hosts",
+
count_comma_separated_elems(conn->pgport), conn->nconnhost);
return false;
}
}
@@ -1250,9 +1247,8 @@ connectOptions2(PGconn *conn)
&& strcmp(conn->channel_binding, "require") != 0)
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("invalid %s value: \"%s\"\n"),
- "channel_binding",
conn->channel_binding);
+ libpq_append_error(conn, "invalid %s value: \"%s\"",
+ "channel_binding",
conn->channel_binding);
return false;
}
}
@@ -1276,9 +1272,8 @@ connectOptions2(PGconn *conn)
&& strcmp(conn->sslmode, "verify-full") != 0)
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("invalid %s value: \"%s\"\n"),
- "sslmode",
conn->sslmode);
+ libpq_append_error(conn, "invalid %s value: \"%s\"",
+ "sslmode",
conn->sslmode);
return false;
}
@@ -1297,9 +1292,8 @@ connectOptions2(PGconn *conn)
case 'r': /* "require" */
case 'v': /* "verify-ca" or
"verify-full" */
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled
in\n"),
-
conn->sslmode);
+ libpq_append_error(conn, "sslmode value \"%s\"
invalid when SSL support is not compiled in",
+
conn->sslmode);
return false;
}
#endif
@@ -1318,19 +1312,17 @@ connectOptions2(PGconn *conn)
if (!sslVerifyProtocolVersion(conn->ssl_min_protocol_version))
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid %s
value: \"%s\"\n"),
- "ssl_min_protocol_version",
-
conn->ssl_min_protocol_version);
+ libpq_append_error(conn, "invalid %s value: \"%s\"",
+ "ssl_min_protocol_version",
+
conn->ssl_min_protocol_version);
return false;
}
if (!sslVerifyProtocolVersion(conn->ssl_max_protocol_version))
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid %s
value: \"%s\"\n"),
- "ssl_max_protocol_version",
-
conn->ssl_max_protocol_version);
+ libpq_append_error(conn, "invalid %s value: \"%s\"",
+ "ssl_max_protocol_version",
+
conn->ssl_max_protocol_version);
return false;
}
@@ -1345,8 +1337,7 @@ connectOptions2(PGconn *conn)
conn->ssl_max_protocol_version))
{
conn->status = CONNECTION_BAD;
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("invalid
SSL protocol version range\n"));
+ libpq_append_error(conn, "invalid SSL protocol version range");
return false;
}
@@ -1360,19 +1351,15 @@ connectOptions2(PGconn *conn)
strcmp(conn->gssencmode, "require") != 0)
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("invalid %s value: \"%s\"\n"),
- "gssencmode",
- conn->gssencmode);
+ libpq_append_error(conn, "invalid %s value: \"%s\"",
"gssencmode", conn->gssencmode);
return false;
}
#ifndef ENABLE_GSS
if (strcmp(conn->gssencmode, "require") == 0)
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not
compiled in\n"),
- conn->gssencmode);
+ libpq_append_error(conn, "gssencmode value \"%s\"
invalid when GSSAPI support is not compiled in",
+ conn->gssencmode);
return false;
}
#endif
@@ -1404,10 +1391,9 @@ connectOptions2(PGconn *conn)
else
{
conn->status = CONNECTION_BAD;
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("invalid %s value: \"%s\"\n"),
-
"target_session_attrs",
-
conn->target_session_attrs);
+ libpq_append_error(conn, "invalid %s value: \"%s\"",
+
"target_session_attrs",
+
conn->target_session_attrs);
return false;
}
}
@@ -1437,8 +1423,7 @@ connectOptions2(PGconn *conn)
oom_error:
conn->status = CONNECTION_BAD;
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("out of
memory\n"));
+ libpq_append_error(conn, "out of memory");
return false;
}
@@ -1600,8 +1585,7 @@ PQsetdbLogin(const char *pghost, const char *pgport,
const char *pgoptions,
oom_error:
conn->status = CONNECTION_BAD;
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("out of
memory\n"));
+ libpq_append_error(conn, "out of memory");
return conn;
}
@@ -1624,9 +1608,8 @@ connectNoDelay(PGconn *conn)
{
char sebuf[PG_STRERROR_R_BUFLEN];
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not set
socket to TCP no delay mode: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could not set socket to TCP no delay
mode: %s",
+ SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
return 0;
}
#endif
@@ -1738,11 +1721,9 @@ connectFailureMessage(PGconn *conn, int errorno)
SOCK_STRERROR(errorno, sebuf,
sizeof(sebuf)));
if (conn->raddr.addr.ss_family == AF_UNIX)
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("\tIs
the server running locally and accepting connections on that socket?\n"));
+ libpq_append_error(conn, "\tIs the server running locally and
accepting connections on that socket?");
else
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("\tIs
the server running on that host and accepting TCP/IP connections?\n"));
+ libpq_append_error(conn, "\tIs the server running on that host
and accepting TCP/IP connections?");
}
/*
@@ -1805,9 +1786,8 @@ parse_int_param(const char *value, int *result, PGconn
*conn,
return true;
error:
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid integer value
\"%s\" for connection option \"%s\"\n"),
- value, context);
+ libpq_append_error(conn, "invalid integer value \"%s\" for connection
option \"%s\"",
+ value, context);
return false;
}
@@ -1835,11 +1815,10 @@ setKeepalivesIdle(PGconn *conn)
{
char sebuf[PG_STRERROR_R_BUFLEN];
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("%s(%s) failed:
%s\n"),
- "setsockopt",
- PG_TCP_KEEPALIVE_IDLE_STR,
- SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ PG_TCP_KEEPALIVE_IDLE_STR,
+ SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
return 0;
}
#endif
@@ -1870,11 +1849,10 @@ setKeepalivesInterval(PGconn *conn)
{
char sebuf[PG_STRERROR_R_BUFLEN];
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("%s(%s) failed:
%s\n"),
- "setsockopt",
- "TCP_KEEPINTVL",
- SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "TCP_KEEPINTVL",
+ SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
return 0;
}
#endif
@@ -1906,11 +1884,10 @@ setKeepalivesCount(PGconn *conn)
{
char sebuf[PG_STRERROR_R_BUFLEN];
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("%s(%s) failed:
%s\n"),
- "setsockopt",
- "TCP_KEEPCNT",
- SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "TCP_KEEPCNT",
+ SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
return 0;
}
#endif
@@ -1971,8 +1948,7 @@ prepKeepalivesWin32(PGconn *conn)
if (!setKeepalivesWin32(conn->sock, idle, interval))
{
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("%s(%s) failed:
error code %d\n"),
+ libpq_append_error(conn, "%s(%s) failed: error code %d",
"WSAIoctl",
"SIO_KEEPALIVE_VALS",
WSAGetLastError());
return 0;
@@ -2006,11 +1982,10 @@ setTCPUserTimeout(PGconn *conn)
{
char sebuf[256];
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("%s(%s) failed:
%s\n"),
- "setsockopt",
- "TCP_USER_TIMEOUT",
- SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "TCP_USER_TIMEOUT",
+ SOCK_STRERROR(SOCK_ERRNO,
sebuf, sizeof(sebuf)));
return 0;
}
#endif
@@ -2286,8 +2261,7 @@ PQconnectPoll(PGconn *conn)
break;
default:
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("invalid connection state, probably indicative of memory
corruption\n"));
+ libpq_append_error(conn, "invalid connection state,
probably indicative of memory corruption");
goto error_return;
}
@@ -2365,9 +2339,7 @@ PQconnectPoll(PGconn *conn)
if (thisport < 1 || thisport > 65535)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("invalid port number: \"%s\"\n"),
- ch->port);
+ libpq_append_error(conn, "invalid port number:
\"%s\"", ch->port);
goto keep_going;
}
}
@@ -2381,9 +2353,8 @@ PQconnectPoll(PGconn *conn)
&conn->addrlist);
if (ret || !conn->addrlist)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
-
ch->host, gai_strerror(ret));
+ libpq_append_error(conn, "could not
translate host name \"%s\" to address: %s",
+
ch->host, gai_strerror(ret));
goto keep_going;
}
break;
@@ -2394,9 +2365,8 @@ PQconnectPoll(PGconn *conn)
&conn->addrlist);
if (ret || !conn->addrlist)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not parse network address \"%s\": %s\n"),
-
ch->hostaddr, gai_strerror(ret));
+ libpq_append_error(conn, "could not
parse network address \"%s\": %s",
+
ch->hostaddr, gai_strerror(ret));
goto keep_going;
}
break;
@@ -2406,10 +2376,9 @@ PQconnectPoll(PGconn *conn)
UNIXSOCK_PATH(portstr, thisport, ch->host);
if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d
bytes)\n"),
-
portstr,
- (int)
(UNIXSOCK_PATH_BUFLEN - 1));
+ libpq_append_error(conn, "Unix-domain
socket path \"%s\" is too long (maximum %d bytes)",
+
portstr,
+
(int) (UNIXSOCK_PATH_BUFLEN - 1));
goto keep_going;
}
@@ -2421,9 +2390,8 @@ PQconnectPoll(PGconn *conn)
&conn->addrlist);
if (ret || !conn->addrlist)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not translate Unix-domain socket path \"%s\" to address:
%s\n"),
-
portstr, gai_strerror(ret));
+ libpq_append_error(conn, "could not
translate Unix-domain socket path \"%s\" to address: %s",
+
portstr, gai_strerror(ret));
goto keep_going;
}
break;
@@ -2544,9 +2512,8 @@ PQconnectPoll(PGconn *conn)
goto keep_going;
}
emitHostIdentityInfo(conn,
host_addr);
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not create socket: %s\n"),
-
SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could
not create socket: %s",
+
SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
goto error_return;
}
@@ -2575,9 +2542,8 @@ PQconnectPoll(PGconn *conn)
}
if (!pg_set_noblock(conn->sock))
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not set socket to nonblocking mode: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could
not set socket to nonblocking mode: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
conn->try_next_addr = true;
goto keep_going;
}
@@ -2585,9 +2551,8 @@ PQconnectPoll(PGconn *conn)
#ifdef F_SETFD
if (fcntl(conn->sock, F_SETFD,
FD_CLOEXEC) == -1)
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could
not set socket to close-on-exec mode: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
conn->try_next_addr = true;
goto keep_going;
}
@@ -2603,8 +2568,7 @@ PQconnectPoll(PGconn *conn)
if (usekeepalives < 0)
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("keepalives parameter must be an integer\n"));
+
libpq_append_error(conn, "keepalives parameter must be an integer");
err = 1;
}
else if (usekeepalives == 0)
@@ -2616,11 +2580,10 @@ PQconnectPoll(PGconn *conn)
SOL_SOCKET, SO_KEEPALIVE,
(char *) &on, sizeof(on)) < 0)
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("%s(%s) failed: %s\n"),
-
"setsockopt",
-
"SO_KEEPALIVE",
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+
libpq_append_error(conn, "%s(%s) failed: %s",
+
"setsockopt",
+
"SO_KEEPALIVE",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
err = 1;
}
else if
(!setKeepalivesIdle(conn)
@@ -2744,9 +2707,8 @@ PQconnectPoll(PGconn *conn)
if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
(char *) &optval,
&optlen) == -1)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not get socket error status: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could not get
socket error status: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
else if (optval != 0)
@@ -2772,9 +2734,8 @@ PQconnectPoll(PGconn *conn)
(struct
sockaddr *) &conn->laddr.addr,
&conn->laddr.salen) < 0)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not get client address from socket: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could not get
client address from socket: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
@@ -2811,12 +2772,10 @@ PQconnectPoll(PGconn *conn)
* stub
*/
if (errno == ENOSYS)
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("requirepeer parameter is not supported on this
platform\n"));
+
libpq_append_error(conn, "requirepeer parameter is not supported on this
platform");
else
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not get peer credentials: %s\n"),
-
strerror_r(errno, sebuf, sizeof(sebuf)));
+
libpq_append_error(conn, "could not get peer credentials: %s",
+
strerror_r(errno, sebuf, sizeof(sebuf)));
goto error_return;
}
@@ -2828,9 +2787,8 @@ PQconnectPoll(PGconn *conn)
if (strcmp(remote_username,
conn->requirepeer) != 0)
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is
\"%s\"\n"),
-
conn->requirepeer, remote_username);
+ libpq_append_error(conn,
"requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
+
conn->requirepeer, remote_username);
free(remote_username);
goto error_return;
}
@@ -2870,9 +2828,8 @@ PQconnectPoll(PGconn *conn)
if (pqPacketSend(conn, 0, &pv,
sizeof(pv)) != STATUS_OK)
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not send GSSAPI negotiation packet: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could
not send GSSAPI negotiation packet: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
@@ -2882,8 +2839,8 @@ PQconnectPoll(PGconn *conn)
}
else if (!conn->gctx && conn->gssencmode[0] ==
'r')
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("GSSAPI encryption required but was impossible (possibly no
credential cache, no server support, or using a local socket)\n"));
+ libpq_append_error(conn,
+
"GSSAPI encryption required but was impossible (possibly no credential cache,
no server support, or using a local socket)");
goto error_return;
}
#endif
@@ -2924,9 +2881,8 @@ PQconnectPoll(PGconn *conn)
pv = pg_hton32(NEGOTIATE_SSL_CODE);
if (pqPacketSend(conn, 0, &pv,
sizeof(pv)) != STATUS_OK)
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not send SSL negotiation packet: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could
not send SSL negotiation packet: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
/* Ok, wait for response */
@@ -2942,8 +2898,7 @@ PQconnectPoll(PGconn *conn)
EnvironmentOptions);
if (!startpacket)
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("out of memory\n"));
+ libpq_append_error(conn, "out of
memory");
goto error_return;
}
@@ -2955,9 +2910,8 @@ PQconnectPoll(PGconn *conn)
*/
if (pqPacketSend(conn, 0, startpacket,
packetlen) != STATUS_OK)
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("could not send startup packet: %s\n"),
-
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ libpq_append_error(conn, "could not
send startup packet: %s",
+
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
free(startpacket);
goto error_return;
}
@@ -3031,8 +2985,7 @@ PQconnectPoll(PGconn *conn)
* "verify-full" */
{
/* Require SSL, but
server does not want it */
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("server does not support SSL, but SSL was
required\n"));
+
libpq_append_error(conn, "server does not support SSL, but SSL was required");
goto error_return;
}
/* Otherwise, proceed with
normal startup */
@@ -3058,9 +3011,8 @@ PQconnectPoll(PGconn *conn)
}
else
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("received invalid response to SSL negotiation: %c\n"),
-
SSLok);
+ libpq_append_error(conn,
"received invalid response to SSL negotiation: %c",
+
SSLok);
goto error_return;
}
}
@@ -3079,8 +3031,7 @@ PQconnectPoll(PGconn *conn)
*/
if (conn->inCursor != conn->inEnd)
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("received unencrypted data after SSL response\n"));
+ libpq_append_error(conn,
"received unencrypted data after SSL response");
goto error_return;
}
@@ -3160,8 +3111,7 @@ PQconnectPoll(PGconn *conn)
/* Server doesn't want GSSAPI;
fall back if we can */
if (conn->gssencmode[0] == 'r')
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("server doesn't support GSSAPI encryption, but
it was required\n"));
+
libpq_append_error(conn, "server doesn't support GSSAPI encryption, but it was
required");
goto error_return;
}
@@ -3172,9 +3122,8 @@ PQconnectPoll(PGconn *conn)
}
else if (gss_ok != 'G')
{
-
appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("received invalid response to GSSAPI negotiation: %c\n"),
-
gss_ok);
+ libpq_append_error(conn,
"received invalid response to GSSAPI negotiation: %c",
+
gss_ok);
goto error_return;
}
}
@@ -3191,8 +3140,7 @@ PQconnectPoll(PGconn *conn)
*/
if (conn->inCursor != conn->inEnd)
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("received unencrypted data after GSSAPI encryption
response\n"));
+ libpq_append_error(conn,
"received unencrypted data after GSSAPI encryption response");
goto error_return;
}
@@ -3251,9 +3199,8 @@ PQconnectPoll(PGconn *conn)
*/
if (!(beresp == 'R' || beresp == 'E'))
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("expected authentication request from server, but received %c\n"),
-
beresp);
+ libpq_append_error(conn, "expected
authentication request from server, but received %c",
+
beresp);
goto error_return;
}
@@ -3276,9 +3223,8 @@ PQconnectPoll(PGconn *conn)
*/
if (beresp == 'R' && (msgLength < 8 ||
msgLength > 2000))
{
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("expected authentication request from server, but received %c\n"),
-
beresp);
+ libpq_append_error(conn, "expected
authentication request from server, but received %c",
+
beresp);
goto error_return;
}
@@ -3483,8 +3429,7 @@ PQconnectPoll(PGconn *conn)
if (res)
{
if (res->resultStatus !=
PGRES_FATAL_ERROR)
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("unexpected message from server during startup\n"));
+ libpq_append_error(conn,
"unexpected message from server during startup");
else if (conn->send_appname &&
(conn->appname ||
conn->fbappname))
{
@@ -3575,11 +3520,9 @@ PQconnectPoll(PGconn *conn)
{
/* Wrong server state, reject
and try the next host */
if (conn->target_server_type ==
SERVER_TYPE_READ_WRITE)
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("session is read-only\n"));
+
libpq_append_error(conn, "session is read-only");
else
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("session is not read-only\n"));
+
libpq_append_error(conn, "session is not read-only");
/* Close connection politely. */
conn->status = CONNECTION_OK;
@@ -3632,11 +3575,9 @@ PQconnectPoll(PGconn *conn)
{
/* Wrong server state, reject
and try the next host */
if (conn->target_server_type ==
SERVER_TYPE_PRIMARY)
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("server is in hot standby mode\n"));
+
libpq_append_error(conn, "server is in hot standby mode");
else
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("server is not in hot standby mode\n"));
+
libpq_append_error(conn, "server is not in hot standby mode");
/* Close connection politely. */
conn->status = CONNECTION_OK;
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 0274c1b156c6..5bc5d963aa68 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -1316,8 +1316,7 @@ pqAllocCmdQueueEntry(PGconn *conn)
entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry));
if (entry == NULL)
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("out of memory\n"));
+ libpq_append_error(conn, "out of memory");
return NULL;
}
}
@@ -1440,8 +1439,7 @@ PQsendQueryInternal(PGconn *conn, const char *query, bool
newQuery)
/* check the argument */
if (!query)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("command
string is a null pointer\n"));
+ libpq_append_error(conn, "command string is a null pointer");
return 0;
}
@@ -1511,15 +1509,13 @@ PQsendQueryParams(PGconn *conn,
/* check the arguments */
if (!command)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("command
string is a null pointer\n"));
+ libpq_append_error(conn, "command string is a null pointer");
return 0;
}
if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
{
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of
parameters must be between 0 and %d\n"),
- PQ_QUERY_PARAM_MAX_LIMIT);
+ libpq_append_error(conn, "number of parameters must be between
0 and %d",
+ PQ_QUERY_PARAM_MAX_LIMIT);
return 0;
}
@@ -1554,21 +1550,18 @@ PQsendPrepare(PGconn *conn,
/* check the arguments */
if (!stmtName)
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("statement name is a null pointer\n"));
+ libpq_append_error(conn, "statement name is a null pointer");
return 0;
}
if (!query)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("command
string is a null pointer\n"));
+ libpq_append_error(conn, "command string is a null pointer");
return 0;
}
if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
{
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of
parameters must be between 0 and %d\n"),
- PQ_QUERY_PARAM_MAX_LIMIT);
+ libpq_append_error(conn, "number of parameters must be between
0 and %d",
+ PQ_QUERY_PARAM_MAX_LIMIT);
return 0;
}
@@ -1656,15 +1649,13 @@ PQsendQueryPrepared(PGconn *conn,
/* check the arguments */
if (!stmtName)
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("statement name is a null pointer\n"));
+ libpq_append_error(conn, "statement name is a null pointer");
return 0;
}
if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
{
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of
parameters must be between 0 and %d\n"),
- PQ_QUERY_PARAM_MAX_LIMIT);
+ libpq_append_error(conn, "number of parameters must be between
0 and %d",
+ PQ_QUERY_PARAM_MAX_LIMIT);
return 0;
}
@@ -1700,8 +1691,7 @@ PQsendQueryStart(PGconn *conn, bool newQuery)
/* Don't try to send if we know there's no live connection. */
if (conn->status != CONNECTION_OK)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("no
connection to the server\n"));
+ libpq_append_error(conn, "no connection to the server");
return false;
}
@@ -1709,8 +1699,7 @@ PQsendQueryStart(PGconn *conn, bool newQuery)
if (conn->asyncStatus != PGASYNC_IDLE &&
conn->pipelineStatus == PQ_PIPELINE_OFF)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("another
command is already in progress\n"));
+ libpq_append_error(conn, "another command is already in
progress");
return false;
}
@@ -1740,8 +1729,7 @@ PQsendQueryStart(PGconn *conn, bool newQuery)
case PGASYNC_COPY_IN:
case PGASYNC_COPY_OUT:
case PGASYNC_COPY_BOTH:
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("cannot queue commands during COPY\n"));
+ libpq_append_error(conn, "cannot queue commands
during COPY");
return false;
}
}
@@ -1858,8 +1846,7 @@ PQsendQueryGuts(PGconn *conn,
nbytes = paramLengths[i];
else
{
-
appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("length must be given for binary parameter\n"));
+ libpq_append_error(conn, "length must
be given for binary parameter");
goto sendFailed;
}
}
@@ -2181,9 +2168,7 @@ PQgetResult(PGconn *conn)
res = getCopyResult(conn, PGRES_COPY_BOTH);
break;
default:
- appendPQExpBuffer(&conn->errorMessage,
-
libpq_gettext("unexpected asyncStatus: %d\n"),
- (int)
conn->asyncStatus);
+ libpq_append_error(conn, "unexpected asyncStatus: %d",
(int) conn->asyncStatus);
pqSaveErrorResult(conn);
conn->asyncStatus = PGASYNC_IDLE; /* try to
restore valid state */
res = pqPrepareAsyncResult(conn);
@@ -2339,8 +2324,7 @@ PQexecStart(PGconn *conn)
if (conn->pipelineStatus != PQ_PIPELINE_OFF)
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("synchronous command execution functions are not allowed in
pipeline mode\n"));
+ libpq_append_error(conn, "synchronous command execution
functions are not allowed in pipeline mode");
return false;
}
@@ -2373,8 +2357,7 @@ PQexecStart(PGconn *conn)
else if (resultStatus == PGRES_COPY_BOTH)
{
/* We don't allow PQexec during COPY BOTH */
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("PQexec not allowed during COPY BOTH\n"));
+ libpq_append_error(conn, "PQexec not allowed during
COPY BOTH");
return false;
}
/* check for loss of connection, too */
@@ -2600,8 +2583,7 @@ PQputCopyData(PGconn *conn, const char *buffer, int
nbytes)
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("no COPY
in progress\n"));
+ libpq_append_error(conn, "no COPY in progress");
return -1;
}
@@ -2656,8 +2638,7 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("no COPY
in progress\n"));
+ libpq_append_error(conn, "no COPY in progress");
return -1;
}
@@ -2725,8 +2706,7 @@ PQgetCopyData(PGconn *conn, char **buffer, int async)
if (conn->asyncStatus != PGASYNC_COPY_OUT &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("no COPY
in progress\n"));
+ libpq_append_error(conn, "no COPY in progress");
return -2;
}
return pqGetCopyData3(conn, buffer, async);
@@ -2905,17 +2885,14 @@ PQfn(PGconn *conn,
if (conn->pipelineStatus != PQ_PIPELINE_OFF)
{
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("%s not allowed
in pipeline mode\n"),
- "PQfn");
+ libpq_append_error(conn, "%s not allowed in pipeline mode",
"PQfn");
return NULL;
}
if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE
||
pgHavePendingResult(conn))
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("connection in wrong state\n"));
+ libpq_append_error(conn, "connection in wrong state");
return NULL;
}
@@ -2958,8 +2935,7 @@ PQenterPipelineMode(PGconn *conn)
if (conn->asyncStatus != PGASYNC_IDLE)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("cannot
enter pipeline mode, connection not idle\n"));
+ libpq_append_error(conn, "cannot enter pipeline mode,
connection not idle");
return 0;
}
@@ -2995,13 +2971,11 @@ PQexitPipelineMode(PGconn *conn)
case PGASYNC_READY:
case PGASYNC_READY_MORE:
/* there are some uncollected results */
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("cannot exit pipeline mode with uncollected results\n"));
+ libpq_append_error(conn, "cannot exit pipeline mode
with uncollected results");
return 0;
case PGASYNC_BUSY:
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("cannot exit pipeline mode while busy\n"));
+ libpq_append_error(conn, "cannot exit pipeline mode
while busy");
return 0;
case PGASYNC_IDLE:
@@ -3012,15 +2986,13 @@ PQexitPipelineMode(PGconn *conn)
case PGASYNC_COPY_IN:
case PGASYNC_COPY_OUT:
case PGASYNC_COPY_BOTH:
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("cannot exit pipeline mode while in COPY\n"));
+ libpq_append_error(conn, "cannot exit pipeline mode
while in COPY");
}
/* still work to process */
if (conn->cmd_queue_head != NULL)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("cannot
exit pipeline mode with uncollected results\n"));
+ libpq_append_error(conn, "cannot exit pipeline mode with
uncollected results");
return 0;
}
@@ -3135,8 +3107,7 @@ pqPipelineProcessQueue(PGconn *conn)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_PIPELINE_ABORTED);
if (!conn->result)
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("out of memory\n"));
+ libpq_append_error(conn, "out of memory");
pqSaveErrorResult(conn);
return;
}
@@ -3179,8 +3150,7 @@ PQpipelineSync(PGconn *conn)
if (conn->pipelineStatus == PQ_PIPELINE_OFF)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("cannot
send pipeline when not in pipeline mode\n"));
+ libpq_append_error(conn, "cannot send pipeline when not in
pipeline mode");
return 0;
}
@@ -3246,8 +3216,7 @@ PQsendFlushRequest(PGconn *conn)
/* Don't try to send if we know there's no live connection. */
if (conn->status != CONNECTION_OK)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("no
connection to the server\n"));
+ libpq_append_error(conn, "no connection to the server");
return 0;
}
@@ -3255,8 +3224,7 @@ PQsendFlushRequest(PGconn *conn)
if (conn->asyncStatus != PGASYNC_IDLE &&
conn->pipelineStatus == PQ_PIPELINE_OFF)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("another
command is already in progress\n"));
+ libpq_append_error(conn, "another command is already in
progress");
return 0;
}
@@ -3992,8 +3960,7 @@ PQescapeStringInternal(PGconn *conn,
if (error)
*error = 1;
if (conn)
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("incomplete multibyte character\n"));
+ libpq_append_error(conn, "incomplete multibyte
character");
for (; i < len; i++)
{
if (((size_t) (target - to)) / 2 >= length)
@@ -4083,8 +4050,7 @@ PQescapeInternal(PGconn *conn, const char *str, size_t
len, bool as_ident)
/* Multibyte character overruns allowable length. */
if ((s - str) + charlen > len || memchr(s, 0, charlen)
!= NULL)
{
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("incomplete multibyte character\n"));
+ libpq_append_error(conn, "incomplete multibyte
character");
return NULL;
}
@@ -4101,8 +4067,7 @@ PQescapeInternal(PGconn *conn, const char *str, size_t
len, bool as_ident)
result = rp = (char *) malloc(result_size);
if (rp == NULL)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("out of
memory\n"));
+ libpq_append_error(conn, "out of memory");
return NULL;
}
@@ -4266,8 +4231,7 @@ PQescapeByteaInternal(PGconn *conn,
if (rp == NULL)
{
if (conn)
- appendPQExpBufferStr(&conn->errorMessage,
-
libpq_gettext("out of memory\n"));
+ libpq_append_error(conn, "out of memory");
return NULL;
}
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 795500c59354..d505ed67cc1d 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -1278,3 +1278,18 @@ libpq_ngettext(const char *msgid, const char
*msgid_plural, unsigned long n)
}
#endif /* ENABLE_NLS */
+
+void
+libpq_append_error(PGconn *conn, const char *fmt, ...)
+{
+ va_list args;
+
+ Assert(fmt[strlen(fmt) - 1] != '\n');
+
+ va_start(args, fmt);
+
+ appendPQExpBufferVA(&conn->errorMessage, libpq_gettext(fmt), args);
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+
+ va_end(args);
+}
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index c75ed63a2c62..eeef80ab2b71 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -887,6 +887,8 @@ extern char *libpq_ngettext(const char *msgid, const char
*msgid_plural, unsigne
*/
#undef _
+extern void libpq_append_error(PGconn *conn, const char *fmt, ...)
pg_attribute_printf(2, 3);
+
/*
* These macros are needed to let error-handling code be portable between
* Unix and Windows. (ugh)
diff --git a/src/interfaces/libpq/nls.mk b/src/interfaces/libpq/nls.mk
index 9256b426c1d4..9d994ac1960a 100644
--- a/src/interfaces/libpq/nls.mk
+++ b/src/interfaces/libpq/nls.mk
@@ -1,5 +1,5 @@
# src/interfaces/libpq/nls.mk
CATALOG_NAME = libpq
GETTEXT_FILES = fe-auth.c fe-auth-scram.c fe-connect.c fe-exec.c
fe-gssapi-common.c fe-lobj.c fe-misc.c fe-protocol3.c fe-secure.c
fe-secure-common.c fe-secure-gssapi.c fe-secure-openssl.c win32.c
../../port/thread.c
-GETTEXT_TRIGGERS = libpq_gettext pqInternalNotice:2
-GETTEXT_FLAGS = libpq_gettext:1:pass-c-format pqInternalNotice:2:c-format
+GETTEXT_TRIGGERS = libpq_append_error:2 libpq_gettext pqInternalNotice:2
+GETTEXT_FLAGS = libpq_append_error:2 libpq_gettext:1:pass-c-format
pqInternalNotice:2:c-format
diff --git a/src/interfaces/libpq/pqexpbuffer.c
b/src/interfaces/libpq/pqexpbuffer.c
index eb51e6d08840..65621ec3b1c8 100644
--- a/src/interfaces/libpq/pqexpbuffer.c
+++ b/src/interfaces/libpq/pqexpbuffer.c
@@ -40,7 +40,7 @@ static const char oom_buffer[1] = "";
/* Need a char * for unconstify() compatibility */
static const char *oom_buffer_ptr = oom_buffer;
-static bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list
args) pg_attribute_printf(2, 0);
+static bool appendPQExpBufferVA_internal(PQExpBuffer str, const char *fmt,
va_list args) pg_attribute_printf(2, 0);
/*
@@ -250,7 +250,7 @@ printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
errno = save_errno;
va_start(args, fmt);
- done = appendPQExpBufferVA(str, fmt, args);
+ done = appendPQExpBufferVA_internal(str, fmt, args);
va_end(args);
} while (!done);
}
@@ -278,13 +278,30 @@ appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
errno = save_errno;
va_start(args, fmt);
- done = appendPQExpBufferVA(str, fmt, args);
+ done = appendPQExpBufferVA_internal(str, fmt, args);
va_end(args);
} while (!done);
}
+void
+appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
+{
+ int save_errno = errno;
+ bool done;
+
+ if (PQExpBufferBroken(str))
+ return; /* already failed */
+
+ /* Loop in case we have to retry after enlarging the buffer. */
+ do
+ {
+ errno = save_errno;
+ done = appendPQExpBufferVA_internal(str, fmt, args);
+ } while (!done);
+}
+
/*
- * appendPQExpBufferVA
+ * appendPQExpBufferVA_internal
* Shared guts of printfPQExpBuffer/appendPQExpBuffer.
* Attempt to format data and append it to str. Returns true if done
* (either successful or hard failure), false if need to retry.
@@ -293,7 +310,7 @@ appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
* when looping, in case the fmt contains "%m".
*/
static bool
-appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
+appendPQExpBufferVA_internal(PQExpBuffer str, const char *fmt, va_list args)
{
size_t avail;
size_t needed;
diff --git a/src/interfaces/libpq/pqexpbuffer.h
b/src/interfaces/libpq/pqexpbuffer.h
index efd652c80a33..b8216b8a7bd9 100644
--- a/src/interfaces/libpq/pqexpbuffer.h
+++ b/src/interfaces/libpq/pqexpbuffer.h
@@ -157,6 +157,8 @@ extern void printfPQExpBuffer(PQExpBuffer str, const char
*fmt,...) pg_attribute
*/
extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
pg_attribute_printf(2, 3);
+extern void appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list
args) pg_attribute_printf(2, 0);
+
/*------------------------
* appendPQExpBufferStr
* Append the given string to a PQExpBuffer, allocating more space
--
2.37.3