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

Commit f3a0688

Browse files
committed
Add support for multiple error messages from libpq, by simply appending them
after each other (since we already add a newline on each, this makes them multiline). Previously a new error would just overwrite the old one, so for example any error caused when trying to connect with SSL enabled would be overwritten by the error message form the non-SSL connection when using sslmode=prefer.
1 parent 0fec77a commit f3a0688

File tree

5 files changed

+54
-36
lines changed

5 files changed

+54
-36
lines changed

doc/src/sgml/libpq.sgml

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.265 2008/09/22 14:21:44 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.266 2008/10/27 09:42:31 mha Exp $ -->
22

33
<chapter id="libpq">
44
<title><application>libpq</application> - C Library</title>
@@ -1137,10 +1137,11 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
11371137
Nearly all <application>libpq</> functions will set a message for
11381138
<function>PQerrorMessage</function> if they fail. Note that by
11391139
<application>libpq</application> convention, a nonempty
1140-
<function>PQerrorMessage</function> result will include a trailing
1141-
newline. The caller should not free the result directly. It will
1142-
be freed when the associated <structname>PGconn</> handle is passed
1143-
to <function>PQfinish</function>. The result string should not be
1140+
<function>PQerrorMessage</function> result can be multiple lines,
1141+
and will include a trailing newline. The caller should not free
1142+
the result directly. It will be freed when the associated
1143+
<structname>PGconn</> handle is passed to
1144+
<function>PQfinish</function>. The result string should not be
11441145
expected to remain the same across operations on the
11451146
<literal>PGconn</> structure.
11461147
</para>

src/interfaces/libpq/fe-connect.c

