LCOV - differential code coverage report
Current view: top level - src/interfaces/libpq - fe-protocol3.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 65.1 % 921 600 42 66 170 43 73 350 177 201 348 4 9
Current Date: 2023-04-08 15:15:32 Functions: 81.0 % 21 17 1 3 17 4 17
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * fe-protocol3.c
       4                 :  *    functions that are specific to frontend/backend protocol version 3
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/interfaces/libpq/fe-protocol3.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                 : #include <netinet/tcp.h>
      25                 : #endif
      26                 : 
      27                 : #include "libpq-fe.h"
      28                 : #include "libpq-int.h"
      29                 : #include "mb/pg_wchar.h"
      30                 : #include "port/pg_bswap.h"
      31                 : 
      32                 : /*
      33                 :  * This macro lists the backend message types that could be "long" (more
      34                 :  * than a couple of kilobytes).
      35                 :  */
      36                 : #define VALID_LONG_MESSAGE_TYPE(id) \
      37                 :     ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
      38                 :      (id) == 'E' || (id) == 'N' || (id) == 'A')
      39                 : 
      40                 : 
      41                 : static void handleSyncLoss(PGconn *conn, char id, int msgLength);
      42                 : static int  getRowDescriptions(PGconn *conn, int msgLength);
      43                 : static int  getParamDescriptions(PGconn *conn, int msgLength);
      44                 : static int  getAnotherTuple(PGconn *conn, int msgLength);
      45                 : static int  getParameterStatus(PGconn *conn);
      46                 : static int  getNotify(PGconn *conn);
      47                 : static int  getCopyStart(PGconn *conn, ExecStatusType copytype);
      48                 : static int  getReadyForQuery(PGconn *conn);
      49                 : static void reportErrorPosition(PQExpBuffer msg, const char *query,
      50                 :                                 int loc, int encoding);
      51                 : static int  build_startup_packet(const PGconn *conn, char *packet,
      52                 :                                  const PQEnvironmentOption *options);
      53                 : 
      54                 : 
      55                 : /*
      56                 :  * parseInput: if appropriate, parse input data from backend
      57                 :  * until input is exhausted or a stopping state is reached.
      58                 :  * Note that this function will NOT attempt to read more data from the backend.
      59 ECB             :  */
      60                 : void
      61 GIC     1413708 : pqParseInput3(PGconn *conn)
      62                 : {
      63                 :     char        id;
      64                 :     int         msgLength;
      65                 :     int         avail;
      66                 : 
      67                 :     /*
      68                 :      * Loop to parse successive complete messages available in the buffer.
      69                 :      */
      70                 :     for (;;)
      71                 :     {
      72                 :         /*
      73                 :          * Try to read a message.  First get the type code and length. Return
      74 ECB             :          * if not enough data.
      75                 :          */
      76 CBC     6255869 :         conn->inCursor = conn->inStart;
      77         6255869 :         if (pqGetc(&id, conn))
      78         1097123 :             return;
      79 GIC     5158746 :         if (pqGetInt(&msgLength, 4, conn))
      80            1630 :             return;
      81                 : 
      82                 :         /*
      83                 :          * Try to validate message type/length here.  A length less than 4 is
      84                 :          * definitely broken.  Large lengths should only be believed for a few
      85 ECB             :          * message types.
      86                 :          */
      87 GBC     5157116 :         if (msgLength < 4)
      88 EUB             :         {
      89 UIC           0 :             handleSyncLoss(conn, id, msgLength);
      90 LBC           0 :             return;
      91                 :         }
      92 GBC     5157116 :         if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
      93 EUB             :         {
      94 UIC           0 :             handleSyncLoss(conn, id, msgLength);
      95               0 :             return;
      96                 :         }
      97                 : 
      98                 :         /*
      99 ECB             :          * Can't process if message body isn't all here yet.
     100                 :          */
     101 CBC     5157116 :         msgLength -= 4;
     102 GIC     5157116 :         avail = conn->inEnd - conn->inCursor;
     103         5157116 :         if (avail < msgLength)
     104                 :         {
     105                 :             /*
     106                 :              * Before returning, enlarge the input buffer if needed to hold
     107                 :              * the whole message.  This is better than leaving it to
     108                 :              * pqReadData because we can avoid multiple cycles of realloc()
     109                 :              * when the message is large; also, we can implement a reasonable
     110                 :              * recovery strategy if we are unable to make the buffer big
     111 ECB             :              * enough.
     112                 :              */
     113 GIC       25743 :             if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
     114                 :                                      conn))
     115                 :             {
     116                 :                 /*
     117                 :                  * XXX add some better recovery code... plan is to skip over
     118                 :                  * the message using its length, then report an error. For the
     119                 :                  * moment, just treat this like loss of sync (which indeed it
     120 EUB             :                  * might be!)
     121                 :                  */
     122 LBC           0 :                 handleSyncLoss(conn, id, msgLength);
     123                 :             }
     124 GIC       25743 :             return;
     125                 :         }
     126                 : 
     127                 :         /*
     128                 :          * NOTIFY and NOTICE messages can happen in any state; always process
     129                 :          * them right away.
     130                 :          *
     131                 :          * Most other messages should only be processed while in BUSY state.
     132                 :          * (In particular, in READY state we hold off further parsing until
     133                 :          * the application collects the current PGresult.)
     134                 :          *
     135                 :          * However, if the state is IDLE then we got trouble; we need to deal
     136                 :          * with the unexpected message somehow.
     137                 :          *
     138                 :          * ParameterStatus ('S') messages are a special case: in IDLE state we
     139                 :          * must process 'em (this case could happen if a new value was adopted
     140                 :          * from config file due to SIGHUP), but otherwise we hold off until
     141 ECB             :          * BUSY state.
     142                 :          */
     143 CBC     5131373 :         if (id == 'A')
     144 EUB             :         {
     145 GIC          31 :             if (getNotify(conn))
     146 LBC           0 :                 return;
     147                 :         }
     148 CBC     5131342 :         else if (id == 'N')
     149 EUB             :         {
     150 GIC       10376 :             if (pqGetErrorNotice3(conn, false))
     151 LBC           0 :                 return;
     152                 :         }
     153 GIC     5120966 :         else if (conn->asyncStatus != PGASYNC_BUSY)
     154 ECB             :         {
     155                 :             /* If not IDLE state, just wait ... */
     156 GIC      289212 :             if (conn->asyncStatus != PGASYNC_IDLE)
     157          289212 :                 return;
     158                 : 
     159                 :             /*
     160                 :              * Unexpected message in IDLE state; need to recover somehow.
     161                 :              * ERROR messages are handled using the notice processor;
     162                 :              * ParameterStatus is handled normally; anything else is just
     163                 :              * dropped on the floor after displaying a suitable warning
     164                 :              * notice.  (An ERROR is very possibly the backend telling us why
     165                 :              * it is about to close the connection, so we don't want to just
     166 EUB             :              * discard it...)
     167                 :              */
     168 UBC           0 :             if (id == 'E')
     169 EUB             :             {
     170 UIC           0 :                 if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
     171 UBC           0 :                     return;
     172                 :             }
     173               0 :             else if (id == 'S')
     174 EUB             :             {
     175 UIC           0 :                 if (getParameterStatus(conn))
     176               0 :                     return;
     177                 :             }
     178                 :             else
     179 EUB             :             {
     180                 :                 /* Any other case is unexpected and we summarily skip it */
     181 UIC           0 :                 pqInternalNotice(&conn->noticeHooks,
     182                 :                                  "message type 0x%02x arrived from server while idle",
     183 EUB             :                                  id);
     184                 :                 /* Discard the unexpected message */
     185 UIC           0 :                 conn->inCursor += msgLength;
     186                 :             }
     187                 :         }
     188                 :         else
     189                 :         {
     190                 :             /*
     191 ECB             :              * In BUSY state, we can process everything.
     192                 :              */
     193 CBC     4831754 :             switch (id)
     194 ECB             :             {
     195 GBC      243357 :                 case 'C':       /* command complete */
     196 CBC      243357 :                     if (pqGets(&conn->workBuffer, conn))
     197 UIC           0 :                         return;
     198 CBC      243357 :                     if (!pgHavePendingResult(conn))
     199                 :                     {
     200          125820 :                         conn->result = PQmakeEmptyPGresult(conn,
     201                 :                                                            PGRES_COMMAND_OK);
     202 GBC      125820 :                         if (!conn->result)
     203 EUB             :                         {
     204 UNC           0 :                             libpq_append_conn_error(conn, "out of memory");
     205 LBC           0 :                             pqSaveErrorResult(conn);
     206 ECB             :                         }
     207                 :                     }
     208 CBC      243357 :                     if (conn->result)
     209          243357 :                         strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
     210 ECB             :                                 CMDSTATUS_LEN);
     211 CBC      243357 :                     conn->asyncStatus = PGASYNC_READY;
     212 GBC      243357 :                     break;
     213 CBC       17766 :                 case 'E':       /* error return */
     214           17766 :                     if (pqGetErrorNotice3(conn, true))
     215 LBC           0 :                         return;
     216 GIC       17766 :                     conn->asyncStatus = PGASYNC_READY;
     217 CBC       17766 :                     break;
     218 GBC      253403 :                 case 'Z':       /* sync response, backend is ready for new
     219 ECB             :                                  * query */
     220 GIC      253403 :                     if (getReadyForQuery(conn))
     221 LBC           0 :                         return;
     222 GIC      253403 :                     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
     223 ECB             :                     {
     224 GIC          57 :                         conn->result = PQmakeEmptyPGresult(conn,
     225 EUB             :                                                            PGRES_PIPELINE_SYNC);
     226 GBC          57 :                         if (!conn->result)
     227                 :                         {
     228 UNC           0 :                             libpq_append_conn_error(conn, "out of memory");
     229 LBC           0 :                             pqSaveErrorResult(conn);
     230 ECB             :                         }
     231                 :                         else
     232                 :                         {
     233 GIC          57 :                             conn->pipelineStatus = PQ_PIPELINE_ON;
     234              57 :                             conn->asyncStatus = PGASYNC_READY;
     235                 :                         }
     236                 :                     }
     237                 :                     else
     238                 :                     {
     239 ECB             :                         /*
     240                 :                          * In simple query protocol, advance the command queue
     241                 :                          * (see PQgetResult).
     242                 :                          */
     243 GIC      253346 :                         if (conn->cmd_queue_head &&
     244 CBC      234506 :                             conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE)
     245          234506 :                             pqCommandQueueAdvance(conn);
     246          253346 :                         conn->asyncStatus = PGASYNC_IDLE;
     247                 :                     }
     248          253403 :                     break;
     249 GIC         231 :                 case 'I':       /* empty query */
     250 CBC         231 :                     if (!pgHavePendingResult(conn))
     251                 :                     {
     252 GBC         231 :                         conn->result = PQmakeEmptyPGresult(conn,
     253 EUB             :                                                            PGRES_EMPTY_QUERY);
     254 GIC         231 :                         if (!conn->result)
     255                 :                         {
     256 UNC           0 :                             libpq_append_conn_error(conn, "out of memory");
     257 LBC           0 :                             pqSaveErrorResult(conn);
     258                 :                         }
     259 ECB             :                     }
     260 CBC         231 :                     conn->asyncStatus = PGASYNC_READY;
     261 GIC         231 :                     break;
     262 CBC        3680 :                 case '1':       /* Parse Complete */
     263                 :                     /* If we're doing PQprepare, we're done; else ignore */
     264            3680 :                     if (conn->cmd_queue_head &&
     265 GIC        3680 :                         conn->cmd_queue_head->queryclass == PGQUERY_PREPARE)
     266 ECB             :                     {
     267 GIC        1291 :                         if (!pgHavePendingResult(conn))
     268 EUB             :                         {
     269 GBC        1291 :                             conn->result = PQmakeEmptyPGresult(conn,
     270                 :                                                                PGRES_COMMAND_OK);
     271 GIC        1291 :                             if (!conn->result)
     272 ECB             :                             {
     273 UNC           0 :                                 libpq_append_conn_error(conn, "out of memory");
     274 LBC           0 :                                 pqSaveErrorResult(conn);
     275                 :                             }
     276                 :                         }
     277 CBC        1291 :                         conn->asyncStatus = PGASYNC_READY;
     278 ECB             :                     }
     279 CBC        3680 :                     break;
     280 GBC       10251 :                 case '2':       /* Bind Complete */
     281 ECB             :                 case '3':       /* Close Complete */
     282                 :                     /* Nothing to do for these message types */
     283 GIC       10251 :                     break;
     284          128398 :                 case 'S':       /* parameter status */
     285          128398 :                     if (getParameterStatus(conn))
     286 UIC           0 :                         return;
     287 GIC      128398 :                     break;
     288            8885 :                 case 'K':       /* secret key data from the backend */
     289 ECB             : 
     290 EUB             :                     /*
     291 ECB             :                      * This is expected only during backend startup, but it's
     292 EUB             :                      * just as easy to handle it as part of the main loop.
     293 ECB             :                      * Save the data and continue processing.
     294                 :                      */
     295 CBC        8885 :                     if (pqGetInt(&(conn->be_pid), 4, conn))
     296 LBC           0 :                         return;
     297 CBC        8885 :                     if (pqGetInt(&(conn->be_key), 4, conn))
     298 UIC           0 :                         return;
     299 GIC        8885 :                     break;
     300          120041 :                 case 'T':       /* Row Description */
     301          120041 :                     if (conn->error_result ||
     302          120041 :                         (conn->result != NULL &&
     303 GBC          43 :                          conn->result->resultStatus == PGRES_FATAL_ERROR))
     304                 :                     {
     305 ECB             :                         /*
     306                 :                          * We've already choked for some reason.  Just discard
     307                 :                          * the data till we get to the end of the query.
     308                 :                          */
     309 UIC           0 :                         conn->inCursor += msgLength;
     310 ECB             :                     }
     311 GBC      120041 :                     else if (conn->result == NULL ||
     312 GIC          43 :                              (conn->cmd_queue_head &&
     313              43 :                               conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
     314                 :                     {
     315                 :                         /* First 'T' in a query sequence */
     316          120041 :                         if (getRowDescriptions(conn, msgLength))
     317 UIC           0 :                             return;
     318                 :                     }
     319                 :                     else
     320                 :                     {
     321                 :                         /*
     322 EUB             :                          * A new 'T' message is treated as the start of
     323                 :                          * another PGresult.  (It is not clear that this is
     324                 :                          * really possible with the current backend.) We stop
     325 ECB             :                          * parsing until the application accepts the current
     326                 :                          * result.
     327                 :                          */
     328 UIC           0 :                         conn->asyncStatus = PGASYNC_READY;
     329               0 :                         return;
     330                 :                     }
     331 GIC      120041 :                     break;
     332            4668 :                 case 'n':       /* No Data */
     333                 : 
     334                 :                     /*
     335                 :                      * NoData indicates that we will not be seeing a
     336                 :                      * RowDescription message because the statement or portal
     337                 :                      * inquired about doesn't return rows.
     338 ECB             :                      *
     339                 :                      * If we're doing a Describe, we have to pass something
     340                 :                      * back to the client, so set up a COMMAND_OK result,
     341                 :                      * instead of PGRES_TUPLES_OK.  Otherwise we can just
     342                 :                      * ignore this message.
     343 EUB             :                      */
     344 GIC        4668 :                     if (conn->cmd_queue_head &&
     345 GBC        4668 :                         conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)
     346                 :                     {
     347               3 :                         if (!pgHavePendingResult(conn))
     348 EUB             :                         {
     349 UIC           0 :                             conn->result = PQmakeEmptyPGresult(conn,
     350                 :                                                                PGRES_COMMAND_OK);
     351 LBC           0 :                             if (!conn->result)
     352                 :                             {
     353 UNC           0 :                                 libpq_append_conn_error(conn, "out of memory");
     354 LBC           0 :                                 pqSaveErrorResult(conn);
     355 EUB             :                             }
     356 ECB             :                         }
     357 CBC           3 :                         conn->asyncStatus = PGASYNC_READY;
     358 ECB             :                     }
     359 CBC        4668 :                     break;
     360 GIC          46 :                 case 't':       /* Parameter Description */
     361              46 :                     if (getParamDescriptions(conn, msgLength))
     362 LBC           0 :                         return;
     363 GBC          46 :                     break;
     364 GIC     4032843 :                 case 'D':       /* Data Row */
     365 GBC     4032843 :                     if (conn->result != NULL &&
     366         4032843 :                         conn->result->resultStatus == PGRES_TUPLES_OK)
     367 EUB             :                     {
     368                 :                         /* Read another tuple of a normal query response */
     369 GIC     4032843 :                         if (getAnotherTuple(conn, msgLength))
     370 UIC           0 :                             return;
     371                 :                     }
     372               0 :                     else if (conn->error_result ||
     373 UBC           0 :                              (conn->result != NULL &&
     374 UIC           0 :                               conn->result->resultStatus == PGRES_FATAL_ERROR))
     375                 :                     {
     376                 :                         /*
     377                 :                          * We've already choked for some reason.  Just discard
     378 EUB             :                          * tuples till we get to the end of the query.
     379                 :                          */
     380 UIC           0 :                         conn->inCursor += msgLength;
     381 EUB             :                     }
     382                 :                     else
     383 ECB             :                     {
     384                 :                         /* Set up to report error at end of query */
     385 UNC           0 :                         libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)");
     386 LBC           0 :                         pqSaveErrorResult(conn);
     387 ECB             :                         /* Discard the unexpected message */
     388 LBC           0 :                         conn->inCursor += msgLength;
     389 ECB             :                     }
     390 GBC     4032843 :                     break;
     391 CBC         411 :                 case 'G':       /* Start Copy In */
     392             411 :                     if (getCopyStart(conn, PGRES_COPY_IN))
     393 LBC           0 :                         return;
     394 CBC         411 :                     conn->asyncStatus = PGASYNC_COPY_IN;
     395             411 :                     break;
     396 GBC        3506 :                 case 'H':       /* Start Copy Out */
     397 CBC        3506 :                     if (getCopyStart(conn, PGRES_COPY_OUT))
     398 LBC           0 :                         return;
     399 CBC        3506 :                     conn->asyncStatus = PGASYNC_COPY_OUT;
     400 GBC        3506 :                     conn->copy_already_done = 0;
     401 GIC        3506 :                     break;
     402             503 :                 case 'W':       /* Start Copy Both */
     403             503 :                     if (getCopyStart(conn, PGRES_COPY_BOTH))
     404 UIC           0 :                         return;
     405 GIC         503 :                     conn->asyncStatus = PGASYNC_COPY_BOTH;
     406             503 :                     conn->copy_already_done = 0;
     407 GBC         503 :                     break;
     408 UBC           0 :                 case 'd':       /* Copy Data */
     409 ECB             : 
     410                 :                     /*
     411                 :                      * If we see Copy Data, just silently drop it.  This would
     412                 :                      * only occur if application exits COPY OUT mode too
     413                 :                      * early.
     414                 :                      */
     415 UIC           0 :                     conn->inCursor += msgLength;
     416               0 :                     break;
     417 CBC        3765 :                 case 'c':       /* Copy Done */
     418 EUB             : 
     419                 :                     /*
     420                 :                      * If we see Copy Done, just silently drop it.  This is
     421                 :                      * the normal case during PQendcopy.  We will keep
     422                 :                      * swallowing data, expecting to see command-complete for
     423                 :                      * the COPY command.
     424                 :                      */
     425 GBC        3765 :                     break;
     426 UBC           0 :                 default:
     427 UNC           0 :                     libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id);
     428 ECB             :                     /* build an error result holding the error message */
     429 UIC           0 :                     pqSaveErrorResult(conn);
     430                 :                     /* not sure if we will see more, so go to ready state */
     431 LBC           0 :                     conn->asyncStatus = PGASYNC_READY;
     432 ECB             :                     /* Discard the unexpected message */
     433 UIC           0 :                     conn->inCursor += msgLength;
     434               0 :                     break;
     435 ECB             :             }                   /* switch on protocol character */
     436                 :         }
     437                 :         /* Successfully consumed this message */
     438 GIC     4842161 :         if (conn->inCursor == conn->inStart + 5 + msgLength)
     439                 :         {
     440 EUB             :             /* trace server-to-client message */
     441 GIC     4842161 :             if (conn->Pfdebug)
     442 GBC         190 :                 pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
     443 EUB             : 
     444                 :             /* Normal case: parsing agrees with specified length */
     445 GBC     4842161 :             conn->inStart = conn->inCursor;
     446                 :         }
     447                 :         else
     448                 :         {
     449                 :             /* Trouble --- report it */
     450 UNC           0 :             libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id);
     451                 :             /* build an error result holding the error message */
     452 UIC           0 :             pqSaveErrorResult(conn);
     453               0 :             conn->asyncStatus = PGASYNC_READY;
     454 EUB             :             /* trust the specified message length as what to skip */
     455 UIC           0 :             conn->inStart += 5 + msgLength;
     456 EUB             :         }
     457                 :     }
     458                 : }
     459                 : 
     460                 : /*
     461                 :  * handleSyncLoss: clean up after loss of message-boundary sync
     462                 :  *
     463                 :  * There isn't really a lot we can do here except abandon the connection.
     464                 :  */
     465                 : static void
     466 UIC           0 : handleSyncLoss(PGconn *conn, char id, int msgLength)
     467                 : {
     468 UNC           0 :     libpq_append_conn_error(conn, "lost synchronization with server: got message type \"%c\", length %d",
     469                 :                       id, msgLength);
     470                 :     /* build an error result holding the error message */
     471 UIC           0 :     pqSaveErrorResult(conn);
     472               0 :     conn->asyncStatus = PGASYNC_READY;   /* drop out of PQgetResult wait loop */
     473 ECB             :     /* flush input data since we're giving up on processing it */
     474 UIC           0 :     pqDropConnection(conn, true);
     475               0 :     conn->status = CONNECTION_BAD;   /* No more connection to backend */
     476               0 : }
     477                 : 
     478                 : /*
     479                 :  * parseInput subroutine to read a 'T' (row descriptions) message.
     480                 :  * We'll build a new PGresult structure (unless called for a Describe
     481                 :  * command for a prepared statement) containing the attribute data.
     482                 :  * Returns: 0 if processed message successfully, EOF to suspend parsing
     483                 :  * (the latter case is not actually used currently).
     484                 :  */
     485 ECB             : static int
     486 CBC      120041 : getRowDescriptions(PGconn *conn, int msgLength)
     487 ECB             : {
     488                 :     PGresult   *result;
     489                 :     int         nfields;
     490                 :     const char *errmsg;
     491                 :     int         i;
     492                 : 
     493                 :     /*
     494                 :      * When doing Describe for a prepared statement, there'll already be a
     495                 :      * PGresult created by getParamDescriptions, and we should fill data into
     496                 :      * that.  Otherwise, create a new, empty PGresult.
     497                 :      */
     498 GBC      120041 :     if (!conn->cmd_queue_head ||
     499          120041 :         (conn->cmd_queue_head &&
     500 GIC      120041 :          conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
     501                 :     {
     502              44 :         if (conn->result)
     503              43 :             result = conn->result;
     504 ECB             :         else
     505 GIC           1 :             result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
     506                 :     }
     507 EUB             :     else
     508 GBC      119997 :         result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
     509 GIC      120041 :     if (!result)
     510 ECB             :     {
     511 UIC           0 :         errmsg = NULL;          /* means "out of memory", see below */
     512               0 :         goto advance_and_error;
     513 ECB             :     }
     514                 : 
     515                 :     /* parseInput already read the 'T' label and message length. */
     516                 :     /* the next two bytes are the number of fields */
     517 CBC      120041 :     if (pqGetInt(&(result->numAttributes), 2, conn))
     518                 :     {
     519 EUB             :         /* We should not run out of data here, so complain */
     520 UBC           0 :         errmsg = libpq_gettext("insufficient data in \"T\" message");
     521 UIC           0 :         goto advance_and_error;
     522 ECB             :     }
     523 GIC      120041 :     nfields = result->numAttributes;
     524                 : 
     525                 :     /* allocate space for the attribute descriptors */
     526 CBC      120041 :     if (nfields > 0)
     527                 :     {
     528 GIC      119981 :         result->attDescs = (PGresAttDesc *)
     529 CBC      119981 :             pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
     530 GIC      119981 :         if (!result->attDescs)
     531                 :         {
     532 UIC           0 :             errmsg = NULL;      /* means "out of memory", see below */
     533               0 :             goto advance_and_error;
     534                 :         }
     535 GIC     1512053 :         MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
     536                 :     }
     537                 : 
     538 ECB             :     /* result->binary is true only if ALL columns are binary */
     539 CBC      120041 :     result->binary = (nfields > 0) ? 1 : 0;
     540 ECB             : 
     541                 :     /* get type info */
     542 CBC      473293 :     for (i = 0; i < nfields; i++)
     543 ECB             :     {
     544                 :         int         tableid;
     545                 :         int         columnid;
     546                 :         int         typid;
     547 EUB             :         int         typlen;
     548                 :         int         atttypmod;
     549                 :         int         format;
     550                 : 
     551 GIC      706504 :         if (pqGets(&conn->workBuffer, conn) ||
     552          706504 :             pqGetInt(&tableid, 4, conn) ||
     553          706504 :             pqGetInt(&columnid, 2, conn) ||
     554          706504 :             pqGetInt(&typid, 4, conn) ||
     555 CBC      706504 :             pqGetInt(&typlen, 2, conn) ||
     556          706504 :             pqGetInt(&atttypmod, 4, conn) ||
     557          353252 :             pqGetInt(&format, 2, conn))
     558                 :         {
     559 ECB             :             /* We should not run out of data here, so complain */
     560 LBC           0 :             errmsg = libpq_gettext("insufficient data in \"T\" message");
     561               0 :             goto advance_and_error;
     562                 :         }
     563 EUB             : 
     564                 :         /*
     565                 :          * Since pqGetInt treats 2-byte integers as unsigned, we need to
     566 ECB             :          * coerce these results to signed form.
     567                 :          */
     568 CBC      353252 :         columnid = (int) ((int16) columnid);
     569          353252 :         typlen = (int) ((int16) typlen);
     570          353252 :         format = (int) ((int16) format);
     571 ECB             : 
     572 GIC      706504 :         result->attDescs[i].name = pqResultStrdup(result,
     573 CBC      353252 :                                                   conn->workBuffer.data);
     574          353252 :         if (!result->attDescs[i].name)
     575                 :         {
     576 UIC           0 :             errmsg = NULL;      /* means "out of memory", see below */
     577               0 :             goto advance_and_error;
     578 ECB             :         }
     579 GIC      353252 :         result->attDescs[i].tableid = tableid;
     580          353252 :         result->attDescs[i].columnid = columnid;
     581          353252 :         result->attDescs[i].format = format;
     582          353252 :         result->attDescs[i].typid = typid;
     583          353252 :         result->attDescs[i].typlen = typlen;
     584 CBC      353252 :         result->attDescs[i].atttypmod = atttypmod;
     585 ECB             : 
     586 CBC      353252 :         if (format != 1)
     587 GIC      353213 :             result->binary = 0;
     588 ECB             :     }
     589                 : 
     590                 :     /* Success! */
     591 GIC      120041 :     conn->result = result;
     592                 : 
     593                 :     /*
     594                 :      * If we're doing a Describe, we're done, and ready to pass the result
     595                 :      * back to the client.
     596                 :      */
     597          120041 :     if ((!conn->cmd_queue_head) ||
     598 CBC      120041 :         (conn->cmd_queue_head &&
     599 GIC      120041 :          conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
     600 EUB             :     {
     601 GIC          44 :         conn->asyncStatus = PGASYNC_READY;
     602 GBC          44 :         return 0;
     603 EUB             :     }
     604                 : 
     605                 :     /*
     606                 :      * We could perform additional setup for the new result set here, but for
     607                 :      * now there's nothing else to do.
     608                 :      */
     609                 : 
     610                 :     /* And we're done. */
     611 GIC      119997 :     return 0;
     612                 : 
     613 UIC           0 : advance_and_error:
     614                 :     /* Discard unsaved result, if any */
     615               0 :     if (result && result != conn->result)
     616               0 :         PQclear(result);
     617 EUB             : 
     618                 :     /*
     619                 :      * Replace partially constructed result with an error result. First
     620                 :      * discard the old result to try to win back some memory.
     621                 :      */
     622 UIC           0 :     pqClearAsyncResult(conn);
     623                 : 
     624                 :     /*
     625                 :      * If preceding code didn't provide an error message, assume "out of
     626                 :      * memory" was meant.  The advantage of having this special case is that
     627 EUB             :      * freeing the old result first greatly improves the odds that gettext()
     628                 :      * will succeed in providing a translation.
     629                 :      */
     630 UIC           0 :     if (!errmsg)
     631               0 :         errmsg = libpq_gettext("out of memory for query result");
     632                 : 
     633               0 :     appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
     634 UBC           0 :     pqSaveErrorResult(conn);
     635                 : 
     636                 :     /*
     637                 :      * Show the message as fully consumed, else pqParseInput3 will overwrite
     638                 :      * our error with a complaint about that.
     639                 :      */
     640 UIC           0 :     conn->inCursor = conn->inStart + 5 + msgLength;
     641                 : 
     642                 :     /*
     643                 :      * Return zero to allow input parsing to continue.  Subsequent "D"
     644 ECB             :      * messages will be ignored until we get to end of data, since an error
     645                 :      * result is already set up.
     646                 :      */
     647 LBC           0 :     return 0;
     648                 : }
     649                 : 
     650                 : /*
     651 ECB             :  * parseInput subroutine to read a 't' (ParameterDescription) message.
     652                 :  * We'll build a new PGresult structure containing the parameter data.
     653 EUB             :  * Returns: 0 if processed message successfully, EOF to suspend parsing
     654                 :  * (the latter case is not actually used currently).
     655                 :  */
     656                 : static int
     657 CBC          46 : getParamDescriptions(PGconn *conn, int msgLength)
     658 EUB             : {
     659 ECB             :     PGresult   *result;
     660 GIC          46 :     const char *errmsg = NULL;  /* means "out of memory", see below */
     661                 :     int         nparams;
     662 ECB             :     int         i;
     663                 : 
     664 CBC          46 :     result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
     665              46 :     if (!result)
     666 LBC           0 :         goto advance_and_error;
     667 EUB             : 
     668 ECB             :     /* parseInput already read the 't' label and message length. */
     669                 :     /* the next two bytes are the number of parameters */
     670 GIC          46 :     if (pqGetInt(&(result->numParameters), 2, conn))
     671 UIC           0 :         goto not_enough_data;
     672 CBC          46 :     nparams = result->numParameters;
     673                 : 
     674                 :     /* allocate space for the parameter descriptors */
     675 GIC          46 :     if (nparams > 0)
     676 ECB             :     {
     677 GBC           4 :         result->paramDescs = (PGresParamDesc *)
     678 CBC           4 :             pqResultAlloc(result, nparams * sizeof(PGresParamDesc), true);
     679 GIC           4 :         if (!result->paramDescs)
     680 UIC           0 :             goto advance_and_error;
     681 GIC           7 :         MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc));
     682 ECB             :     }
     683                 : 
     684                 :     /* get parameter info */
     685 GIC          53 :     for (i = 0; i < nparams; i++)
     686 EUB             :     {
     687                 :         int         typid;
     688                 : 
     689 GBC           7 :         if (pqGetInt(&typid, 4, conn))
     690 UIC           0 :             goto not_enough_data;
     691 GBC           7 :         result->paramDescs[i].typid = typid;
     692 EUB             :     }
     693                 : 
     694                 :     /* Success! */
     695 GIC          46 :     conn->result = result;
     696                 : 
     697              46 :     return 0;
     698 EUB             : 
     699 UIC           0 : not_enough_data:
     700               0 :     errmsg = libpq_gettext("insufficient data in \"t\" message");
     701                 : 
     702               0 : advance_and_error:
     703                 :     /* Discard unsaved result, if any */
     704               0 :     if (result && result != conn->result)
     705               0 :         PQclear(result);
     706 EUB             : 
     707                 :     /*
     708                 :      * Replace partially constructed result with an error result. First
     709                 :      * discard the old result to try to win back some memory.
     710                 :      */
     711 UIC           0 :     pqClearAsyncResult(conn);
     712                 : 
     713                 :     /*
     714                 :      * If preceding code didn't provide an error message, assume "out of
     715 EUB             :      * memory" was meant.  The advantage of having this special case is that
     716                 :      * freeing the old result first greatly improves the odds that gettext()
     717                 :      * will succeed in providing a translation.
     718                 :      */
     719 UIC           0 :     if (!errmsg)
     720               0 :         errmsg = libpq_gettext("out of memory");
     721               0 :     appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
     722 UBC           0 :     pqSaveErrorResult(conn);
     723                 : 
     724                 :     /*
     725                 :      * Show the message as fully consumed, else pqParseInput3 will overwrite
     726                 :      * our error with a complaint about that.
     727                 :      */
     728 UIC           0 :     conn->inCursor = conn->inStart + 5 + msgLength;
     729                 : 
     730                 :     /*
     731                 :      * Return zero to allow input parsing to continue.  Essentially, we've
     732 ECB             :      * replaced the COMMAND_OK result with an error result, but since this
     733                 :      * doesn't affect the protocol state, it's fine.
     734                 :      */
     735 LBC           0 :     return 0;
     736                 : }
     737                 : 
     738                 : /*
     739                 :  * parseInput subroutine to read a 'D' (row data) message.
     740                 :  * We fill rowbuf with column pointers and then call the row processor.
     741                 :  * Returns: 0 if processed message successfully, EOF to suspend parsing
     742                 :  * (the latter case is not actually used currently).
     743 ECB             :  */
     744                 : static int
     745 GIC     4032843 : getAnotherTuple(PGconn *conn, int msgLength)
     746 EUB             : {
     747 GBC     4032843 :     PGresult   *result = conn->result;
     748 GIC     4032843 :     int         nfields = result->numAttributes;
     749                 :     const char *errmsg;
     750 ECB             :     PGdataValue *rowbuf;
     751                 :     int         tupnfields;     /* # fields from tuple */
     752 EUB             :     int         vlen;           /* length of the current field value */
     753                 :     int         i;
     754                 : 
     755                 :     /* Get the field count and make sure it's what we expect */
     756 GIC     4032843 :     if (pqGetInt(&tupnfields, 2, conn))
     757 ECB             :     {
     758                 :         /* We should not run out of data here, so complain */
     759 UIC           0 :         errmsg = libpq_gettext("insufficient data in \"D\" message");
     760 LBC           0 :         goto advance_and_error;
     761                 :     }
     762 ECB             : 
     763 GIC     4032843 :     if (tupnfields != nfields)
     764 EUB             :     {
     765 UBC           0 :         errmsg = libpq_gettext("unexpected field count in \"D\" message");
     766 UIC           0 :         goto advance_and_error;
     767 ECB             :     }
     768                 : 
     769                 :     /* Resize row buffer if needed */
     770 GIC     4032843 :     rowbuf = conn->rowBuf;
     771         4032843 :     if (nfields > conn->rowBufLen)
     772 ECB             :     {
     773 GIC         142 :         rowbuf = (PGdataValue *) realloc(rowbuf,
     774                 :                                          nfields * sizeof(PGdataValue));
     775 CBC         142 :         if (!rowbuf)
     776                 :         {
     777 UIC           0 :             errmsg = NULL;      /* means "out of memory", see below */
     778 UBC           0 :             goto advance_and_error;
     779 EUB             :         }
     780 GIC         142 :         conn->rowBuf = rowbuf;
     781 CBC         142 :         conn->rowBufLen = nfields;
     782                 :     }
     783                 : 
     784                 :     /* Scan the fields */
     785 GIC    19068104 :     for (i = 0; i < nfields; i++)
     786                 :     {
     787                 :         /* get the value length */
     788 CBC    15035261 :         if (pqGetInt(&vlen, 4, conn))
     789                 :         {
     790                 :             /* We should not run out of data here, so complain */
     791 LBC           0 :             errmsg = libpq_gettext("insufficient data in \"D\" message");
     792 UIC           0 :             goto advance_and_error;
     793 ECB             :         }
     794 GIC    15035261 :         rowbuf[i].len = vlen;
     795                 : 
     796 EUB             :         /*
     797                 :          * rowbuf[i].value always points to the next address in the data
     798                 :          * buffer even if the value is NULL.  This allows row processors to
     799                 :          * estimate data sizes more easily.
     800                 :          */
     801 GIC    15035261 :         rowbuf[i].value = conn->inBuffer + conn->inCursor;
     802                 : 
     803 ECB             :         /* Skip over the data value */
     804 CBC    15035261 :         if (vlen > 0)
     805 ECB             :         {
     806 GIC    14364540 :             if (pqSkipnchar(vlen, conn))
     807                 :             {
     808                 :                 /* We should not run out of data here, so complain */
     809 UBC           0 :                 errmsg = libpq_gettext("insufficient data in \"D\" message");
     810 UIC           0 :                 goto advance_and_error;
     811                 :             }
     812                 :         }
     813                 :     }
     814                 : 
     815 EUB             :     /* Process the collected row */
     816 GIC     4032843 :     errmsg = NULL;
     817         4032843 :     if (pqRowProcessor(conn, &errmsg))
     818         4032843 :         return 0;               /* normal, successful exit */
     819                 : 
     820                 :     /* pqRowProcessor failed, fall through to report it */
     821                 : 
     822 UIC           0 : advance_and_error:
     823 EUB             : 
     824                 :     /*
     825                 :      * Replace partially constructed result with an error result. First
     826                 :      * discard the old result to try to win back some memory.
     827                 :      */
     828 UIC           0 :     pqClearAsyncResult(conn);
     829                 : 
     830                 :     /*
     831                 :      * If preceding code didn't provide an error message, assume "out of
     832                 :      * memory" was meant.  The advantage of having this special case is that
     833 EUB             :      * freeing the old result first greatly improves the odds that gettext()
     834                 :      * will succeed in providing a translation.
     835                 :      */
     836 UIC           0 :     if (!errmsg)
     837               0 :         errmsg = libpq_gettext("out of memory for query result");
     838                 : 
     839               0 :     appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
     840 UBC           0 :     pqSaveErrorResult(conn);
     841                 : 
     842                 :     /*
     843                 :      * Show the message as fully consumed, else pqParseInput3 will overwrite
     844                 :      * our error with a complaint about that.
     845                 :      */
     846 UIC           0 :     conn->inCursor = conn->inStart + 5 + msgLength;
     847                 : 
     848                 :     /*
     849                 :      * Return zero to allow input parsing to continue.  Subsequent "D"
     850                 :      * messages will be ignored until we get to end of data, since an error
     851                 :      * result is already set up.
     852 ECB             :      */
     853 UIC           0 :     return 0;
     854 ECB             : }
     855                 : 
     856                 : 
     857                 : /*
     858                 :  * Attempt to read an Error or Notice response message.
     859                 :  * This is possible in several places, so we break it out as a subroutine.
     860                 :  * Entry: 'E' or 'N' message type and length have already been consumed.
     861                 :  * Exit: returns 0 if successfully consumed message.
     862                 :  *       returns EOF if not enough data.
     863                 :  */
     864                 : int
     865 GIC       28236 : pqGetErrorNotice3(PGconn *conn, bool isError)
     866                 : {
     867           28236 :     PGresult   *res = NULL;
     868 CBC       28236 :     bool        have_position = false;
     869 ECB             :     PQExpBufferData workBuf;
     870                 :     char        id;
     871                 : 
     872                 :     /* If in pipeline mode, set error indicator for it */
     873 GIC       28236 :     if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF)
     874               6 :         conn->pipelineStatus = PQ_PIPELINE_ABORTED;
     875                 : 
     876                 :     /*
     877 ECB             :      * If this is an error message, pre-emptively clear any incomplete query
     878                 :      * result we may have.  We'd just throw it away below anyway, and
     879                 :      * releasing it before collecting the error might avoid out-of-memory.
     880                 :      */
     881 GIC       28236 :     if (isError)
     882           17836 :         pqClearAsyncResult(conn);
     883                 : 
     884                 :     /*
     885                 :      * Since the fields might be pretty long, we create a temporary
     886                 :      * PQExpBuffer rather than using conn->workBuffer.  workBuffer is intended
     887                 :      * for stuff that is expected to be short.  We shouldn't use
     888 ECB             :      * conn->errorMessage either, since this might be only a notice.
     889                 :      */
     890 CBC       28236 :     initPQExpBuffer(&workBuf);
     891                 : 
     892                 :     /*
     893                 :      * Make a PGresult to hold the accumulated fields.  We temporarily lie
     894                 :      * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
     895                 :      * copy conn->errorMessage.
     896                 :      *
     897                 :      * NB: This allocation can fail, if you run out of memory. The rest of the
     898                 :      * function handles that gracefully, and we still try to set the error
     899                 :      * message as the connection's error message.
     900 ECB             :      */
     901 GBC       28236 :     res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
     902 CBC       28236 :     if (res)
     903           28236 :         res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
     904 ECB             : 
     905 EUB             :     /*
     906 ECB             :      * Read the fields and save into res.
     907                 :      *
     908                 :      * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
     909                 :      * we saw a PG_DIAG_STATEMENT_POSITION field.
     910                 :      */
     911                 :     for (;;)
     912                 :     {
     913 GIC      249943 :         if (pqGetc(&id, conn))
     914 UIC           0 :             goto fail;
     915 GIC      249943 :         if (id == '\0')
     916           28236 :             break;              /* terminator found */
     917          221707 :         if (pqGets(&workBuf, conn))
     918 UIC           0 :             goto fail;
     919 CBC      221707 :         pqSaveMessageField(res, id, workBuf.data);
     920          221707 :         if (id == PG_DIAG_SQLSTATE)
     921 GIC       28236 :             strlcpy(conn->last_sqlstate, workBuf.data,
     922                 :                     sizeof(conn->last_sqlstate));
     923          193471 :         else if (id == PG_DIAG_STATEMENT_POSITION)
     924            4504 :             have_position = true;
     925 ECB             :     }
     926                 : 
     927                 :     /*
     928                 :      * Save the active query text, if any, into res as well; but only if we
     929                 :      * might need it for an error cursor display, which is only true if there
     930                 :      * is a PG_DIAG_STATEMENT_POSITION field.
     931                 :      */
     932 GIC       28236 :     if (have_position && res && conn->cmd_queue_head && conn->cmd_queue_head->query)
     933 CBC        4504 :         res->errQuery = pqResultStrdup(res, conn->cmd_queue_head->query);
     934 ECB             : 
     935                 :     /*
     936                 :      * Now build the "overall" error message for PQresultErrorMessage.
     937                 :      */
     938 GIC       28236 :     resetPQExpBuffer(&workBuf);
     939           28236 :     pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
     940                 : 
     941                 :     /*
     942 EUB             :      * Either save error as current async result, or just emit the notice.
     943                 :      */
     944 GIC       28236 :     if (isError)
     945 ECB             :     {
     946 GBC       17836 :         pqClearAsyncResult(conn);   /* redundant, but be safe */
     947 GIC       17836 :         if (res)
     948 ECB             :         {
     949 GIC       17836 :             pqSetResultError(res, &workBuf, 0);
     950           17836 :             conn->result = res;
     951                 :         }
     952                 :         else
     953 ECB             :         {
     954                 :             /* Fall back to using the internal-error processing paths */
     955 UIC           0 :             conn->error_result = true;
     956                 :         }
     957                 : 
     958 GIC       17836 :         if (PQExpBufferDataBroken(workBuf))
     959 UNC           0 :             libpq_append_conn_error(conn, "out of memory");
     960 EUB             :         else
     961 GIC       17836 :             appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
     962 ECB             :     }
     963                 :     else
     964                 :     {
     965                 :         /* if we couldn't allocate the result set, just discard the NOTICE */
     966 GIC       10400 :         if (res)
     967                 :         {
     968                 :             /*
     969 ECB             :              * We can cheat a little here and not copy the message.  But if we
     970                 :              * were unlucky enough to run out of memory while filling workBuf,
     971                 :              * insert "out of memory", as in pqSetResultError.
     972 EUB             :              */
     973 GBC       10400 :             if (PQExpBufferDataBroken(workBuf))
     974 UBC           0 :                 res->errMsg = libpq_gettext("out of memory\n");
     975 EUB             :             else
     976 GIC       10400 :                 res->errMsg = workBuf.data;
     977           10400 :             if (res->noticeHooks.noticeRec != NULL)
     978           10400 :                 res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res);
     979           10400 :             PQclear(res);
     980                 :         }
     981                 :     }
     982                 : 
     983 CBC       28236 :     termPQExpBuffer(&workBuf);
     984 GIC       28236 :     return 0;
     985                 : 
     986 UIC           0 : fail:
     987 LBC           0 :     PQclear(res);
     988               0 :     termPQExpBuffer(&workBuf);
     989 UIC           0 :     return EOF;
     990                 : }
     991 ECB             : 
     992                 : /*
     993 EUB             :  * Construct an error message from the fields in the given PGresult,
     994                 :  * appending it to the contents of "msg".
     995                 :  */
     996                 : void
     997 GIC       28239 : pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
     998                 :                      PGVerbosity verbosity, PGContextVisibility show_context)
     999                 : {
    1000                 :     const char *val;
    1001 CBC       28239 :     const char *querytext = NULL;
    1002 GIC       28239 :     int         querypos = 0;
    1003 EUB             : 
    1004                 :     /* If we couldn't allocate a PGresult, just say "out of memory" */
    1005 GIC       28239 :     if (res == NULL)
    1006 EUB             :     {
    1007 UBC           0 :         appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
    1008 UIC           0 :         return;
    1009                 :     }
    1010                 : 
    1011 ECB             :     /*
    1012                 :      * If we don't have any broken-down fields, just return the base message.
    1013                 :      * This mainly applies if we're given a libpq-generated error result.
    1014                 :      */
    1015 CBC       28239 :     if (res->errFields == NULL)
    1016                 :     {
    1017 UIC           0 :         if (res->errMsg && res->errMsg[0])
    1018               0 :             appendPQExpBufferStr(msg, res->errMsg);
    1019                 :         else
    1020               0 :             appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
    1021               0 :         return;
    1022                 :     }
    1023 ECB             : 
    1024                 :     /* Else build error message from relevant fields */
    1025 GIC       28239 :     val = PQresultErrorField(res, PG_DIAG_SEVERITY);
    1026 CBC       28239 :     if (val)
    1027           28239 :         appendPQExpBuffer(msg, "%s:  ", val);
    1028                 : 
    1029 GBC       28239 :     if (verbosity == PQERRORS_SQLSTATE)
    1030                 :     {
    1031                 :         /*
    1032 ECB             :          * If we have a SQLSTATE, print that and nothing else.  If not (which
    1033                 :          * shouldn't happen for server-generated errors, but might possibly
    1034                 :          * happen for libpq-generated ones), fall back to TERSE format, as
    1035                 :          * that seems better than printing nothing at all.
    1036                 :          */
    1037 GIC          18 :         val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
    1038 CBC          18 :         if (val)
    1039 ECB             :         {
    1040 CBC          18 :             appendPQExpBuffer(msg, "%s\n", val);
    1041              18 :             return;
    1042 ECB             :         }
    1043 UIC           0 :         verbosity = PQERRORS_TERSE;
    1044 ECB             :     }
    1045                 : 
    1046 GIC       28221 :     if (verbosity == PQERRORS_VERBOSE)
    1047 ECB             :     {
    1048 CBC           3 :         val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
    1049 GIC           3 :         if (val)
    1050               3 :             appendPQExpBuffer(msg, "%s: ", val);
    1051                 :     }
    1052           28221 :     val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
    1053           28221 :     if (val)
    1054 CBC       28221 :         appendPQExpBufferStr(msg, val);
    1055 GIC       28221 :     val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
    1056           28221 :     if (val)
    1057                 :     {
    1058            4504 :         if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
    1059                 :         {
    1060 ECB             :             /* emit position as a syntax cursor display */
    1061 CBC        4500 :             querytext = res->errQuery;
    1062 GIC        4500 :             querypos = atoi(val);
    1063 ECB             :         }
    1064                 :         else
    1065                 :         {
    1066                 :             /* emit position as text addition to primary message */
    1067                 :             /* translator: %s represents a digit string */
    1068 GIC           4 :             appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
    1069                 :                               val);
    1070                 :         }
    1071                 :     }
    1072                 :     else
    1073 EUB             :     {
    1074 GIC       23717 :         val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
    1075           23717 :         if (val)
    1076                 :         {
    1077              44 :             querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
    1078 CBC          44 :             if (verbosity != PQERRORS_TERSE && querytext != NULL)
    1079 ECB             :             {
    1080                 :                 /* emit position as a syntax cursor display */
    1081 CBC          44 :                 querypos = atoi(val);
    1082 ECB             :             }
    1083                 :             else
    1084                 :             {
    1085                 :                 /* emit position as text addition to primary message */
    1086                 :                 /* translator: %s represents a digit string */
    1087 LBC           0 :                 appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
    1088 ECB             :                                   val);
    1089                 :             }
    1090                 :         }
    1091                 :     }
    1092 CBC       28221 :     appendPQExpBufferChar(msg, '\n');
    1093           28221 :     if (verbosity != PQERRORS_TERSE)
    1094 ECB             :     {
    1095 CBC       27863 :         if (querytext && querypos > 0)
    1096 GIC        4544 :             reportErrorPosition(msg, querytext, querypos,
    1097 CBC        4544 :                                 res->client_encoding);
    1098           27863 :         val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
    1099           27863 :         if (val)
    1100 GIC        4403 :             appendPQExpBuffer(msg, libpq_gettext("DETAIL:  %s\n"), val);
    1101           27863 :         val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
    1102           27863 :         if (val)
    1103 CBC        1998 :             appendPQExpBuffer(msg, libpq_gettext("HINT:  %s\n"), val);
    1104 GIC       27863 :         val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
    1105 CBC       27863 :         if (val)
    1106              44 :             appendPQExpBuffer(msg, libpq_gettext("QUERY:  %s\n"), val);
    1107 GBC       27863 :         if (show_context == PQSHOW_CONTEXT_ALWAYS ||
    1108           27757 :             (show_context == PQSHOW_CONTEXT_ERRORS &&
    1109 CBC       27757 :              res->resultStatus == PGRES_FATAL_ERROR))
    1110 ECB             :         {
    1111 GBC       17727 :             val = PQresultErrorField(res, PG_DIAG_CONTEXT);
    1112           17727 :             if (val)
    1113 CBC        1060 :                 appendPQExpBuffer(msg, libpq_gettext("CONTEXT:  %s\n"),
    1114 ECB             :                                   val);
    1115 EUB             :         }
    1116                 :     }
    1117 CBC       28221 :     if (verbosity == PQERRORS_VERBOSE)
    1118 ECB             :     {
    1119 GBC           3 :         val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
    1120               3 :         if (val)
    1121 LBC           0 :             appendPQExpBuffer(msg,
    1122               0 :                               libpq_gettext("SCHEMA NAME:  %s\n"), val);
    1123 GBC           3 :         val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
    1124               3 :         if (val)
    1125 UIC           0 :             appendPQExpBuffer(msg,
    1126 LBC           0 :                               libpq_gettext("TABLE NAME:  %s\n"), val);
    1127 GIC           3 :         val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
    1128               3 :         if (val)
    1129 UIC           0 :             appendPQExpBuffer(msg,
    1130               0 :                               libpq_gettext("COLUMN NAME:  %s\n"), val);
    1131 CBC           3 :         val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
    1132               3 :         if (val)
    1133 LBC           0 :             appendPQExpBuffer(msg,
    1134               0 :                               libpq_gettext("DATATYPE NAME:  %s\n"), val);
    1135 GIC           3 :         val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
    1136 CBC           3 :         if (val)
    1137 LBC           0 :             appendPQExpBuffer(msg,
    1138               0 :                               libpq_gettext("CONSTRAINT NAME:  %s\n"), val);
    1139 ECB             :     }
    1140 CBC       28221 :     if (verbosity == PQERRORS_VERBOSE)
    1141                 :     {
    1142 ECB             :         const char *valf;
    1143                 :         const char *vall;
    1144                 : 
    1145 GIC           3 :         valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE);
    1146               3 :         vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE);
    1147               3 :         val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
    1148               3 :         if (val || valf || vall)
    1149                 :         {
    1150               3 :             appendPQExpBufferStr(msg, libpq_gettext("LOCATION:  "));
    1151               3 :             if (val)
    1152               3 :                 appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
    1153               3 :             if (valf && vall)   /* unlikely we'd have just one */
    1154 CBC           3 :                 appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
    1155                 :                                   valf, vall);
    1156 GIC           3 :             appendPQExpBufferChar(msg, '\n');
    1157                 :         }
    1158                 :     }
    1159                 : }
    1160                 : 
    1161                 : /*
    1162                 :  * Add an error-location display to the error message under construction.
    1163                 :  *
    1164                 :  * The cursor location is measured in logical characters; the query string
    1165                 :  * is presumed to be in the specified encoding.
    1166                 :  */
    1167                 : static void
    1168            4544 : reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
    1169                 : {
    1170                 : #define DISPLAY_SIZE    60      /* screen width limit, in screen cols */
    1171                 : #define MIN_RIGHT_CUT   10      /* try to keep this far away from EOL */
    1172                 : 
    1173                 :     char       *wquery;
    1174                 :     int         slen,
    1175 ECB             :                 cno,
    1176                 :                 i,
    1177 EUB             :                *qidx,
    1178                 :                *scridx,
    1179                 :                 qoffset,
    1180 ECB             :                 scroffset,
    1181                 :                 ibeg,
    1182 EUB             :                 iend,
    1183                 :                 loc_line;
    1184                 :     bool        mb_encoding,
    1185                 :                 beg_trunc,
    1186                 :                 end_trunc;
    1187                 : 
    1188                 :     /* Convert loc from 1-based to 0-based; no-op if out of range */
    1189 GIC        4544 :     loc--;
    1190            4544 :     if (loc < 0)
    1191 UIC           0 :         return;
    1192                 : 
    1193 ECB             :     /* Need a writable copy of the query */
    1194 GIC        4544 :     wquery = strdup(query);
    1195 CBC        4544 :     if (wquery == NULL)
    1196 LBC           0 :         return;                 /* fail silently if out of memory */
    1197                 : 
    1198 EUB             :     /*
    1199                 :      * Each character might occupy multiple physical bytes in the string, and
    1200                 :      * in some Far Eastern character sets it might take more than one screen
    1201 ECB             :      * column as well.  We compute the starting byte offset and starting
    1202                 :      * screen column of each logical character, and store these in qidx[] and
    1203                 :      * scridx[] respectively.
    1204 EUB             :      */
    1205                 : 
    1206                 :     /* we need a safe allocation size... */
    1207 GIC        4544 :     slen = strlen(wquery) + 1;
    1208                 : 
    1209            4544 :     qidx = (int *) malloc(slen * sizeof(int));
    1210 CBC        4544 :     if (qidx == NULL)
    1211                 :     {
    1212 UIC           0 :         free(wquery);
    1213               0 :         return;
    1214                 :     }
    1215 GIC        4544 :     scridx = (int *) malloc(slen * sizeof(int));
    1216            4544 :     if (scridx == NULL)
    1217                 :     {
    1218 UIC           0 :         free(qidx);
    1219               0 :         free(wquery);
    1220               0 :         return;
    1221 ECB             :     }
    1222                 : 
    1223                 :     /* We can optimize a bit if it's a single-byte encoding */
    1224 CBC        4544 :     mb_encoding = (pg_encoding_max_length(encoding) != 1);
    1225 ECB             : 
    1226                 :     /*
    1227                 :      * Within the scanning loop, cno is the current character's logical
    1228                 :      * number, qoffset is its offset in wquery, and scroffset is its starting
    1229                 :      * logical screen column (all indexed from 0).  "loc" is the logical
    1230                 :      * character number of the error location.  We scan to determine loc_line
    1231                 :      * (the 1-based line number containing loc) and ibeg/iend (first character
    1232                 :      * number and last+1 character number of the line containing loc). Note
    1233                 :      * that qidx[] and scridx[] are filled only as far as iend.
    1234                 :      */
    1235 GIC        4544 :     qoffset = 0;
    1236            4544 :     scroffset = 0;
    1237            4544 :     loc_line = 1;
    1238            4544 :     ibeg = 0;
    1239 CBC        4544 :     iend = -1;                  /* -1 means not set yet */
    1240 ECB             : 
    1241 GIC      236460 :     for (cno = 0; wquery[qoffset] != '\0'; cno++)
    1242                 :     {
    1243          232393 :         char        ch = wquery[qoffset];
    1244                 : 
    1245          232393 :         qidx[cno] = qoffset;
    1246 CBC      232393 :         scridx[cno] = scroffset;
    1247                 : 
    1248 ECB             :         /*
    1249                 :          * Replace tabs with spaces in the writable copy.  (Later we might
    1250                 :          * want to think about coping with their variable screen width, but
    1251                 :          * not today.)
    1252                 :          */
    1253 CBC      232393 :         if (ch == '\t')
    1254 GIC         381 :             wquery[qoffset] = ' ';
    1255 ECB             : 
    1256                 :         /*
    1257                 :          * If end-of-line, count lines and mark positions. Each \r or \n
    1258                 :          * counts as a line except when \r \n appear together.
    1259                 :          */
    1260 CBC      232012 :         else if (ch == '\r' || ch == '\n')
    1261                 :         {
    1262            1693 :             if (cno < loc)
    1263                 :             {
    1264 GIC        1216 :                 if (ch == '\r' ||
    1265            1213 :                     cno == 0 ||
    1266            1213 :                     wquery[qidx[cno - 1]] != '\r')
    1267 CBC        1216 :                     loc_line++;
    1268                 :                 /* extract beginning = last line start before loc. */
    1269 GIC        1216 :                 ibeg = cno + 1;
    1270                 :             }
    1271 ECB             :             else
    1272                 :             {
    1273                 :                 /* set extract end. */
    1274 CBC         477 :                 iend = cno;
    1275 ECB             :                 /* done scanning. */
    1276 CBC         477 :                 break;
    1277                 :             }
    1278                 :         }
    1279                 : 
    1280                 :         /* Advance */
    1281 GBC      231916 :         if (mb_encoding)
    1282 EUB             :         {
    1283                 :             int         w;
    1284                 : 
    1285 GIC      231916 :             w = pg_encoding_dsplen(encoding, &wquery[qoffset]);
    1286 ECB             :             /* treat any non-tab control chars as width 1 */
    1287 GIC      231916 :             if (w <= 0)
    1288 CBC        1216 :                 w = 1;
    1289          231916 :             scroffset += w;
    1290          231916 :             qoffset += PQmblenBounded(&wquery[qoffset], encoding);
    1291                 :         }
    1292                 :         else
    1293                 :         {
    1294 ECB             :             /* We assume wide chars only exist in multibyte encodings */
    1295 UIC           0 :             scroffset++;
    1296               0 :             qoffset++;
    1297 ECB             :         }
    1298                 :     }
    1299                 :     /* Fix up if we didn't find an end-of-line after loc */
    1300 GIC        4544 :     if (iend < 0)
    1301                 :     {
    1302            4067 :         iend = cno;             /* query length in chars, +1 */
    1303            4067 :         qidx[iend] = qoffset;
    1304            4067 :         scridx[iend] = scroffset;
    1305                 :     }
    1306 ECB             : 
    1307                 :     /* Print only if loc is within computed query length */
    1308 CBC        4544 :     if (loc <= cno)
    1309 ECB             :     {
    1310                 :         /* If the line extracted is too long, we truncate it. */
    1311 GIC        4535 :         beg_trunc = false;
    1312            4535 :         end_trunc = false;
    1313            4535 :         if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
    1314                 :         {
    1315 ECB             :             /*
    1316                 :              * We first truncate right if it is enough.  This code might be
    1317                 :              * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
    1318                 :              * character right there, but that should be okay.
    1319                 :              */
    1320 GIC         963 :             if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
    1321                 :             {
    1322 CBC        8283 :                 while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
    1323 GIC        7731 :                     iend--;
    1324 CBC         552 :                 end_trunc = true;
    1325 ECB             :             }
    1326                 :             else
    1327                 :             {
    1328                 :                 /* Truncate right if not too close to loc. */
    1329 GIC        4700 :                 while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
    1330                 :                 {
    1331 CBC        4289 :                     iend--;
    1332 GIC        4289 :                     end_trunc = true;
    1333                 :                 }
    1334 ECB             : 
    1335                 :                 /* Truncate left if still too long. */
    1336 CBC        7458 :                 while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
    1337 ECB             :                 {
    1338 GIC        7047 :                     ibeg++;
    1339            7047 :                     beg_trunc = true;
    1340                 :                 }
    1341                 :             }
    1342                 :         }
    1343 ECB             : 
    1344                 :         /* truncate working copy at desired endpoint */
    1345 GIC        4535 :         wquery[qidx[iend]] = '\0';
    1346 ECB             : 
    1347                 :         /* Begin building the finished message. */
    1348 CBC        4535 :         i = msg->len;
    1349 GBC        4535 :         appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
    1350 CBC        4535 :         if (beg_trunc)
    1351 GIC         411 :             appendPQExpBufferStr(msg, "...");
    1352                 : 
    1353                 :         /*
    1354 ECB             :          * While we have the prefix in the msg buffer, compute its screen
    1355                 :          * width.
    1356                 :          */
    1357 CBC        4535 :         scroffset = 0;
    1358 GIC       42054 :         for (; i < msg->len; i += PQmblenBounded(&msg->data[i], encoding))
    1359                 :         {
    1360 CBC       37519 :             int         w = pg_encoding_dsplen(encoding, &msg->data[i]);
    1361 ECB             : 
    1362 CBC       37519 :             if (w <= 0)
    1363 LBC           0 :                 w = 1;
    1364 CBC       37519 :             scroffset += w;
    1365                 :         }
    1366                 : 
    1367                 :         /* Finish up the LINE message line. */
    1368            4535 :         appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
    1369            4535 :         if (end_trunc)
    1370             818 :             appendPQExpBufferStr(msg, "...");
    1371 GIC        4535 :         appendPQExpBufferChar(msg, '\n');
    1372                 : 
    1373                 :         /* Now emit the cursor marker line. */
    1374            4535 :         scroffset += scridx[loc] - scridx[ibeg];
    1375          139902 :         for (i = 0; i < scroffset; i++)
    1376          135367 :             appendPQExpBufferChar(msg, ' ');
    1377            4535 :         appendPQExpBufferChar(msg, '^');
    1378            4535 :         appendPQExpBufferChar(msg, '\n');
    1379                 :     }
    1380                 : 
    1381 EUB             :     /* Clean up. */
    1382 GIC        4544 :     free(scridx);
    1383            4544 :     free(qidx);
    1384            4544 :     free(wquery);
    1385                 : }
    1386                 : 
    1387                 : 
    1388                 : /*
    1389                 :  * Attempt to read a NegotiateProtocolVersion message.
    1390                 :  * Entry: 'v' message type and length have already been consumed.
    1391                 :  * Exit: returns 0 if successfully consumed message.
    1392                 :  *       returns EOF if not enough data.
    1393                 :  */
    1394                 : int
    1395 UNC           0 : pqGetNegotiateProtocolVersion3(PGconn *conn)
    1396                 : {
    1397                 :     int         tmp;
    1398                 :     ProtocolVersion their_version;
    1399                 :     int         num;
    1400                 :     PQExpBufferData buf;
    1401                 : 
    1402               0 :     if (pqGetInt(&tmp, 4, conn) != 0)
    1403               0 :         return EOF;
    1404               0 :     their_version = tmp;
    1405                 : 
    1406               0 :     if (pqGetInt(&num, 4, conn) != 0)
    1407               0 :         return EOF;
    1408                 : 
    1409               0 :     initPQExpBuffer(&buf);
    1410               0 :     for (int i = 0; i < num; i++)
    1411                 :     {
    1412               0 :         if (pqGets(&conn->workBuffer, conn))
    1413                 :         {
    1414               0 :             termPQExpBuffer(&buf);
    1415               0 :             return EOF;
    1416                 :         }
    1417               0 :         if (buf.len > 0)
    1418               0 :             appendPQExpBufferChar(&buf, ' ');
    1419               0 :         appendPQExpBufferStr(&buf, conn->workBuffer.data);
    1420                 :     }
    1421                 : 
    1422               0 :     if (their_version < conn->pversion)
    1423               0 :         appendPQExpBuffer(&conn->errorMessage,
    1424               0 :                           libpq_gettext("protocol version not supported by server: client uses %u.%u, server supports up to %u.%u\n"),
    1425               0 :                           PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion),
    1426                 :                           PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version));
    1427               0 :     if (num > 0)
    1428               0 :         appendPQExpBuffer(&conn->errorMessage,
    1429               0 :                           libpq_ngettext("protocol extension not supported by server: %s\n",
    1430                 :                                          "protocol extensions not supported by server: %s\n", num),
    1431                 :                           buf.data);
    1432                 : 
    1433                 :     /* neither -- server shouldn't have sent it */
    1434               0 :     if (!(their_version < conn->pversion) && !(num > 0))
    1435               0 :         appendPQExpBuffer(&conn->errorMessage,
    1436               0 :                           libpq_gettext("invalid %s message"), "NegotiateProtocolVersion");
    1437                 : 
    1438               0 :     termPQExpBuffer(&buf);
    1439               0 :     return 0;
    1440                 : }
    1441                 : 
    1442                 : 
    1443 EUB             : /*
    1444                 :  * Attempt to read a ParameterStatus message.
    1445                 :  * This is possible in several places, so we break it out as a subroutine.
    1446                 :  * Entry: 'S' message type and length have already been consumed.
    1447                 :  * Exit: returns 0 if successfully consumed message.
    1448                 :  *       returns EOF if not enough data.
    1449                 :  */
    1450                 : static int
    1451 GBC      128398 : getParameterStatus(PGconn *conn)
    1452                 : {
    1453 EUB             :     PQExpBufferData valueBuf;
    1454                 : 
    1455                 :     /* Get the parameter name */
    1456 GBC      128398 :     if (pqGets(&conn->workBuffer, conn))
    1457 UIC           0 :         return EOF;
    1458 EUB             :     /* Get the parameter value (could be large) */
    1459 GBC      128398 :     initPQExpBuffer(&valueBuf);
    1460          128398 :     if (pqGets(&valueBuf, conn))
    1461                 :     {
    1462 UIC           0 :         termPQExpBuffer(&valueBuf);
    1463 UBC           0 :         return EOF;
    1464 EUB             :     }
    1465                 :     /* And save it */
    1466 GBC      128398 :     pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data);
    1467 GIC      128398 :     termPQExpBuffer(&valueBuf);
    1468 GBC      128398 :     return 0;
    1469 EUB             : }
    1470                 : 
    1471                 : 
    1472                 : /*
    1473                 :  * Attempt to read a Notify response message.
    1474                 :  * This is possible in several places, so we break it out as a subroutine.
    1475                 :  * Entry: 'A' message type and length have already been consumed.
    1476                 :  * Exit: returns 0 if successfully consumed Notify message.
    1477                 :  *       returns EOF if not enough data.
    1478                 :  */
    1479                 : static int
    1480 GBC          31 : getNotify(PGconn *conn)
    1481                 : {
    1482                 :     int         be_pid;
    1483                 :     char       *svname;
    1484                 :     int         nmlen;
    1485                 :     int         extralen;
    1486                 :     PGnotify   *newNotify;
    1487                 : 
    1488 GIC          31 :     if (pqGetInt(&be_pid, 4, conn))
    1489 UIC           0 :         return EOF;
    1490 GIC          31 :     if (pqGets(&conn->workBuffer, conn))
    1491 UIC           0 :         return EOF;
    1492 ECB             :     /* must save name while getting extra string */
    1493 GIC          31 :     svname = strdup(conn->workBuffer.data);
    1494              31 :     if (!svname)
    1495 UIC           0 :         return EOF;
    1496 GIC          31 :     if (pqGets(&conn->workBuffer, conn))
    1497 ECB             :     {
    1498 UBC           0 :         free(svname);
    1499 UIC           0 :         return EOF;
    1500 ECB             :     }
    1501                 : 
    1502                 :     /*
    1503 EUB             :      * Store the strings right after the PQnotify structure so it can all be
    1504                 :      * freed at once.  We don't use NAMEDATALEN because we don't want to tie
    1505                 :      * this interface to a specific server name length.
    1506                 :      */
    1507 CBC          31 :     nmlen = strlen(svname);
    1508              31 :     extralen = strlen(conn->workBuffer.data);
    1509              31 :     newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2);
    1510 GIC          31 :     if (newNotify)
    1511                 :     {
    1512              31 :         newNotify->relname = (char *) newNotify + sizeof(PGnotify);
    1513              31 :         strcpy(newNotify->relname, svname);
    1514              31 :         newNotify->extra = newNotify->relname + nmlen + 1;
    1515              31 :         strcpy(newNotify->extra, conn->workBuffer.data);
    1516              31 :         newNotify->be_pid = be_pid;
    1517              31 :         newNotify->next = NULL;
    1518              31 :         if (conn->notifyTail)
    1519              12 :             conn->notifyTail->next = newNotify;
    1520                 :         else
    1521 CBC          19 :             conn->notifyHead = newNotify;
    1522 GIC          31 :         conn->notifyTail = newNotify;
    1523                 :     }
    1524                 : 
    1525              31 :     free(svname);
    1526              31 :     return 0;
    1527                 : }
    1528                 : 
    1529 ECB             : /*
    1530 EUB             :  * getCopyStart - process CopyInResponse, CopyOutResponse or
    1531 ECB             :  * CopyBothResponse message
    1532 EUB             :  *
    1533                 :  * parseInput already read the message type and length.
    1534 ECB             :  */
    1535                 : static int
    1536 GBC        4420 : getCopyStart(PGconn *conn, ExecStatusType copytype)
    1537 ECB             : {
    1538                 :     PGresult   *result;
    1539 EUB             :     int         nfields;
    1540                 :     int         i;
    1541                 : 
    1542 GIC        4420 :     result = PQmakeEmptyPGresult(conn, copytype);
    1543            4420 :     if (!result)
    1544 UIC           0 :         goto failure;
    1545                 : 
    1546 GIC        4420 :     if (pqGetc(&conn->copy_is_binary, conn))
    1547 UIC           0 :         goto failure;
    1548 CBC        4420 :     result->binary = conn->copy_is_binary;
    1549 ECB             :     /* the next two bytes are the number of fields  */
    1550 CBC        4420 :     if (pqGetInt(&(result->numAttributes), 2, conn))
    1551 LBC           0 :         goto failure;
    1552 GIC        4420 :     nfields = result->numAttributes;
    1553 ECB             : 
    1554                 :     /* allocate space for the attribute descriptors */
    1555 CBC        4420 :     if (nfields > 0)
    1556 ECB             :     {
    1557 CBC        3671 :         result->attDescs = (PGresAttDesc *)
    1558            3671 :             pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
    1559            3671 :         if (!result->attDescs)
    1560 LBC           0 :             goto failure;
    1561 GIC       38011 :         MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
    1562 ECB             :     }
    1563                 : 
    1564 GIC       17701 :     for (i = 0; i < nfields; i++)
    1565                 :     {
    1566 ECB             :         int         format;
    1567                 : 
    1568 GIC       13281 :         if (pqGetInt(&format, 2, conn))
    1569 UIC           0 :             goto failure;
    1570                 : 
    1571                 :         /*
    1572                 :          * Since pqGetInt treats 2-byte integers as unsigned, we need to
    1573                 :          * coerce these results to signed form.
    1574                 :          */
    1575 GIC       13281 :         format = (int) ((int16) format);
    1576           13281 :         result->attDescs[i].format = format;
    1577 ECB             :     }
    1578                 : 
    1579                 :     /* Success! */
    1580 GIC        4420 :     conn->result = result;
    1581            4420 :     return 0;
    1582                 : 
    1583 LBC           0 : failure:
    1584               0 :     PQclear(result);
    1585 UBC           0 :     return EOF;
    1586                 : }
    1587 ECB             : 
    1588 EUB             : /*
    1589 ECB             :  * getReadyForQuery - process ReadyForQuery message
    1590                 :  */
    1591                 : static int
    1592 GBC      254466 : getReadyForQuery(PGconn *conn)
    1593 ECB             : {
    1594                 :     char        xact_status;
    1595                 : 
    1596 CBC      254466 :     if (pqGetc(&xact_status, conn))
    1597 UIC           0 :         return EOF;
    1598 CBC      254466 :     switch (xact_status)
    1599 ECB             :     {
    1600 CBC      195904 :         case 'I':
    1601 GBC      195904 :             conn->xactStatus = PQTRANS_IDLE;
    1602 CBC      195904 :             break;
    1603 GIC       57755 :         case 'T':
    1604           57755 :             conn->xactStatus = PQTRANS_INTRANS;
    1605 CBC       57755 :             break;
    1606 GIC         807 :         case 'E':
    1607             807 :             conn->xactStatus = PQTRANS_INERROR;
    1608             807 :             break;
    1609 LBC           0 :         default:
    1610 UBC           0 :             conn->xactStatus = PQTRANS_UNKNOWN;
    1611 UIC           0 :             break;
    1612                 :     }
    1613                 : 
    1614 GIC      254466 :     return 0;
    1615                 : }
    1616 ECB             : 
    1617                 : /*
    1618                 :  * getCopyDataMessage - fetch next CopyData message, process async messages
    1619                 :  *
    1620                 :  * Returns length word of CopyData message (> 0), or 0 if no complete
    1621                 :  * message available, -1 if end of copy, -2 if error.
    1622                 :  */
    1623                 : static int
    1624 GBC     2612538 : getCopyDataMessage(PGconn *conn)
    1625 EUB             : {
    1626                 :     char        id;
    1627                 :     int         msgLength;
    1628                 :     int         avail;
    1629                 : 
    1630                 :     for (;;)
    1631                 :     {
    1632                 :         /*
    1633 ECB             :          * Do we have the next input message?  To make life simpler for async
    1634                 :          * callers, we keep returning 0 until the next message is fully
    1635                 :          * available, even if it is not Copy Data.
    1636                 :          */
    1637 CBC     2612562 :         conn->inCursor = conn->inStart;
    1638 GBC     2612562 :         if (pqGetc(&id, conn))
    1639 CBC      287330 :             return 0;
    1640 GIC     2325232 :         if (pqGetInt(&msgLength, 4, conn))
    1641 CBC         810 :             return 0;
    1642         2324422 :         if (msgLength < 4)
    1643 ECB             :         {
    1644 LBC           0 :             handleSyncLoss(conn, id, msgLength);
    1645               0 :             return -2;
    1646 ECB             :         }
    1647 CBC     2324422 :         avail = conn->inEnd - conn->inCursor;
    1648         2324422 :         if (avail < msgLength - 4)
    1649 ECB             :         {
    1650 EUB             :             /*
    1651                 :              * Before returning, enlarge the input buffer if needed to hold
    1652                 :              * the whole message.  See notes in parseInput.
    1653                 :              */
    1654 GIC      153924 :             if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4,
    1655 ECB             :                                      conn))
    1656                 :             {
    1657                 :                 /*
    1658                 :                  * XXX add some better recovery code... plan is to skip over
    1659                 :                  * the message using its length, then report an error. For the
    1660                 :                  * moment, just treat this like loss of sync (which indeed it
    1661                 :                  * might be!)
    1662                 :                  */
    1663 UIC           0 :                 handleSyncLoss(conn, id, msgLength);
    1664               0 :                 return -2;
    1665 ECB             :             }
    1666 GIC      153924 :             return 0;
    1667                 :         }
    1668                 : 
    1669                 :         /*
    1670                 :          * If it's a legitimate async message type, process it.  (NOTIFY
    1671                 :          * messages are not currently possible here, but we handle them for
    1672                 :          * completeness.)  Otherwise, if it's anything except Copy Data,
    1673                 :          * report end-of-copy.
    1674                 :          */
    1675         2170498 :         switch (id)
    1676                 :         {
    1677 UIC           0 :             case 'A':           /* NOTIFY */
    1678 LBC           0 :                 if (getNotify(conn))
    1679               0 :                     return 0;
    1680               0 :                 break;
    1681 CBC          24 :             case 'N':           /* NOTICE */
    1682              24 :                 if (pqGetErrorNotice3(conn, false))
    1683 LBC           0 :                     return 0;
    1684 GIC          24 :                 break;
    1685 UBC           0 :             case 'S':           /* ParameterStatus */
    1686               0 :                 if (getParameterStatus(conn))
    1687 UIC           0 :                     return 0;
    1688 LBC           0 :                 break;
    1689 CBC     2166817 :             case 'd':           /* Copy Data, pass it back to caller */
    1690 GIC     2166817 :                 return msgLength;
    1691            3616 :             case 'c':
    1692                 : 
    1693                 :                 /*
    1694                 :                  * If this is a CopyDone message, exit COPY_OUT mode and let
    1695 ECB             :                  * caller read status with PQgetResult().  If we're in
    1696                 :                  * COPY_BOTH mode, return to COPY_IN mode.
    1697                 :                  */
    1698 GIC        3616 :                 if (conn->asyncStatus == PGASYNC_COPY_BOTH)
    1699              13 :                     conn->asyncStatus = PGASYNC_COPY_IN;
    1700                 :                 else
    1701            3603 :                     conn->asyncStatus = PGASYNC_BUSY;
    1702            3616 :                 return -1;
    1703              41 :             default:            /* treat as end of copy */
    1704 EUB             : 
    1705                 :                 /*
    1706                 :                  * Any other message terminates either COPY_IN or COPY_BOTH
    1707 ECB             :                  * mode.
    1708                 :                  */
    1709 GIC          41 :                 conn->asyncStatus = PGASYNC_BUSY;
    1710              41 :                 return -1;
    1711                 :         }
    1712                 : 
    1713                 :         /* trace server-to-client message */
    1714              24 :         if (conn->Pfdebug)
    1715 UIC           0 :             pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
    1716 ECB             : 
    1717                 :         /* Drop the processed message and loop around for another */
    1718 GBC          24 :         conn->inStart = conn->inCursor;
    1719 EUB             :     }
    1720                 : }
    1721                 : 
    1722 ECB             : /*
    1723                 :  * PQgetCopyData - read a row of data from the backend during COPY OUT
    1724 EUB             :  * or COPY BOTH
    1725 ECB             :  *
    1726 EUB             :  * If successful, sets *buffer to point to a malloc'd row of data, and
    1727                 :  * returns row length (always > 0) as result.
    1728                 :  * Returns 0 if no row available yet (only possible if async is true),
    1729                 :  * -1 if end of copy (consult PQgetResult), or -2 if error (consult
    1730 ECB             :  * PQerrorMessage).
    1731                 :  */
    1732                 : int
    1733 GIC     2470798 : pqGetCopyData3(PGconn *conn, char **buffer, int async)
    1734                 : {
    1735                 :     int         msgLength;
    1736                 : 
    1737                 :     for (;;)
    1738                 :     {
    1739 ECB             :         /*
    1740                 :          * Collect the next input message.  To make life simpler for async
    1741                 :          * callers, we keep returning 0 until the next message is fully
    1742                 :          * available, even if it is not Copy Data.
    1743                 :          */
    1744 CBC     2612538 :         msgLength = getCopyDataMessage(conn);
    1745 GIC     2612538 :         if (msgLength < 0)
    1746            3657 :             return msgLength;   /* end-of-copy or error */
    1747         2608881 :         if (msgLength == 0)
    1748                 :         {
    1749                 :             /* Don't block if async read requested */
    1750 CBC      442064 :             if (async)
    1751          300324 :                 return 0;
    1752                 :             /* Need to load more data */
    1753 GIC      283480 :             if (pqWait(true, false, conn) ||
    1754          141740 :                 pqReadData(conn) < 0)
    1755 LBC           0 :                 return -2;
    1756 GBC      141740 :             continue;
    1757                 :         }
    1758                 : 
    1759 ECB             :         /*
    1760                 :          * Drop zero-length messages (shouldn't happen anyway).  Otherwise
    1761                 :          * pass the data back to the caller.
    1762                 :          */
    1763 GIC     2166817 :         msgLength -= 4;
    1764         2166817 :         if (msgLength > 0)
    1765                 :         {
    1766         2166817 :             *buffer = (char *) malloc(msgLength + 1);
    1767         2166817 :             if (*buffer == NULL)
    1768                 :             {
    1769 UNC           0 :                 libpq_append_conn_error(conn, "out of memory");
    1770 UIC           0 :                 return -2;
    1771                 :             }
    1772 GIC     2166817 :             memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
    1773 CBC     2166817 :             (*buffer)[msgLength] = '\0';    /* Add terminating null */
    1774                 : 
    1775                 :             /* Mark message consumed */
    1776 GIC     2166817 :             conn->inStart = conn->inCursor + msgLength;
    1777                 : 
    1778         2166817 :             return msgLength;
    1779                 :         }
    1780                 : 
    1781                 :         /* Empty, so drop it and loop around for another */
    1782 UIC           0 :         conn->inStart = conn->inCursor;
    1783                 :     }
    1784 ECB             : }
    1785                 : 
    1786                 : /*
    1787                 :  * PQgetline - gets a newline-terminated string from the backend.
    1788                 :  *
    1789                 :  * See fe-exec.c for documentation.
    1790                 :  */
    1791                 : int
    1792 UIC           0 : pqGetline3(PGconn *conn, char *s, int maxlen)
    1793 ECB             : {
    1794                 :     int         status;
    1795 EUB             : 
    1796 LBC           0 :     if (conn->sock == PGINVALID_SOCKET ||
    1797 UIC           0 :         (conn->asyncStatus != PGASYNC_COPY_OUT &&
    1798               0 :          conn->asyncStatus != PGASYNC_COPY_BOTH) ||
    1799               0 :         conn->copy_is_binary)
    1800                 :     {
    1801 UNC           0 :         libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT");
    1802 LBC           0 :         *s = '\0';
    1803               0 :         return EOF;
    1804                 :     }
    1805 ECB             : 
    1806 LBC           0 :     while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
    1807                 :     {
    1808 EUB             :         /* need to load more data */
    1809 UBC           0 :         if (pqWait(true, false, conn) ||
    1810 UIC           0 :             pqReadData(conn) < 0)
    1811 ECB             :         {
    1812 LBC           0 :             *s = '\0';
    1813 UIC           0 :             return EOF;
    1814                 :         }
    1815 ECB             :     }
    1816                 : 
    1817 LBC           0 :     if (status < 0)
    1818                 :     {
    1819                 :         /* End of copy detected; gin up old-style terminator */
    1820 UIC           0 :         strcpy(s, "\\.");
    1821 UBC           0 :         return 0;
    1822                 :     }
    1823                 : 
    1824                 :     /* Add null terminator, and strip trailing \n if present */
    1825 UIC           0 :     if (s[status - 1] == '\n')
    1826                 :     {
    1827               0 :         s[status - 1] = '\0';
    1828               0 :         return 0;
    1829                 :     }
    1830                 :     else
    1831 EUB             :     {
    1832 UIC           0 :         s[status] = '\0';
    1833               0 :         return 1;
    1834                 :     }
    1835 EUB             : }
    1836                 : 
    1837                 : /*
    1838                 :  * PQgetlineAsync - gets a COPY data row without blocking.
    1839                 :  *
    1840                 :  * See fe-exec.c for documentation.
    1841                 :  */
    1842                 : int
    1843 UIC           0 : pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
    1844                 : {
    1845 EUB             :     int         msgLength;
    1846                 :     int         avail;
    1847                 : 
    1848 UBC           0 :     if (conn->asyncStatus != PGASYNC_COPY_OUT
    1849               0 :         && conn->asyncStatus != PGASYNC_COPY_BOTH)
    1850 UIC           0 :         return -1;              /* we are not doing a copy... */
    1851 EUB             : 
    1852                 :     /*
    1853                 :      * Recognize the next input message.  To make life simpler for async
    1854                 :      * callers, we keep returning 0 until the next message is fully available
    1855                 :      * even if it is not Copy Data.  This should keep PQendcopy from blocking.
    1856                 :      * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
    1857                 :      */
    1858 UIC           0 :     msgLength = getCopyDataMessage(conn);
    1859 UBC           0 :     if (msgLength < 0)
    1860               0 :         return -1;              /* end-of-copy or error */
    1861 UIC           0 :     if (msgLength == 0)
    1862               0 :         return 0;               /* no data yet */
    1863                 : 
    1864 EUB             :     /*
    1865                 :      * Move data from libpq's buffer to the caller's.  In the case where a
    1866                 :      * prior call found the caller's buffer too small, we use
    1867                 :      * conn->copy_already_done to remember how much of the row was already
    1868                 :      * returned to the caller.
    1869                 :      */
    1870 UIC           0 :     conn->inCursor += conn->copy_already_done;
    1871 UBC           0 :     avail = msgLength - 4 - conn->copy_already_done;
    1872               0 :     if (avail <= bufsize)
    1873                 :     {
    1874                 :         /* Able to consume the whole message */
    1875 UIC           0 :         memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
    1876                 :         /* Mark message consumed */
    1877               0 :         conn->inStart = conn->inCursor + avail;
    1878                 :         /* Reset state for next time */
    1879               0 :         conn->copy_already_done = 0;
    1880               0 :         return avail;
    1881                 :     }
    1882 EUB             :     else
    1883                 :     {
    1884                 :         /* We must return a partial message */
    1885 UIC           0 :         memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
    1886                 :         /* The message is NOT consumed from libpq's buffer */
    1887 UBC           0 :         conn->copy_already_done += bufsize;
    1888               0 :         return bufsize;
    1889 EUB             :     }
    1890                 : }
    1891                 : 
    1892                 : /*
    1893                 :  * PQendcopy
    1894                 :  *
    1895                 :  * See fe-exec.c for documentation.
    1896                 :  */
    1897                 : int
    1898 GBC         151 : pqEndcopy3(PGconn *conn)
    1899 EUB             : {
    1900                 :     PGresult   *result;
    1901                 : 
    1902 GIC         151 :     if (conn->asyncStatus != PGASYNC_COPY_IN &&
    1903             149 :         conn->asyncStatus != PGASYNC_COPY_OUT &&
    1904 UIC           0 :         conn->asyncStatus != PGASYNC_COPY_BOTH)
    1905                 :     {
    1906 UNC           0 :         libpq_append_conn_error(conn, "no COPY in progress");
    1907 UIC           0 :         return 1;
    1908 EUB             :     }
    1909                 : 
    1910                 :     /* Send the CopyDone message if needed */
    1911 GIC         151 :     if (conn->asyncStatus == PGASYNC_COPY_IN ||
    1912             149 :         conn->asyncStatus == PGASYNC_COPY_BOTH)
    1913 EUB             :     {
    1914 GIC           4 :         if (pqPutMsgStart('c', conn) < 0 ||
    1915 GBC           2 :             pqPutMsgEnd(conn) < 0)
    1916 UIC           0 :             return 1;
    1917 EUB             : 
    1918                 :         /*
    1919                 :          * If we sent the COPY command in extended-query mode, we must issue a
    1920                 :          * Sync as well.
    1921                 :          */
    1922 GIC           2 :         if (conn->cmd_queue_head &&
    1923 GBC           2 :             conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
    1924                 :         {
    1925 UBC           0 :             if (pqPutMsgStart('S', conn) < 0 ||
    1926               0 :                 pqPutMsgEnd(conn) < 0)
    1927 UIC           0 :                 return 1;
    1928                 :         }
    1929                 :     }
    1930                 : 
    1931                 :     /*
    1932                 :      * make sure no data is waiting to be sent, abort if we are non-blocking
    1933                 :      * and the flush fails
    1934                 :      */
    1935 GIC         151 :     if (pqFlush(conn) && pqIsnonblocking(conn))
    1936 LBC           0 :         return 1;
    1937                 : 
    1938                 :     /* Return to active duty */
    1939 GIC         151 :     conn->asyncStatus = PGASYNC_BUSY;
    1940 ECB             : 
    1941                 :     /*
    1942 EUB             :      * Non blocking connections may have to abort at this point.  If everyone
    1943                 :      * played the game there should be no problem, but in error scenarios the
    1944                 :      * expected messages may not have arrived yet.  (We are assuming that the
    1945                 :      * backend's packetizing will ensure that CommandComplete arrives along
    1946                 :      * with the CopyDone; are there corner cases where that doesn't happen?)
    1947                 :      */
    1948 GIC         151 :     if (pqIsnonblocking(conn) && PQisBusy(conn))
    1949 LBC           0 :         return 1;
    1950 ECB             : 
    1951                 :     /* Wait for the completion response */
    1952 CBC         151 :     result = PQgetResult(conn);
    1953 ECB             : 
    1954 EUB             :     /* Expecting a successful result */
    1955 GIC         151 :     if (result && result->resultStatus == PGRES_COMMAND_OK)
    1956                 :     {
    1957             150 :         PQclear(result);
    1958             150 :         return 0;
    1959                 :     }
    1960 ECB             : 
    1961                 :     /*
    1962                 :      * Trouble. For backwards-compatibility reasons, we issue the error
    1963 EUB             :      * message as if it were a notice (would be nice to get rid of this
    1964                 :      * silliness, but too many apps probably don't handle errors from
    1965                 :      * PQendcopy reasonably).  Note that the app can still obtain the error
    1966                 :      * status from the PGconn object.
    1967                 :      */
    1968 GIC           1 :     if (conn->errorMessage.len > 0)
    1969                 :     {
    1970                 :         /* We have to strip the trailing newline ... pain in neck... */
    1971               1 :         char        svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
    1972                 : 
    1973 CBC           1 :         if (svLast == '\n')
    1974 GBC           1 :             conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
    1975 GIC           1 :         pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
    1976               1 :         conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
    1977 ECB             :     }
    1978                 : 
    1979 GIC           1 :     PQclear(result);
    1980                 : 
    1981               1 :     return 1;
    1982                 : }
    1983                 : 
    1984                 : 
    1985                 : /*
    1986 ECB             :  * PQfn - Send a function call to the POSTGRES backend.
    1987 EUB             :  *
    1988                 :  * See fe-exec.c for documentation.
    1989                 :  */
    1990 ECB             : PGresult *
    1991 GIC        1063 : pqFunctionCall3(PGconn *conn, Oid fnid,
    1992                 :                 int *result_buf, int *actual_result_len,
    1993 ECB             :                 int result_is_int,
    1994                 :                 const PQArgBlock *args, int nargs)
    1995                 : {
    1996 CBC        1063 :     bool        needInput = false;
    1997 GIC        1063 :     ExecStatusType status = PGRES_FATAL_ERROR;
    1998                 :     char        id;
    1999                 :     int         msgLength;
    2000                 :     int         avail;
    2001                 :     int         i;
    2002                 : 
    2003                 :     /* already validated by PQfn */
    2004            1063 :     Assert(conn->pipelineStatus == PQ_PIPELINE_OFF);
    2005                 : 
    2006 ECB             :     /* PQfn already validated connection state */
    2007                 : 
    2008 GIC        2126 :     if (pqPutMsgStart('F', conn) < 0 || /* function call msg */
    2009 CBC        2126 :         pqPutInt(fnid, 4, conn) < 0 ||   /* function id */
    2010 GIC        2126 :         pqPutInt(1, 2, conn) < 0 || /* # of format codes */
    2011 CBC        2126 :         pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
    2012            1063 :         pqPutInt(nargs, 2, conn) < 0)    /* # of args */
    2013 ECB             :     {
    2014                 :         /* error message should be set up already */
    2015 UIC           0 :         return NULL;
    2016                 :     }
    2017 ECB             : 
    2018 GIC        3080 :     for (i = 0; i < nargs; ++i)
    2019 ECB             :     {                           /* len.int4 + contents     */
    2020 GIC        2017 :         if (pqPutInt(args[i].len, 4, conn))
    2021 UIC           0 :             return NULL;
    2022 GIC        2017 :         if (args[i].len == -1)
    2023 UIC           0 :             continue;           /* it's NULL */
    2024                 : 
    2025 GIC        2017 :         if (args[i].isint)
    2026                 :         {
    2027            1524 :             if (pqPutInt(args[i].u.integer, args[i].len, conn))
    2028 UIC           0 :                 return NULL;
    2029 ECB             :         }
    2030                 :         else
    2031                 :         {
    2032 GIC         493 :             if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
    2033 UIC           0 :                 return NULL;
    2034 ECB             :         }
    2035                 :     }
    2036                 : 
    2037 GIC        1063 :     if (pqPutInt(1, 2, conn) < 0)    /* result format code: BINARY */
    2038 UIC           0 :         return NULL;
    2039                 : 
    2040 GIC        2126 :     if (pqPutMsgEnd(conn) < 0 ||
    2041            1063 :         pqFlush(conn))
    2042 LBC           0 :         return NULL;
    2043                 : 
    2044                 :     for (;;)
    2045                 :     {
    2046 CBC        3432 :         if (needInput)
    2047 ECB             :         {
    2048                 :             /* Wait for some data to arrive (or for the channel to close) */
    2049 CBC        2612 :             if (pqWait(true, false, conn) ||
    2050            1306 :                 pqReadData(conn) < 0)
    2051                 :                 break;
    2052                 :         }
    2053 EUB             : 
    2054                 :         /*
    2055                 :          * Scan the message. If we run out of data, loop around to try again.
    2056 ECB             :          */
    2057 GIC        3432 :         needInput = true;
    2058 ECB             : 
    2059 GBC        3432 :         conn->inCursor = conn->inStart;
    2060 CBC        3432 :         if (pqGetc(&id, conn))
    2061 GBC        1063 :             continue;
    2062 GIC        2369 :         if (pqGetInt(&msgLength, 4, conn))
    2063 LBC           0 :             continue;
    2064                 : 
    2065 ECB             :         /*
    2066 EUB             :          * Try to validate message type/length here.  A length less than 4 is
    2067                 :          * definitely broken.  Large lengths should only be believed for a few
    2068                 :          * message types.
    2069                 :          */
    2070 CBC        2369 :         if (msgLength < 4)
    2071 EUB             :         {
    2072 UIC           0 :             handleSyncLoss(conn, id, msgLength);
    2073               0 :             break;
    2074                 :         }
    2075 CBC        2369 :         if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
    2076 EUB             :         {
    2077 UIC           0 :             handleSyncLoss(conn, id, msgLength);
    2078 LBC           0 :             break;
    2079 ECB             :         }
    2080 EUB             : 
    2081                 :         /*
    2082                 :          * Can't process if message body isn't all here yet.
    2083                 :          */
    2084 CBC        2369 :         msgLength -= 4;
    2085 GIC        2369 :         avail = conn->inEnd - conn->inCursor;
    2086            2369 :         if (avail < msgLength)
    2087 ECB             :         {
    2088                 :             /*
    2089                 :              * Before looping, enlarge the input buffer if needed to hold the
    2090                 :              * whole message.  See notes in parseInput.
    2091                 :              */
    2092 GIC         243 :             if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
    2093                 :                                      conn))
    2094                 :             {
    2095 ECB             :                 /*
    2096                 :                  * XXX add some better recovery code... plan is to skip over
    2097                 :                  * the message using its length, then report an error. For the
    2098                 :                  * moment, just treat this like loss of sync (which indeed it
    2099                 :                  * might be!)
    2100                 :                  */
    2101 UBC           0 :                 handleSyncLoss(conn, id, msgLength);
    2102 UIC           0 :                 break;
    2103                 :             }
    2104 GIC         243 :             continue;
    2105                 :         }
    2106                 : 
    2107                 :         /*
    2108 ECB             :          * We should see V or E response to the command, but might get N
    2109                 :          * and/or A notices first. We also need to swallow the final Z before
    2110 EUB             :          * returning.
    2111                 :          */
    2112 GIC        2126 :         switch (id)
    2113 ECB             :         {
    2114 GIC        1063 :             case 'V':           /* function result */
    2115 GBC        1063 :                 if (pqGetInt(actual_result_len, 4, conn))
    2116 UBC           0 :                     continue;
    2117 GIC        1063 :                 if (*actual_result_len != -1)
    2118                 :                 {
    2119            1063 :                     if (result_is_int)
    2120                 :                     {
    2121             692 :                         if (pqGetInt(result_buf, *actual_result_len, conn))
    2122 LBC           0 :                             continue;
    2123 ECB             :                     }
    2124                 :                     else
    2125                 :                     {
    2126 GIC         371 :                         if (pqGetnchar((char *) result_buf,
    2127             371 :                                        *actual_result_len,
    2128                 :                                        conn))
    2129 UIC           0 :                             continue;
    2130 ECB             :                     }
    2131                 :                 }
    2132                 :                 /* correctly finished function result message */
    2133 GIC        1063 :                 status = PGRES_COMMAND_OK;
    2134            1063 :                 break;
    2135 UIC           0 :             case 'E':           /* error return */
    2136               0 :                 if (pqGetErrorNotice3(conn, true))
    2137               0 :                     continue;
    2138               0 :                 status = PGRES_FATAL_ERROR;
    2139 UBC           0 :                 break;
    2140               0 :             case 'A':           /* notify message */
    2141                 :                 /* handle notify and go back to processing return values */
    2142 LBC           0 :                 if (getNotify(conn))
    2143 UIC           0 :                     continue;
    2144               0 :                 break;
    2145               0 :             case 'N':           /* notice */
    2146                 :                 /* handle notice and go back to processing return values */
    2147               0 :                 if (pqGetErrorNotice3(conn, false))
    2148               0 :                     continue;
    2149               0 :                 break;
    2150 CBC        1063 :             case 'Z':           /* backend is ready for new query */
    2151 GIC        1063 :                 if (getReadyForQuery(conn))
    2152 LBC           0 :                     continue;
    2153 ECB             :                 /* consume the message and exit */
    2154 GBC        1063 :                 conn->inStart += 5 + msgLength;
    2155 ECB             : 
    2156                 :                 /*
    2157                 :                  * If we already have a result object (probably an error), use
    2158                 :                  * that.  Otherwise, if we saw a function result message,
    2159                 :                  * report COMMAND_OK.  Otherwise, the backend violated the
    2160 EUB             :                  * protocol, so complain.
    2161                 :                  */
    2162 GIC        1063 :                 if (!pgHavePendingResult(conn))
    2163                 :                 {
    2164 CBC        1063 :                     if (status == PGRES_COMMAND_OK)
    2165 ECB             :                     {
    2166 GIC        1063 :                         conn->result = PQmakeEmptyPGresult(conn, status);
    2167 GBC        1063 :                         if (!conn->result)
    2168                 :                         {
    2169 UNC           0 :                             libpq_append_conn_error(conn, "out of memory");
    2170 LBC           0 :                             pqSaveErrorResult(conn);
    2171 ECB             :                         }
    2172 EUB             :                     }
    2173                 :                     else
    2174                 :                     {
    2175 UNC           0 :                         libpq_append_conn_error(conn, "protocol error: no function result");
    2176 UBC           0 :                         pqSaveErrorResult(conn);
    2177                 :                     }
    2178 EUB             :                 }
    2179 GBC        1063 :                 return pqPrepareAsyncResult(conn);
    2180 UBC           0 :             case 'S':           /* parameter status */
    2181               0 :                 if (getParameterStatus(conn))
    2182 UIC           0 :                     continue;
    2183 UBC           0 :                 break;
    2184               0 :             default:
    2185 EUB             :                 /* The backend violates the protocol. */
    2186 UNC           0 :                 libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
    2187 UIC           0 :                 pqSaveErrorResult(conn);
    2188 ECB             :                 /* trust the specified message length as what to skip */
    2189 UIC           0 :                 conn->inStart += 5 + msgLength;
    2190               0 :                 return pqPrepareAsyncResult(conn);
    2191                 :         }
    2192                 : 
    2193                 :         /* trace server-to-client message */
    2194 GIC        1063 :         if (conn->Pfdebug)
    2195 UIC           0 :             pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
    2196 ECB             : 
    2197                 :         /* Completed this message, keep going */
    2198                 :         /* trust the specified message length as what to skip */
    2199 GIC        1063 :         conn->inStart += 5 + msgLength;
    2200 CBC        1063 :         needInput = false;
    2201 ECB             :     }
    2202                 : 
    2203 EUB             :     /*
    2204                 :      * We fall out of the loop only upon failing to read data.
    2205                 :      * conn->errorMessage has been set by pqWait or pqReadData. We want to
    2206                 :      * append it to any already-received error message.
    2207                 :      */
    2208 UIC           0 :     pqSaveErrorResult(conn);
    2209 UBC           0 :     return pqPrepareAsyncResult(conn);
    2210 EUB             : }
    2211                 : 
    2212                 : 
    2213 ECB             : /*
    2214 EUB             :  * Construct startup packet
    2215                 :  *
    2216                 :  * Returns a malloc'd packet buffer, or NULL if out of memory
    2217                 :  */
    2218                 : char *
    2219 GIC        9005 : pqBuildStartupPacket3(PGconn *conn, int *packetlen,
    2220 EUB             :                       const PQEnvironmentOption *options)
    2221                 : {
    2222                 :     char       *startpacket;
    2223                 : 
    2224 GBC        9005 :     *packetlen = build_startup_packet(conn, NULL, options);
    2225 GIC        9005 :     startpacket = (char *) malloc(*packetlen);
    2226            9005 :     if (!startpacket)
    2227 UIC           0 :         return NULL;
    2228 CBC        9005 :     *packetlen = build_startup_packet(conn, startpacket, options);
    2229 GBC        9005 :     return startpacket;
    2230                 : }
    2231                 : 
    2232                 : /*
    2233 ECB             :  * Build a startup packet given a filled-in PGconn structure.
    2234                 :  *
    2235                 :  * We need to figure out how much space is needed, then fill it in.
    2236                 :  * To avoid duplicate logic, this routine is called twice: the first time
    2237                 :  * (with packet == NULL) just counts the space needed, the second time
    2238                 :  * (with packet == allocated space) fills it in.  Return value is the number
    2239                 :  * of bytes used.
    2240                 :  */
    2241                 : static int
    2242 GBC       18010 : build_startup_packet(const PGconn *conn, char *packet,
    2243 EUB             :                      const PQEnvironmentOption *options)
    2244                 : {
    2245 GIC       18010 :     int         packet_len = 0;
    2246                 :     const PQEnvironmentOption *next_eo;
    2247                 :     const char *val;
    2248                 : 
    2249                 :     /* Protocol version comes first. */
    2250           18010 :     if (packet)
    2251                 :     {
    2252            9005 :         ProtocolVersion pv = pg_hton32(conn->pversion);
    2253 ECB             : 
    2254 GIC        9005 :         memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion));
    2255                 :     }
    2256           18010 :     packet_len += sizeof(ProtocolVersion);
    2257                 : 
    2258 ECB             :     /* Add user name, database name, options */
    2259                 : 
    2260                 : #define ADD_STARTUP_OPTION(optname, optval) \
    2261 EUB             :     do { \
    2262 ECB             :         if (packet) \
    2263                 :             strcpy(packet + packet_len, optname); \
    2264                 :         packet_len += strlen(optname) + 1; \
    2265                 :         if (packet) \
    2266                 :             strcpy(packet + packet_len, optval); \
    2267                 :         packet_len += strlen(optval) + 1; \
    2268                 :     } while(0)
    2269                 : 
    2270 GIC       18010 :     if (conn->pguser && conn->pguser[0])
    2271           18010 :         ADD_STARTUP_OPTION("user", conn->pguser);
    2272           18010 :     if (conn->dbName && conn->dbName[0])
    2273           18010 :         ADD_STARTUP_OPTION("database", conn->dbName);
    2274           18010 :     if (conn->replication && conn->replication[0])
    2275            2124 :         ADD_STARTUP_OPTION("replication", conn->replication);
    2276 CBC       18010 :     if (conn->pgoptions && conn->pgoptions[0])
    2277 GIC        5018 :         ADD_STARTUP_OPTION("options", conn->pgoptions);
    2278           18010 :     if (conn->send_appname)
    2279 ECB             :     {
    2280                 :         /* Use appname if present, otherwise use fallback */
    2281 GIC       18010 :         val = conn->appname ? conn->appname : conn->fbappname;
    2282           18010 :         if (val && val[0])
    2283           18008 :             ADD_STARTUP_OPTION("application_name", val);
    2284 ECB             :     }
    2285                 : 
    2286 CBC       18010 :     if (conn->client_encoding_initial && conn->client_encoding_initial[0])
    2287 GIC        1192 :         ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
    2288 ECB             : 
    2289                 :     /* Add any environment-driven GUC settings needed */
    2290 CBC       72040 :     for (next_eo = options; next_eo->envName; next_eo++)
    2291                 :     {
    2292 GIC       54030 :         if ((val = getenv(next_eo->envName)) != NULL)
    2293                 :         {
    2294            7540 :             if (pg_strcasecmp(val, "default") != 0)
    2295            7540 :                 ADD_STARTUP_OPTION(next_eo->pgName, val);
    2296                 :         }
    2297                 :     }
    2298                 : 
    2299                 :     /* Add trailing terminator */
    2300           18010 :     if (packet)
    2301            9005 :         packet[packet_len] = '\0';
    2302           18010 :     packet_len++;
    2303                 : 
    2304 CBC       18010 :     return packet_len;
    2305 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a