]> granicus.if.org Git - postgresql/commitdiff
Add support for multiple error messages from libpq, by simply appending them
authorMagnus Hagander <magnus@hagander.net>
Mon, 27 Oct 2008 09:42:31 +0000 (09:42 +0000)
committerMagnus Hagander <magnus@hagander.net>
Mon, 27 Oct 2008 09:42:31 +0000 (09:42 +0000)
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.

doc/src/sgml/libpq.sgml
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/fe-protocol3.c
src/interfaces/libpq/libpq-int.h

index 2e13e1daa4f960cdb9f4669f5ae26d6672aa6dd1..0aa134f4cdefbcd4af405d64d652f100e0821300 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.265 2008/09/22 14:21:44 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.266 2008/10/27 09:42:31 mha Exp $ -->
 
 <chapter id="libpq">
  <title><application>libpq</application> - C Library</title>
@@ -1137,10 +1137,11 @@ PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
        Nearly all <application>libpq</> functions will set a message for
        <function>PQerrorMessage</function> if they fail.  Note that by
        <application>libpq</application> convention, a nonempty
-       <function>PQerrorMessage</function> result will include a trailing
-       newline. The caller should not free the result directly. It will
-       be freed when the associated <structname>PGconn</> handle is passed
-       to <function>PQfinish</function>.  The result string should not be
+       <function>PQerrorMessage</function> result can be multiple lines,
+       and will include a trailing newline. The caller should not free
+       the result directly. It will be freed when the associated
+       <structname>PGconn</> handle is passed to
+       <function>PQfinish</function>.  The result string should not be
        expected to remain the same across operations on the
        <literal>PGconn</> structure.
       </para>
