LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-protocol2.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 0 576 0.0 %
Date: 2017-09-29 15:12:54 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * fe-protocol2.c
       4             :  *    functions that are specific to frontend/backend protocol version 2
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/interfaces/libpq/fe-protocol2.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres_fe.h"
      16             : 
      17             : #include <ctype.h>
      18             : #include <fcntl.h>
      19             : 
      20             : #include "libpq-fe.h"
      21             : #include "libpq-int.h"
      22             : 
      23             : 
      24             : #ifdef WIN32
      25             : #include "win32.h"
      26             : #else
      27             : #include <unistd.h>
      28             : #include <netinet/in.h>
      29             : #ifdef HAVE_NETINET_TCP_H
      30             : #include <netinet/tcp.h>
      31             : #endif
      32             : #include <arpa/inet.h>
      33             : #endif
      34             : 
      35             : 
      36             : static int  getRowDescriptions(PGconn *conn);
      37             : static int  getAnotherTuple(PGconn *conn, bool binary);
      38             : static int  pqGetErrorNotice2(PGconn *conn, bool isError);
      39             : static void checkXactStatus(PGconn *conn, const char *cmdTag);
      40             : static int  getNotify(PGconn *conn);
      41             : 
      42             : 
      43             : /*
      44             :  *      pqSetenvPoll
      45             :  *
      46             :  * Polls the process of passing the values of a standard set of environment
      47             :  * variables to the backend.
      48             :  */
      49             : PostgresPollingStatusType
      50           0 : pqSetenvPoll(PGconn *conn)
      51             : {
      52             :     PGresult   *res;
      53             : 
      54           0 :     if (conn == NULL || conn->status == CONNECTION_BAD)
      55           0 :         return PGRES_POLLING_FAILED;
      56             : 
      57             :     /* Check whether there are any data for us */
      58           0 :     switch (conn->setenv_state)
      59             :     {
      60             :             /* These are reading states */
      61             :         case SETENV_STATE_CLIENT_ENCODING_WAIT:
      62             :         case SETENV_STATE_OPTION_WAIT:
      63             :         case SETENV_STATE_QUERY1_WAIT:
      64             :         case SETENV_STATE_QUERY2_WAIT:
      65             :             {
      66             :                 /* Load waiting data */
      67           0 :                 int         n = pqReadData(conn);
      68             : 
      69           0 :                 if (n < 0)
      70           0 :                     goto error_return;
      71           0 :                 if (n == 0)
      72           0 :                     return PGRES_POLLING_READING;
      73             : 
      74           0 :                 break;
      75             :             }
      76             : 
      77             :             /* These are writing states, so we just proceed. */
      78             :         case SETENV_STATE_CLIENT_ENCODING_SEND:
      79             :         case SETENV_STATE_OPTION_SEND:
      80             :         case SETENV_STATE_QUERY1_SEND:
      81             :         case SETENV_STATE_QUERY2_SEND:
      82           0 :             break;
      83             : 
      84             :             /* Should we raise an error if called when not active? */
      85             :         case SETENV_STATE_IDLE:
      86           0 :             return PGRES_POLLING_OK;
      87             : 
      88             :         default:
      89           0 :             printfPQExpBuffer(&conn->errorMessage,
      90             :                               libpq_gettext(
      91             :                                             "invalid setenv state %c, "
      92             :                                             "probably indicative of memory corruption\n"
      93             :                                             ),
      94           0 :                               conn->setenv_state);
      95           0 :             goto error_return;
      96             :     }
      97             : 
      98             :     /* We will loop here until there is nothing left to do in this call. */
      99             :     for (;;)
     100             :     {
     101           0 :         switch (conn->setenv_state)
     102             :         {
     103             :                 /*
     104             :                  * The _CLIENT_ENCODING_SEND code is slightly different from
     105             :                  * _OPTION_SEND below (e.g., no getenv() call), which is why a
     106             :                  * different state is used.
     107             :                  */
     108             :             case SETENV_STATE_CLIENT_ENCODING_SEND:
     109             :                 {
     110             :                     char        setQuery[100];  /* note length limit in
     111             :                                                  * sprintf below */
     112           0 :                     const char *val = conn->client_encoding_initial;
     113             : 
     114           0 :                     if (val)
     115             :                     {
     116           0 :                         if (pg_strcasecmp(val, "default") == 0)
     117           0 :                             sprintf(setQuery, "SET client_encoding = DEFAULT");
     118             :                         else
     119           0 :                             sprintf(setQuery, "SET client_encoding = '%.60s'",
     120             :                                     val);
     121             : #ifdef CONNECTDEBUG
     122             :                         fprintf(stderr,
     123             :                                 "Sending client_encoding with %s\n",
     124             :                                 setQuery);
     125             : #endif
     126           0 :                         if (!PQsendQuery(conn, setQuery))
     127           0 :                             goto error_return;
     128             : 
     129           0 :                         conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_WAIT;
     130             :                     }
     131             :                     else
     132           0 :                         conn->setenv_state = SETENV_STATE_OPTION_SEND;
     133           0 :                     break;
     134             :                 }
     135             : 
     136             :             case SETENV_STATE_OPTION_SEND:
     137             :                 {
     138             :                     /*
     139             :                      * Send SET commands for stuff directed by Environment
     140             :                      * Options.  Note: we assume that SET commands won't start
     141             :                      * transaction blocks, even in a 7.3 server with
     142             :                      * autocommit off.
     143             :                      */
     144             :                     char        setQuery[100];  /* note length limit in
     145             :                                                  * sprintf below */
     146             : 
     147           0 :                     if (conn->next_eo->envName)
     148             :                     {
     149             :                         const char *val;
     150             : 
     151           0 :                         if ((val = getenv(conn->next_eo->envName)))
     152             :                         {
     153           0 :                             if (pg_strcasecmp(val, "default") == 0)
     154           0 :                                 sprintf(setQuery, "SET %s = DEFAULT",
     155           0 :                                         conn->next_eo->pgName);
     156             :                             else
     157           0 :                                 sprintf(setQuery, "SET %s = '%.60s'",
     158           0 :                                         conn->next_eo->pgName, val);
     159             : #ifdef CONNECTDEBUG
     160             :                             fprintf(stderr,
     161             :                                     "Use environment variable %s to send %s\n",
     162             :                                     conn->next_eo->envName, setQuery);
     163             : #endif
     164           0 :                             if (!PQsendQuery(conn, setQuery))
     165           0 :                                 goto error_return;
     166             : 
     167           0 :                             conn->setenv_state = SETENV_STATE_OPTION_WAIT;
     168             :                         }
     169             :                         else
     170           0 :                             conn->next_eo++;
     171             :                     }
     172             :                     else
     173             :                     {
     174             :                         /* No more options to send, so move on to querying */
     175           0 :                         conn->setenv_state = SETENV_STATE_QUERY1_SEND;
     176             :                     }
     177           0 :                     break;
     178             :                 }
     179             : 
     180             :             case SETENV_STATE_CLIENT_ENCODING_WAIT:
     181             :                 {
     182           0 :                     if (PQisBusy(conn))
     183           0 :                         return PGRES_POLLING_READING;
     184             : 
     185           0 :                     res = PQgetResult(conn);
     186             : 
     187           0 :                     if (res)
     188             :                     {
     189           0 :                         if (PQresultStatus(res) != PGRES_COMMAND_OK)
     190             :                         {
     191           0 :                             PQclear(res);
     192           0 :                             goto error_return;
     193             :                         }
     194           0 :                         PQclear(res);
     195             :                         /* Keep reading until PQgetResult returns NULL */
     196             :                     }
     197             :                     else
     198             :                     {
     199             :                         /* Query finished, so send the next option */
     200           0 :                         conn->setenv_state = SETENV_STATE_OPTION_SEND;
     201             :                     }
     202           0 :                     break;
     203             :                 }
     204             : 
     205             :             case SETENV_STATE_OPTION_WAIT:
     206             :                 {
     207           0 :                     if (PQisBusy(conn))
     208           0 :                         return PGRES_POLLING_READING;
     209             : 
     210           0 :                     res = PQgetResult(conn);
     211             : 
     212           0 :                     if (res)
     213             :                     {
     214           0 :                         if (PQresultStatus(res) != PGRES_COMMAND_OK)
     215             :                         {
     216           0 :                             PQclear(res);
     217           0 :                             goto error_return;
     218             :                         }
     219           0 :                         PQclear(res);
     220             :                         /* Keep reading until PQgetResult returns NULL */
     221             :                     }
     222             :                     else
     223             :                     {
     224             :                         /* Query finished, so send the next option */
     225           0 :                         conn->next_eo++;
     226           0 :                         conn->setenv_state = SETENV_STATE_OPTION_SEND;
     227             :                     }
     228           0 :                     break;
     229             :                 }
     230             : 
     231             :             case SETENV_STATE_QUERY1_SEND:
     232             :                 {
     233             :                     /*
     234             :                      * Issue query to get information we need.  Here we must
     235             :                      * use begin/commit in case autocommit is off by default
     236             :                      * in a 7.3 server.
     237             :                      *
     238             :                      * Note: version() exists in all protocol-2.0-supporting
     239             :                      * backends.  In 7.3 it would be safer to write
     240             :                      * pg_catalog.version(), but we can't do that without
     241             :                      * causing problems on older versions.
     242             :                      */
     243           0 :                     if (!PQsendQuery(conn, "begin; select version(); end"))
     244           0 :                         goto error_return;
     245             : 
     246           0 :                     conn->setenv_state = SETENV_STATE_QUERY1_WAIT;
     247           0 :                     return PGRES_POLLING_READING;
     248             :                 }
     249             : 
     250             :             case SETENV_STATE_QUERY1_WAIT:
     251             :                 {
     252           0 :                     if (PQisBusy(conn))
     253           0 :                         return PGRES_POLLING_READING;
     254             : 
     255           0 :                     res = PQgetResult(conn);
     256             : 
     257           0 :                     if (res)
     258             :                     {
     259             :                         char       *val;
     260             : 
     261           0 :                         if (PQresultStatus(res) == PGRES_COMMAND_OK)
     262             :                         {
     263             :                             /* ignore begin/commit command results */
     264           0 :                             PQclear(res);
     265           0 :                             continue;
     266             :                         }
     267             : 
     268           0 :                         if (PQresultStatus(res) != PGRES_TUPLES_OK ||
     269           0 :                             PQntuples(res) != 1)
     270             :                         {
     271           0 :                             PQclear(res);
     272           0 :                             goto error_return;
     273             :                         }
     274             : 
     275             :                         /*
     276             :                          * Extract server version and save as if
     277             :                          * ParameterStatus
     278             :                          */
     279           0 :                         val = PQgetvalue(res, 0, 0);
     280           0 :                         if (val && strncmp(val, "PostgreSQL ", 11) == 0)
     281             :                         {
     282             :                             char       *ptr;
     283             : 
     284             :                             /* strip off PostgreSQL part */
     285           0 :                             val += 11;
     286             : 
     287             :                             /*
     288             :                              * strip off platform part (scribbles on result,
     289             :                              * naughty naughty)
     290             :                              */
     291           0 :                             ptr = strchr(val, ' ');
     292           0 :                             if (ptr)
     293           0 :                                 *ptr = '\0';
     294             : 
     295           0 :                             pqSaveParameterStatus(conn, "server_version",
     296             :                                                   val);
     297             :                         }
     298             : 
     299           0 :                         PQclear(res);
     300             :                         /* Keep reading until PQgetResult returns NULL */
     301             :                     }
     302             :                     else
     303             :                     {
     304             :                         /* Query finished, move to next */
     305           0 :                         conn->setenv_state = SETENV_STATE_QUERY2_SEND;
     306             :                     }
     307           0 :                     break;
     308             :                 }
     309             : 
     310             :             case SETENV_STATE_QUERY2_SEND:
     311             :                 {
     312             :                     const char *query;
     313             : 
     314             :                     /*
     315             :                      * pg_client_encoding does not exist in pre-7.2 servers.
     316             :                      * So we need to be prepared for an error here.  Do *not*
     317             :                      * start a transaction block, except in 7.3 servers where
     318             :                      * we need to prevent autocommit-off from starting a
     319             :                      * transaction anyway.
     320             :                      */
     321           0 :                     if (conn->sversion >= 70300 &&
     322           0 :                         conn->sversion < 70400)
     323           0 :                         query = "begin; select pg_catalog.pg_client_encoding(); end";
     324             :                     else
     325           0 :                         query = "select pg_client_encoding()";
     326           0 :                     if (!PQsendQuery(conn, query))
     327           0 :                         goto error_return;
     328             : 
     329           0 :                     conn->setenv_state = SETENV_STATE_QUERY2_WAIT;
     330           0 :                     return PGRES_POLLING_READING;
     331             :                 }
     332             : 
     333             :             case SETENV_STATE_QUERY2_WAIT:
     334             :                 {
     335           0 :                     if (PQisBusy(conn))
     336           0 :                         return PGRES_POLLING_READING;
     337             : 
     338           0 :                     res = PQgetResult(conn);
     339             : 
     340           0 :                     if (res)
     341             :                     {
     342             :                         const char *val;
     343             : 
     344           0 :                         if (PQresultStatus(res) == PGRES_COMMAND_OK)
     345             :                         {
     346             :                             /* ignore begin/commit command results */
     347           0 :                             PQclear(res);
     348           0 :                             continue;
     349             :                         }
     350             : 
     351           0 :                         if (PQresultStatus(res) == PGRES_TUPLES_OK &&
     352           0 :                             PQntuples(res) == 1)
     353             :                         {
     354             :                             /* Extract client encoding and save it */
     355           0 :                             val = PQgetvalue(res, 0, 0);
     356           0 :                             if (val && *val)    /* null should not happen, but */
     357           0 :                                 pqSaveParameterStatus(conn, "client_encoding",
     358             :                                                       val);
     359             :                         }
     360             :                         else
     361             :                         {
     362             :                             /*
     363             :                              * Error: presumably function not available, so
     364             :                              * use PGCLIENTENCODING or SQL_ASCII as the
     365             :                              * fallback.
     366             :                              */
     367           0 :                             val = getenv("PGCLIENTENCODING");
     368           0 :                             if (val && *val)
     369           0 :                                 pqSaveParameterStatus(conn, "client_encoding",
     370             :                                                       val);
     371             :                             else
     372           0 :                                 pqSaveParameterStatus(conn, "client_encoding",
     373             :                                                       "SQL_ASCII");
     374             :                         }
     375             : 
     376           0 :                         PQclear(res);
     377             :                         /* Keep reading until PQgetResult returns NULL */
     378             :                     }
     379             :                     else
     380             :                     {
     381             :                         /* Query finished, so we're done */
     382           0 :                         conn->setenv_state = SETENV_STATE_IDLE;
     383           0 :                         return PGRES_POLLING_OK;
     384             :                     }
     385           0 :                     break;
     386             :                 }
     387             : 
     388             :             default:
     389           0 :                 printfPQExpBuffer(&conn->errorMessage,
     390             :                                   libpq_gettext("invalid state %c, "
     391             :                                                 "probably indicative of memory corruption\n"),
     392           0 :                                   conn->setenv_state);
     393           0 :                 goto error_return;
     394             :         }
     395           0 :     }
     396             : 
     397             :     /* Unreachable */
     398             : 
     399             : error_return:
     400           0 :     conn->setenv_state = SETENV_STATE_IDLE;
     401           0 :     return PGRES_POLLING_FAILED;
     402             : }
     403             : 
     404             : 
     405             : /*
     406             :  * parseInput: if appropriate, parse input data from backend
     407             :  * until input is exhausted or a stopping state is reached.
     408             :  * Note that this function will NOT attempt to read more data from the backend.
     409             :  */
     410             : void
     411           0 : pqParseInput2(PGconn *conn)
     412             : {
     413             :     char        id;
     414             : 
     415             :     /*
     416             :      * Loop to parse successive complete messages available in the buffer.
     417             :      */
     418             :     for (;;)
     419             :     {
     420             :         /*
     421             :          * Quit if in COPY_OUT state: we expect raw data from the server until
     422             :          * PQendcopy is called.  Don't try to parse it according to the normal
     423             :          * protocol.  (This is bogus.  The data lines ought to be part of the
     424             :          * protocol and have identifying leading characters.)
     425             :          */
     426           0 :         if (conn->asyncStatus == PGASYNC_COPY_OUT)
     427           0 :             return;
     428             : 
     429             :         /*
     430             :          * OK to try to read a message type code.
     431             :          */
     432           0 :         conn->inCursor = conn->inStart;
     433           0 :         if (pqGetc(&id, conn))
     434           0 :             return;
     435             : 
     436             :         /*
     437             :          * NOTIFY and NOTICE messages can happen in any state besides COPY
     438             :          * OUT; always process them right away.
     439             :          *
     440             :          * Most other messages should only be processed while in BUSY state.
     441             :          * (In particular, in READY state we hold off further parsing until
     442             :          * the application collects the current PGresult.)
     443             :          *
     444             :          * However, if the state is IDLE then we got trouble; we need to deal
     445             :          * with the unexpected message somehow.
     446             :          */
     447           0 :         if (id == 'A')
     448             :         {
     449           0 :             if (getNotify(conn))
     450           0 :                 return;
     451             :         }
     452           0 :         else if (id == 'N')
     453             :         {
     454           0 :             if (pqGetErrorNotice2(conn, false))
     455           0 :                 return;
     456             :         }
     457           0 :         else if (conn->asyncStatus != PGASYNC_BUSY)
     458             :         {
     459             :             /* If not IDLE state, just wait ... */
     460           0 :             if (conn->asyncStatus != PGASYNC_IDLE)
     461           0 :                 return;
     462             : 
     463             :             /*
     464             :              * Unexpected message in IDLE state; need to recover somehow.
     465             :              * ERROR messages are displayed using the notice processor;
     466             :              * anything else is just dropped on the floor after displaying a
     467             :              * suitable warning notice.  (An ERROR is very possibly the
     468             :              * backend telling us why it is about to close the connection, so
     469             :              * we don't want to just discard it...)
     470             :              */
     471           0 :             if (id == 'E')
     472             :             {
     473           0 :                 if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
     474           0 :                     return;
     475             :             }
     476             :             else
     477             :             {
     478           0 :                 pqInternalNotice(&conn->noticeHooks,
     479             :                                  "message type 0x%02x arrived from server while idle",
     480             :                                  id);
     481             :                 /* Discard the unexpected message; good idea?? */
     482           0 :                 conn->inStart = conn->inEnd;
     483           0 :                 break;
     484             :             }
     485             :         }
     486             :         else
     487             :         {
     488             :             /*
     489             :              * In BUSY state, we can process everything.
     490             :              */
     491           0 :             switch (id)
     492             :             {
     493             :                 case 'C':       /* command complete */
     494           0 :                     if (pqGets(&conn->workBuffer, conn))
     495           0 :                         return;
     496           0 :                     if (conn->result == NULL)
     497             :                     {
     498           0 :                         conn->result = PQmakeEmptyPGresult(conn,
     499             :                                                            PGRES_COMMAND_OK);
     500           0 :                         if (!conn->result)
     501             :                         {
     502           0 :                             printfPQExpBuffer(&conn->errorMessage,
     503             :                                               libpq_gettext("out of memory"));
     504           0 :                             pqSaveErrorResult(conn);
     505             :                         }
     506             :                     }
     507           0 :                     if (conn->result)
     508             :                     {
     509           0 :                         strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
     510             :                                 CMDSTATUS_LEN);
     511             :                     }
     512           0 :                     checkXactStatus(conn, conn->workBuffer.data);
     513           0 :                     conn->asyncStatus = PGASYNC_READY;
     514           0 :                     break;
     515             :                 case 'E':       /* error return */
     516           0 :                     if (pqGetErrorNotice2(conn, true))
     517           0 :                         return;
     518           0 :                     conn->asyncStatus = PGASYNC_READY;
     519           0 :                     break;
     520             :                 case 'Z':       /* backend is ready for new query */
     521           0 :                     conn->asyncStatus = PGASYNC_IDLE;
     522           0 :                     break;
     523             :                 case 'I':       /* empty query */
     524             :                     /* read and throw away the closing '\0' */
     525           0 :                     if (pqGetc(&id, conn))
     526           0 :                         return;
     527           0 :                     if (id != '\0')
     528           0 :                         pqInternalNotice(&conn->noticeHooks,
     529             :                                          "unexpected character %c following empty query response (\"I\" message)",
     530             :                                          id);
     531           0 :                     if (conn->result == NULL)
     532             :                     {
     533           0 :                         conn->result = PQmakeEmptyPGresult(conn,
     534             :                                                            PGRES_EMPTY_QUERY);
     535           0 :                         if (!conn->result)
     536             :                         {
     537           0 :                             printfPQExpBuffer(&conn->errorMessage,
     538             :                                               libpq_gettext("out of memory"));
     539           0 :                             pqSaveErrorResult(conn);
     540             :                         }
     541             :                     }
     542           0 :                     conn->asyncStatus = PGASYNC_READY;
     543           0 :                     break;
     544             :                 case 'K':       /* secret key data from the backend */
     545             : 
     546             :                     /*
     547             :                      * This is expected only during backend startup, but it's
     548             :                      * just as easy to handle it as part of the main loop.
     549             :                      * Save the data and continue processing.
     550             :                      */
     551           0 :                     if (pqGetInt(&(conn->be_pid), 4, conn))
     552           0 :                         return;
     553           0 :                     if (pqGetInt(&(conn->be_key), 4, conn))
     554           0 :                         return;
     555           0 :                     break;
     556             :                 case 'P':       /* synchronous (normal) portal */
     557           0 :                     if (pqGets(&conn->workBuffer, conn))
     558           0 :                         return;
     559             :                     /* We pretty much ignore this message type... */
     560           0 :                     break;
     561             :                 case 'T':       /* row descriptions (start of query results) */
     562           0 :                     if (conn->result == NULL)
     563             :                     {
     564             :                         /* First 'T' in a query sequence */
     565           0 :                         if (getRowDescriptions(conn))
     566           0 :                             return;
     567             :                         /* getRowDescriptions() moves inStart itself */
     568           0 :                         continue;
     569             :                     }
     570             :                     else
     571             :                     {
     572             :                         /*
     573             :                          * A new 'T' message is treated as the start of
     574             :                          * another PGresult.  (It is not clear that this is
     575             :                          * really possible with the current backend.) We stop
     576             :                          * parsing until the application accepts the current
     577             :                          * result.
     578             :                          */
     579           0 :                         conn->asyncStatus = PGASYNC_READY;
     580           0 :                         return;
     581             :                     }
     582             :                     break;
     583             :                 case 'D':       /* ASCII data tuple */
     584           0 :                     if (conn->result != NULL)
     585             :                     {
     586             :                         /* Read another tuple of a normal query response */
     587           0 :                         if (getAnotherTuple(conn, FALSE))
     588           0 :                             return;
     589             :                         /* getAnotherTuple() moves inStart itself */
     590           0 :                         continue;
     591             :                     }
     592             :                     else
     593             :                     {
     594           0 :                         pqInternalNotice(&conn->noticeHooks,
     595             :                                          "server sent data (\"D\" message) without prior row description (\"T\" message)");
     596             :                         /* Discard the unexpected message; good idea?? */
     597           0 :                         conn->inStart = conn->inEnd;
     598           0 :                         return;
     599             :                     }
     600             :                     break;
     601             :                 case 'B':       /* Binary data tuple */
     602           0 :                     if (conn->result != NULL)
     603             :                     {
     604             :                         /* Read another tuple of a normal query response */
     605           0 :                         if (getAnotherTuple(conn, TRUE))
     606           0 :                             return;
     607             :                         /* getAnotherTuple() moves inStart itself */
     608           0 :                         continue;
     609             :                     }
     610             :                     else
     611             :                     {
     612           0 :                         pqInternalNotice(&conn->noticeHooks,
     613             :                                          "server sent binary data (\"B\" message) without prior row description (\"T\" message)");
     614             :                         /* Discard the unexpected message; good idea?? */
     615           0 :                         conn->inStart = conn->inEnd;
     616           0 :                         return;
     617             :                     }
     618             :                     break;
     619             :                 case 'G':       /* Start Copy In */
     620           0 :                     conn->asyncStatus = PGASYNC_COPY_IN;
     621           0 :                     break;
     622             :                 case 'H':       /* Start Copy Out */
     623           0 :                     conn->asyncStatus = PGASYNC_COPY_OUT;
     624           0 :                     break;
     625             : 
     626             :                     /*
     627             :                      * Don't need to process CopyBothResponse here because it
     628             :                      * never arrives from the server during protocol 2.0.
     629             :                      */
     630             :                 default:
     631           0 :                     printfPQExpBuffer(&conn->errorMessage,
     632             :                                       libpq_gettext(
     633             :                                                     "unexpected response from server; first received character was \"%c\"\n"),
     634             :                                       id);
     635             :                     /* build an error result holding the error message */
     636           0 :                     pqSaveErrorResult(conn);
     637             :                     /* Discard the unexpected message; good idea?? */
     638           0 :                     conn->inStart = conn->inEnd;
     639           0 :                     conn->asyncStatus = PGASYNC_READY;
     640           0 :                     return;
     641             :             }                   /* switch on protocol character */
     642             :         }
     643             :         /* Successfully consumed this message */
     644           0 :         conn->inStart = conn->inCursor;
     645           0 :     }
     646             : }
     647             : 
     648             : /*
     649             :  * parseInput subroutine to read a 'T' (row descriptions) message.
     650             :  * We build a PGresult structure containing the attribute data.
     651             :  * Returns: 0 if completed message, EOF if error or not enough data
     652             :  * received yet.
     653             :  *
     654             :  * Note that if we run out of data, we have to suspend and reprocess
     655             :  * the message after more data is received.  Otherwise, conn->inStart
     656             :  * must get advanced past the processed data.
     657             :  */
     658             : static int
     659           0 : getRowDescriptions(PGconn *conn)
     660             : {
     661             :     PGresult   *result;
     662             :     int         nfields;
     663             :     const char *errmsg;
     664             :     int         i;
     665             : 
     666           0 :     result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
     667           0 :     if (!result)
     668             :     {
     669           0 :         errmsg = NULL;          /* means "out of memory", see below */
     670           0 :         goto advance_and_error;
     671             :     }
     672             : 
     673             :     /* parseInput already read the 'T' label. */
     674             :     /* the next two bytes are the number of fields  */
     675           0 :     if (pqGetInt(&(result->numAttributes), 2, conn))
     676           0 :         goto EOFexit;
     677           0 :     nfields = result->numAttributes;
     678             : 
     679             :     /* allocate space for the attribute descriptors */
     680           0 :     if (nfields > 0)
     681             :     {
     682           0 :         result->attDescs = (PGresAttDesc *)
     683           0 :             pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
     684           0 :         if (!result->attDescs)
     685             :         {
     686           0 :             errmsg = NULL;      /* means "out of memory", see below */
     687           0 :             goto advance_and_error;
     688             :         }
     689           0 :         MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
     690             :     }
     691             : 
     692             :     /* get type info */
     693           0 :     for (i = 0; i < nfields; i++)
     694             :     {
     695             :         int         typid;
     696             :         int         typlen;
     697             :         int         atttypmod;
     698             : 
     699           0 :         if (pqGets(&conn->workBuffer, conn) ||
     700           0 :             pqGetInt(&typid, 4, conn) ||
     701           0 :             pqGetInt(&typlen, 2, conn) ||
     702           0 :             pqGetInt(&atttypmod, 4, conn))
     703             :             goto EOFexit;
     704             : 
     705             :         /*
     706             :          * Since pqGetInt treats 2-byte integers as unsigned, we need to
     707             :          * coerce the result to signed form.
     708             :          */
     709           0 :         typlen = (int) ((int16) typlen);
     710             : 
     711           0 :         result->attDescs[i].name = pqResultStrdup(result,
     712           0 :                                                   conn->workBuffer.data);
     713           0 :         if (!result->attDescs[i].name)
     714             :         {
     715           0 :             errmsg = NULL;      /* means "out of memory", see below */
     716           0 :             goto advance_and_error;
     717             :         }
     718           0 :         result->attDescs[i].tableid = 0;
     719           0 :         result->attDescs[i].columnid = 0;
     720           0 :         result->attDescs[i].format = 0;
     721           0 :         result->attDescs[i].typid = typid;
     722           0 :         result->attDescs[i].typlen = typlen;
     723           0 :         result->attDescs[i].atttypmod = atttypmod;
     724             :     }
     725             : 
     726             :     /* Success! */
     727           0 :     conn->result = result;
     728             : 
     729             :     /* Advance inStart to show that the "T" message has been processed. */
     730           0 :     conn->inStart = conn->inCursor;
     731             : 
     732             :     /*
     733             :      * We could perform additional setup for the new result set here, but for
     734             :      * now there's nothing else to do.
     735             :      */
     736             : 
     737             :     /* And we're done. */
     738           0 :     return 0;
     739             : 
     740             : advance_and_error:
     741             : 
     742             :     /*
     743             :      * Discard the failed message.  Unfortunately we don't know for sure where
     744             :      * the end is, so just throw away everything in the input buffer. This is
     745             :      * not very desirable but it's the best we can do in protocol v2.
     746             :      */
     747           0 :     conn->inStart = conn->inEnd;
     748             : 
     749             :     /*
     750             :      * Replace partially constructed result with an error result. First
     751             :      * discard the old result to try to win back some memory.
     752             :      */
     753           0 :     pqClearAsyncResult(conn);
     754             : 
     755             :     /*
     756             :      * If preceding code didn't provide an error message, assume "out of
     757             :      * memory" was meant.  The advantage of having this special case is that
     758             :      * freeing the old result first greatly improves the odds that gettext()
     759             :      * will succeed in providing a translation.
     760             :      */
     761           0 :     if (!errmsg)
     762           0 :         errmsg = libpq_gettext("out of memory for query result");
     763             : 
     764           0 :     printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
     765             : 
     766             :     /*
     767             :      * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
     768             :      * do to recover...
     769             :      */
     770           0 :     conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
     771           0 :     conn->asyncStatus = PGASYNC_READY;
     772             : 
     773             : EOFexit:
     774           0 :     if (result && result != conn->result)
     775           0 :         PQclear(result);
     776           0 :     return EOF;
     777             : }
     778             : 
     779             : /*
     780             :  * parseInput subroutine to read a 'B' or 'D' (row data) message.
     781             :  * We fill rowbuf with column pointers and then call the row processor.
     782             :  * Returns: 0 if completed message, EOF if error or not enough data
     783             :  * received yet.
     784             :  *
     785             :  * Note that if we run out of data, we have to suspend and reprocess
     786             :  * the message after more data is received.  Otherwise, conn->inStart
     787             :  * must get advanced past the processed data.
     788             :  */
     789             : static int
     790           0 : getAnotherTuple(PGconn *conn, bool binary)
     791             : {
     792           0 :     PGresult   *result = conn->result;
     793           0 :     int         nfields = result->numAttributes;
     794             :     const char *errmsg;
     795             :     PGdataValue *rowbuf;
     796             : 
     797             :     /* the backend sends us a bitmap of which attributes are null */
     798             :     char        std_bitmap[64]; /* used unless it doesn't fit */
     799           0 :     char       *bitmap = std_bitmap;
     800             :     int         i;
     801             :     size_t      nbytes;         /* the number of bytes in bitmap  */
     802             :     char        bmap;           /* One byte of the bitmap */
     803             :     int         bitmap_index;   /* Its index */
     804             :     int         bitcnt;         /* number of bits examined in current byte */
     805             :     int         vlen;           /* length of the current field value */
     806             : 
     807             :     /* Resize row buffer if needed */
     808           0 :     rowbuf = conn->rowBuf;
     809           0 :     if (nfields > conn->rowBufLen)
     810             :     {
     811           0 :         rowbuf = (PGdataValue *) realloc(rowbuf,
     812             :                                          nfields * sizeof(PGdataValue));
     813           0 :         if (!rowbuf)
     814             :         {
     815           0 :             errmsg = NULL;      /* means "out of memory", see below */
     816           0 :             goto advance_and_error;
     817             :         }
     818           0 :         conn->rowBuf = rowbuf;
     819           0 :         conn->rowBufLen = nfields;
     820             :     }
     821             : 
     822             :     /* Save format specifier */
     823           0 :     result->binary = binary;
     824             : 
     825             :     /*
     826             :      * If it's binary, fix the column format indicators.  We assume the
     827             :      * backend will consistently send either B or D, not a mix.
     828             :      */
     829           0 :     if (binary)
     830             :     {
     831           0 :         for (i = 0; i < nfields; i++)
     832           0 :             result->attDescs[i].format = 1;
     833             :     }
     834             : 
     835             :     /* Get the null-value bitmap */
     836           0 :     nbytes = (nfields + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
     837             :     /* malloc() only for unusually large field counts... */
     838           0 :     if (nbytes > sizeof(std_bitmap))
     839             :     {
     840           0 :         bitmap = (char *) malloc(nbytes);
     841           0 :         if (!bitmap)
     842             :         {
     843           0 :             errmsg = NULL;      /* means "out of memory", see below */
     844           0 :             goto advance_and_error;
     845             :         }
     846             :     }
     847             : 
     848           0 :     if (pqGetnchar(bitmap, nbytes, conn))
     849           0 :         goto EOFexit;
     850             : 
     851             :     /* Scan the fields */
     852           0 :     bitmap_index = 0;
     853           0 :     bmap = bitmap[bitmap_index];
     854           0 :     bitcnt = 0;
     855             : 
     856           0 :     for (i = 0; i < nfields; i++)
     857             :     {
     858             :         /* get the value length */
     859           0 :         if (!(bmap & 0200))
     860           0 :             vlen = NULL_LEN;
     861           0 :         else if (pqGetInt(&vlen, 4, conn))
     862           0 :             goto EOFexit;
     863             :         else
     864             :         {
     865           0 :             if (!binary)
     866           0 :                 vlen = vlen - 4;
     867           0 :             if (vlen < 0)
     868           0 :                 vlen = 0;
     869             :         }
     870           0 :         rowbuf[i].len = vlen;
     871             : 
     872             :         /*
     873             :          * rowbuf[i].value always points to the next address in the data
     874             :          * buffer even if the value is NULL.  This allows row processors to
     875             :          * estimate data sizes more easily.
     876             :          */
     877           0 :         rowbuf[i].value = conn->inBuffer + conn->inCursor;
     878             : 
     879             :         /* Skip over the data value */
     880           0 :         if (vlen > 0)
     881             :         {
     882           0 :             if (pqSkipnchar(vlen, conn))
     883           0 :                 goto EOFexit;
     884             :         }
     885             : 
     886             :         /* advance the bitmap stuff */
     887           0 :         bitcnt++;
     888           0 :         if (bitcnt == BITS_PER_BYTE)
     889             :         {
     890           0 :             bitmap_index++;
     891           0 :             bmap = bitmap[bitmap_index];
     892           0 :             bitcnt = 0;
     893             :         }
     894             :         else
     895           0 :             bmap <<= 1;
     896             :     }
     897             : 
     898             :     /* Release bitmap now if we allocated it */
     899           0 :     if (bitmap != std_bitmap)
     900           0 :         free(bitmap);
     901           0 :     bitmap = NULL;
     902             : 
     903             :     /* Advance inStart to show that the "D" message has been processed. */
     904           0 :     conn->inStart = conn->inCursor;
     905             : 
     906             :     /* Process the collected row */
     907           0 :     errmsg = NULL;
     908           0 :     if (pqRowProcessor(conn, &errmsg))
     909           0 :         return 0;               /* normal, successful exit */
     910             : 
     911           0 :     goto set_error_result;      /* pqRowProcessor failed, report it */
     912             : 
     913             : advance_and_error:
     914             : 
     915             :     /*
     916             :      * Discard the failed message.  Unfortunately we don't know for sure where
     917             :      * the end is, so just throw away everything in the input buffer. This is
     918             :      * not very desirable but it's the best we can do in protocol v2.
     919             :      */
     920           0 :     conn->inStart = conn->inEnd;
     921             : 
     922             : set_error_result:
     923             : 
     924             :     /*
     925             :      * Replace partially constructed result with an error result. First
     926             :      * discard the old result to try to win back some memory.
     927             :      */
     928           0 :     pqClearAsyncResult(conn);
     929             : 
     930             :     /*
     931             :      * If preceding code didn't provide an error message, assume "out of
     932             :      * memory" was meant.  The advantage of having this special case is that
     933             :      * freeing the old result first greatly improves the odds that gettext()
     934             :      * will succeed in providing a translation.
     935             :      */
     936           0 :     if (!errmsg)
     937           0 :         errmsg = libpq_gettext("out of memory for query result");
     938             : 
     939           0 :     printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
     940             : 
     941             :     /*
     942             :      * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
     943             :      * do to recover...
     944             :      */
     945           0 :     conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
     946           0 :     conn->asyncStatus = PGASYNC_READY;
     947             : 
     948             : EOFexit:
     949           0 :     if (bitmap != NULL && bitmap != std_bitmap)
     950           0 :         free(bitmap);
     951           0 :     return EOF;
     952             : }
     953             : 
     954             : 
     955             : /*
     956             :  * Attempt to read an Error or Notice response message.
     957             :  * This is possible in several places, so we break it out as a subroutine.
     958             :  * Entry: 'E' or 'N' message type has already been consumed.
     959             :  * Exit: returns 0 if successfully consumed message.
     960             :  *       returns EOF if not enough data.
     961             :  */
     962             : static int
     963           0 : pqGetErrorNotice2(PGconn *conn, bool isError)
     964             : {
     965           0 :     PGresult   *res = NULL;
     966             :     PQExpBufferData workBuf;
     967             :     char       *startp;
     968             :     char       *splitp;
     969             : 
     970             :     /*
     971             :      * Since the message might be pretty long, we create a temporary
     972             :      * PQExpBuffer rather than using conn->workBuffer.  workBuffer is intended
     973             :      * for stuff that is expected to be short.
     974             :      */
     975           0 :     initPQExpBuffer(&workBuf);
     976           0 :     if (pqGets(&workBuf, conn))
     977           0 :         goto failure;
     978             : 
     979             :     /*
     980             :      * Make a PGresult to hold the message.  We temporarily lie about the
     981             :      * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
     982             :      * conn->errorMessage.
     983             :      *
     984             :      * NB: This allocation can fail, if you run out of memory. The rest of the
     985             :      * function handles that gracefully, and we still try to set the error
     986             :      * message as the connection's error message.
     987             :      */
     988           0 :     res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
     989           0 :     if (res)
     990             :     {
     991           0 :         res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
     992           0 :         res->errMsg = pqResultStrdup(res, workBuf.data);
     993             :     }
     994             : 
     995             :     /*
     996             :      * Break the message into fields.  We can't do very much here, but we can
     997             :      * split the severity code off, and remove trailing newlines. Also, we use
     998             :      * the heuristic that the primary message extends only to the first
     999             :      * newline --- anything after that is detail message.  (In some cases it'd
    1000             :      * be better classed as hint, but we can hardly be expected to guess that
    1001             :      * here.)
    1002             :      */
    1003           0 :     while (workBuf.len > 0 && workBuf.data[workBuf.len - 1] == '\n')
    1004           0 :         workBuf.data[--workBuf.len] = '\0';
    1005           0 :     splitp = strstr(workBuf.data, ":  ");
    1006           0 :     if (splitp)
    1007             :     {
    1008             :         /* what comes before the colon is severity */
    1009           0 :         *splitp = '\0';
    1010           0 :         pqSaveMessageField(res, PG_DIAG_SEVERITY, workBuf.data);
    1011           0 :         startp = splitp + 3;
    1012             :     }
    1013             :     else
    1014             :     {
    1015             :         /* can't find a colon?  oh well... */
    1016           0 :         startp = workBuf.data;
    1017             :     }
    1018           0 :     splitp = strchr(startp, '\n');
    1019           0 :     if (splitp)
    1020             :     {
    1021             :         /* what comes before the newline is primary message */
    1022           0 :         *splitp++ = '\0';
    1023           0 :         pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, startp);
    1024             :         /* the rest is detail; strip any leading whitespace */
    1025           0 :         while (*splitp && isspace((unsigned char) *splitp))
    1026           0 :             splitp++;
    1027           0 :         pqSaveMessageField(res, PG_DIAG_MESSAGE_DETAIL, splitp);
    1028             :     }
    1029             :     else
    1030             :     {
    1031             :         /* single-line message, so all primary */
    1032           0 :         pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, startp);
    1033             :     }
    1034             : 
    1035             :     /*
    1036             :      * Either save error as current async result, or just emit the notice.
    1037             :      * Also, if it's an error and we were in a transaction block, assume the
    1038             :      * server has now gone to error-in-transaction state.
    1039             :      */
    1040           0 :     if (isError)
    1041             :     {
    1042           0 :         pqClearAsyncResult(conn);
    1043           0 :         conn->result = res;
    1044           0 :         resetPQExpBuffer(&conn->errorMessage);
    1045           0 :         if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
    1046           0 :             appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
    1047             :         else
    1048           0 :             printfPQExpBuffer(&conn->errorMessage,
    1049             :                               libpq_gettext("out of memory"));
    1050           0 :         if (conn->xactStatus == PQTRANS_INTRANS)
    1051           0 :             conn->xactStatus = PQTRANS_INERROR;
    1052             :     }
    1053             :     else
    1054             :     {
    1055           0 :         if (res)
    1056             :         {
    1057           0 :             if (res->noticeHooks.noticeRec != NULL)
    1058           0 :                 (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
    1059           0 :             PQclear(res);
    1060             :         }
    1061             :     }
    1062             : 
    1063           0 :     termPQExpBuffer(&workBuf);
    1064           0 :     return 0;
    1065             : 
    1066             : failure:
    1067           0 :     if (res)
    1068           0 :         PQclear(res);
    1069           0 :     termPQExpBuffer(&workBuf);
    1070           0 :     return EOF;
    1071             : }
    1072             : 
    1073             : /*
    1074             :  * checkXactStatus - attempt to track transaction-block status of server
    1075             :  *
    1076             :  * This is called each time we receive a command-complete message.  By
    1077             :  * watching for messages from BEGIN/COMMIT/ROLLBACK commands, we can do
    1078             :  * a passable job of tracking the server's xact status.  BUT: this does
    1079             :  * not work at all on 7.3 servers with AUTOCOMMIT OFF.  (Man, was that
    1080             :  * feature ever a mistake.)  Caveat user.
    1081             :  *
    1082             :  * The tags known here are all those used as far back as 7.0; is it worth
    1083             :  * adding those from even-older servers?
    1084             :  */
    1085             : static void
    1086           0 : checkXactStatus(PGconn *conn, const char *cmdTag)
    1087             : {
    1088           0 :     if (strcmp(cmdTag, "BEGIN") == 0)
    1089           0 :         conn->xactStatus = PQTRANS_INTRANS;
    1090           0 :     else if (strcmp(cmdTag, "COMMIT") == 0)
    1091           0 :         conn->xactStatus = PQTRANS_IDLE;
    1092           0 :     else if (strcmp(cmdTag, "ROLLBACK") == 0)
    1093           0 :         conn->xactStatus = PQTRANS_IDLE;
    1094           0 :     else if (strcmp(cmdTag, "START TRANSACTION") == 0)    /* 7.3 only */
    1095           0 :         conn->xactStatus = PQTRANS_INTRANS;
    1096             : 
    1097             :     /*
    1098             :      * Normally we get into INERROR state by detecting an Error message.
    1099             :      * However, if we see one of these tags then we know for sure the server
    1100             :      * is in abort state ...
    1101             :      */
    1102           0 :     else if (strcmp(cmdTag, "*ABORT STATE*") == 0)    /* pre-7.3 only */
    1103           0 :         conn->xactStatus = PQTRANS_INERROR;
    1104           0 : }
    1105             : 
    1106             : /*
    1107             :  * Attempt to read a Notify response message.
    1108             :  * This is possible in several places, so we break it out as a subroutine.
    1109             :  * Entry: 'A' message type and length have already been consumed.
    1110             :  * Exit: returns 0 if successfully consumed Notify message.
    1111             :  *       returns EOF if not enough data.
    1112             :  */
    1113             : static int
    1114           0 : getNotify(PGconn *conn)
    1115             : {
    1116             :     int         be_pid;
    1117             :     int         nmlen;
    1118             :     PGnotify   *newNotify;
    1119             : 
    1120           0 :     if (pqGetInt(&be_pid, 4, conn))
    1121           0 :         return EOF;
    1122           0 :     if (pqGets(&conn->workBuffer, conn))
    1123           0 :         return EOF;
    1124             : 
    1125             :     /*
    1126             :      * Store the relation name right after the PQnotify structure so it can
    1127             :      * all be freed at once.  We don't use NAMEDATALEN because we don't want
    1128             :      * to tie this interface to a specific server name length.
    1129             :      */
    1130           0 :     nmlen = strlen(conn->workBuffer.data);
    1131           0 :     newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + 1);
    1132           0 :     if (newNotify)
    1133             :     {
    1134           0 :         newNotify->relname = (char *) newNotify + sizeof(PGnotify);
    1135           0 :         strcpy(newNotify->relname, conn->workBuffer.data);
    1136             :         /* fake up an empty-string extra field */
    1137           0 :         newNotify->extra = newNotify->relname + nmlen;
    1138           0 :         newNotify->be_pid = be_pid;
    1139           0 :         newNotify->next = NULL;
    1140           0 :         if (conn->notifyTail)
    1141           0 :             conn->notifyTail->next = newNotify;
    1142             :         else
    1143           0 :             conn->notifyHead = newNotify;
    1144           0 :         conn->notifyTail = newNotify;
    1145             :     }
    1146             : 
    1147           0 :     return 0;
    1148             : }
    1149             : 
    1150             : 
    1151             : /*
    1152             :  * PQgetCopyData - read a row of data from the backend during COPY OUT
    1153             :  *
    1154             :  * If successful, sets *buffer to point to a malloc'd row of data, and
    1155             :  * returns row length (always > 0) as result.
    1156             :  * Returns 0 if no row available yet (only possible if async is true),
    1157             :  * -1 if end of copy (consult PQgetResult), or -2 if error (consult
    1158             :  * PQerrorMessage).
    1159             :  */
    1160             : int
    1161           0 : pqGetCopyData2(PGconn *conn, char **buffer, int async)
    1162             : {
    1163             :     bool        found;
    1164             :     int         msgLength;
    1165             : 
    1166             :     for (;;)
    1167             :     {
    1168             :         /*
    1169             :          * Do we have a complete line of data?
    1170             :          */
    1171           0 :         conn->inCursor = conn->inStart;
    1172           0 :         found = false;
    1173           0 :         while (conn->inCursor < conn->inEnd)
    1174             :         {
    1175           0 :             char        c = conn->inBuffer[conn->inCursor++];
    1176             : 
    1177           0 :             if (c == '\n')
    1178             :             {
    1179           0 :                 found = true;
    1180           0 :                 break;
    1181             :             }
    1182             :         }
    1183           0 :         if (!found)
    1184           0 :             goto nodata;
    1185           0 :         msgLength = conn->inCursor - conn->inStart;
    1186             : 
    1187             :         /*
    1188             :          * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and
    1189             :          * let caller read status with PQgetResult().
    1190             :          */
    1191           0 :         if (msgLength == 3 &&
    1192           0 :             strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)
    1193             :         {
    1194           0 :             conn->inStart = conn->inCursor;
    1195           0 :             conn->asyncStatus = PGASYNC_BUSY;
    1196           0 :             return -1;
    1197             :         }
    1198             : 
    1199             :         /*
    1200             :          * Pass the line back to the caller.
    1201             :          */
    1202           0 :         *buffer = (char *) malloc(msgLength + 1);
    1203           0 :         if (*buffer == NULL)
    1204             :         {
    1205           0 :             printfPQExpBuffer(&conn->errorMessage,
    1206             :                               libpq_gettext("out of memory\n"));
    1207           0 :             return -2;
    1208             :         }
    1209           0 :         memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
    1210           0 :         (*buffer)[msgLength] = '\0';    /* Add terminating null */
    1211             : 
    1212             :         /* Mark message consumed */
    1213           0 :         conn->inStart = conn->inCursor;
    1214             : 
    1215           0 :         return msgLength;
    1216             : 
    1217             : nodata:
    1218             :         /* Don't block if async read requested */
    1219           0 :         if (async)
    1220           0 :             return 0;
    1221             :         /* Need to load more data */
    1222           0 :         if (pqWait(TRUE, FALSE, conn) ||
    1223           0 :             pqReadData(conn) < 0)
    1224           0 :             return -2;
    1225           0 :     }
    1226             : }
    1227             : 
    1228             : 
    1229             : /*
    1230             :  * PQgetline - gets a newline-terminated string from the backend.
    1231             :  *
    1232             :  * See fe-exec.c for documentation.
    1233             :  */
    1234             : int
    1235           0 : pqGetline2(PGconn *conn, char *s, int maxlen)
    1236             : {
    1237           0 :     int         result = 1;     /* return value if buffer overflows */
    1238             : 
    1239           0 :     if (conn->sock == PGINVALID_SOCKET ||
    1240           0 :         conn->asyncStatus != PGASYNC_COPY_OUT)
    1241             :     {
    1242           0 :         *s = '\0';
    1243           0 :         return EOF;
    1244             :     }
    1245             : 
    1246             :     /*
    1247             :      * Since this is a purely synchronous routine, we don't bother to maintain
    1248             :      * conn->inCursor; there is no need to back up.
    1249             :      */
    1250           0 :     while (maxlen > 1)
    1251             :     {
    1252           0 :         if (conn->inStart < conn->inEnd)
    1253             :         {
    1254           0 :             char        c = conn->inBuffer[conn->inStart++];
    1255             : 
    1256           0 :             if (c == '\n')
    1257             :             {
    1258           0 :                 result = 0;     /* success exit */
    1259           0 :                 break;
    1260             :             }
    1261           0 :             *s++ = c;
    1262           0 :             maxlen--;
    1263             :         }
    1264             :         else
    1265             :         {
    1266             :             /* need to load more data */
    1267           0 :             if (pqWait(TRUE, FALSE, conn) ||
    1268           0 :                 pqReadData(conn) < 0)
    1269             :             {
    1270           0 :                 result = EOF;
    1271           0 :                 break;
    1272             :             }
    1273             :         }
    1274             :     }
    1275           0 :     *s = '\0';
    1276             : 
    1277           0 :     return result;
    1278             : }
    1279             : 
    1280             : /*
    1281             :  * PQgetlineAsync - gets a COPY data row without blocking.
    1282             :  *
    1283             :  * See fe-exec.c for documentation.
    1284             :  */
    1285             : int
    1286           0 : pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize)
    1287             : {
    1288             :     int         avail;
    1289             : 
    1290           0 :     if (conn->asyncStatus != PGASYNC_COPY_OUT)
    1291           0 :         return -1;              /* we are not doing a copy... */
    1292             : 
    1293             :     /*
    1294             :      * Move data from libpq's buffer to the caller's. We want to accept data
    1295             :      * only in units of whole lines, not partial lines.  This ensures that we
    1296             :      * can recognize the terminator line "\\.\n".  (Otherwise, if it happened
    1297             :      * to cross a packet/buffer boundary, we might hand the first one or two
    1298             :      * characters off to the caller, which we shouldn't.)
    1299             :      */
    1300             : 
    1301           0 :     conn->inCursor = conn->inStart;
    1302             : 
    1303           0 :     avail = bufsize;
    1304           0 :     while (avail > 0 && conn->inCursor < conn->inEnd)
    1305             :     {
    1306           0 :         char        c = conn->inBuffer[conn->inCursor++];
    1307             : 
    1308           0 :         *buffer++ = c;
    1309           0 :         --avail;
    1310           0 :         if (c == '\n')
    1311             :         {
    1312             :             /* Got a complete line; mark the data removed from libpq */
    1313           0 :             conn->inStart = conn->inCursor;
    1314             :             /* Is it the endmarker line? */
    1315           0 :             if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
    1316           0 :                 return -1;
    1317             :             /* No, return the data line to the caller */
    1318           0 :             return bufsize - avail;
    1319             :         }
    1320             :     }
    1321             : 
    1322             :     /*
    1323             :      * We don't have a complete line. We'd prefer to leave it in libpq's
    1324             :      * buffer until the rest arrives, but there is a special case: what if the
    1325             :      * line is longer than the buffer the caller is offering us?  In that case
    1326             :      * we'd better hand over a partial line, else we'd get into an infinite
    1327             :      * loop. Do this in a way that ensures we can't misrecognize a terminator
    1328             :      * line later: leave last 3 characters in libpq buffer.
    1329             :      */
    1330           0 :     if (avail == 0 && bufsize > 3)
    1331             :     {
    1332           0 :         conn->inStart = conn->inCursor - 3;
    1333           0 :         return bufsize - 3;
    1334             :     }
    1335           0 :     return 0;
    1336             : }
    1337             : 
    1338             : /*
    1339             :  * PQendcopy
    1340             :  *
    1341             :  * See fe-exec.c for documentation.
    1342             :  */
    1343             : int
    1344           0 : pqEndcopy2(PGconn *conn)
    1345             : {
    1346             :     PGresult   *result;
    1347             : 
    1348           0 :     if (conn->asyncStatus != PGASYNC_COPY_IN &&
    1349           0 :         conn->asyncStatus != PGASYNC_COPY_OUT)
    1350             :     {
    1351           0 :         printfPQExpBuffer(&conn->errorMessage,
    1352             :                           libpq_gettext("no COPY in progress\n"));
    1353           0 :         return 1;
    1354             :     }
    1355             : 
    1356             :     /*
    1357             :      * make sure no data is waiting to be sent, abort if we are non-blocking
    1358             :      * and the flush fails
    1359             :      */
    1360           0 :     if (pqFlush(conn) && pqIsnonblocking(conn))
    1361           0 :         return 1;
    1362             : 
    1363             :     /* non blocking connections may have to abort at this point. */
    1364           0 :     if (pqIsnonblocking(conn) && PQisBusy(conn))
    1365           0 :         return 1;
    1366             : 
    1367             :     /* Return to active duty */
    1368           0 :     conn->asyncStatus = PGASYNC_BUSY;
    1369           0 :     resetPQExpBuffer(&conn->errorMessage);
    1370             : 
    1371             :     /* Wait for the completion response */
    1372           0 :     result = PQgetResult(conn);
    1373             : 
    1374             :     /* Expecting a successful result */
    1375           0 :     if (result && result->resultStatus == PGRES_COMMAND_OK)
    1376             :     {
    1377           0 :         PQclear(result);
    1378           0 :         return 0;
    1379             :     }
    1380             : 
    1381             :     /*
    1382             :      * Trouble. For backwards-compatibility reasons, we issue the error
    1383             :      * message as if it were a notice (would be nice to get rid of this
    1384             :      * silliness, but too many apps probably don't handle errors from
    1385             :      * PQendcopy reasonably).  Note that the app can still obtain the error
    1386             :      * status from the PGconn object.
    1387             :      */
    1388           0 :     if (conn->errorMessage.len > 0)
    1389             :     {
    1390             :         /* We have to strip the trailing newline ... pain in neck... */
    1391           0 :         char        svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
    1392             : 
    1393           0 :         if (svLast == '\n')
    1394           0 :             conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
    1395           0 :         pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
    1396           0 :         conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
    1397             :     }
    1398             : 
    1399           0 :     PQclear(result);
    1400             : 
    1401             :     /*
    1402             :      * The worst case is that we've lost sync with the backend entirely due to
    1403             :      * application screwup of the copy in/out protocol. To recover, reset the
    1404             :      * connection (talk about using a sledgehammer...)
    1405             :      */
    1406           0 :     pqInternalNotice(&conn->noticeHooks,
    1407             :                      "lost synchronization with server, resetting connection");
    1408             : 
    1409             :     /*
    1410             :      * Users doing non-blocking connections need to handle the reset
    1411             :      * themselves, they'll need to check the connection status if we return an
    1412             :      * error.
    1413             :      */
    1414           0 :     if (pqIsnonblocking(conn))
    1415           0 :         PQresetStart(conn);
    1416             :     else
    1417           0 :         PQreset(conn);
    1418             : 
    1419           0 :     return 1;
    1420             : }
    1421             : 
    1422             : 
    1423             : /*
    1424             :  * PQfn - Send a function call to the POSTGRES backend.
    1425             :  *
    1426             :  * See fe-exec.c for documentation.
    1427             :  */
    1428             : PGresult *
    1429           0 : pqFunctionCall2(PGconn *conn, Oid fnid,
    1430             :                 int *result_buf, int *actual_result_len,
    1431             :                 int result_is_int,
    1432             :                 const PQArgBlock *args, int nargs)
    1433             : {
    1434           0 :     bool        needInput = false;
    1435           0 :     ExecStatusType status = PGRES_FATAL_ERROR;
    1436             :     char        id;
    1437             :     int         i;
    1438             : 
    1439             :     /* PQfn already validated connection state */
    1440             : 
    1441           0 :     if (pqPutMsgStart('F', false, conn) < 0 ||   /* function call msg */
    1442           0 :         pqPuts(" ", conn) < 0 ||   /* dummy string */
    1443           0 :         pqPutInt(fnid, 4, conn) != 0 || /* function id */
    1444           0 :         pqPutInt(nargs, 4, conn) != 0)  /* # of args */
    1445             :     {
    1446           0 :         pqHandleSendFailure(conn);
    1447           0 :         return NULL;
    1448             :     }
    1449             : 
    1450           0 :     for (i = 0; i < nargs; ++i)
    1451             :     {                           /* len.int4 + contents     */
    1452           0 :         if (pqPutInt(args[i].len, 4, conn))
    1453             :         {
    1454           0 :             pqHandleSendFailure(conn);
    1455           0 :             return NULL;
    1456             :         }
    1457             : 
    1458           0 :         if (args[i].isint)
    1459             :         {
    1460           0 :             if (pqPutInt(args[i].u.integer, 4, conn))
    1461             :             {
    1462           0 :                 pqHandleSendFailure(conn);
    1463           0 :                 return NULL;
    1464             :             }
    1465             :         }
    1466             :         else
    1467             :         {
    1468           0 :             if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
    1469             :             {
    1470           0 :                 pqHandleSendFailure(conn);
    1471           0 :                 return NULL;
    1472             :             }
    1473             :         }
    1474             :     }
    1475             : 
    1476           0 :     if (pqPutMsgEnd(conn) < 0 ||
    1477           0 :         pqFlush(conn))
    1478             :     {
    1479           0 :         pqHandleSendFailure(conn);
    1480           0 :         return NULL;
    1481             :     }
    1482             : 
    1483             :     for (;;)
    1484             :     {
    1485           0 :         if (needInput)
    1486             :         {
    1487             :             /* Wait for some data to arrive (or for the channel to close) */
    1488           0 :             if (pqWait(TRUE, FALSE, conn) ||
    1489           0 :                 pqReadData(conn) < 0)
    1490             :                 break;
    1491             :         }
    1492             : 
    1493             :         /*
    1494             :          * Scan the message. If we run out of data, loop around to try again.
    1495             :          */
    1496           0 :         conn->inCursor = conn->inStart;
    1497           0 :         needInput = true;
    1498             : 
    1499           0 :         if (pqGetc(&id, conn))
    1500           0 :             continue;
    1501             : 
    1502             :         /*
    1503             :          * We should see V or E response to the command, but might get N
    1504             :          * and/or A notices first. We also need to swallow the final Z before
    1505             :          * returning.
    1506             :          */
    1507           0 :         switch (id)
    1508             :         {
    1509             :             case 'V':           /* function result */
    1510           0 :                 if (pqGetc(&id, conn))
    1511           0 :                     continue;
    1512           0 :                 if (id == 'G')
    1513             :                 {
    1514             :                     /* function returned nonempty value */
    1515           0 :                     if (pqGetInt(actual_result_len, 4, conn))
    1516           0 :                         continue;
    1517           0 :                     if (result_is_int)
    1518             :                     {
    1519           0 :                         if (pqGetInt(result_buf, 4, conn))
    1520           0 :                             continue;
    1521             :                     }
    1522             :                     else
    1523             :                     {
    1524           0 :                         if (pqGetnchar((char *) result_buf,
    1525           0 :                                        *actual_result_len,
    1526             :                                        conn))
    1527           0 :                             continue;
    1528             :                     }
    1529           0 :                     if (pqGetc(&id, conn))  /* get the last '0' */
    1530           0 :                         continue;
    1531             :                 }
    1532           0 :                 if (id == '0')
    1533             :                 {
    1534             :                     /* correctly finished function result message */
    1535           0 :                     status = PGRES_COMMAND_OK;
    1536             :                 }
    1537             :                 else
    1538             :                 {
    1539             :                     /* The backend violates the protocol. */
    1540           0 :                     printfPQExpBuffer(&conn->errorMessage,
    1541             :                                       libpq_gettext("protocol error: id=0x%x\n"),
    1542             :                                       id);
    1543           0 :                     pqSaveErrorResult(conn);
    1544           0 :                     conn->inStart = conn->inCursor;
    1545           0 :                     return pqPrepareAsyncResult(conn);
    1546             :                 }
    1547           0 :                 break;
    1548             :             case 'E':           /* error return */
    1549           0 :                 if (pqGetErrorNotice2(conn, true))
    1550           0 :                     continue;
    1551           0 :                 status = PGRES_FATAL_ERROR;
    1552           0 :                 break;
    1553             :             case 'A':           /* notify message */
    1554             :                 /* handle notify and go back to processing return values */
    1555           0 :                 if (getNotify(conn))
    1556           0 :                     continue;
    1557           0 :                 break;
    1558             :             case 'N':           /* notice */
    1559             :                 /* handle notice and go back to processing return values */
    1560           0 :                 if (pqGetErrorNotice2(conn, false))
    1561           0 :                     continue;
    1562           0 :                 break;
    1563             :             case 'Z':           /* backend is ready for new query */
    1564             :                 /* consume the message and exit */
    1565           0 :                 conn->inStart = conn->inCursor;
    1566             :                 /* if we saved a result object (probably an error), use it */
    1567           0 :                 if (conn->result)
    1568           0 :                     return pqPrepareAsyncResult(conn);
    1569           0 :                 return PQmakeEmptyPGresult(conn, status);
    1570             :             default:
    1571             :                 /* The backend violates the protocol. */
    1572           0 :                 printfPQExpBuffer(&conn->errorMessage,
    1573             :                                   libpq_gettext("protocol error: id=0x%x\n"),
    1574             :                                   id);
    1575           0 :                 pqSaveErrorResult(conn);
    1576           0 :                 conn->inStart = conn->inCursor;
    1577           0 :                 return pqPrepareAsyncResult(conn);
    1578             :         }
    1579             :         /* Completed this message, keep going */
    1580           0 :         conn->inStart = conn->inCursor;
    1581           0 :         needInput = false;
    1582           0 :     }
    1583             : 
    1584             :     /*
    1585             :      * We fall out of the loop only upon failing to read data.
    1586             :      * conn->errorMessage has been set by pqWait or pqReadData. We want to
    1587             :      * append it to any already-received error message.
    1588             :      */
    1589           0 :     pqSaveErrorResult(conn);
    1590           0 :     return pqPrepareAsyncResult(conn);
    1591             : }
    1592             : 
    1593             : 
    1594             : /*
    1595             :  * Construct startup packet
    1596             :  *
    1597             :  * Returns a malloc'd packet buffer, or NULL if out of memory
    1598             :  */
    1599             : char *
    1600           0 : pqBuildStartupPacket2(PGconn *conn, int *packetlen,
    1601             :                       const PQEnvironmentOption *options)
    1602             : {
    1603             :     StartupPacket *startpacket;
    1604             : 
    1605           0 :     *packetlen = sizeof(StartupPacket);
    1606           0 :     startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
    1607           0 :     if (!startpacket)
    1608           0 :         return NULL;
    1609             : 
    1610           0 :     MemSet(startpacket, 0, sizeof(StartupPacket));
    1611             : 
    1612           0 :     startpacket->protoVersion = htonl(conn->pversion);
    1613             : 
    1614             :     /* strncpy is safe here: postmaster will handle full fields correctly */
    1615           0 :     strncpy(startpacket->user, conn->pguser, SM_USER);
    1616           0 :     strncpy(startpacket->database, conn->dbName, SM_DATABASE);
    1617           0 :     strncpy(startpacket->tty, conn->pgtty, SM_TTY);
    1618             : 
    1619           0 :     if (conn->pgoptions)
    1620           0 :         strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
    1621             : 
    1622           0 :     return (char *) startpacket;
    1623             : }

Generated by: LCOV version 1.11