+26-23
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.363 2008/10/23 16:17:19 mha Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.364 2008/10/27 09:42:31 mha Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -699,7 +699,7 @@ connectNoDelay(PGconn *conn)
699699
{
700700
char sebuf[256];
701701

702-
printfPQExpBuffer(&conn->errorMessage,
702+
appendPQExpBuffer(&conn->errorMessage,
703703
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
704704
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
705705
return 0;
@@ -729,7 +729,7 @@ connectFailureMessage(PGconn *conn, int errorno)
729729
NULL, 0,
730730
service, sizeof(service),
731731
NI_NUMERICSERV);
732-
printfPQExpBuffer(&conn->errorMessage,
732+
appendPQExpBuffer(&conn->errorMessage,
733733
libpq_gettext("could not connect to server: %s\n"
734734
"\tIs the server running locally and accepting\n"
735735
"\tconnections on Unix domain socket \"%s\"?\n"),
@@ -739,7 +739,7 @@ connectFailureMessage(PGconn *conn, int errorno)
739739
else
740740
#endif /* HAVE_UNIX_SOCKETS */
741741
{
742-
printfPQExpBuffer(&conn->errorMessage,
742+
appendPQExpBuffer(&conn->errorMessage,
743743
libpq_gettext("could not connect to server: %s\n"
744744
"\tIs the server running on host \"%s\" and accepting\n"
745745
"\tTCP/IP connections on port %s?\n"),
@@ -829,11 +829,11 @@ connectDBStart(PGconn *conn)
829829
if (ret || !addrs)
830830
{
831831
if (node)
832-
printfPQExpBuffer(&conn->errorMessage,
832+
appendPQExpBuffer(&conn->errorMessage,
833833
libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
834834
node, gai_strerror(ret));
835835
else
836-
printfPQExpBuffer(&conn->errorMessage,
836+
appendPQExpBuffer(&conn->errorMessage,
837837
libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
838838
portstr, gai_strerror(ret));
839839
if (addrs)
@@ -924,6 +924,8 @@ connectDBComplete(PGconn *conn)
924924
switch (flag)
925925
{
926926
case PGRES_POLLING_OK:
927+
/* Reset stored error messages since we now have a working connection */
928+
resetPQExpBuffer(&conn->errorMessage);
927929
return 1; /* success! */
928930

929931
case PGRES_POLLING_READING:
@@ -1033,7 +1035,7 @@ PQconnectPoll(PGconn *conn)
10331035
break;
10341036

10351037
default:
1036-
printfPQExpBuffer(&conn->errorMessage,
1038+
appendPQExpBuffer(&conn->errorMessage,
10371039
libpq_gettext(
10381040
"invalid connection state, "
10391041
"probably indicative of memory corruption\n"
@@ -1077,7 +1079,7 @@ PQconnectPoll(PGconn *conn)
10771079
conn->addr_cur = addr_cur->ai_next;
10781080
continue;
10791081
}
1080-
printfPQExpBuffer(&conn->errorMessage,
1082+
appendPQExpBuffer(&conn->errorMessage,
10811083
libpq_gettext("could not create socket: %s\n"),
10821084
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
10831085
break;
@@ -1100,7 +1102,7 @@ PQconnectPoll(PGconn *conn)
11001102
}
11011103
if (!pg_set_noblock(conn->sock))
11021104
{
1103-
printfPQExpBuffer(&conn->errorMessage,
1105+
appendPQExpBuffer(&conn->errorMessage,
11041106
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
11051107
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
11061108
closesocket(conn->sock);
@@ -1112,7 +1114,7 @@ PQconnectPoll(PGconn *conn)
11121114
#ifdef F_SETFD
11131115
if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
11141116
{
1115-
printfPQExpBuffer(&conn->errorMessage,
1117+
appendPQExpBuffer(&conn->errorMessage,
11161118
libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
11171119
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
11181120
closesocket(conn->sock);
@@ -1199,7 +1201,7 @@ PQconnectPoll(PGconn *conn)
11991201
if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
12001202
(char *) &optval, &optlen) == -1)
12011203
{
1202-
printfPQExpBuffer(&conn->errorMessage,
1204+
appendPQExpBuffer(&conn->errorMessage,
12031205
libpq_gettext("could not get socket error status: %s\n"),
12041206
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
12051207
goto error_return;
@@ -1237,7 +1239,7 @@ PQconnectPoll(PGconn *conn)
12371239
(struct sockaddr *) & conn->laddr.addr,
12381240
&conn->laddr.salen) < 0)
12391241
{
1240-
printfPQExpBuffer(&conn->errorMessage,
1242+
appendPQExpBuffer(&conn->errorMessage,
12411243
libpq_gettext("could not get client address from socket: %s\n"),
12421244
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
12431245
goto error_return;
@@ -1281,7 +1283,7 @@ PQconnectPoll(PGconn *conn)
12811283
pv = htonl(NEGOTIATE_SSL_CODE);
12821284
if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
12831285
{
1284-
printfPQExpBuffer(&conn->errorMessage,
1286+
appendPQExpBuffer(&conn->errorMessage,
12851287
libpq_gettext("could not send SSL negotiation packet: %s\n"),
12861288
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
12871289
goto error_return;
@@ -1303,6 +1305,7 @@ PQconnectPoll(PGconn *conn)
13031305
EnvironmentOptions);
13041306
if (!startpacket)
13051307
{
1308+
/* will not appendbuffer here, since it's likely to also run out of memory */
13061309
printfPQExpBuffer(&conn->errorMessage,
13071310
libpq_gettext("out of memory\n"));
13081311
goto error_return;
@@ -1316,7 +1319,7 @@ PQconnectPoll(PGconn *conn)
13161319
*/
13171320
if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
13181321
{
1319-
printfPQExpBuffer(&conn->errorMessage,
1322+
appendPQExpBuffer(&conn->errorMessage,
13201323
libpq_gettext("could not send startup packet: %s\n"),
13211324
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
13221325
free(startpacket);
@@ -1381,7 +1384,7 @@ PQconnectPoll(PGconn *conn)
13811384
if (conn->sslmode[0] == 'r') /* "require" */
13821385
{
13831386
/* Require SSL, but server does not want it */
1384-
printfPQExpBuffer(&conn->errorMessage,
1387+
appendPQExpBuffer(&conn->errorMessage,
13851388
libpq_gettext("server does not support SSL, but SSL was required\n"));
13861389
goto error_return;
13871390
}
@@ -1398,7 +1401,7 @@ PQconnectPoll(PGconn *conn)
13981401
if (conn->sslmode[0] == 'r') /* "require" */
13991402
{
14001403
/* Require SSL, but server is too old */
1401-
printfPQExpBuffer(&conn->errorMessage,
1404+
appendPQExpBuffer(&conn->errorMessage,
14021405
libpq_gettext("server does not support SSL, but SSL was required\n"));
14031406
goto error_return;
14041407
}
@@ -1414,7 +1417,7 @@ PQconnectPoll(PGconn *conn)
14141417
}
14151418
else
14161419
{
1417-
printfPQExpBuffer(&conn->errorMessage,
1420+
appendPQExpBuffer(&conn->errorMessage,
14181421
libpq_gettext("received invalid response to SSL negotiation: %c\n"),
14191422
SSLok);
14201423
goto error_return;
@@ -1489,7 +1492,7 @@ PQconnectPoll(PGconn *conn)
14891492
*/
14901493
if (!(beresp == 'R' || beresp == 'E'))
14911494
{
1492-
printfPQExpBuffer(&conn->errorMessage,
1495+
appendPQExpBuffer(&conn->errorMessage,
14931496
libpq_gettext(
14941497
"expected authentication request from "
14951498
"server, but received %c\n"),
@@ -1522,7 +1525,7 @@ PQconnectPoll(PGconn *conn)
15221525
*/
15231526
if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
15241527
{
1525-
printfPQExpBuffer(&conn->errorMessage,
1528+
appendPQExpBuffer(&conn->errorMessage,
15261529
libpq_gettext(
15271530
"expected authentication request from "
15281531
"server, but received %c\n"),
@@ -1534,7 +1537,7 @@ PQconnectPoll(PGconn *conn)
15341537
{
15351538
/* Handle error from a pre-3.0 server */
15361539
conn->inCursor = conn->inStart + 1; /* reread data */
1537-
if (pqGets(&conn->errorMessage, conn))
1540+
if (pqGets_append(&conn->errorMessage, conn))
15381541
{
15391542
/* We'll come back when there is more data */
15401543
return PGRES_POLLING_READING;
@@ -1601,7 +1604,7 @@ PQconnectPoll(PGconn *conn)
16011604
}
16021605
else
16031606
{
1604-
if (pqGets(&conn->errorMessage, conn))
1607+
if (pqGets_append(&conn->errorMessage, conn))
16051608
{
16061609
/* We'll come back when there is more data */
16071610
return PGRES_POLLING_READING;
@@ -1788,7 +1791,7 @@ PQconnectPoll(PGconn *conn)
17881791
if (res)
17891792
{
17901793
if (res->resultStatus != PGRES_FATAL_ERROR)
1791-
printfPQExpBuffer(&conn->errorMessage,
1794+
appendPQExpBuffer(&conn->errorMessage,
17921795
libpq_gettext("unexpected message from server during startup\n"));
17931796

17941797
/*
@@ -1855,7 +1858,7 @@ PQconnectPoll(PGconn *conn)
18551858
return PGRES_POLLING_OK;
18561859

18571860
default:
1858-
printfPQExpBuffer(&conn->errorMessage,
1861+
appendPQExpBuffer(&conn->errorMessage,
18591862
libpq_gettext(
18601863
"invalid connection state %c, "
18611864
"probably indicative of memory corruption\n"

src/interfaces/libpq/fe-misc.c

+19-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* Portions Copyright (c) 1994, Regents of the University of California
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.135 2008/08/20 11:53:45 mha Exp $
26+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.136 2008/10/27 09:42:31 mha Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/
@@ -106,14 +106,14 @@ pqPutc(char c, PGconn *conn)
106106

107107

108108
/*
109-
* pqGets:
109+
* pqGets[_append]:
110110
* get a null-terminated string from the connection,
111111
* and store it in an expansible PQExpBuffer.
112112
* If we run out of memory, all of the string is still read,
113113
* but the excess characters are silently discarded.
114114
*/
115-
int
116-
pqGets(PQExpBuffer buf, PGconn *conn)
115+
static int
116+
pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
117117
{
118118
/* Copy conn data to locals for faster search loop */
119119
char *inBuffer = conn->inBuffer;
@@ -129,7 +129,9 @@ pqGets(PQExpBuffer buf, PGconn *conn)
129129

130130
slen = inCursor - conn->inCursor;
131131

132-
resetPQExpBuffer(buf);
132+
if (resetbuffer)
133+
resetPQExpBuffer(buf);
134+
133135
appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
134136

135137
conn->inCursor = ++inCursor;
@@ -141,6 +143,18 @@ pqGets(PQExpBuffer buf, PGconn *conn)
141143
return 0;
142144
}
143145

146+
int
147+
pqGets(PQExpBuffer buf, PGconn *conn)
148+
{
149+
return pqGets_internal(buf, conn, true);
150+
}
151+
152+
int
153+
pqGets_append(PQExpBuffer buf, PGconn *conn)
154+
{
155+
return pqGets_internal(buf, conn, false);
156+
}
157+
144158

145159
/*
146160
* pqPuts: write a null-terminated string to the current message

src/interfaces/libpq/fe-protocol3.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.35 2008/05/29 22:02:44 tgl Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.36 2008/10/27 09:42:31 mha Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -853,7 +853,6 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
853853
goto fail;
854854
pqClearAsyncResult(conn);
855855
conn->result = res;
856-
resetPQExpBuffer(&conn->errorMessage);
857856
appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
858857
}
859858
else

src/interfaces/libpq/libpq-int.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
15-
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.134 2008/09/22 14:21:44 tgl Exp $
15+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.135 2008/10/27 09:42:31 mha Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -519,6 +519,7 @@ extern int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn);
519519
extern int pqGetc(char *result, PGconn *conn);
520520
extern int pqPutc(char c, PGconn *conn);
521521
extern int pqGets(PQExpBuffer buf, PGconn *conn);
522+
extern int pqGets_append(PQExpBuffer buf, PGconn *conn);
522523
extern int pqPuts(const char *s, PGconn *conn);
523524
extern int pqGetnchar(char *s, size_t len, PGconn *conn);
524525
extern int pqPutnchar(const char *s, size_t len, PGconn *conn);

0 commit comments

Comments
 (0)