index 54aa71039705d719f97ae1d0ee15349da585d1a6..c611c0de1cbf969033cd3eeb638684510de3935d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.363 2008/10/23 16:17:19 mha Exp $
+ *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.364 2008/10/27 09:42:31 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -699,7 +699,7 @@ connectNoDelay(PGconn *conn)
        {
                char            sebuf[256];
 
-               printfPQExpBuffer(&conn->errorMessage,
+               appendPQExpBuffer(&conn->errorMessage,
                        libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
                                                  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                return 0;
@@ -729,7 +729,7 @@ connectFailureMessage(PGconn *conn, int errorno)
                                                   NULL, 0,
                                                   service, sizeof(service),
                                                   NI_NUMERICSERV);
-               printfPQExpBuffer(&conn->errorMessage,
+               appendPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("could not connect to server: %s\n"
                                                        "\tIs the server running locally and accepting\n"
                                                        "\tconnections on Unix domain socket \"%s\"?\n"),
@@ -739,7 +739,7 @@ connectFailureMessage(PGconn *conn, int errorno)
        else
 #endif   /* HAVE_UNIX_SOCKETS */
        {
-               printfPQExpBuffer(&conn->errorMessage,
+               appendPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("could not connect to server: %s\n"
                                         "\tIs the server running on host \"%s\" and accepting\n"
                                                                                "\tTCP/IP connections on port %s?\n"),
@@ -829,11 +829,11 @@ connectDBStart(PGconn *conn)
        if (ret || !addrs)
        {
                if (node)
-                       printfPQExpBuffer(&conn->errorMessage,
+                       appendPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
                                                          node, gai_strerror(ret));
                else
-                       printfPQExpBuffer(&conn->errorMessage,
+                       appendPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
                                                          portstr, gai_strerror(ret));
                if (addrs)
@@ -924,6 +924,8 @@ connectDBComplete(PGconn *conn)
                switch (flag)
                {
                        case PGRES_POLLING_OK:
+                               /* Reset stored error messages since we now have a working connection */
+                               resetPQExpBuffer(&conn->errorMessage);
                                return 1;               /* success! */
 
                        case PGRES_POLLING_READING:
@@ -1033,7 +1035,7 @@ PQconnectPoll(PGconn *conn)
                        break;
 
                default:
-                       printfPQExpBuffer(&conn->errorMessage,
+                       appendPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext(
                                                                                        "invalid connection state, "
                                                                 "probably indicative of memory corruption\n"
@@ -1077,7 +1079,7 @@ keep_going:                                               /* We will come back to here until there is
                                                        conn->addr_cur = addr_cur->ai_next;
                                                        continue;
                                                }
-                                               printfPQExpBuffer(&conn->errorMessage,
+                                               appendPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("could not create socket: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                                break;
@@ -1100,7 +1102,7 @@ keep_going:                                               /* We will come back to here until there is
                                        }
                                        if (!pg_set_noblock(conn->sock))
                                        {
-                                               printfPQExpBuffer(&conn->errorMessage,
+                                               appendPQExpBuffer(&conn->errorMessage,
                                                                                  libpq_gettext("could not set socket to non-blocking mode: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                                closesocket(conn->sock);
@@ -1112,7 +1114,7 @@ keep_going:                                               /* We will come back to here until there is
 #ifdef F_SETFD
                                        if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
                                        {
-                                               printfPQExpBuffer(&conn->errorMessage,
+                                               appendPQExpBuffer(&conn->errorMessage,
                                                                                  libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                                closesocket(conn->sock);
@@ -1199,7 +1201,7 @@ keep_going:                                               /* We will come back to here until there is
                                if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
                                                           (char *) &optval, &optlen) == -1)
                                {
-                                       printfPQExpBuffer(&conn->errorMessage,
+                                       appendPQExpBuffer(&conn->errorMessage,
                                        libpq_gettext("could not get socket error status: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        goto error_return;
@@ -1237,7 +1239,7 @@ keep_going:                                               /* We will come back to here until there is
                                                                (struct sockaddr *) & conn->laddr.addr,
                                                                &conn->laddr.salen) < 0)
                                {
-                                       printfPQExpBuffer(&conn->errorMessage,
+                                       appendPQExpBuffer(&conn->errorMessage,
                                                                          libpq_gettext("could not get client address from socket: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        goto error_return;
@@ -1281,7 +1283,7 @@ keep_going:                                               /* We will come back to here until there is
                                        pv = htonl(NEGOTIATE_SSL_CODE);
                                        if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
                                        {
-                                               printfPQExpBuffer(&conn->errorMessage,
+                                               appendPQExpBuffer(&conn->errorMessage,
                                                                                  libpq_gettext("could not send SSL negotiation packet: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                                goto error_return;
@@ -1303,6 +1305,7 @@ keep_going:                                               /* We will come back to here until there is
                                                                                                                EnvironmentOptions);
                                if (!startpacket)
                                {
+                                       /* will not appendbuffer here, since it's likely to also run out of memory */
                                        printfPQExpBuffer(&conn->errorMessage,
                                                                          libpq_gettext("out of memory\n"));
                                        goto error_return;
@@ -1316,7 +1319,7 @@ keep_going:                                               /* We will come back to here until there is
                                 */
                                if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
                                {
-                                       printfPQExpBuffer(&conn->errorMessage,
+                                       appendPQExpBuffer(&conn->errorMessage,
                                                libpq_gettext("could not send startup packet: %s\n"),
                                                        SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
                                        free(startpacket);
@@ -1381,7 +1384,7 @@ keep_going:                                               /* We will come back to here until there is
                                                if (conn->sslmode[0] == 'r')    /* "require" */
                                                {
                                                        /* Require SSL, but server does not want it */
-                                                       printfPQExpBuffer(&conn->errorMessage,
+                                                       appendPQExpBuffer(&conn->errorMessage,
                                                                                          libpq_gettext("server does not support SSL, but SSL was required\n"));
                                                        goto error_return;
                                                }
@@ -1398,7 +1401,7 @@ keep_going:                                               /* We will come back to here until there is
                                                if (conn->sslmode[0] == 'r')    /* "require" */
                                                {
                                                        /* Require SSL, but server is too old */
-                                                       printfPQExpBuffer(&conn->errorMessage,
+                                                       appendPQExpBuffer(&conn->errorMessage,
                                                                                          libpq_gettext("server does not support SSL, but SSL was required\n"));
                                                        goto error_return;
                                                }
@@ -1414,7 +1417,7 @@ keep_going:                                               /* We will come back to here until there is
                                        }
                                        else
                                        {
-                                               printfPQExpBuffer(&conn->errorMessage,
+                                               appendPQExpBuffer(&conn->errorMessage,
                                                                                  libpq_gettext("received invalid response to SSL negotiation: %c\n"),
                                                                                  SSLok);
                                                goto error_return;
@@ -1489,7 +1492,7 @@ keep_going:                                               /* We will come back to here until there is
                                 */
                                if (!(beresp == 'R' || beresp == 'E'))
                                {
-                                       printfPQExpBuffer(&conn->errorMessage,
+                                       appendPQExpBuffer(&conn->errorMessage,
                                                                          libpq_gettext(
                                                                          "expected authentication request from "
                                                                                                "server, but received %c\n"),
@@ -1522,7 +1525,7 @@ keep_going:                                               /* We will come back to here until there is
                                 */
                                if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
                                {
-                                       printfPQExpBuffer(&conn->errorMessage,
+                                       appendPQExpBuffer(&conn->errorMessage,
                                                                          libpq_gettext(
                                                                          "expected authentication request from "
                                                                                                "server, but received %c\n"),
@@ -1534,7 +1537,7 @@ keep_going:                                               /* We will come back to here until there is
                                {
                                        /* Handle error from a pre-3.0 server */
                                        conn->inCursor = conn->inStart + 1; /* reread data */
-                                       if (pqGets(&conn->errorMessage, conn))
+                                       if (pqGets_append(&conn->errorMessage, conn))
                                        {
                                                /* We'll come back when there is more data */
                                                return PGRES_POLLING_READING;
@@ -1601,7 +1604,7 @@ keep_going:                                               /* We will come back to here until there is
                                        }
                                        else
                                        {
-                                               if (pqGets(&conn->errorMessage, conn))
+                                               if (pqGets_append(&conn->errorMessage, conn))
                                                {
                                                        /* We'll come back when there is more data */
                                                        return PGRES_POLLING_READING;
@@ -1788,7 +1791,7 @@ keep_going:                                               /* We will come back to here until there is
                                if (res)
                                {
                                        if (res->resultStatus != PGRES_FATAL_ERROR)
-                                               printfPQExpBuffer(&conn->errorMessage,
+                                               appendPQExpBuffer(&conn->errorMessage,
                                                                                  libpq_gettext("unexpected message from server during startup\n"));
 
                                        /*
@@ -1855,7 +1858,7 @@ keep_going:                                               /* We will come back to here until there is
                        return PGRES_POLLING_OK;
 
                default:
-                       printfPQExpBuffer(&conn->errorMessage,
+                       appendPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext(
                                                                                        "invalid connection state %c, "
                                                                 "probably indicative of memory corruption\n"
index cc3e758ef2ecc2f65e183d141c83f80ad3a8111f..691262cf8abc62d2a83f49773f0477f69185b5e8 100644 (file)
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.135 2008/08/20 11:53:45 mha Exp $
+ *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.136 2008/10/27 09:42:31 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -106,14 +106,14 @@ pqPutc(char c, PGconn *conn)
 
 
 /*
- * pqGets:
+ * pqGets[_append]:
  * get a null-terminated string from the connection,
  * and store it in an expansible PQExpBuffer.
  * If we run out of memory, all of the string is still read,
  * but the excess characters are silently discarded.
  */
-int
-pqGets(PQExpBuffer buf, PGconn *conn)
+static int
+pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
 {
        /* Copy conn data to locals for faster search loop */
        char       *inBuffer = conn->inBuffer;
@@ -129,7 +129,9 @@ pqGets(PQExpBuffer buf, PGconn *conn)
 
        slen = inCursor - conn->inCursor;
 
-       resetPQExpBuffer(buf);
+       if (resetbuffer)
+               resetPQExpBuffer(buf);
+
        appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
 
        conn->inCursor = ++inCursor;
@@ -141,6 +143,18 @@ pqGets(PQExpBuffer buf, PGconn *conn)
        return 0;
 }
 
+int
+pqGets(PQExpBuffer buf, PGconn *conn)
+{
+       return pqGets_internal(buf, conn, true);
+}
+
+int
+pqGets_append(PQExpBuffer buf, PGconn *conn)
+{
+       return pqGets_internal(buf, conn, false);
+}
+
 
 /*
  * pqPuts: write a null-terminated string to the current message
index 66059493bb0788a475c1243d7b05c8d58aa259de..ba2798234f02d82a7befda100881cca6cd9b9b77 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.35 2008/05/29 22:02:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.36 2008/10/27 09:42:31 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -853,7 +853,6 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
                        goto fail;
                pqClearAsyncResult(conn);
                conn->result = res;
-               resetPQExpBuffer(&conn->errorMessage);
                appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
        }
        else
index 9702c616820914e460bcaad7a9459249d0e8da71..8525fb15f05906838dacf2c81dcfb589e492c8de 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.134 2008/09/22 14:21:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.135 2008/10/27 09:42:31 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -519,6 +519,7 @@ extern int  pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn);
 extern int     pqGetc(char *result, PGconn *conn);
 extern int     pqPutc(char c, PGconn *conn);
 extern int     pqGets(PQExpBuffer buf, PGconn *conn);
+extern int     pqGets_append(PQExpBuffer buf, PGconn *conn);
 extern int     pqPuts(const char *s, PGconn *conn);
 extern int     pqGetnchar(char *s, size_t len, PGconn *conn);
 extern int     pqPutnchar(const char *s, size_t len, PGconn *conn);