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

Generated by: LCOV version 1.13