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

Generated by: LCOV version 1.13