LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-exec.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 52.1 % 1914 998
Test Date: 2026-01-26 10:56:24 Functions: 64.4 % 118 76
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 41.4 % 1225 507

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * fe-exec.c
       4                 :             :  *        functions related to sending a query down to the backend
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *        src/interfaces/libpq/fe-exec.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres_fe.h"
      16                 :             : 
      17                 :             : #include <ctype.h>
      18                 :             : #include <fcntl.h>
      19                 :             : #include <limits.h>
      20                 :             : 
      21                 :             : #ifdef WIN32
      22                 :             : #include "win32.h"
      23                 :             : #else
      24                 :             : #include <unistd.h>
      25                 :             : #endif
      26                 :             : 
      27                 :             : #include "common/int.h"
      28                 :             : #include "libpq-fe.h"
      29                 :             : #include "libpq-int.h"
      30                 :             : #include "mb/pg_wchar.h"
      31                 :             : 
      32                 :             : /* keep this in same order as ExecStatusType in libpq-fe.h */
      33                 :             : char       *const pgresStatus[] = {
      34                 :             :         "PGRES_EMPTY_QUERY",
      35                 :             :         "PGRES_COMMAND_OK",
      36                 :             :         "PGRES_TUPLES_OK",
      37                 :             :         "PGRES_COPY_OUT",
      38                 :             :         "PGRES_COPY_IN",
      39                 :             :         "PGRES_BAD_RESPONSE",
      40                 :             :         "PGRES_NONFATAL_ERROR",
      41                 :             :         "PGRES_FATAL_ERROR",
      42                 :             :         "PGRES_COPY_BOTH",
      43                 :             :         "PGRES_SINGLE_TUPLE",
      44                 :             :         "PGRES_PIPELINE_SYNC",
      45                 :             :         "PGRES_PIPELINE_ABORTED",
      46                 :             :         "PGRES_TUPLES_CHUNK"
      47                 :             : };
      48                 :             : 
      49                 :             : /* We return this if we're unable to make a PGresult at all */
      50                 :             : static const PGresult OOM_result = {
      51                 :             :         .resultStatus = PGRES_FATAL_ERROR,
      52                 :             :         .client_encoding = PG_SQL_ASCII,
      53                 :             :         .errMsg = "out of memory\n",
      54                 :             : };
      55                 :             : 
      56                 :             : /*
      57                 :             :  * static state needed by PQescapeString and PQescapeBytea; initialize to
      58                 :             :  * values that result in backward-compatible behavior
      59                 :             :  */
      60                 :             : static int      static_client_encoding = PG_SQL_ASCII;
      61                 :             : static bool static_std_strings = false;
      62                 :             : 
      63                 :             : 
      64                 :             : static PGEvent *dupEvents(PGEvent *events, int count, size_t *memSize);
      65                 :             : static bool pqAddTuple(PGresult *res, PGresAttValue *tup,
      66                 :             :                                            const char **errmsgp);
      67                 :             : static int      PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery);
      68                 :             : static bool PQsendQueryStart(PGconn *conn, bool newQuery);
      69                 :             : static int      PQsendQueryGuts(PGconn *conn,
      70                 :             :                                                         const char *command,
      71                 :             :                                                         const char *stmtName,
      72                 :             :                                                         int nParams,
      73                 :             :                                                         const Oid *paramTypes,
      74                 :             :                                                         const char *const *paramValues,
      75                 :             :                                                         const int *paramLengths,
      76                 :             :                                                         const int *paramFormats,
      77                 :             :                                                         int resultFormat);
      78                 :             : static void parseInput(PGconn *conn);
      79                 :             : static PGresult *getCopyResult(PGconn *conn, ExecStatusType copytype);
      80                 :             : static bool PQexecStart(PGconn *conn);
      81                 :             : static PGresult *PQexecFinish(PGconn *conn);
      82                 :             : static int      PQsendTypedCommand(PGconn *conn, char command, char type,
      83                 :             :                                                            const char *target);
      84                 :             : static int      check_field_number(const PGresult *res, int field_num);
      85                 :             : static void pqPipelineProcessQueue(PGconn *conn);
      86                 :             : static int      pqPipelineSyncInternal(PGconn *conn, bool immediate_flush);
      87                 :             : static int      pqPipelineFlush(PGconn *conn);
      88                 :             : 
      89                 :             : 
      90                 :             : /* ----------------
      91                 :             :  * Space management for PGresult.
      92                 :             :  *
      93                 :             :  * Formerly, libpq did a separate malloc() for each field of each tuple
      94                 :             :  * returned by a query.  This was remarkably expensive --- malloc/free
      95                 :             :  * consumed a sizable part of the application's runtime.  And there is
      96                 :             :  * no real need to keep track of the fields separately, since they will
      97                 :             :  * all be freed together when the PGresult is released.  So now, we grab
      98                 :             :  * large blocks of storage from malloc and allocate space for query data
      99                 :             :  * within these blocks, using a trivially simple allocator.  This reduces
     100                 :             :  * the number of malloc/free calls dramatically, and it also avoids
     101                 :             :  * fragmentation of the malloc storage arena.
     102                 :             :  * The PGresult structure itself is still malloc'd separately.  We could
     103                 :             :  * combine it with the first allocation block, but that would waste space
     104                 :             :  * for the common case that no extra storage is actually needed (that is,
     105                 :             :  * the SQL command did not return tuples).
     106                 :             :  *
     107                 :             :  * We also malloc the top-level array of tuple pointers separately, because
     108                 :             :  * we need to be able to enlarge it via realloc, and our trivial space
     109                 :             :  * allocator doesn't handle that effectively.  (Too bad the FE/BE protocol
     110                 :             :  * doesn't tell us up front how many tuples will be returned.)
     111                 :             :  * All other subsidiary storage for a PGresult is kept in PGresult_data blocks
     112                 :             :  * of size PGRESULT_DATA_BLOCKSIZE.  The overhead at the start of each block
     113                 :             :  * is just a link to the next one, if any.  Free-space management info is
     114                 :             :  * kept in the owning PGresult.
     115                 :             :  * A query returning a small amount of data will thus require three malloc
     116                 :             :  * calls: one for the PGresult, one for the tuples pointer array, and one
     117                 :             :  * PGresult_data block.
     118                 :             :  *
     119                 :             :  * Only the most recently allocated PGresult_data block is a candidate to
     120                 :             :  * have more stuff added to it --- any extra space left over in older blocks
     121                 :             :  * is wasted.  We could be smarter and search the whole chain, but the point
     122                 :             :  * here is to be simple and fast.  Typical applications do not keep a PGresult
     123                 :             :  * around very long anyway, so some wasted space within one is not a problem.
     124                 :             :  *
     125                 :             :  * Tuning constants for the space allocator are:
     126                 :             :  * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes
     127                 :             :  * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data
     128                 :             :  * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate
     129                 :             :  *       blocks, instead of being crammed into a regular allocation block.
     130                 :             :  * Requirements for correct function are:
     131                 :             :  * PGRESULT_ALIGN_BOUNDARY must be a multiple of the alignment requirements
     132                 :             :  *              of all machine data types.  (Currently this is set from configure
     133                 :             :  *              tests, so it should be OK automatically.)
     134                 :             :  * PGRESULT_SEP_ALLOC_THRESHOLD + PGRESULT_BLOCK_OVERHEAD <=
     135                 :             :  *                      PGRESULT_DATA_BLOCKSIZE
     136                 :             :  *              pqResultAlloc assumes an object smaller than the threshold will fit
     137                 :             :  *              in a new block.
     138                 :             :  * The amount of space wasted at the end of a block could be as much as
     139                 :             :  * PGRESULT_SEP_ALLOC_THRESHOLD, so it doesn't pay to make that too large.
     140                 :             :  * ----------------
     141                 :             :  */
     142                 :             : 
     143                 :             : #define PGRESULT_DATA_BLOCKSIZE         2048
     144                 :             : #define PGRESULT_ALIGN_BOUNDARY         MAXIMUM_ALIGNOF /* from configure */
     145                 :             : #define PGRESULT_BLOCK_OVERHEAD         Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
     146                 :             : #define PGRESULT_SEP_ALLOC_THRESHOLD    (PGRESULT_DATA_BLOCKSIZE / 2)
     147                 :             : 
     148                 :             : 
     149                 :             : /*
     150                 :             :  * PQmakeEmptyPGresult
     151                 :             :  *       returns a newly allocated, initialized PGresult with given status.
     152                 :             :  *       If conn is not NULL and status indicates an error, the conn's
     153                 :             :  *       errorMessage is copied.  Also, any PGEvents are copied from the conn.
     154                 :             :  *
     155                 :             :  * Note: the logic to copy the conn's errorMessage is now vestigial;
     156                 :             :  * no internal caller uses it.  However, that behavior is documented for
     157                 :             :  * outside callers, so we'd better keep it.
     158                 :             :  */
     159                 :             : PGresult *
     160                 :       62556 : PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
     161                 :             : {
     162                 :       62556 :         PGresult   *result;
     163                 :             : 
     164                 :       62556 :         result = (PGresult *) malloc(sizeof(PGresult));
     165         [ +  - ]:       62556 :         if (!result)
     166                 :           0 :                 return NULL;
     167                 :             : 
     168                 :       62556 :         result->ntups = 0;
     169                 :       62556 :         result->numAttributes = 0;
     170                 :       62556 :         result->attDescs = NULL;
     171                 :       62556 :         result->tuples = NULL;
     172                 :       62556 :         result->tupArrSize = 0;
     173                 :       62556 :         result->numParameters = 0;
     174                 :       62556 :         result->paramDescs = NULL;
     175                 :       62556 :         result->resultStatus = status;
     176                 :       62556 :         result->cmdStatus[0] = '\0';
     177                 :       62556 :         result->binary = 0;
     178                 :       62556 :         result->events = NULL;
     179                 :       62556 :         result->nEvents = 0;
     180                 :       62556 :         result->errMsg = NULL;
     181                 :       62556 :         result->errFields = NULL;
     182                 :       62556 :         result->errQuery = NULL;
     183                 :       62556 :         result->null_field[0] = '\0';
     184                 :       62556 :         result->curBlock = NULL;
     185                 :       62556 :         result->curOffset = 0;
     186                 :       62556 :         result->spaceLeft = 0;
     187                 :       62556 :         result->memorySize = sizeof(PGresult);
     188                 :             : 
     189         [ +  + ]:       62556 :         if (conn)
     190                 :             :         {
     191                 :             :                 /* copy connection data we might need for operations on PGresult */
     192                 :       62540 :                 result->noticeHooks = conn->noticeHooks;
     193                 :       62540 :                 result->client_encoding = conn->client_encoding;
     194                 :             : 
     195                 :             :                 /* consider copying conn's errorMessage */
     196         [ +  + ]:       62540 :                 switch (status)
     197                 :             :                 {
     198                 :             :                         case PGRES_EMPTY_QUERY:
     199                 :             :                         case PGRES_COMMAND_OK:
     200                 :             :                         case PGRES_TUPLES_OK:
     201                 :             :                         case PGRES_COPY_OUT:
     202                 :             :                         case PGRES_COPY_IN:
     203                 :             :                         case PGRES_COPY_BOTH:
     204                 :             :                         case PGRES_SINGLE_TUPLE:
     205                 :             :                         case PGRES_TUPLES_CHUNK:
     206                 :             :                                 /* non-error cases */
     207                 :       62455 :                                 break;
     208                 :             :                         default:
     209                 :             :                                 /* we intentionally do not use or modify errorReported here */
     210                 :          85 :                                 pqSetResultError(result, &conn->errorMessage, 0);
     211                 :          85 :                                 break;
     212                 :             :                 }
     213                 :             : 
     214                 :             :                 /* copy events last; result must be valid if we need to PQclear */
     215         [ +  - ]:       62540 :                 if (conn->nEvents > 0)
     216                 :             :                 {
     217                 :           0 :                         result->events = dupEvents(conn->events, conn->nEvents,
     218                 :           0 :                                                                            &result->memorySize);
     219         [ #  # ]:           0 :                         if (!result->events)
     220                 :             :                         {
     221                 :           0 :                                 PQclear(result);
     222                 :           0 :                                 return NULL;
     223                 :             :                         }
     224                 :           0 :                         result->nEvents = conn->nEvents;
     225                 :           0 :                 }
     226                 :       62540 :         }
     227                 :             :         else
     228                 :             :         {
     229                 :             :                 /* defaults... */
     230                 :          16 :                 result->noticeHooks.noticeRec = NULL;
     231                 :          16 :                 result->noticeHooks.noticeRecArg = NULL;
     232                 :          16 :                 result->noticeHooks.noticeProc = NULL;
     233                 :          16 :                 result->noticeHooks.noticeProcArg = NULL;
     234                 :          16 :                 result->client_encoding = PG_SQL_ASCII;
     235                 :             :         }
     236                 :             : 
     237                 :       62556 :         return result;
     238                 :       62556 : }
     239                 :             : 
     240                 :             : /*
     241                 :             :  * PQsetResultAttrs
     242                 :             :  *
     243                 :             :  * Set the attributes for a given result.  This function fails if there are
     244                 :             :  * already attributes contained in the provided result.  The call is
     245                 :             :  * ignored if numAttributes is zero or attDescs is NULL.  If the
     246                 :             :  * function fails, it returns zero.  If the function succeeds, it
     247                 :             :  * returns a non-zero value.
     248                 :             :  */
     249                 :             : int
     250                 :          16 : PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
     251                 :             : {
     252                 :          16 :         int                     i;
     253                 :             : 
     254                 :             :         /* Fail if argument is NULL or OOM_result */
     255   [ +  -  -  + ]:          16 :         if (!res || (const PGresult *) res == &OOM_result)
     256                 :           0 :                 return false;
     257                 :             : 
     258                 :             :         /* If attrs already exist, they cannot be overwritten. */
     259         [ -  + ]:          16 :         if (res->numAttributes > 0)
     260                 :           0 :                 return false;
     261                 :             : 
     262                 :             :         /* ignore no-op request */
     263   [ +  -  -  + ]:          16 :         if (numAttributes <= 0 || !attDescs)
     264                 :           0 :                 return true;
     265                 :             : 
     266                 :          16 :         res->attDescs = (PGresAttDesc *)
     267                 :          16 :                 PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
     268                 :             : 
     269         [ +  - ]:          16 :         if (!res->attDescs)
     270                 :           0 :                 return false;
     271                 :             : 
     272                 :          16 :         res->numAttributes = numAttributes;
     273                 :          16 :         memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
     274                 :             : 
     275                 :             :         /* deep-copy the attribute names, and determine format */
     276                 :          16 :         res->binary = 1;
     277         [ +  + ]:          40 :         for (i = 0; i < res->numAttributes; i++)
     278                 :             :         {
     279         [ +  - ]:          24 :                 if (res->attDescs[i].name)
     280                 :          24 :                         res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
     281                 :             :                 else
     282                 :           0 :                         res->attDescs[i].name = res->null_field;
     283                 :             : 
     284         [ -  + ]:          24 :                 if (!res->attDescs[i].name)
     285                 :           0 :                         return false;
     286                 :             : 
     287         [ -  + ]:          24 :                 if (res->attDescs[i].format == 0)
     288                 :          24 :                         res->binary = 0;
     289                 :          24 :         }
     290                 :             : 
     291                 :          16 :         return true;
     292                 :          16 : }
     293                 :             : 
     294                 :             : /*
     295                 :             :  * PQcopyResult
     296                 :             :  *
     297                 :             :  * Returns a deep copy of the provided 'src' PGresult, which cannot be NULL.
     298                 :             :  * The 'flags' argument controls which portions of the result will or will
     299                 :             :  * NOT be copied.  The created result is always put into the
     300                 :             :  * PGRES_TUPLES_OK status.  The source result error message is not copied,
     301                 :             :  * although cmdStatus is.
     302                 :             :  *
     303                 :             :  * To set custom attributes, use PQsetResultAttrs.  That function requires
     304                 :             :  * that there are no attrs contained in the result, so to use that
     305                 :             :  * function you cannot use the PG_COPYRES_ATTRS or PG_COPYRES_TUPLES
     306                 :             :  * options with this function.
     307                 :             :  *
     308                 :             :  * Options:
     309                 :             :  *       PG_COPYRES_ATTRS - Copy the source result's attributes
     310                 :             :  *
     311                 :             :  *       PG_COPYRES_TUPLES - Copy the source result's tuples.  This implies
     312                 :             :  *       copying the attrs, seeing how the attrs are needed by the tuples.
     313                 :             :  *
     314                 :             :  *       PG_COPYRES_EVENTS - Copy the source result's events.
     315                 :             :  *
     316                 :             :  *       PG_COPYRES_NOTICEHOOKS - Copy the source result's notice hooks.
     317                 :             :  */
     318                 :             : PGresult *
     319                 :          16 : PQcopyResult(const PGresult *src, int flags)
     320                 :             : {
     321                 :          16 :         PGresult   *dest;
     322                 :          16 :         int                     i;
     323                 :             : 
     324         [ +  - ]:          16 :         if (!src)
     325                 :           0 :                 return NULL;
     326                 :             : 
     327                 :          16 :         dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK);
     328         [ +  - ]:          16 :         if (!dest)
     329                 :           0 :                 return NULL;
     330                 :             : 
     331                 :             :         /* Always copy these over.  Is cmdStatus really useful here? */
     332                 :          16 :         dest->client_encoding = src->client_encoding;
     333                 :          16 :         strcpy(dest->cmdStatus, src->cmdStatus);
     334                 :             : 
     335                 :             :         /* Wants attrs? */
     336         [ -  + ]:          16 :         if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
     337                 :             :         {
     338         [ +  - ]:          16 :                 if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs))
     339                 :             :                 {
     340                 :           0 :                         PQclear(dest);
     341                 :           0 :                         return NULL;
     342                 :             :                 }
     343                 :          16 :         }
     344                 :             : 
     345                 :             :         /* Wants to copy tuples? */
     346         [ +  - ]:          16 :         if (flags & PG_COPYRES_TUPLES)
     347                 :             :         {
     348                 :           0 :                 int                     tup,
     349                 :             :                                         field;
     350                 :             : 
     351         [ #  # ]:           0 :                 for (tup = 0; tup < src->ntups; tup++)
     352                 :             :                 {
     353         [ #  # ]:           0 :                         for (field = 0; field < src->numAttributes; field++)
     354                 :             :                         {
     355   [ #  #  #  # ]:           0 :                                 if (!PQsetvalue(dest, tup, field,
     356                 :           0 :                                                                 src->tuples[tup][field].value,
     357                 :           0 :                                                                 src->tuples[tup][field].len))
     358                 :             :                                 {
     359                 :           0 :                                         PQclear(dest);
     360                 :           0 :                                         return NULL;
     361                 :             :                                 }
     362                 :           0 :                         }
     363                 :           0 :                 }
     364         [ #  # ]:           0 :         }
     365                 :             : 
     366                 :             :         /* Wants to copy notice hooks? */
     367         [ -  + ]:          16 :         if (flags & PG_COPYRES_NOTICEHOOKS)
     368                 :          16 :                 dest->noticeHooks = src->noticeHooks;
     369                 :             : 
     370                 :             :         /* Wants to copy PGEvents? */
     371   [ +  -  +  - ]:          16 :         if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
     372                 :             :         {
     373                 :           0 :                 dest->events = dupEvents(src->events, src->nEvents,
     374                 :           0 :                                                                  &dest->memorySize);
     375         [ #  # ]:           0 :                 if (!dest->events)
     376                 :             :                 {
     377                 :           0 :                         PQclear(dest);
     378                 :           0 :                         return NULL;
     379                 :             :                 }
     380                 :           0 :                 dest->nEvents = src->nEvents;
     381                 :           0 :         }
     382                 :             : 
     383                 :             :         /* Okay, trigger PGEVT_RESULTCOPY event */
     384         [ -  + ]:          16 :         for (i = 0; i < dest->nEvents; i++)
     385                 :             :         {
     386                 :             :                 /* We don't fire events that had some previous failure */
     387         [ #  # ]:           0 :                 if (src->events[i].resultInitialized)
     388                 :             :                 {
     389                 :           0 :                         PGEventResultCopy evt;
     390                 :             : 
     391                 :           0 :                         evt.src = src;
     392                 :           0 :                         evt.dest = dest;
     393   [ #  #  #  # ]:           0 :                         if (dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
     394                 :           0 :                                                                          dest->events[i].passThrough))
     395                 :           0 :                                 dest->events[i].resultInitialized = true;
     396                 :           0 :                 }
     397                 :           0 :         }
     398                 :             : 
     399                 :          16 :         return dest;
     400                 :          16 : }
     401                 :             : 
     402                 :             : /*
     403                 :             :  * Copy an array of PGEvents (with no extra space for more).
     404                 :             :  * Does not duplicate the event instance data, sets this to NULL.
     405                 :             :  * Also, the resultInitialized flags are all cleared.
     406                 :             :  * The total space allocated is added to *memSize.
     407                 :             :  */
     408                 :             : static PGEvent *
     409                 :           0 : dupEvents(PGEvent *events, int count, size_t *memSize)
     410                 :             : {
     411                 :           0 :         PGEvent    *newEvents;
     412                 :           0 :         size_t          msize;
     413                 :           0 :         int                     i;
     414                 :             : 
     415   [ #  #  #  # ]:           0 :         if (!events || count <= 0)
     416                 :           0 :                 return NULL;
     417                 :             : 
     418                 :           0 :         msize = count * sizeof(PGEvent);
     419                 :           0 :         newEvents = (PGEvent *) malloc(msize);
     420         [ #  # ]:           0 :         if (!newEvents)
     421                 :           0 :                 return NULL;
     422                 :             : 
     423         [ #  # ]:           0 :         for (i = 0; i < count; i++)
     424                 :             :         {
     425                 :           0 :                 newEvents[i].proc = events[i].proc;
     426                 :           0 :                 newEvents[i].passThrough = events[i].passThrough;
     427                 :           0 :                 newEvents[i].data = NULL;
     428                 :           0 :                 newEvents[i].resultInitialized = false;
     429                 :           0 :                 newEvents[i].name = strdup(events[i].name);
     430         [ #  # ]:           0 :                 if (!newEvents[i].name)
     431                 :             :                 {
     432         [ #  # ]:           0 :                         while (--i >= 0)
     433                 :           0 :                                 free(newEvents[i].name);
     434                 :           0 :                         free(newEvents);
     435                 :           0 :                         return NULL;
     436                 :             :                 }
     437                 :           0 :                 msize += strlen(events[i].name) + 1;
     438                 :           0 :         }
     439                 :             : 
     440                 :           0 :         *memSize += msize;
     441                 :           0 :         return newEvents;
     442                 :           0 : }
     443                 :             : 
     444                 :             : 
     445                 :             : /*
     446                 :             :  * Sets the value for a tuple field.  The tup_num must be less than or
     447                 :             :  * equal to PQntuples(res).  If it is equal, a new tuple is created and
     448                 :             :  * added to the result.
     449                 :             :  * Returns a non-zero value for success and zero for failure.
     450                 :             :  * (On failure, we report the specific problem via pqInternalNotice.)
     451                 :             :  */
     452                 :             : int
     453                 :           0 : PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
     454                 :             : {
     455                 :           0 :         PGresAttValue *attval;
     456                 :           0 :         const char *errmsg = NULL;
     457                 :             : 
     458                 :             :         /* Fail if argument is NULL or OOM_result */
     459   [ #  #  #  # ]:           0 :         if (!res || (const PGresult *) res == &OOM_result)
     460                 :           0 :                 return false;
     461                 :             : 
     462                 :             :         /* Invalid field_num? */
     463         [ #  # ]:           0 :         if (!check_field_number(res, field_num))
     464                 :           0 :                 return false;
     465                 :             : 
     466                 :             :         /* Invalid tup_num, must be <= ntups */
     467   [ #  #  #  # ]:           0 :         if (tup_num < 0 || tup_num > res->ntups)
     468                 :             :         {
     469                 :           0 :                 pqInternalNotice(&res->noticeHooks,
     470                 :             :                                                  "row number %d is out of range 0..%d",
     471                 :           0 :                                                  tup_num, res->ntups);
     472                 :           0 :                 return false;
     473                 :             :         }
     474                 :             : 
     475                 :             :         /* need to allocate a new tuple? */
     476         [ #  # ]:           0 :         if (tup_num == res->ntups)
     477                 :             :         {
     478                 :           0 :                 PGresAttValue *tup;
     479                 :           0 :                 int                     i;
     480                 :             : 
     481                 :           0 :                 tup = (PGresAttValue *)
     482                 :           0 :                         pqResultAlloc(res, res->numAttributes * sizeof(PGresAttValue),
     483                 :             :                                                   true);
     484                 :             : 
     485         [ #  # ]:           0 :                 if (!tup)
     486                 :           0 :                         goto fail;
     487                 :             : 
     488                 :             :                 /* initialize each column to NULL */
     489         [ #  # ]:           0 :                 for (i = 0; i < res->numAttributes; i++)
     490                 :             :                 {
     491                 :           0 :                         tup[i].len = NULL_LEN;
     492                 :           0 :                         tup[i].value = res->null_field;
     493                 :           0 :                 }
     494                 :             : 
     495                 :             :                 /* add it to the array */
     496         [ #  # ]:           0 :                 if (!pqAddTuple(res, tup, &errmsg))
     497                 :           0 :                         goto fail;
     498      [ #  #  # ]:           0 :         }
     499                 :             : 
     500                 :           0 :         attval = &res->tuples[tup_num][field_num];
     501                 :             : 
     502                 :             :         /* treat either NULL_LEN or NULL value pointer as a NULL field */
     503   [ #  #  #  # ]:           0 :         if (len == NULL_LEN || value == NULL)
     504                 :             :         {
     505                 :           0 :                 attval->len = NULL_LEN;
     506                 :           0 :                 attval->value = res->null_field;
     507                 :           0 :         }
     508         [ #  # ]:           0 :         else if (len <= 0)
     509                 :             :         {
     510                 :           0 :                 attval->len = 0;
     511                 :           0 :                 attval->value = res->null_field;
     512                 :           0 :         }
     513                 :             :         else
     514                 :             :         {
     515                 :           0 :                 attval->value = (char *) pqResultAlloc(res, (size_t) len + 1, true);
     516         [ #  # ]:           0 :                 if (!attval->value)
     517                 :           0 :                         goto fail;
     518                 :           0 :                 attval->len = len;
     519                 :           0 :                 memcpy(attval->value, value, len);
     520                 :           0 :                 attval->value[len] = '\0';
     521                 :             :         }
     522                 :             : 
     523                 :           0 :         return true;
     524                 :             : 
     525                 :             :         /*
     526                 :             :          * Report failure via pqInternalNotice.  If preceding code didn't provide
     527                 :             :          * an error message, assume "out of memory" was meant.
     528                 :             :          */
     529                 :             : fail:
     530         [ #  # ]:           0 :         if (!errmsg)
     531                 :           0 :                 errmsg = libpq_gettext("out of memory");
     532                 :           0 :         pqInternalNotice(&res->noticeHooks, "%s", errmsg);
     533                 :             : 
     534                 :           0 :         return false;
     535                 :           0 : }
     536                 :             : 
     537                 :             : /*
     538                 :             :  * pqResultAlloc - exported routine to allocate local storage in a PGresult.
     539                 :             :  *
     540                 :             :  * We force all such allocations to be maxaligned, since we don't know
     541                 :             :  * whether the value might be binary.
     542                 :             :  */
     543                 :             : void *
     544                 :          16 : PQresultAlloc(PGresult *res, size_t nBytes)
     545                 :             : {
     546                 :             :         /* Fail if argument is NULL or OOM_result */
     547   [ +  -  -  + ]:          16 :         if (!res || (const PGresult *) res == &OOM_result)
     548                 :           0 :                 return NULL;
     549                 :             : 
     550                 :          16 :         return pqResultAlloc(res, nBytes, true);
     551                 :          16 : }
     552                 :             : 
     553                 :             : /*
     554                 :             :  * pqResultAlloc -
     555                 :             :  *              Allocate subsidiary storage for a PGresult.
     556                 :             :  *
     557                 :             :  * nBytes is the amount of space needed for the object.
     558                 :             :  * If isBinary is true, we assume that we need to align the object on
     559                 :             :  * a machine allocation boundary.
     560                 :             :  * If isBinary is false, we assume the object is a char string and can
     561                 :             :  * be allocated on any byte boundary.
     562                 :             :  */
     563                 :             : void *
     564                 :      457714 : pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
     565                 :             : {
     566                 :      457714 :         char       *space;
     567                 :      457714 :         PGresult_data *block;
     568                 :             : 
     569         [ +  - ]:      457714 :         if (!res)
     570                 :           0 :                 return NULL;
     571                 :             : 
     572         [ +  + ]:      457714 :         if (nBytes <= 0)
     573                 :          38 :                 return res->null_field;
     574                 :             : 
     575                 :             :         /*
     576                 :             :          * If alignment is needed, round up the current position to an alignment
     577                 :             :          * boundary.
     578                 :             :          */
     579         [ +  + ]:      457676 :         if (isBinary)
     580                 :             :         {
     581                 :      182522 :                 int                     offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
     582                 :             : 
     583         [ +  + ]:      182522 :                 if (offset)
     584                 :             :                 {
     585                 :      129537 :                         res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
     586                 :      129537 :                         res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
     587                 :      129537 :                 }
     588                 :      182522 :         }
     589                 :             : 
     590                 :             :         /* If there's enough space in the current block, no problem. */
     591         [ +  + ]:      457676 :         if (nBytes <= (size_t) res->spaceLeft)
     592                 :             :         {
     593                 :      419934 :                 space = res->curBlock->space + res->curOffset;
     594                 :      419934 :                 res->curOffset += nBytes;
     595                 :      419934 :                 res->spaceLeft -= nBytes;
     596                 :      419934 :                 return space;
     597                 :             :         }
     598                 :             : 
     599                 :             :         /*
     600                 :             :          * If the requested object is very large, give it its own block; this
     601                 :             :          * avoids wasting what might be most of the current block to start a new
     602                 :             :          * block.  (We'd have to special-case requests bigger than the block size
     603                 :             :          * anyway.)  The object is always given binary alignment in this case.
     604                 :             :          */
     605         [ +  + ]:       37742 :         if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
     606                 :             :         {
     607                 :          34 :                 size_t          alloc_size;
     608                 :             : 
     609                 :             :                 /* Don't wrap around with overly large requests. */
     610         [ -  + ]:          34 :                 if (nBytes > SIZE_MAX - PGRESULT_BLOCK_OVERHEAD)
     611                 :           0 :                         return NULL;
     612                 :             : 
     613                 :          34 :                 alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
     614                 :          34 :                 block = (PGresult_data *) malloc(alloc_size);
     615         [ +  - ]:          34 :                 if (!block)
     616                 :           0 :                         return NULL;
     617                 :          34 :                 res->memorySize += alloc_size;
     618                 :          34 :                 space = block->space + PGRESULT_BLOCK_OVERHEAD;
     619         [ +  - ]:          34 :                 if (res->curBlock)
     620                 :             :                 {
     621                 :             :                         /*
     622                 :             :                          * Tuck special block below the active block, so that we don't
     623                 :             :                          * have to waste the free space in the active block.
     624                 :             :                          */
     625                 :          34 :                         block->next = res->curBlock->next;
     626                 :          34 :                         res->curBlock->next = block;
     627                 :          34 :                 }
     628                 :             :                 else
     629                 :             :                 {
     630                 :             :                         /* Must set up the new block as the first active block. */
     631                 :           0 :                         block->next = NULL;
     632                 :           0 :                         res->curBlock = block;
     633                 :           0 :                         res->spaceLeft = 0; /* be sure it's marked full */
     634                 :             :                 }
     635                 :          34 :                 return space;
     636                 :          34 :         }
     637                 :             : 
     638                 :             :         /* Otherwise, start a new block. */
     639                 :       37708 :         block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
     640         [ +  - ]:       37708 :         if (!block)
     641                 :           0 :                 return NULL;
     642                 :       37708 :         res->memorySize += PGRESULT_DATA_BLOCKSIZE;
     643                 :       37708 :         block->next = res->curBlock;
     644                 :       37708 :         res->curBlock = block;
     645         [ +  + ]:       37708 :         if (isBinary)
     646                 :             :         {
     647                 :             :                 /* object needs full alignment */
     648                 :       37200 :                 res->curOffset = PGRESULT_BLOCK_OVERHEAD;
     649                 :       37200 :                 res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
     650                 :       37200 :         }
     651                 :             :         else
     652                 :             :         {
     653                 :             :                 /* we can cram it right after the overhead pointer */
     654                 :         508 :                 res->curOffset = sizeof(PGresult_data);
     655                 :         508 :                 res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
     656                 :             :         }
     657                 :             : 
     658                 :       37708 :         space = block->space + res->curOffset;
     659                 :       37708 :         res->curOffset += nBytes;
     660                 :       37708 :         res->spaceLeft -= nBytes;
     661                 :       37708 :         return space;
     662                 :      457714 : }
     663                 :             : 
     664                 :             : /*
     665                 :             :  * PQresultMemorySize -
     666                 :             :  *              Returns total space allocated for the PGresult.
     667                 :             :  */
     668                 :             : size_t
     669                 :           0 : PQresultMemorySize(const PGresult *res)
     670                 :             : {
     671         [ #  # ]:           0 :         if (!res)
     672                 :           0 :                 return 0;
     673                 :           0 :         return res->memorySize;
     674                 :           0 : }
     675                 :             : 
     676                 :             : /*
     677                 :             :  * pqResultStrdup -
     678                 :             :  *              Like strdup, but the space is subsidiary PGresult space.
     679                 :             :  */
     680                 :             : char *
     681                 :       83871 : pqResultStrdup(PGresult *res, const char *str)
     682                 :             : {
     683                 :       83871 :         char       *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
     684                 :             : 
     685         [ -  + ]:       83871 :         if (space)
     686                 :       83871 :                 strcpy(space, str);
     687                 :      167742 :         return space;
     688                 :       83871 : }
     689                 :             : 
     690                 :             : /*
     691                 :             :  * pqSetResultError -
     692                 :             :  *              assign a new error message to a PGresult
     693                 :             :  *
     694                 :             :  * Copy text from errorMessage buffer beginning at given offset
     695                 :             :  * (it's caller's responsibility that offset is valid)
     696                 :             :  */
     697                 :             : void
     698                 :        6848 : pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
     699                 :             : {
     700                 :        6848 :         char       *msg;
     701                 :             : 
     702         [ +  - ]:        6848 :         if (!res)
     703                 :           0 :                 return;
     704                 :             : 
     705                 :             :         /*
     706                 :             :          * We handle two OOM scenarios here.  The errorMessage buffer might be
     707                 :             :          * marked "broken" due to having previously failed to allocate enough
     708                 :             :          * memory for the message, or it might be fine but pqResultStrdup fails
     709                 :             :          * and returns NULL.  In either case, just make res->errMsg point directly
     710                 :             :          * at a constant "out of memory" string.
     711                 :             :          */
     712   [ +  -  -  + ]:        6848 :         if (!PQExpBufferBroken(errorMessage))
     713                 :        6848 :                 msg = pqResultStrdup(res, errorMessage->data + offset);
     714                 :             :         else
     715                 :           0 :                 msg = NULL;
     716         [ +  - ]:        6848 :         if (msg)
     717                 :        6848 :                 res->errMsg = msg;
     718                 :             :         else
     719                 :           0 :                 res->errMsg = libpq_gettext("out of memory\n");
     720         [ -  + ]:        6848 : }
     721                 :             : 
     722                 :             : /*
     723                 :             :  * PQclear -
     724                 :             :  *        free's the memory associated with a PGresult
     725                 :             :  */
     726                 :             : void
     727                 :      213333 : PQclear(PGresult *res)
     728                 :             : {
     729                 :      213333 :         PGresult_data *block;
     730                 :      213333 :         int                     i;
     731                 :             : 
     732                 :             :         /* As a convenience, do nothing for a NULL pointer */
     733         [ +  + ]:      213333 :         if (!res)
     734                 :      150967 :                 return;
     735                 :             :         /* Also, do nothing if the argument is OOM_result */
     736         [ +  - ]:       62366 :         if ((const PGresult *) res == &OOM_result)
     737                 :           0 :                 return;
     738                 :             : 
     739                 :             :         /* Close down any events we may have */
     740         [ -  + ]:       62366 :         for (i = 0; i < res->nEvents; i++)
     741                 :             :         {
     742                 :             :                 /* only send DESTROY to successfully-initialized event procs */
     743         [ #  # ]:           0 :                 if (res->events[i].resultInitialized)
     744                 :             :                 {
     745                 :           0 :                         PGEventResultDestroy evt;
     746                 :             : 
     747                 :           0 :                         evt.result = res;
     748                 :           0 :                         (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt,
     749                 :           0 :                                                                            res->events[i].passThrough);
     750                 :           0 :                 }
     751                 :           0 :                 free(res->events[i].name);
     752                 :           0 :         }
     753                 :             : 
     754                 :       62366 :         free(res->events);
     755                 :             : 
     756                 :             :         /* Free all the subsidiary blocks */
     757         [ +  + ]:       99917 :         while ((block = res->curBlock) != NULL)
     758                 :             :         {
     759                 :       37551 :                 res->curBlock = block->next;
     760                 :       37551 :                 free(block);
     761                 :             :         }
     762                 :             : 
     763                 :             :         /* Free the top-level tuple pointer array */
     764                 :       62366 :         free(res->tuples);
     765                 :             : 
     766                 :             :         /* zero out the pointer fields to catch programming errors */
     767                 :       62366 :         res->attDescs = NULL;
     768                 :       62366 :         res->tuples = NULL;
     769                 :       62366 :         res->paramDescs = NULL;
     770                 :       62366 :         res->errFields = NULL;
     771                 :       62366 :         res->events = NULL;
     772                 :       62366 :         res->nEvents = 0;
     773                 :             :         /* res->curBlock was zeroed out earlier */
     774                 :             : 
     775                 :             :         /* Free the PGresult structure itself */
     776                 :       62366 :         free(res);
     777         [ -  + ]:      213333 : }
     778                 :             : 
     779                 :             : /*
     780                 :             :  * Handy subroutine to deallocate any partially constructed async result.
     781                 :             :  *
     782                 :             :  * Any "saved" result gets cleared too.
     783                 :             :  */
     784                 :             : void
     785                 :       72247 : pqClearAsyncResult(PGconn *conn)
     786                 :             : {
     787                 :       72247 :         PQclear(conn->result);
     788                 :       72247 :         conn->result = NULL;
     789                 :       72247 :         conn->error_result = false;
     790                 :       72247 :         PQclear(conn->saved_result);
     791                 :       72247 :         conn->saved_result = NULL;
     792                 :       72247 : }
     793                 :             : 
     794                 :             : /*
     795                 :             :  * pqSaveErrorResult -
     796                 :             :  *        remember that we have an error condition
     797                 :             :  *
     798                 :             :  * In much of libpq, reporting an error just requires appending text to
     799                 :             :  * conn->errorMessage and returning a failure code to one's caller.
     800                 :             :  * Where returning a failure code is impractical, instead call this
     801                 :             :  * function to remember that an error needs to be reported.
     802                 :             :  *
     803                 :             :  * (It might seem that appending text to conn->errorMessage should be
     804                 :             :  * sufficient, but we can't rely on that working under out-of-memory
     805                 :             :  * conditions.  The OOM hazard is also why we don't try to make a new
     806                 :             :  * PGresult right here.)
     807                 :             :  */
     808                 :             : void
     809                 :           0 : pqSaveErrorResult(PGconn *conn)
     810                 :             : {
     811                 :             :         /* Drop any pending result ... */
     812                 :           0 :         pqClearAsyncResult(conn);
     813                 :             :         /* ... and set flag to remember to make an error result later */
     814                 :           0 :         conn->error_result = true;
     815                 :           0 : }
     816                 :             : 
     817                 :             : /*
     818                 :             :  * pqSaveWriteError -
     819                 :             :  *        report a write failure
     820                 :             :  *
     821                 :             :  * As above, after appending conn->write_err_msg to whatever other error we
     822                 :             :  * have.  This is used when we've detected a write failure and have exhausted
     823                 :             :  * our chances of reporting something else instead.
     824                 :             :  */
     825                 :             : static void
     826                 :           0 : pqSaveWriteError(PGconn *conn)
     827                 :             : {
     828                 :             :         /*
     829                 :             :          * If write_err_msg is null because of previous strdup failure, do what we
     830                 :             :          * can.  (It's likely our machinations here will get OOM failures as well,
     831                 :             :          * but might as well try.)
     832                 :             :          */
     833         [ #  # ]:           0 :         if (conn->write_err_msg)
     834                 :             :         {
     835                 :           0 :                 appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg);
     836                 :             :                 /* Avoid possibly appending the same message twice */
     837                 :           0 :                 conn->write_err_msg[0] = '\0';
     838                 :           0 :         }
     839                 :             :         else
     840                 :           0 :                 libpq_append_conn_error(conn, "write to server failed");
     841                 :             : 
     842                 :           0 :         pqSaveErrorResult(conn);
     843                 :           0 : }
     844                 :             : 
     845                 :             : /*
     846                 :             :  * pqPrepareAsyncResult -
     847                 :             :  *        prepare the current async result object for return to the caller
     848                 :             :  *
     849                 :             :  * If there is not already an async result object, build an error object
     850                 :             :  * using whatever is in conn->errorMessage.  In any case, clear the async
     851                 :             :  * result storage, and update our notion of how much error text has been
     852                 :             :  * returned to the application.
     853                 :             :  *
     854                 :             :  * Note that in no case (not even OOM) do we return NULL.
     855                 :             :  */
     856                 :             : PGresult *
     857                 :       58745 : pqPrepareAsyncResult(PGconn *conn)
     858                 :             : {
     859                 :       58745 :         PGresult   *res;
     860                 :             : 
     861                 :       58745 :         res = conn->result;
     862         [ +  - ]:       58745 :         if (res)
     863                 :             :         {
     864                 :             :                 /*
     865                 :             :                  * If the pre-existing result is an ERROR (presumably something
     866                 :             :                  * received from the server), assume that it represents whatever is in
     867                 :             :                  * conn->errorMessage, and advance errorReported.
     868                 :             :                  */
     869         [ +  + ]:       58745 :                 if (res->resultStatus == PGRES_FATAL_ERROR)
     870                 :        6763 :                         conn->errorReported = conn->errorMessage.len;
     871                 :       58745 :         }
     872                 :             :         else
     873                 :             :         {
     874                 :             :                 /*
     875                 :             :                  * We get here after internal-to-libpq errors.  We should probably
     876                 :             :                  * always have error_result = true, but if we don't, gin up some error
     877                 :             :                  * text.
     878                 :             :                  */
     879         [ #  # ]:           0 :                 if (!conn->error_result)
     880                 :           0 :                         libpq_append_conn_error(conn, "no error text available");
     881                 :             : 
     882                 :             :                 /* Paranoia: be sure errorReported offset is sane */
     883   [ #  #  #  # ]:           0 :                 if (conn->errorReported < 0 ||
     884                 :           0 :                         conn->errorReported >= conn->errorMessage.len)
     885                 :           0 :                         conn->errorReported = 0;
     886                 :             : 
     887                 :             :                 /*
     888                 :             :                  * Make a PGresult struct for the error.  We temporarily lie about the
     889                 :             :                  * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
     890                 :             :                  * all of conn->errorMessage.
     891                 :             :                  */
     892                 :           0 :                 res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
     893         [ #  # ]:           0 :                 if (res)
     894                 :             :                 {
     895                 :             :                         /*
     896                 :             :                          * Report whatever new error text we have, and advance
     897                 :             :                          * errorReported.
     898                 :             :                          */
     899                 :           0 :                         res->resultStatus = PGRES_FATAL_ERROR;
     900                 :           0 :                         pqSetResultError(res, &conn->errorMessage, conn->errorReported);
     901                 :           0 :                         conn->errorReported = conn->errorMessage.len;
     902                 :           0 :                 }
     903                 :             :                 else
     904                 :             :                 {
     905                 :             :                         /*
     906                 :             :                          * Ouch, not enough memory for a PGresult.  Fortunately, we have a
     907                 :             :                          * card up our sleeve: we can use the static OOM_result.  Casting
     908                 :             :                          * away const here is a bit ugly, but it seems best to declare
     909                 :             :                          * OOM_result as const, in hopes it will be allocated in read-only
     910                 :             :                          * storage.
     911                 :             :                          */
     912                 :           0 :                         res = unconstify(PGresult *, &OOM_result);
     913                 :             : 
     914                 :             :                         /*
     915                 :             :                          * Don't advance errorReported.  Perhaps we'll be able to report
     916                 :             :                          * the text later.
     917                 :             :                          */
     918                 :             :                 }
     919                 :             :         }
     920                 :             : 
     921                 :             :         /*
     922                 :             :          * Replace conn->result with saved_result, if any.  In the normal case
     923                 :             :          * there isn't a saved result and we're just dropping ownership of the
     924                 :             :          * current result.  In partial-result mode this restores the situation to
     925                 :             :          * what it was before we created the current partial result.
     926                 :             :          */
     927                 :       58745 :         conn->result = conn->saved_result;
     928                 :       58745 :         conn->error_result = false; /* saved_result is never an error */
     929                 :       58745 :         conn->saved_result = NULL;
     930                 :             : 
     931                 :      117490 :         return res;
     932                 :       58745 : }
     933                 :             : 
     934                 :             : /*
     935                 :             :  * pqInternalNotice - produce an internally-generated notice message
     936                 :             :  *
     937                 :             :  * A format string and optional arguments can be passed.  Note that we do
     938                 :             :  * libpq_gettext() here, so callers need not.
     939                 :             :  *
     940                 :             :  * The supplied text is taken as primary message (ie., it should not include
     941                 :             :  * a trailing newline, and should not be more than one line).
     942                 :             :  */
     943                 :             : void
     944                 :           0 : pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
     945                 :             : {
     946                 :           0 :         char            msgBuf[1024];
     947                 :           0 :         va_list         args;
     948                 :           0 :         PGresult   *res;
     949                 :             : 
     950         [ #  # ]:           0 :         if (hooks->noticeRec == NULL)
     951                 :           0 :                 return;                                 /* nobody home to receive notice? */
     952                 :             : 
     953                 :             :         /* Format the message */
     954                 :           0 :         va_start(args, fmt);
     955                 :           0 :         vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args);
     956                 :           0 :         va_end(args);
     957                 :           0 :         msgBuf[sizeof(msgBuf) - 1] = '\0';      /* make real sure it's terminated */
     958                 :             : 
     959                 :             :         /* Make a PGresult to pass to the notice receiver */
     960                 :           0 :         res = PQmakeEmptyPGresult(NULL, PGRES_NONFATAL_ERROR);
     961         [ #  # ]:           0 :         if (!res)
     962                 :           0 :                 return;
     963                 :           0 :         res->noticeHooks = *hooks;
     964                 :             : 
     965                 :             :         /*
     966                 :             :          * Set up fields of notice.
     967                 :             :          */
     968                 :           0 :         pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf);
     969                 :           0 :         pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE"));
     970                 :           0 :         pqSaveMessageField(res, PG_DIAG_SEVERITY_NONLOCALIZED, "NOTICE");
     971                 :             :         /* XXX should provide a SQLSTATE too? */
     972                 :             : 
     973                 :             :         /*
     974                 :             :          * Result text is always just the primary message + newline.  If we can't
     975                 :             :          * allocate it, substitute "out of memory", as in pqSetResultError.
     976                 :             :          */
     977                 :           0 :         res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, false);
     978         [ #  # ]:           0 :         if (res->errMsg)
     979                 :           0 :                 sprintf(res->errMsg, "%s\n", msgBuf);
     980                 :             :         else
     981                 :           0 :                 res->errMsg = libpq_gettext("out of memory\n");
     982                 :             : 
     983                 :             :         /*
     984                 :             :          * Pass to receiver, then free it.
     985                 :             :          */
     986                 :           0 :         res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res);
     987                 :           0 :         PQclear(res);
     988         [ #  # ]:           0 : }
     989                 :             : 
     990                 :             : /*
     991                 :             :  * pqAddTuple
     992                 :             :  *        add a row pointer to the PGresult structure, growing it if necessary
     993                 :             :  *        Returns true if OK, false if an error prevented adding the row
     994                 :             :  *
     995                 :             :  * On error, *errmsgp can be set to an error string to be returned.
     996                 :             :  * If it is left NULL, the error is presumed to be "out of memory".
     997                 :             :  */
     998                 :             : static bool
     999                 :       79839 : pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
    1000                 :             : {
    1001         [ +  + ]:       79839 :         if (res->ntups >= res->tupArrSize)
    1002                 :             :         {
    1003                 :             :                 /*
    1004                 :             :                  * Try to grow the array.
    1005                 :             :                  *
    1006                 :             :                  * We can use realloc because shallow copying of the structure is
    1007                 :             :                  * okay. Note that the first time through, res->tuples is NULL. While
    1008                 :             :                  * ANSI says that realloc() should act like malloc() in that case,
    1009                 :             :                  * some old C libraries (like SunOS 4.1.x) coredump instead. On
    1010                 :             :                  * failure realloc is supposed to return NULL without damaging the
    1011                 :             :                  * existing allocation. Note that the positions beyond res->ntups are
    1012                 :             :                  * garbage, not necessarily NULL.
    1013                 :             :                  */
    1014                 :       21343 :                 int                     newSize;
    1015                 :       21343 :                 PGresAttValue **newTuples;
    1016                 :             : 
    1017                 :             :                 /*
    1018                 :             :                  * Since we use integers for row numbers, we can't support more than
    1019                 :             :                  * INT_MAX rows.  Make sure we allow that many, though.
    1020                 :             :                  */
    1021         [ +  - ]:       21343 :                 if (res->tupArrSize <= INT_MAX / 2)
    1022         [ +  + ]:       21343 :                         newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
    1023         [ #  # ]:           0 :                 else if (res->tupArrSize < INT_MAX)
    1024                 :           0 :                         newSize = INT_MAX;
    1025                 :             :                 else
    1026                 :             :                 {
    1027                 :           0 :                         *errmsgp = libpq_gettext("PGresult cannot support more than INT_MAX tuples");
    1028                 :           0 :                         return false;
    1029                 :             :                 }
    1030                 :             : 
    1031                 :             :                 /*
    1032                 :             :                  * Also, on 32-bit platforms we could, in theory, overflow size_t even
    1033                 :             :                  * before newSize gets to INT_MAX.  (In practice we'd doubtless hit
    1034                 :             :                  * OOM long before that, but let's check.)
    1035                 :             :                  */
    1036                 :             : #if INT_MAX >= (SIZE_MAX / 2)
    1037                 :             :                 if (newSize > SIZE_MAX / sizeof(PGresAttValue *))
    1038                 :             :                 {
    1039                 :             :                         *errmsgp = libpq_gettext("size_t overflow");
    1040                 :             :                         return false;
    1041                 :             :                 }
    1042                 :             : #endif
    1043                 :             : 
    1044         [ +  + ]:       21343 :                 if (res->tuples == NULL)
    1045                 :       21319 :                         newTuples = (PGresAttValue **)
    1046                 :       21319 :                                 malloc(newSize * sizeof(PGresAttValue *));
    1047                 :             :                 else
    1048                 :          24 :                         newTuples = (PGresAttValue **)
    1049                 :          24 :                                 realloc(res->tuples, newSize * sizeof(PGresAttValue *));
    1050         [ +  - ]:       21343 :                 if (!newTuples)
    1051                 :           0 :                         return false;           /* malloc or realloc failed */
    1052                 :       21343 :                 res->memorySize +=
    1053                 :       21343 :                         (newSize - res->tupArrSize) * sizeof(PGresAttValue *);
    1054                 :       21343 :                 res->tupArrSize = newSize;
    1055                 :       21343 :                 res->tuples = newTuples;
    1056      [ -  -  + ]:       21343 :         }
    1057                 :       79839 :         res->tuples[res->ntups] = tup;
    1058                 :       79839 :         res->ntups++;
    1059                 :       79839 :         return true;
    1060                 :       79839 : }
    1061                 :             : 
    1062                 :             : /*
    1063                 :             :  * pqSaveMessageField - save one field of an error or notice message
    1064                 :             :  */
    1065                 :             : void
    1066                 :       75699 : pqSaveMessageField(PGresult *res, char code, const char *value)
    1067                 :             : {
    1068                 :       75699 :         PGMessageField *pfield;
    1069                 :             : 
    1070                 :       75699 :         pfield = (PGMessageField *)
    1071                 :      151398 :                 pqResultAlloc(res,
    1072                 :       75699 :                                           offsetof(PGMessageField, contents) +
    1073                 :      151398 :                                           strlen(value) + 1,
    1074                 :             :                                           true);
    1075         [ +  - ]:       75699 :         if (!pfield)
    1076                 :           0 :                 return;                                 /* out of memory? */
    1077                 :       75699 :         pfield->code = code;
    1078                 :       75699 :         strcpy(pfield->contents, value);
    1079                 :       75699 :         pfield->next = res->errFields;
    1080                 :       75699 :         res->errFields = pfield;
    1081         [ -  + ]:       75699 : }
    1082                 :             : 
    1083                 :             : /*
    1084                 :             :  * pqSaveParameterStatus - remember parameter status sent by backend
    1085                 :             :  *
    1086                 :             :  * Returns 1 on success, 0 on out-of-memory.  (Note that on out-of-memory, we
    1087                 :             :  * have already released the old value of the parameter, if any.  The only
    1088                 :             :  * really safe way to recover is to terminate the connection.)
    1089                 :             :  */
    1090                 :             : int
    1091                 :        6032 : pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
    1092                 :             : {
    1093                 :        6032 :         pgParameterStatus *pstatus;
    1094                 :        6032 :         pgParameterStatus *prev;
    1095                 :             : 
    1096                 :             :         /*
    1097                 :             :          * Forget any old information about the parameter
    1098                 :             :          */
    1099         [ +  + ]:       41727 :         for (pstatus = conn->pstatus, prev = NULL;
    1100                 :       41727 :                  pstatus != NULL;
    1101                 :       35695 :                  prev = pstatus, pstatus = pstatus->next)
    1102                 :             :         {
    1103         [ +  + ]:       36987 :                 if (strcmp(pstatus->name, name) == 0)
    1104                 :             :                 {
    1105         [ +  + ]:        1292 :                         if (prev)
    1106                 :         720 :                                 prev->next = pstatus->next;
    1107                 :             :                         else
    1108                 :         572 :                                 conn->pstatus = pstatus->next;
    1109                 :        1292 :                         free(pstatus);          /* frees name and value strings too */
    1110                 :        1292 :                         break;
    1111                 :             :                 }
    1112                 :       35695 :         }
    1113                 :             : 
    1114                 :             :         /*
    1115                 :             :          * Store new info as a single malloc block
    1116                 :             :          */
    1117                 :       12064 :         pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
    1118                 :       12064 :                                                                                    strlen(name) + strlen(value) + 2);
    1119         [ +  - ]:        6032 :         if (pstatus)
    1120                 :             :         {
    1121                 :        6032 :                 char       *ptr;
    1122                 :             : 
    1123                 :        6032 :                 ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
    1124                 :        6032 :                 pstatus->name = ptr;
    1125                 :        6032 :                 strcpy(ptr, name);
    1126                 :        6032 :                 ptr += strlen(name) + 1;
    1127                 :        6032 :                 pstatus->value = ptr;
    1128                 :        6032 :                 strcpy(ptr, value);
    1129                 :        6032 :                 pstatus->next = conn->pstatus;
    1130                 :        6032 :                 conn->pstatus = pstatus;
    1131                 :        6032 :         }
    1132                 :             :         else
    1133                 :             :         {
    1134                 :             :                 /* out of memory */
    1135                 :           0 :                 return 0;
    1136                 :             :         }
    1137                 :             : 
    1138                 :             :         /*
    1139                 :             :          * Save values of settings that are of interest to libpq in fields of the
    1140                 :             :          * PGconn object.  We keep client_encoding and standard_conforming_strings
    1141                 :             :          * in static variables as well, so that PQescapeString and PQescapeBytea
    1142                 :             :          * can behave somewhat sanely (at least in single-connection-using
    1143                 :             :          * programs).
    1144                 :             :          */
    1145         [ +  + ]:        6032 :         if (strcmp(name, "client_encoding") == 0)
    1146                 :             :         {
    1147                 :         320 :                 conn->client_encoding = pg_char_to_encoding(value);
    1148                 :             :                 /* if we don't recognize the encoding name, fall back to SQL_ASCII */
    1149         [ +  - ]:         320 :                 if (conn->client_encoding < 0)
    1150                 :           0 :                         conn->client_encoding = PG_SQL_ASCII;
    1151                 :         320 :                 static_client_encoding = conn->client_encoding;
    1152                 :         320 :         }
    1153         [ +  + ]:        5712 :         else if (strcmp(name, "standard_conforming_strings") == 0)
    1154                 :             :         {
    1155                 :         316 :                 conn->std_strings = (strcmp(value, "on") == 0);
    1156                 :         316 :                 static_std_strings = conn->std_strings;
    1157                 :         316 :         }
    1158         [ +  + ]:        5396 :         else if (strcmp(name, "server_version") == 0)
    1159                 :             :         {
    1160                 :             :                 /* We convert the server version to numeric form. */
    1161                 :         316 :                 int                     cnt;
    1162                 :         316 :                 int                     vmaj,
    1163                 :             :                                         vmin,
    1164                 :             :                                         vrev;
    1165                 :             : 
    1166                 :         316 :                 cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
    1167                 :             : 
    1168         [ -  + ]:         316 :                 if (cnt == 3)
    1169                 :             :                 {
    1170                 :             :                         /* old style, e.g. 9.6.1 */
    1171                 :           0 :                         conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
    1172                 :           0 :                 }
    1173         [ -  + ]:         316 :                 else if (cnt == 2)
    1174                 :             :                 {
    1175         [ #  # ]:           0 :                         if (vmaj >= 10)
    1176                 :             :                         {
    1177                 :             :                                 /* new style, e.g. 10.1 */
    1178                 :           0 :                                 conn->sversion = 100 * 100 * vmaj + vmin;
    1179                 :           0 :                         }
    1180                 :             :                         else
    1181                 :             :                         {
    1182                 :             :                                 /* old style without minor version, e.g. 9.6devel */
    1183                 :           0 :                                 conn->sversion = (100 * vmaj + vmin) * 100;
    1184                 :             :                         }
    1185                 :           0 :                 }
    1186         [ +  - ]:         316 :                 else if (cnt == 1)
    1187                 :             :                 {
    1188                 :             :                         /* new style without minor version, e.g. 10devel */
    1189                 :         316 :                         conn->sversion = 100 * 100 * vmaj;
    1190                 :         316 :                 }
    1191                 :             :                 else
    1192                 :           0 :                         conn->sversion = 0; /* unknown */
    1193                 :         316 :         }
    1194         [ +  + ]:        5080 :         else if (strcmp(name, "default_transaction_read_only") == 0)
    1195                 :             :         {
    1196                 :         320 :                 conn->default_transaction_read_only =
    1197                 :         320 :                         (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
    1198                 :         320 :         }
    1199         [ +  + ]:        4760 :         else if (strcmp(name, "in_hot_standby") == 0)
    1200                 :             :         {
    1201                 :         316 :                 conn->in_hot_standby =
    1202                 :         316 :                         (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
    1203                 :         316 :         }
    1204         [ +  + ]:        4444 :         else if (strcmp(name, "scram_iterations") == 0)
    1205                 :             :         {
    1206                 :         317 :                 conn->scram_sha_256_iterations = atoi(value);
    1207                 :         317 :         }
    1208                 :             : 
    1209                 :        6032 :         return 1;
    1210                 :        6032 : }
    1211                 :             : 
    1212                 :             : 
    1213                 :             : /*
    1214                 :             :  * pqRowProcessor
    1215                 :             :  *        Add the received row to the current async result (conn->result).
    1216                 :             :  *        Returns 1 if OK, 0 if error occurred.
    1217                 :             :  *
    1218                 :             :  * On error, *errmsgp can be set to an error string to be returned.
    1219                 :             :  * (Such a string should already be translated via libpq_gettext().)
    1220                 :             :  * If it is left NULL, the error is presumed to be "out of memory".
    1221                 :             :  */
    1222                 :             : int
    1223                 :       79839 : pqRowProcessor(PGconn *conn, const char **errmsgp)
    1224                 :             : {
    1225                 :       79839 :         PGresult   *res = conn->result;
    1226                 :       79839 :         int                     nfields = res->numAttributes;
    1227                 :       79839 :         const PGdataValue *columns = conn->rowBuf;
    1228                 :       79839 :         PGresAttValue *tup;
    1229                 :       79839 :         int                     i;
    1230                 :             : 
    1231                 :             :         /*
    1232                 :             :          * In partial-result mode, if we don't already have a partial PGresult
    1233                 :             :          * then make one by cloning conn->result (which should hold the correct
    1234                 :             :          * result metadata by now).  Then the original conn->result is moved over
    1235                 :             :          * to saved_result so that we can re-use it as a reference for future
    1236                 :             :          * partial results.  The saved result will become active again after
    1237                 :             :          * pqPrepareAsyncResult() returns the partial result to the application.
    1238                 :             :          */
    1239   [ +  +  +  + ]:       79839 :         if (conn->partialResMode && conn->saved_result == NULL)
    1240                 :             :         {
    1241                 :             :                 /* Copy everything that should be in the result at this point */
    1242                 :          16 :                 res = PQcopyResult(res,
    1243                 :             :                                                    PG_COPYRES_ATTRS | PG_COPYRES_EVENTS |
    1244                 :             :                                                    PG_COPYRES_NOTICEHOOKS);
    1245         [ +  - ]:          16 :                 if (!res)
    1246                 :           0 :                         return 0;
    1247                 :             :                 /* Change result status to appropriate special value */
    1248                 :          16 :                 res->resultStatus = (conn->singleRowMode ? PGRES_SINGLE_TUPLE : PGRES_TUPLES_CHUNK);
    1249                 :             :                 /* And stash it as the active result */
    1250                 :          16 :                 conn->saved_result = conn->result;
    1251                 :          16 :                 conn->result = res;
    1252                 :          16 :         }
    1253                 :             : 
    1254                 :             :         /*
    1255                 :             :          * Basically we just allocate space in the PGresult for each field and
    1256                 :             :          * copy the data over.
    1257                 :             :          *
    1258                 :             :          * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
    1259                 :             :          * caller will take to mean "out of memory".  This is preferable to trying
    1260                 :             :          * to set up such a message here, because evidently there's not enough
    1261                 :             :          * memory for gettext() to do anything.
    1262                 :             :          */
    1263                 :       79839 :         tup = (PGresAttValue *)
    1264                 :       79839 :                 pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
    1265         [ +  - ]:       79839 :         if (tup == NULL)
    1266                 :           0 :                 return 0;
    1267                 :             : 
    1268         [ +  + ]:      285236 :         for (i = 0; i < nfields; i++)
    1269                 :             :         {
    1270                 :      205397 :                 int                     clen = columns[i].len;
    1271                 :             : 
    1272         [ +  + ]:      205397 :                 if (clen < 0)
    1273                 :             :                 {
    1274                 :             :                         /* null field */
    1275                 :       14114 :                         tup[i].len = NULL_LEN;
    1276                 :       14114 :                         tup[i].value = res->null_field;
    1277                 :       14114 :                 }
    1278                 :             :                 else
    1279                 :             :                 {
    1280                 :      191283 :                         bool            isbinary = (res->attDescs[i].format != 0);
    1281                 :      191283 :                         char       *val;
    1282                 :             : 
    1283                 :      191283 :                         val = (char *) pqResultAlloc(res, (size_t) clen + 1, isbinary);
    1284         [ +  - ]:      191283 :                         if (val == NULL)
    1285                 :           0 :                                 return 0;
    1286                 :             : 
    1287                 :             :                         /* copy and zero-terminate the data (even if it's binary) */
    1288                 :      191283 :                         memcpy(val, columns[i].value, clen);
    1289                 :      191283 :                         val[clen] = '\0';
    1290                 :             : 
    1291                 :      191283 :                         tup[i].len = clen;
    1292                 :      191283 :                         tup[i].value = val;
    1293         [ -  + ]:      191283 :                 }
    1294         [ -  + ]:      205397 :         }
    1295                 :             : 
    1296                 :             :         /* And add the tuple to the PGresult's tuple array */
    1297         [ +  - ]:       79839 :         if (!pqAddTuple(res, tup, errmsgp))
    1298                 :           0 :                 return 0;
    1299                 :             : 
    1300                 :             :         /*
    1301                 :             :          * Success.  In partial-result mode, if we have enough rows then make the
    1302                 :             :          * result available to the client immediately.
    1303                 :             :          */
    1304   [ +  +  +  + ]:       79839 :         if (conn->partialResMode && res->ntups >= conn->maxChunkSize)
    1305                 :          12 :                 conn->asyncStatus = PGASYNC_READY_MORE;
    1306                 :             : 
    1307                 :       79839 :         return 1;
    1308                 :       79839 : }
    1309                 :             : 
    1310                 :             : 
    1311                 :             : /*
    1312                 :             :  * pqAllocCmdQueueEntry
    1313                 :             :  *              Get a command queue entry for caller to fill.
    1314                 :             :  *
    1315                 :             :  * If the recycle queue has a free element, that is returned; if not, a
    1316                 :             :  * fresh one is allocated.  Caller is responsible for adding it to the
    1317                 :             :  * command queue (pqAppendCmdQueueEntry) once the struct is filled in, or
    1318                 :             :  * releasing the memory (pqRecycleCmdQueueEntry) if an error occurs.
    1319                 :             :  *
    1320                 :             :  * If allocation fails, sets the error message and returns NULL.
    1321                 :             :  */
    1322                 :             : static PGcmdQueueEntry *
    1323                 :       58139 : pqAllocCmdQueueEntry(PGconn *conn)
    1324                 :             : {
    1325                 :       58139 :         PGcmdQueueEntry *entry;
    1326                 :             : 
    1327         [ +  + ]:       58139 :         if (conn->cmd_queue_recycle == NULL)
    1328                 :             :         {
    1329                 :         326 :                 entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry));
    1330         [ +  - ]:         326 :                 if (entry == NULL)
    1331                 :             :                 {
    1332                 :           0 :                         libpq_append_conn_error(conn, "out of memory");
    1333                 :           0 :                         return NULL;
    1334                 :             :                 }
    1335                 :         326 :         }
    1336                 :             :         else
    1337                 :             :         {
    1338                 :       57813 :                 entry = conn->cmd_queue_recycle;
    1339                 :       57813 :                 conn->cmd_queue_recycle = entry->next;
    1340                 :             :         }
    1341                 :       58139 :         entry->next = NULL;
    1342                 :       58139 :         entry->query = NULL;
    1343                 :             : 
    1344                 :       58139 :         return entry;
    1345                 :       58139 : }
    1346                 :             : 
    1347                 :             : /*
    1348                 :             :  * pqAppendCmdQueueEntry
    1349                 :             :  *              Append a caller-allocated entry to the command queue, and update
    1350                 :             :  *              conn->asyncStatus to account for it.
    1351                 :             :  *
    1352                 :             :  * The query itself must already have been put in the output buffer by the
    1353                 :             :  * caller.
    1354                 :             :  */
    1355                 :             : static void
    1356                 :       58139 : pqAppendCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
    1357                 :             : {
    1358         [ +  - ]:       58139 :         Assert(entry->next == NULL);
    1359                 :             : 
    1360         [ +  + ]:       58139 :         if (conn->cmd_queue_head == NULL)
    1361                 :       58010 :                 conn->cmd_queue_head = entry;
    1362                 :             :         else
    1363                 :         129 :                 conn->cmd_queue_tail->next = entry;
    1364                 :             : 
    1365                 :       58139 :         conn->cmd_queue_tail = entry;
    1366                 :             : 
    1367      [ +  -  + ]:       58139 :         switch (conn->pipelineStatus)
    1368                 :             :         {
    1369                 :             :                 case PQ_PIPELINE_OFF:
    1370                 :             :                 case PQ_PIPELINE_ON:
    1371                 :             : 
    1372                 :             :                         /*
    1373                 :             :                          * When not in pipeline aborted state, if there's a result ready
    1374                 :             :                          * to be consumed, let it be so (that is, don't change away from
    1375                 :             :                          * READY or READY_MORE); otherwise set us busy to wait for
    1376                 :             :                          * something to arrive from the server.
    1377                 :             :                          */
    1378         [ +  + ]:       58131 :                         if (conn->asyncStatus == PGASYNC_IDLE)
    1379                 :       58007 :                                 conn->asyncStatus = PGASYNC_BUSY;
    1380                 :       58131 :                         break;
    1381                 :             : 
    1382                 :             :                 case PQ_PIPELINE_ABORTED:
    1383                 :             : 
    1384                 :             :                         /*
    1385                 :             :                          * In aborted pipeline state, we don't expect anything from the
    1386                 :             :                          * server (since we don't send any queries that are queued).
    1387                 :             :                          * Therefore, if IDLE then do what PQgetResult would do to let
    1388                 :             :                          * itself consume commands from the queue; if we're in any other
    1389                 :             :                          * state, we don't have to do anything.
    1390                 :             :                          */
    1391   [ +  +  -  + ]:           8 :                         if (conn->asyncStatus == PGASYNC_IDLE ||
    1392                 :           5 :                                 conn->asyncStatus == PGASYNC_PIPELINE_IDLE)
    1393                 :           3 :                                 pqPipelineProcessQueue(conn);
    1394                 :           8 :                         break;
    1395                 :             :         }
    1396                 :       58139 : }
    1397                 :             : 
    1398                 :             : /*
    1399                 :             :  * pqRecycleCmdQueueEntry
    1400                 :             :  *              Push a command queue entry onto the freelist.
    1401                 :             :  */
    1402                 :             : static void
    1403                 :       58139 : pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
    1404                 :             : {
    1405         [ +  - ]:       58139 :         if (entry == NULL)
    1406                 :           0 :                 return;
    1407                 :             : 
    1408                 :             :         /* recyclable entries should not have a follow-on command */
    1409         [ +  - ]:       58139 :         Assert(entry->next == NULL);
    1410                 :             : 
    1411         [ +  + ]:       58139 :         if (entry->query)
    1412                 :             :         {
    1413                 :       58044 :                 free(entry->query);
    1414                 :       58044 :                 entry->query = NULL;
    1415                 :       58044 :         }
    1416                 :             : 
    1417                 :       58139 :         entry->next = conn->cmd_queue_recycle;
    1418                 :       58139 :         conn->cmd_queue_recycle = entry;
    1419                 :       58139 : }
    1420                 :             : 
    1421                 :             : 
    1422                 :             : /*
    1423                 :             :  * PQsendQuery
    1424                 :             :  *       Submit a query, but don't wait for it to finish
    1425                 :             :  *
    1426                 :             :  * Returns: 1 if successfully submitted
    1427                 :             :  *                      0 if error (conn->errorMessage is set)
    1428                 :             :  *
    1429                 :             :  * PQsendQueryContinue is a non-exported version that behaves identically
    1430                 :             :  * except that it doesn't reset conn->errorMessage.
    1431                 :             :  */
    1432                 :             : int
    1433                 :       57908 : PQsendQuery(PGconn *conn, const char *query)
    1434                 :             : {
    1435                 :       57908 :         return PQsendQueryInternal(conn, query, true);
    1436                 :             : }
    1437                 :             : 
    1438                 :             : int
    1439                 :           0 : PQsendQueryContinue(PGconn *conn, const char *query)
    1440                 :             : {
    1441                 :           0 :         return PQsendQueryInternal(conn, query, false);
    1442                 :             : }
    1443                 :             : 
    1444                 :             : static int
    1445                 :       57908 : PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
    1446                 :             : {
    1447                 :       57908 :         PGcmdQueueEntry *entry = NULL;
    1448                 :             : 
    1449         [ -  + ]:       57908 :         if (!PQsendQueryStart(conn, newQuery))
    1450                 :           0 :                 return 0;
    1451                 :             : 
    1452                 :             :         /* check the argument */
    1453         [ +  - ]:       57908 :         if (!query)
    1454                 :             :         {
    1455                 :           0 :                 libpq_append_conn_error(conn, "command string is a null pointer");
    1456                 :           0 :                 return 0;
    1457                 :             :         }
    1458                 :             : 
    1459         [ -  + ]:       57908 :         if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    1460                 :             :         {
    1461                 :           0 :                 libpq_append_conn_error(conn, "%s not allowed in pipeline mode",
    1462                 :             :                                                                 "PQsendQuery");
    1463                 :           0 :                 return 0;
    1464                 :             :         }
    1465                 :             : 
    1466                 :       57908 :         entry = pqAllocCmdQueueEntry(conn);
    1467         [ +  - ]:       57908 :         if (entry == NULL)
    1468                 :           0 :                 return 0;                               /* error msg already set */
    1469                 :             : 
    1470                 :             :         /* Send the query message(s) */
    1471                 :             :         /* construct the outgoing Query message */
    1472         [ +  - ]:       57908 :         if (pqPutMsgStart(PqMsg_Query, conn) < 0 ||
    1473   [ +  -  -  + ]:       57908 :                 pqPuts(query, conn) < 0 ||
    1474                 :       57908 :                 pqPutMsgEnd(conn) < 0)
    1475                 :             :         {
    1476                 :             :                 /* error message should be set up already */
    1477                 :           0 :                 pqRecycleCmdQueueEntry(conn, entry);
    1478                 :           0 :                 return 0;
    1479                 :             :         }
    1480                 :             : 
    1481                 :             :         /* remember we are using simple query protocol */
    1482                 :       57908 :         entry->queryclass = PGQUERY_SIMPLE;
    1483                 :             :         /* and remember the query text too, if possible */
    1484                 :       57908 :         entry->query = strdup(query);
    1485                 :             : 
    1486                 :             :         /*
    1487                 :             :          * Give the data a push.  In nonblock mode, don't complain if we're unable
    1488                 :             :          * to send it all; PQgetResult() will do any additional flushing needed.
    1489                 :             :          */
    1490         [ +  - ]:       57908 :         if (pqFlush(conn) < 0)
    1491                 :           0 :                 goto sendFailed;
    1492                 :             : 
    1493                 :             :         /* OK, it's launched! */
    1494                 :       57908 :         pqAppendCmdQueueEntry(conn, entry);
    1495                 :             : 
    1496                 :       57908 :         return 1;
    1497                 :             : 
    1498                 :             : sendFailed:
    1499                 :           0 :         pqRecycleCmdQueueEntry(conn, entry);
    1500                 :             :         /* error message should be set up already */
    1501                 :           0 :         return 0;
    1502                 :       57908 : }
    1503                 :             : 
    1504                 :             : /*
    1505                 :             :  * PQsendQueryParams
    1506                 :             :  *              Like PQsendQuery, but use extended query protocol so we can pass parameters
    1507                 :             :  */
    1508                 :             : int
    1509                 :         110 : PQsendQueryParams(PGconn *conn,
    1510                 :             :                                   const char *command,
    1511                 :             :                                   int nParams,
    1512                 :             :                                   const Oid *paramTypes,
    1513                 :             :                                   const char *const *paramValues,
    1514                 :             :                                   const int *paramLengths,
    1515                 :             :                                   const int *paramFormats,
    1516                 :             :                                   int resultFormat)
    1517                 :             : {
    1518         [ -  + ]:         110 :         if (!PQsendQueryStart(conn, true))
    1519                 :           0 :                 return 0;
    1520                 :             : 
    1521                 :             :         /* check the arguments */
    1522         [ +  - ]:         110 :         if (!command)
    1523                 :             :         {
    1524                 :           0 :                 libpq_append_conn_error(conn, "command string is a null pointer");
    1525                 :           0 :                 return 0;
    1526                 :             :         }
    1527   [ +  -  -  + ]:         110 :         if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
    1528                 :             :         {
    1529                 :           0 :                 libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
    1530                 :             :                                                                 PQ_QUERY_PARAM_MAX_LIMIT);
    1531                 :           0 :                 return 0;
    1532                 :             :         }
    1533                 :             : 
    1534                 :         220 :         return PQsendQueryGuts(conn,
    1535                 :         110 :                                                    command,
    1536                 :             :                                                    "",        /* use unnamed statement */
    1537                 :         110 :                                                    nParams,
    1538                 :         110 :                                                    paramTypes,
    1539                 :         110 :                                                    paramValues,
    1540                 :         110 :                                                    paramLengths,
    1541                 :         110 :                                                    paramFormats,
    1542                 :         110 :                                                    resultFormat);
    1543                 :         110 : }
    1544                 :             : 
    1545                 :             : /*
    1546                 :             :  * PQsendPrepare
    1547                 :             :  *       Submit a Parse message, but don't wait for it to finish
    1548                 :             :  *
    1549                 :             :  * Returns: 1 if successfully submitted
    1550                 :             :  *                      0 if error (conn->errorMessage is set)
    1551                 :             :  */
    1552                 :             : int
    1553                 :          26 : PQsendPrepare(PGconn *conn,
    1554                 :             :                           const char *stmtName, const char *query,
    1555                 :             :                           int nParams, const Oid *paramTypes)
    1556                 :             : {
    1557                 :          26 :         PGcmdQueueEntry *entry = NULL;
    1558                 :             : 
    1559         [ +  - ]:          26 :         if (!PQsendQueryStart(conn, true))
    1560                 :           0 :                 return 0;
    1561                 :             : 
    1562                 :             :         /* check the arguments */
    1563         [ +  - ]:          26 :         if (!stmtName)
    1564                 :             :         {
    1565                 :           0 :                 libpq_append_conn_error(conn, "statement name is a null pointer");
    1566                 :           0 :                 return 0;
    1567                 :             :         }
    1568         [ +  - ]:          26 :         if (!query)
    1569                 :             :         {
    1570                 :           0 :                 libpq_append_conn_error(conn, "command string is a null pointer");
    1571                 :           0 :                 return 0;
    1572                 :             :         }
    1573   [ +  -  -  + ]:          26 :         if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
    1574                 :             :         {
    1575                 :           0 :                 libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
    1576                 :             :                                                                 PQ_QUERY_PARAM_MAX_LIMIT);
    1577                 :           0 :                 return 0;
    1578                 :             :         }
    1579                 :             : 
    1580                 :          26 :         entry = pqAllocCmdQueueEntry(conn);
    1581         [ +  - ]:          26 :         if (entry == NULL)
    1582                 :           0 :                 return 0;                               /* error msg already set */
    1583                 :             : 
    1584                 :             :         /* construct the Parse message */
    1585         [ +  - ]:          26 :         if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
    1586   [ +  -  -  + ]:          26 :                 pqPuts(stmtName, conn) < 0 ||
    1587                 :          26 :                 pqPuts(query, conn) < 0)
    1588                 :           0 :                 goto sendFailed;
    1589                 :             : 
    1590   [ -  +  #  # ]:          26 :         if (nParams > 0 && paramTypes)
    1591                 :             :         {
    1592                 :           0 :                 int                     i;
    1593                 :             : 
    1594         [ #  # ]:           0 :                 if (pqPutInt(nParams, 2, conn) < 0)
    1595                 :           0 :                         goto sendFailed;
    1596         [ #  # ]:           0 :                 for (i = 0; i < nParams; i++)
    1597                 :             :                 {
    1598         [ #  # ]:           0 :                         if (pqPutInt(paramTypes[i], 4, conn) < 0)
    1599                 :           0 :                                 goto sendFailed;
    1600                 :           0 :                 }
    1601      [ #  #  # ]:           0 :         }
    1602                 :             :         else
    1603                 :             :         {
    1604         [ +  - ]:          26 :                 if (pqPutInt(0, 2, conn) < 0)
    1605                 :           0 :                         goto sendFailed;
    1606                 :             :         }
    1607         [ +  - ]:          26 :         if (pqPutMsgEnd(conn) < 0)
    1608                 :           0 :                 goto sendFailed;
    1609                 :             : 
    1610                 :             :         /* Add a Sync, unless in pipeline mode. */
    1611         [ +  + ]:          26 :         if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    1612                 :             :         {
    1613   [ +  -  -  + ]:          15 :                 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    1614                 :          15 :                         pqPutMsgEnd(conn) < 0)
    1615                 :           0 :                         goto sendFailed;
    1616                 :          15 :         }
    1617                 :             : 
    1618                 :             :         /* remember we are doing just a Parse */
    1619                 :          26 :         entry->queryclass = PGQUERY_PREPARE;
    1620                 :             : 
    1621                 :             :         /* and remember the query text too, if possible */
    1622                 :             :         /* if insufficient memory, query just winds up NULL */
    1623                 :          26 :         entry->query = strdup(query);
    1624                 :             : 
    1625                 :             :         /*
    1626                 :             :          * Give the data a push (in pipeline mode, only if we're past the size
    1627                 :             :          * threshold).  In nonblock mode, don't complain if we're unable to send
    1628                 :             :          * it all; PQgetResult() will do any additional flushing needed.
    1629                 :             :          */
    1630         [ +  - ]:          26 :         if (pqPipelineFlush(conn) < 0)
    1631                 :           0 :                 goto sendFailed;
    1632                 :             : 
    1633                 :             :         /* OK, it's launched! */
    1634                 :          26 :         pqAppendCmdQueueEntry(conn, entry);
    1635                 :             : 
    1636                 :          26 :         return 1;
    1637                 :             : 
    1638                 :             : sendFailed:
    1639                 :           0 :         pqRecycleCmdQueueEntry(conn, entry);
    1640                 :             :         /* error message should be set up already */
    1641                 :           0 :         return 0;
    1642                 :          26 : }
    1643                 :             : 
    1644                 :             : /*
    1645                 :             :  * PQsendQueryPrepared
    1646                 :             :  *              Like PQsendQuery, but execute a previously prepared statement,
    1647                 :             :  *              using extended query protocol so we can pass parameters
    1648                 :             :  */
    1649                 :             : int
    1650                 :          17 : PQsendQueryPrepared(PGconn *conn,
    1651                 :             :                                         const char *stmtName,
    1652                 :             :                                         int nParams,
    1653                 :             :                                         const char *const *paramValues,
    1654                 :             :                                         const int *paramLengths,
    1655                 :             :                                         const int *paramFormats,
    1656                 :             :                                         int resultFormat)
    1657                 :             : {
    1658         [ -  + ]:          17 :         if (!PQsendQueryStart(conn, true))
    1659                 :           0 :                 return 0;
    1660                 :             : 
    1661                 :             :         /* check the arguments */
    1662         [ +  - ]:          17 :         if (!stmtName)
    1663                 :             :         {
    1664                 :           0 :                 libpq_append_conn_error(conn, "statement name is a null pointer");
    1665                 :           0 :                 return 0;
    1666                 :             :         }
    1667   [ +  -  -  + ]:          17 :         if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
    1668                 :             :         {
    1669                 :           0 :                 libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
    1670                 :             :                                                                 PQ_QUERY_PARAM_MAX_LIMIT);
    1671                 :           0 :                 return 0;
    1672                 :             :         }
    1673                 :             : 
    1674                 :          34 :         return PQsendQueryGuts(conn,
    1675                 :             :                                                    NULL,        /* no command to parse */
    1676                 :          17 :                                                    stmtName,
    1677                 :          17 :                                                    nParams,
    1678                 :             :                                                    NULL,        /* no param types */
    1679                 :          17 :                                                    paramValues,
    1680                 :          17 :                                                    paramLengths,
    1681                 :          17 :                                                    paramFormats,
    1682                 :          17 :                                                    resultFormat);
    1683                 :          17 : }
    1684                 :             : 
    1685                 :             : /*
    1686                 :             :  * PQsendQueryStart
    1687                 :             :  *      Common startup code for PQsendQuery and sibling routines
    1688                 :             :  */
    1689                 :             : static bool
    1690                 :       58076 : PQsendQueryStart(PGconn *conn, bool newQuery)
    1691                 :             : {
    1692         [ +  - ]:       58076 :         if (!conn)
    1693                 :           0 :                 return false;
    1694                 :             : 
    1695                 :             :         /*
    1696                 :             :          * If this is the beginning of a query cycle, reset the error state.
    1697                 :             :          * However, in pipeline mode with something already queued, the error
    1698                 :             :          * buffer belongs to that command and we shouldn't clear it.
    1699                 :             :          */
    1700   [ +  -  +  + ]:       58076 :         if (newQuery && conn->cmd_queue_head == NULL)
    1701                 :       58000 :                 pqClearConnErrorState(conn);
    1702                 :             : 
    1703                 :             :         /* Don't try to send if we know there's no live connection. */
    1704         [ -  + ]:       58076 :         if (conn->status != CONNECTION_OK)
    1705                 :             :         {
    1706                 :           0 :                 libpq_append_conn_error(conn, "no connection to the server");
    1707                 :           0 :                 return false;
    1708                 :             :         }
    1709                 :             : 
    1710                 :             :         /* Can't send while already busy, either, unless enqueuing for later */
    1711   [ +  +  +  - ]:       58076 :         if (conn->asyncStatus != PGASYNC_IDLE &&
    1712                 :          76 :                 conn->pipelineStatus == PQ_PIPELINE_OFF)
    1713                 :             :         {
    1714                 :           0 :                 libpq_append_conn_error(conn, "another command is already in progress");
    1715                 :           0 :                 return false;
    1716                 :             :         }
    1717                 :             : 
    1718         [ +  + ]:       58076 :         if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    1719                 :             :         {
    1720                 :             :                 /*
    1721                 :             :                  * When enqueuing commands we don't change much of the connection
    1722                 :             :                  * state since it's already in use for the current command. The
    1723                 :             :                  * connection state will get updated when pqPipelineProcessQueue()
    1724                 :             :                  * advances to start processing the queued message.
    1725                 :             :                  *
    1726                 :             :                  * Just make sure we can safely enqueue given the current connection
    1727                 :             :                  * state. We can enqueue behind another queue item, or behind a
    1728                 :             :                  * non-queue command (one that sends its own sync), but we can't
    1729                 :             :                  * enqueue if the connection is in a copy state.
    1730                 :             :                  */
    1731      [ +  -  - ]:         123 :                 switch (conn->asyncStatus)
    1732                 :             :                 {
    1733                 :             :                         case PGASYNC_IDLE:
    1734                 :             :                         case PGASYNC_PIPELINE_IDLE:
    1735                 :             :                         case PGASYNC_READY:
    1736                 :             :                         case PGASYNC_READY_MORE:
    1737                 :             :                         case PGASYNC_BUSY:
    1738                 :             :                                 /* ok to queue */
    1739                 :         123 :                                 break;
    1740                 :             : 
    1741                 :             :                         case PGASYNC_COPY_IN:
    1742                 :             :                         case PGASYNC_COPY_OUT:
    1743                 :             :                         case PGASYNC_COPY_BOTH:
    1744                 :           0 :                                 libpq_append_conn_error(conn, "cannot queue commands during COPY");
    1745                 :           0 :                                 return false;
    1746                 :             :                 }
    1747                 :         123 :         }
    1748                 :             :         else
    1749                 :             :         {
    1750                 :             :                 /*
    1751                 :             :                  * This command's results will come in immediately. Initialize async
    1752                 :             :                  * result-accumulation state
    1753                 :             :                  */
    1754                 :       57953 :                 pqClearAsyncResult(conn);
    1755                 :             : 
    1756                 :             :                 /* reset partial-result mode */
    1757                 :       57953 :                 conn->partialResMode = false;
    1758                 :       57953 :                 conn->singleRowMode = false;
    1759                 :       57953 :                 conn->maxChunkSize = 0;
    1760                 :             :         }
    1761                 :             : 
    1762                 :             :         /* ready to send command message */
    1763                 :       58076 :         return true;
    1764                 :       58076 : }
    1765                 :             : 
    1766                 :             : /*
    1767                 :             :  * PQsendQueryGuts
    1768                 :             :  *              Common code for sending a query with extended query protocol
    1769                 :             :  *              PQsendQueryStart should be done already
    1770                 :             :  *
    1771                 :             :  * command may be NULL to indicate we use an already-prepared statement
    1772                 :             :  */
    1773                 :             : static int
    1774                 :         127 : PQsendQueryGuts(PGconn *conn,
    1775                 :             :                                 const char *command,
    1776                 :             :                                 const char *stmtName,
    1777                 :             :                                 int nParams,
    1778                 :             :                                 const Oid *paramTypes,
    1779                 :             :                                 const char *const *paramValues,
    1780                 :             :                                 const int *paramLengths,
    1781                 :             :                                 const int *paramFormats,
    1782                 :             :                                 int resultFormat)
    1783                 :             : {
    1784                 :         127 :         int                     i;
    1785                 :         127 :         PGcmdQueueEntry *entry;
    1786                 :             : 
    1787                 :         127 :         entry = pqAllocCmdQueueEntry(conn);
    1788         [ +  - ]:         127 :         if (entry == NULL)
    1789                 :           0 :                 return 0;                               /* error msg already set */
    1790                 :             : 
    1791                 :             :         /*
    1792                 :             :          * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync
    1793                 :             :          * (if not in pipeline mode), using specified statement name and the
    1794                 :             :          * unnamed portal.
    1795                 :             :          */
    1796                 :             : 
    1797         [ +  + ]:         127 :         if (command)
    1798                 :             :         {
    1799                 :             :                 /* construct the Parse message */
    1800         [ +  - ]:         110 :                 if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
    1801   [ +  -  -  + ]:         110 :                         pqPuts(stmtName, conn) < 0 ||
    1802                 :         110 :                         pqPuts(command, conn) < 0)
    1803                 :           0 :                         goto sendFailed;
    1804   [ +  +  +  - ]:         110 :                 if (nParams > 0 && paramTypes)
    1805                 :             :                 {
    1806         [ #  # ]:           0 :                         if (pqPutInt(nParams, 2, conn) < 0)
    1807                 :           0 :                                 goto sendFailed;
    1808         [ #  # ]:           0 :                         for (i = 0; i < nParams; i++)
    1809                 :             :                         {
    1810         [ #  # ]:           0 :                                 if (pqPutInt(paramTypes[i], 4, conn) < 0)
    1811                 :           0 :                                         goto sendFailed;
    1812                 :           0 :                         }
    1813                 :           0 :                 }
    1814                 :             :                 else
    1815                 :             :                 {
    1816         [ +  - ]:         110 :                         if (pqPutInt(0, 2, conn) < 0)
    1817                 :           0 :                                 goto sendFailed;
    1818                 :             :                 }
    1819         [ +  - ]:         110 :                 if (pqPutMsgEnd(conn) < 0)
    1820                 :           0 :                         goto sendFailed;
    1821                 :         110 :         }
    1822                 :             : 
    1823                 :             :         /* Construct the Bind message */
    1824         [ +  - ]:         127 :         if (pqPutMsgStart(PqMsg_Bind, conn) < 0 ||
    1825   [ +  -  -  + ]:         127 :                 pqPuts("", conn) < 0 ||
    1826                 :         127 :                 pqPuts(stmtName, conn) < 0)
    1827                 :           0 :                 goto sendFailed;
    1828                 :             : 
    1829                 :             :         /* Send parameter formats */
    1830   [ +  +  +  - ]:         127 :         if (nParams > 0 && paramFormats)
    1831                 :             :         {
    1832         [ #  # ]:           0 :                 if (pqPutInt(nParams, 2, conn) < 0)
    1833                 :           0 :                         goto sendFailed;
    1834         [ #  # ]:           0 :                 for (i = 0; i < nParams; i++)
    1835                 :             :                 {
    1836         [ #  # ]:           0 :                         if (pqPutInt(paramFormats[i], 2, conn) < 0)
    1837                 :           0 :                                 goto sendFailed;
    1838                 :           0 :                 }
    1839                 :           0 :         }
    1840                 :             :         else
    1841                 :             :         {
    1842         [ +  - ]:         127 :                 if (pqPutInt(0, 2, conn) < 0)
    1843                 :           0 :                         goto sendFailed;
    1844                 :             :         }
    1845                 :             : 
    1846         [ +  - ]:         127 :         if (pqPutInt(nParams, 2, conn) < 0)
    1847                 :           0 :                 goto sendFailed;
    1848                 :             : 
    1849                 :             :         /* Send parameters */
    1850         [ +  + ]:         212 :         for (i = 0; i < nParams; i++)
    1851                 :             :         {
    1852   [ +  -  -  + ]:          85 :                 if (paramValues && paramValues[i])
    1853                 :             :                 {
    1854                 :          85 :                         int                     nbytes;
    1855                 :             : 
    1856   [ -  +  #  # ]:          85 :                         if (paramFormats && paramFormats[i] != 0)
    1857                 :             :                         {
    1858                 :             :                                 /* binary parameter */
    1859         [ #  # ]:           0 :                                 if (paramLengths)
    1860                 :           0 :                                         nbytes = paramLengths[i];
    1861                 :             :                                 else
    1862                 :             :                                 {
    1863                 :           0 :                                         libpq_append_conn_error(conn, "length must be given for binary parameter");
    1864                 :           0 :                                         goto sendFailed;
    1865                 :             :                                 }
    1866                 :           0 :                         }
    1867                 :             :                         else
    1868                 :             :                         {
    1869                 :             :                                 /* text parameter, do not use paramLengths */
    1870                 :          85 :                                 nbytes = strlen(paramValues[i]);
    1871                 :             :                         }
    1872   [ +  -  -  + ]:          85 :                         if (pqPutInt(nbytes, 4, conn) < 0 ||
    1873                 :          85 :                                 pqPutnchar(paramValues[i], nbytes, conn) < 0)
    1874                 :           0 :                                 goto sendFailed;
    1875      [ -  -  + ]:          85 :                 }
    1876                 :             :                 else
    1877                 :             :                 {
    1878                 :             :                         /* take the param as NULL */
    1879         [ #  # ]:           0 :                         if (pqPutInt(-1, 4, conn) < 0)
    1880                 :           0 :                                 goto sendFailed;
    1881                 :             :                 }
    1882                 :          85 :         }
    1883   [ +  -  -  + ]:         127 :         if (pqPutInt(1, 2, conn) < 0 ||
    1884                 :         127 :                 pqPutInt(resultFormat, 2, conn))
    1885                 :           0 :                 goto sendFailed;
    1886         [ +  - ]:         127 :         if (pqPutMsgEnd(conn) < 0)
    1887                 :           0 :                 goto sendFailed;
    1888                 :             : 
    1889                 :             :         /* construct the Describe Portal message */
    1890         [ +  - ]:         127 :         if (pqPutMsgStart(PqMsg_Describe, conn) < 0 ||
    1891         [ +  - ]:         127 :                 pqPutc('P', conn) < 0 ||
    1892   [ +  -  -  + ]:         127 :                 pqPuts("", conn) < 0 ||
    1893                 :         127 :                 pqPutMsgEnd(conn) < 0)
    1894                 :           0 :                 goto sendFailed;
    1895                 :             : 
    1896                 :             :         /* construct the Execute message */
    1897         [ +  - ]:         127 :         if (pqPutMsgStart(PqMsg_Execute, conn) < 0 ||
    1898         [ +  - ]:         127 :                 pqPuts("", conn) < 0 ||
    1899   [ +  -  -  + ]:         127 :                 pqPutInt(0, 4, conn) < 0 ||
    1900                 :         127 :                 pqPutMsgEnd(conn) < 0)
    1901                 :           0 :                 goto sendFailed;
    1902                 :             : 
    1903                 :             :         /* construct the Sync message if not in pipeline mode */
    1904         [ +  + ]:         127 :         if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    1905                 :             :         {
    1906   [ +  -  -  + ]:          18 :                 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    1907                 :          18 :                         pqPutMsgEnd(conn) < 0)
    1908                 :           0 :                         goto sendFailed;
    1909                 :          18 :         }
    1910                 :             : 
    1911                 :             :         /* remember we are using extended query protocol */
    1912                 :         127 :         entry->queryclass = PGQUERY_EXTENDED;
    1913                 :             : 
    1914                 :             :         /* and remember the query text too, if possible */
    1915                 :             :         /* if insufficient memory, query just winds up NULL */
    1916         [ +  + ]:         127 :         if (command)
    1917                 :         110 :                 entry->query = strdup(command);
    1918                 :             : 
    1919                 :             :         /*
    1920                 :             :          * Give the data a push (in pipeline mode, only if we're past the size
    1921                 :             :          * threshold).  In nonblock mode, don't complain if we're unable to send
    1922                 :             :          * it all; PQgetResult() will do any additional flushing needed.
    1923                 :             :          */
    1924         [ +  - ]:         127 :         if (pqPipelineFlush(conn) < 0)
    1925                 :           0 :                 goto sendFailed;
    1926                 :             : 
    1927                 :             :         /* OK, it's launched! */
    1928                 :         127 :         pqAppendCmdQueueEntry(conn, entry);
    1929                 :             : 
    1930                 :         127 :         return 1;
    1931                 :             : 
    1932                 :             : sendFailed:
    1933                 :           0 :         pqRecycleCmdQueueEntry(conn, entry);
    1934                 :             :         /* error message should be set up already */
    1935                 :           0 :         return 0;
    1936                 :         127 : }
    1937                 :             : 
    1938                 :             : /*
    1939                 :             :  * Is it OK to change partial-result mode now?
    1940                 :             :  */
    1941                 :             : static bool
    1942                 :          17 : canChangeResultMode(PGconn *conn)
    1943                 :             : {
    1944                 :             :         /*
    1945                 :             :          * Only allow changing the mode when we have launched a query and not yet
    1946                 :             :          * received any results.
    1947                 :             :          */
    1948         [ +  - ]:          17 :         if (!conn)
    1949                 :           0 :                 return false;
    1950         [ +  + ]:          17 :         if (conn->asyncStatus != PGASYNC_BUSY)
    1951                 :           1 :                 return false;
    1952   [ +  -  -  + ]:          19 :         if (!conn->cmd_queue_head ||
    1953         [ +  + ]:          16 :                 (conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE &&
    1954                 :           3 :                  conn->cmd_queue_head->queryclass != PGQUERY_EXTENDED))
    1955                 :           0 :                 return false;
    1956   [ +  -  -  + ]:          16 :         if (pgHavePendingResult(conn))
    1957                 :           0 :                 return false;
    1958                 :          16 :         return true;
    1959                 :          17 : }
    1960                 :             : 
    1961                 :             : /*
    1962                 :             :  * Select row-by-row processing mode
    1963                 :             :  */
    1964                 :             : int
    1965                 :           0 : PQsetSingleRowMode(PGconn *conn)
    1966                 :             : {
    1967         [ #  # ]:           0 :         if (canChangeResultMode(conn))
    1968                 :             :         {
    1969                 :           0 :                 conn->partialResMode = true;
    1970                 :           0 :                 conn->singleRowMode = true;
    1971                 :           0 :                 conn->maxChunkSize = 1;
    1972                 :           0 :                 return 1;
    1973                 :             :         }
    1974                 :             :         else
    1975                 :           0 :                 return 0;
    1976                 :           0 : }
    1977                 :             : 
    1978                 :             : /*
    1979                 :             :  * Select chunked results processing mode
    1980                 :             :  */
    1981                 :             : int
    1982                 :          17 : PQsetChunkedRowsMode(PGconn *conn, int chunkSize)
    1983                 :             : {
    1984   [ +  -  +  + ]:          17 :         if (chunkSize > 0 && canChangeResultMode(conn))
    1985                 :             :         {
    1986                 :          16 :                 conn->partialResMode = true;
    1987                 :          16 :                 conn->singleRowMode = false;
    1988                 :          16 :                 conn->maxChunkSize = chunkSize;
    1989                 :          16 :                 return 1;
    1990                 :             :         }
    1991                 :             :         else
    1992                 :           1 :                 return 0;
    1993                 :          17 : }
    1994                 :             : 
    1995                 :             : /*
    1996                 :             :  * Consume any available input from the backend
    1997                 :             :  * 0 return: some kind of trouble
    1998                 :             :  * 1 return: no problem
    1999                 :             :  */
    2000                 :             : int
    2001                 :       51039 : PQconsumeInput(PGconn *conn)
    2002                 :             : {
    2003         [ +  - ]:       51039 :         if (!conn)
    2004                 :           0 :                 return 0;
    2005                 :             : 
    2006                 :             :         /*
    2007                 :             :          * for non-blocking connections try to flush the send-queue, otherwise we
    2008                 :             :          * may never get a response for something that may not have already been
    2009                 :             :          * sent because it's in our write buffer!
    2010                 :             :          */
    2011         [ +  - ]:       51039 :         if (pqIsnonblocking(conn))
    2012                 :             :         {
    2013         [ #  # ]:           0 :                 if (pqFlush(conn) < 0)
    2014                 :           0 :                         return 0;
    2015                 :           0 :         }
    2016                 :             : 
    2017                 :             :         /*
    2018                 :             :          * Load more data, if available. We do this no matter what state we are
    2019                 :             :          * in, since we are probably getting called because the application wants
    2020                 :             :          * to get rid of a read-select condition. Note that we will NOT block
    2021                 :             :          * waiting for more input.
    2022                 :             :          */
    2023         [ +  - ]:       51039 :         if (pqReadData(conn) < 0)
    2024                 :           0 :                 return 0;
    2025                 :             : 
    2026                 :             :         /* Parsing of the data waits till later. */
    2027                 :       51039 :         return 1;
    2028                 :       51039 : }
    2029                 :             : 
    2030                 :             : 
    2031                 :             : /*
    2032                 :             :  * parseInput: if appropriate, parse input data from backend
    2033                 :             :  * until input is exhausted or a stopping state is reached.
    2034                 :             :  * Note that this function will NOT attempt to read more data from the backend.
    2035                 :             :  */
    2036                 :             : static void
    2037                 :      238071 : parseInput(PGconn *conn)
    2038                 :             : {
    2039                 :      238071 :         pqParseInput3(conn);
    2040                 :      238071 : }
    2041                 :             : 
    2042                 :             : /*
    2043                 :             :  * PQisBusy
    2044                 :             :  *       Return true if PQgetResult would block waiting for input.
    2045                 :             :  */
    2046                 :             : 
    2047                 :             : int
    2048                 :         318 : PQisBusy(PGconn *conn)
    2049                 :             : {
    2050         [ +  - ]:         318 :         if (!conn)
    2051                 :           0 :                 return false;
    2052                 :             : 
    2053                 :             :         /* Parse any available data, if our state permits. */
    2054                 :         318 :         parseInput(conn);
    2055                 :             : 
    2056                 :             :         /*
    2057                 :             :          * PQgetResult will return immediately in all states except BUSY.  Also,
    2058                 :             :          * if we've detected read EOF and dropped the connection, we can expect
    2059                 :             :          * that PQgetResult will fail immediately.  Note that we do *not* check
    2060                 :             :          * conn->write_failed here --- once that's become set, we know we have
    2061                 :             :          * trouble, but we need to keep trying to read until we have a complete
    2062                 :             :          * server message or detect read EOF.
    2063                 :             :          */
    2064         [ +  + ]:         318 :         return conn->asyncStatus == PGASYNC_BUSY && conn->status != CONNECTION_BAD;
    2065                 :         318 : }
    2066                 :             : 
    2067                 :             : /*
    2068                 :             :  * PQgetResult
    2069                 :             :  *        Get the next PGresult produced by a query.  Returns NULL if no
    2070                 :             :  *        query work remains or an error has occurred (e.g. out of
    2071                 :             :  *        memory).
    2072                 :             :  *
    2073                 :             :  *        In pipeline mode, once all the result of a query have been returned,
    2074                 :             :  *        PQgetResult returns NULL to let the user know that the next
    2075                 :             :  *        query is being processed.  At the end of the pipeline, returns a
    2076                 :             :  *        result with PQresultStatus(result) == PGRES_PIPELINE_SYNC.
    2077                 :             :  */
    2078                 :             : PGresult *
    2079                 :      124122 : PQgetResult(PGconn *conn)
    2080                 :             : {
    2081                 :      124122 :         PGresult   *res;
    2082                 :             : 
    2083         [ +  - ]:      124122 :         if (!conn)
    2084                 :           0 :                 return NULL;
    2085                 :             : 
    2086                 :             :         /* Parse any available data, if our state permits. */
    2087                 :      124122 :         parseInput(conn);
    2088                 :             : 
    2089                 :             :         /* If not ready to return something, block until we are. */
    2090         [ +  + ]:      186583 :         while (conn->asyncStatus == PGASYNC_BUSY)
    2091                 :             :         {
    2092                 :       62461 :                 int                     flushResult;
    2093                 :             : 
    2094                 :             :                 /*
    2095                 :             :                  * If data remains unsent, send it.  Else we might be waiting for the
    2096                 :             :                  * result of a command the backend hasn't even got yet.
    2097                 :             :                  */
    2098         [ +  - ]:       62461 :                 while ((flushResult = pqFlush(conn)) > 0)
    2099                 :             :                 {
    2100         [ #  # ]:           0 :                         if (pqWait(false, true, conn))
    2101                 :             :                         {
    2102                 :           0 :                                 flushResult = -1;
    2103                 :           0 :                                 break;
    2104                 :             :                         }
    2105                 :             :                 }
    2106                 :             : 
    2107                 :             :                 /*
    2108                 :             :                  * Wait for some more data, and load it.  (Note: if the connection has
    2109                 :             :                  * been lost, pqWait should return immediately because the socket
    2110                 :             :                  * should be read-ready, either with the last server data or with an
    2111                 :             :                  * EOF indication.  We expect therefore that this won't result in any
    2112                 :             :                  * undue delay in reporting a previous write failure.)
    2113                 :             :                  */
    2114         [ +  - ]:       62461 :                 if (flushResult ||
    2115   [ +  -  -  + ]:       62461 :                         pqWait(true, false, conn) ||
    2116                 :       62461 :                         pqReadData(conn) < 0)
    2117                 :             :                 {
    2118                 :             :                         /* Report the error saved by pqWait or pqReadData */
    2119                 :           0 :                         pqSaveErrorResult(conn);
    2120                 :           0 :                         conn->asyncStatus = PGASYNC_IDLE;
    2121                 :           0 :                         return pqPrepareAsyncResult(conn);
    2122                 :             :                 }
    2123                 :             : 
    2124                 :             :                 /* Parse it. */
    2125                 :       62461 :                 parseInput(conn);
    2126                 :             : 
    2127                 :             :                 /*
    2128                 :             :                  * If we had a write error, but nothing above obtained a query result
    2129                 :             :                  * or detected a read error, report the write error.
    2130                 :             :                  */
    2131   [ -  +  #  # ]:       62461 :                 if (conn->write_failed && conn->asyncStatus == PGASYNC_BUSY)
    2132                 :             :                 {
    2133                 :           0 :                         pqSaveWriteError(conn);
    2134                 :           0 :                         conn->asyncStatus = PGASYNC_IDLE;
    2135                 :           0 :                         return pqPrepareAsyncResult(conn);
    2136                 :             :                 }
    2137         [ -  + ]:       62461 :         }
    2138                 :             : 
    2139                 :             :         /* Return the appropriate thing. */
    2140   [ +  -  +  +  :      124122 :         switch (conn->asyncStatus)
             +  +  +  - ]
    2141                 :             :         {
    2142                 :             :                 case PGASYNC_IDLE:
    2143                 :       65513 :                         res = NULL;                     /* query is complete */
    2144                 :       65513 :                         break;
    2145                 :             :                 case PGASYNC_PIPELINE_IDLE:
    2146         [ +  - ]:         123 :                         Assert(conn->pipelineStatus != PQ_PIPELINE_OFF);
    2147                 :             : 
    2148                 :             :                         /*
    2149                 :             :                          * We're about to return the NULL that terminates the round of
    2150                 :             :                          * results from the current query; prepare to send the results of
    2151                 :             :                          * the next query, if any, when we're called next.  If there's no
    2152                 :             :                          * next element in the command queue, this gets us in IDLE state.
    2153                 :             :                          */
    2154                 :         123 :                         pqPipelineProcessQueue(conn);
    2155                 :         123 :                         res = NULL;                     /* query is complete */
    2156                 :         123 :                         break;
    2157                 :             : 
    2158                 :             :                 case PGASYNC_READY:
    2159                 :       58253 :                         res = pqPrepareAsyncResult(conn);
    2160                 :             : 
    2161                 :             :                         /*
    2162                 :             :                          * Normally pqPrepareAsyncResult will have left conn->result
    2163                 :             :                          * empty.  Otherwise, "res" must be a not-full PGRES_TUPLES_CHUNK
    2164                 :             :                          * result, which we want to return to the caller while staying in
    2165                 :             :                          * PGASYNC_READY state.  Then the next call here will return the
    2166                 :             :                          * empty PGRES_TUPLES_OK result that was restored from
    2167                 :             :                          * saved_result, after which we can proceed.
    2168                 :             :                          */
    2169         [ +  + ]:       58253 :                         if (conn->result)
    2170                 :             :                         {
    2171         [ +  - ]:           3 :                                 Assert(res->resultStatus == PGRES_TUPLES_CHUNK);
    2172                 :           3 :                                 break;
    2173                 :             :                         }
    2174                 :             : 
    2175                 :             :                         /* Advance the queue as appropriate */
    2176                 :      116500 :                         pqCommandQueueAdvance(conn, false,
    2177                 :       58250 :                                                                   res->resultStatus == PGRES_PIPELINE_SYNC);
    2178                 :             : 
    2179         [ +  + ]:       58250 :                         if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    2180                 :             :                         {
    2181                 :             :                                 /*
    2182                 :             :                                  * We're about to send the results of the current query.  Set
    2183                 :             :                                  * us idle now, and ...
    2184                 :             :                                  */
    2185                 :         186 :                                 conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
    2186                 :             : 
    2187                 :             :                                 /*
    2188                 :             :                                  * ... in cases when we're sending a pipeline-sync result,
    2189                 :             :                                  * move queue processing forwards immediately, so that next
    2190                 :             :                                  * time we're called, we're prepared to return the next result
    2191                 :             :                                  * received from the server.  In all other cases, leave the
    2192                 :             :                                  * queue state change for next time, so that a terminating
    2193                 :             :                                  * NULL result is sent.
    2194                 :             :                                  *
    2195                 :             :                                  * (In other words: we don't return a NULL after a pipeline
    2196                 :             :                                  * sync.)
    2197                 :             :                                  */
    2198         [ +  + ]:         186 :                                 if (res->resultStatus == PGRES_PIPELINE_SYNC)
    2199                 :          63 :                                         pqPipelineProcessQueue(conn);
    2200                 :         186 :                         }
    2201                 :             :                         else
    2202                 :             :                         {
    2203                 :             :                                 /* Set the state back to BUSY, allowing parsing to proceed. */
    2204                 :       58064 :                                 conn->asyncStatus = PGASYNC_BUSY;
    2205                 :             :                         }
    2206                 :       58250 :                         break;
    2207                 :             :                 case PGASYNC_READY_MORE:
    2208                 :          12 :                         res = pqPrepareAsyncResult(conn);
    2209                 :             :                         /* Set the state back to BUSY, allowing parsing to proceed. */
    2210                 :          12 :                         conn->asyncStatus = PGASYNC_BUSY;
    2211                 :          12 :                         break;
    2212                 :             :                 case PGASYNC_COPY_IN:
    2213                 :         132 :                         res = getCopyResult(conn, PGRES_COPY_IN);
    2214                 :         132 :                         break;
    2215                 :             :                 case PGASYNC_COPY_OUT:
    2216                 :          89 :                         res = getCopyResult(conn, PGRES_COPY_OUT);
    2217                 :          89 :                         break;
    2218                 :             :                 case PGASYNC_COPY_BOTH:
    2219                 :           0 :                         res = getCopyResult(conn, PGRES_COPY_BOTH);
    2220                 :           0 :                         break;
    2221                 :             :                 default:
    2222                 :           0 :                         libpq_append_conn_error(conn, "unexpected asyncStatus: %d", (int) conn->asyncStatus);
    2223                 :           0 :                         pqSaveErrorResult(conn);
    2224                 :           0 :                         conn->asyncStatus = PGASYNC_IDLE;    /* try to restore valid state */
    2225                 :           0 :                         res = pqPrepareAsyncResult(conn);
    2226                 :           0 :                         break;
    2227                 :             :         }
    2228                 :             : 
    2229                 :             :         /* Time to fire PGEVT_RESULTCREATE events, if there are any */
    2230   [ +  +  +  - ]:      124122 :         if (res && res->nEvents > 0)
    2231                 :           0 :                 (void) PQfireResultCreateEvents(conn, res);
    2232                 :             : 
    2233                 :      124122 :         return res;
    2234                 :      124122 : }
    2235                 :             : 
    2236                 :             : /*
    2237                 :             :  * getCopyResult
    2238                 :             :  *        Helper for PQgetResult: generate result for COPY-in-progress cases
    2239                 :             :  */
    2240                 :             : static PGresult *
    2241                 :         221 : getCopyResult(PGconn *conn, ExecStatusType copytype)
    2242                 :             : {
    2243                 :             :         /*
    2244                 :             :          * If the server connection has been lost, don't pretend everything is
    2245                 :             :          * hunky-dory; instead return a PGRES_FATAL_ERROR result, and reset the
    2246                 :             :          * asyncStatus to idle (corresponding to what we'd do if we'd detected I/O
    2247                 :             :          * error in the earlier steps in PQgetResult).  The text returned in the
    2248                 :             :          * result is whatever is in conn->errorMessage; we hope that was filled
    2249                 :             :          * with something relevant when the lost connection was detected.
    2250                 :             :          */
    2251         [ -  + ]:         221 :         if (conn->status != CONNECTION_OK)
    2252                 :             :         {
    2253                 :           0 :                 pqSaveErrorResult(conn);
    2254                 :           0 :                 conn->asyncStatus = PGASYNC_IDLE;
    2255                 :           0 :                 return pqPrepareAsyncResult(conn);
    2256                 :             :         }
    2257                 :             : 
    2258                 :             :         /* If we have an async result for the COPY, return that */
    2259   [ +  -  -  + ]:         221 :         if (conn->result && conn->result->resultStatus == copytype)
    2260                 :         221 :                 return pqPrepareAsyncResult(conn);
    2261                 :             : 
    2262                 :             :         /* Otherwise, invent a suitable PGresult */
    2263                 :           0 :         return PQmakeEmptyPGresult(conn, copytype);
    2264                 :         221 : }
    2265                 :             : 
    2266                 :             : 
    2267                 :             : /*
    2268                 :             :  * PQexec
    2269                 :             :  *        send a query to the backend and package up the result in a PGresult
    2270                 :             :  *
    2271                 :             :  * If the query was not even sent, return NULL; conn->errorMessage is set to
    2272                 :             :  * a relevant message.
    2273                 :             :  * If the query was sent, a new PGresult is returned (which could indicate
    2274                 :             :  * either success or failure).
    2275                 :             :  * The user is responsible for freeing the PGresult via PQclear()
    2276                 :             :  * when done with it.
    2277                 :             :  */
    2278                 :             : PGresult *
    2279                 :        7178 : PQexec(PGconn *conn, const char *query)
    2280                 :             : {
    2281         [ -  + ]:        7178 :         if (!PQexecStart(conn))
    2282                 :           0 :                 return NULL;
    2283         [ +  - ]:        7178 :         if (!PQsendQuery(conn, query))
    2284                 :           0 :                 return NULL;
    2285                 :        7178 :         return PQexecFinish(conn);
    2286                 :        7178 : }
    2287                 :             : 
    2288                 :             : /*
    2289                 :             :  * PQexecParams
    2290                 :             :  *              Like PQexec, but use extended query protocol so we can pass parameters
    2291                 :             :  */
    2292                 :             : PGresult *
    2293                 :           0 : PQexecParams(PGconn *conn,
    2294                 :             :                          const char *command,
    2295                 :             :                          int nParams,
    2296                 :             :                          const Oid *paramTypes,
    2297                 :             :                          const char *const *paramValues,
    2298                 :             :                          const int *paramLengths,
    2299                 :             :                          const int *paramFormats,
    2300                 :             :                          int resultFormat)
    2301                 :             : {
    2302         [ #  # ]:           0 :         if (!PQexecStart(conn))
    2303                 :           0 :                 return NULL;
    2304   [ #  #  #  # ]:           0 :         if (!PQsendQueryParams(conn, command,
    2305                 :           0 :                                                    nParams, paramTypes, paramValues, paramLengths,
    2306                 :           0 :                                                    paramFormats, resultFormat))
    2307                 :           0 :                 return NULL;
    2308                 :           0 :         return PQexecFinish(conn);
    2309                 :           0 : }
    2310                 :             : 
    2311                 :             : /*
    2312                 :             :  * PQprepare
    2313                 :             :  *        Creates a prepared statement by issuing a Parse message.
    2314                 :             :  *
    2315                 :             :  * If the query was not even sent, return NULL; conn->errorMessage is set to
    2316                 :             :  * a relevant message.
    2317                 :             :  * If the query was sent, a new PGresult is returned (which could indicate
    2318                 :             :  * either success or failure).
    2319                 :             :  * The user is responsible for freeing the PGresult via PQclear()
    2320                 :             :  * when done with it.
    2321                 :             :  */
    2322                 :             : PGresult *
    2323                 :          14 : PQprepare(PGconn *conn,
    2324                 :             :                   const char *stmtName, const char *query,
    2325                 :             :                   int nParams, const Oid *paramTypes)
    2326                 :             : {
    2327         [ +  + ]:          14 :         if (!PQexecStart(conn))
    2328                 :           3 :                 return NULL;
    2329         [ +  - ]:          11 :         if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
    2330                 :           0 :                 return NULL;
    2331                 :          11 :         return PQexecFinish(conn);
    2332                 :          14 : }
    2333                 :             : 
    2334                 :             : /*
    2335                 :             :  * PQexecPrepared
    2336                 :             :  *              Like PQexec, but execute a previously prepared statement,
    2337                 :             :  *              using extended query protocol so we can pass parameters
    2338                 :             :  */
    2339                 :             : PGresult *
    2340                 :           0 : PQexecPrepared(PGconn *conn,
    2341                 :             :                            const char *stmtName,
    2342                 :             :                            int nParams,
    2343                 :             :                            const char *const *paramValues,
    2344                 :             :                            const int *paramLengths,
    2345                 :             :                            const int *paramFormats,
    2346                 :             :                            int resultFormat)
    2347                 :             : {
    2348         [ #  # ]:           0 :         if (!PQexecStart(conn))
    2349                 :           0 :                 return NULL;
    2350   [ #  #  #  # ]:           0 :         if (!PQsendQueryPrepared(conn, stmtName,
    2351                 :           0 :                                                          nParams, paramValues, paramLengths,
    2352                 :           0 :                                                          paramFormats, resultFormat))
    2353                 :           0 :                 return NULL;
    2354                 :           0 :         return PQexecFinish(conn);
    2355                 :           0 : }
    2356                 :             : 
    2357                 :             : /*
    2358                 :             :  * Common code for PQexec and sibling routines: prepare to send command
    2359                 :             :  */
    2360                 :             : static bool
    2361                 :        7201 : PQexecStart(PGconn *conn)
    2362                 :             : {
    2363                 :        7201 :         PGresult   *result;
    2364                 :             : 
    2365         [ +  - ]:        7201 :         if (!conn)
    2366                 :           0 :                 return false;
    2367                 :             : 
    2368                 :             :         /*
    2369                 :             :          * Since this is the beginning of a query cycle, reset the error state.
    2370                 :             :          * However, in pipeline mode with something already queued, the error
    2371                 :             :          * buffer belongs to that command and we shouldn't clear it.
    2372                 :             :          */
    2373         [ +  + ]:        7201 :         if (conn->cmd_queue_head == NULL)
    2374                 :        7199 :                 pqClearConnErrorState(conn);
    2375                 :             : 
    2376         [ +  + ]:        7201 :         if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    2377                 :             :         {
    2378                 :           3 :                 libpq_append_conn_error(conn, "synchronous command execution functions are not allowed in pipeline mode");
    2379                 :           3 :                 return false;
    2380                 :             :         }
    2381                 :             : 
    2382                 :             :         /*
    2383                 :             :          * Silently discard any prior query result that application didn't eat.
    2384                 :             :          * This is probably poor design, but it's here for backward compatibility.
    2385                 :             :          */
    2386         [ -  + ]:        7198 :         while ((result = PQgetResult(conn)) != NULL)
    2387                 :             :         {
    2388                 :           0 :                 ExecStatusType resultStatus = result->resultStatus;
    2389                 :             : 
    2390                 :           0 :                 PQclear(result);                /* only need its status */
    2391         [ #  # ]:           0 :                 if (resultStatus == PGRES_COPY_IN)
    2392                 :             :                 {
    2393                 :             :                         /* get out of a COPY IN state */
    2394                 :           0 :                         if (PQputCopyEnd(conn,
    2395   [ #  #  #  # ]:           0 :                                                          libpq_gettext("COPY terminated by new PQexec")) < 0)
    2396                 :           0 :                                 return false;
    2397                 :             :                         /* keep waiting to swallow the copy's failure message */
    2398                 :           0 :                 }
    2399         [ #  # ]:           0 :                 else if (resultStatus == PGRES_COPY_OUT)
    2400                 :             :                 {
    2401                 :             :                         /*
    2402                 :             :                          * Get out of a COPY OUT state: we just switch back to BUSY and
    2403                 :             :                          * allow the remaining COPY data to be dropped on the floor.
    2404                 :             :                          */
    2405                 :           0 :                         conn->asyncStatus = PGASYNC_BUSY;
    2406                 :             :                         /* keep waiting to swallow the copy's completion message */
    2407                 :           0 :                 }
    2408         [ #  # ]:           0 :                 else if (resultStatus == PGRES_COPY_BOTH)
    2409                 :             :                 {
    2410                 :             :                         /* We don't allow PQexec during COPY BOTH */
    2411                 :           0 :                         libpq_append_conn_error(conn, "PQexec not allowed during COPY BOTH");
    2412                 :           0 :                         return false;
    2413                 :             :                 }
    2414                 :             :                 /* check for loss of connection, too */
    2415         [ #  # ]:           0 :                 if (conn->status == CONNECTION_BAD)
    2416                 :           0 :                         return false;
    2417         [ #  # ]:           0 :         }
    2418                 :             : 
    2419                 :             :         /* OK to send a command */
    2420                 :        7198 :         return true;
    2421                 :        7201 : }
    2422                 :             : 
    2423                 :             : /*
    2424                 :             :  * Common code for PQexec and sibling routines: wait for command result
    2425                 :             :  */
    2426                 :             : static PGresult *
    2427                 :        7198 : PQexecFinish(PGconn *conn)
    2428                 :             : {
    2429                 :        7198 :         PGresult   *result;
    2430                 :        7198 :         PGresult   *lastResult;
    2431                 :             : 
    2432                 :             :         /*
    2433                 :             :          * For backwards compatibility, return the last result if there are more
    2434                 :             :          * than one.  (We used to have logic here to concatenate successive error
    2435                 :             :          * messages, but now that happens automatically, since conn->errorMessage
    2436                 :             :          * will continue to accumulate errors throughout this loop.)
    2437                 :             :          *
    2438                 :             :          * We have to stop if we see copy in/out/both, however. We will resume
    2439                 :             :          * parsing after application performs the data transfer.
    2440                 :             :          *
    2441                 :             :          * Also stop if the connection is lost (else we'll loop infinitely).
    2442                 :             :          */
    2443                 :        7198 :         lastResult = NULL;
    2444         [ +  + ]:       14396 :         while ((result = PQgetResult(conn)) != NULL)
    2445                 :             :         {
    2446                 :        7198 :                 PQclear(lastResult);
    2447                 :        7198 :                 lastResult = result;
    2448         [ +  - ]:        7198 :                 if (result->resultStatus == PGRES_COPY_IN ||
    2449         [ +  - ]:        7198 :                         result->resultStatus == PGRES_COPY_OUT ||
    2450   [ +  -  -  + ]:        7198 :                         result->resultStatus == PGRES_COPY_BOTH ||
    2451                 :        7198 :                         conn->status == CONNECTION_BAD)
    2452                 :           0 :                         break;
    2453                 :             :         }
    2454                 :             : 
    2455                 :       14396 :         return lastResult;
    2456                 :        7198 : }
    2457                 :             : 
    2458                 :             : /*
    2459                 :             :  * PQdescribePrepared
    2460                 :             :  *        Obtain information about a previously prepared statement
    2461                 :             :  *
    2462                 :             :  * If the query was not even sent, return NULL; conn->errorMessage is set to
    2463                 :             :  * a relevant message.
    2464                 :             :  * If the query was sent, a new PGresult is returned (which could indicate
    2465                 :             :  * either success or failure).  On success, the PGresult contains status
    2466                 :             :  * PGRES_COMMAND_OK, and its parameter and column-heading fields describe
    2467                 :             :  * the statement's inputs and outputs respectively.
    2468                 :             :  * The user is responsible for freeing the PGresult via PQclear()
    2469                 :             :  * when done with it.
    2470                 :             :  */
    2471                 :             : PGresult *
    2472                 :           9 : PQdescribePrepared(PGconn *conn, const char *stmt)
    2473                 :             : {
    2474         [ -  + ]:           9 :         if (!PQexecStart(conn))
    2475                 :           0 :                 return NULL;
    2476         [ +  - ]:           9 :         if (!PQsendTypedCommand(conn, PqMsg_Describe, 'S', stmt))
    2477                 :           0 :                 return NULL;
    2478                 :           9 :         return PQexecFinish(conn);
    2479                 :           9 : }
    2480                 :             : 
    2481                 :             : /*
    2482                 :             :  * PQdescribePortal
    2483                 :             :  *        Obtain information about a previously created portal
    2484                 :             :  *
    2485                 :             :  * This is much like PQdescribePrepared, except that no parameter info is
    2486                 :             :  * returned.  Note that at the moment, libpq doesn't really expose portals
    2487                 :             :  * to the client; but this can be used with a portal created by a SQL
    2488                 :             :  * DECLARE CURSOR command.
    2489                 :             :  */
    2490                 :             : PGresult *
    2491                 :           0 : PQdescribePortal(PGconn *conn, const char *portal)
    2492                 :             : {
    2493         [ #  # ]:           0 :         if (!PQexecStart(conn))
    2494                 :           0 :                 return NULL;
    2495         [ #  # ]:           0 :         if (!PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal))
    2496                 :           0 :                 return NULL;
    2497                 :           0 :         return PQexecFinish(conn);
    2498                 :           0 : }
    2499                 :             : 
    2500                 :             : /*
    2501                 :             :  * PQsendDescribePrepared
    2502                 :             :  *       Submit a Describe Statement command, but don't wait for it to finish
    2503                 :             :  *
    2504                 :             :  * Returns: 1 if successfully submitted
    2505                 :             :  *                      0 if error (conn->errorMessage is set)
    2506                 :             :  */
    2507                 :             : int
    2508                 :           0 : PQsendDescribePrepared(PGconn *conn, const char *stmt)
    2509                 :             : {
    2510                 :           0 :         return PQsendTypedCommand(conn, PqMsg_Describe, 'S', stmt);
    2511                 :             : }
    2512                 :             : 
    2513                 :             : /*
    2514                 :             :  * PQsendDescribePortal
    2515                 :             :  *       Submit a Describe Portal command, but don't wait for it to finish
    2516                 :             :  *
    2517                 :             :  * Returns: 1 if successfully submitted
    2518                 :             :  *                      0 if error (conn->errorMessage is set)
    2519                 :             :  */
    2520                 :             : int
    2521                 :           0 : PQsendDescribePortal(PGconn *conn, const char *portal)
    2522                 :             : {
    2523                 :           0 :         return PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal);
    2524                 :             : }
    2525                 :             : 
    2526                 :             : /*
    2527                 :             :  * PQclosePrepared
    2528                 :             :  *        Close a previously prepared statement
    2529                 :             :  *
    2530                 :             :  * If the query was not even sent, return NULL; conn->errorMessage is set to
    2531                 :             :  * a relevant message.
    2532                 :             :  * If the query was sent, a new PGresult is returned (which could indicate
    2533                 :             :  * either success or failure).  On success, the PGresult contains status
    2534                 :             :  * PGRES_COMMAND_OK. The user is responsible for freeing the PGresult via
    2535                 :             :  * PQclear() when done with it.
    2536                 :             :  */
    2537                 :             : PGresult *
    2538                 :           0 : PQclosePrepared(PGconn *conn, const char *stmt)
    2539                 :             : {
    2540         [ #  # ]:           0 :         if (!PQexecStart(conn))
    2541                 :           0 :                 return NULL;
    2542         [ #  # ]:           0 :         if (!PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt))
    2543                 :           0 :                 return NULL;
    2544                 :           0 :         return PQexecFinish(conn);
    2545                 :           0 : }
    2546                 :             : 
    2547                 :             : /*
    2548                 :             :  * PQclosePortal
    2549                 :             :  *        Close a previously created portal
    2550                 :             :  *
    2551                 :             :  * This is exactly like PQclosePrepared, but for portals.  Note that at the
    2552                 :             :  * moment, libpq doesn't really expose portals to the client; but this can be
    2553                 :             :  * used with a portal created by a SQL DECLARE CURSOR command.
    2554                 :             :  */
    2555                 :             : PGresult *
    2556                 :           0 : PQclosePortal(PGconn *conn, const char *portal)
    2557                 :             : {
    2558         [ #  # ]:           0 :         if (!PQexecStart(conn))
    2559                 :           0 :                 return NULL;
    2560         [ #  # ]:           0 :         if (!PQsendTypedCommand(conn, PqMsg_Close, 'P', portal))
    2561                 :           0 :                 return NULL;
    2562                 :           0 :         return PQexecFinish(conn);
    2563                 :           0 : }
    2564                 :             : 
    2565                 :             : /*
    2566                 :             :  * PQsendClosePrepared
    2567                 :             :  *       Submit a Close Statement command, but don't wait for it to finish
    2568                 :             :  *
    2569                 :             :  * Returns: 1 if successfully submitted
    2570                 :             :  *                      0 if error (conn->errorMessage is set)
    2571                 :             :  */
    2572                 :             : int
    2573                 :           6 : PQsendClosePrepared(PGconn *conn, const char *stmt)
    2574                 :             : {
    2575                 :           6 :         return PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt);
    2576                 :             : }
    2577                 :             : 
    2578                 :             : /*
    2579                 :             :  * PQsendClosePortal
    2580                 :             :  *       Submit a Close Portal command, but don't wait for it to finish
    2581                 :             :  *
    2582                 :             :  * Returns: 1 if successfully submitted
    2583                 :             :  *                      0 if error (conn->errorMessage is set)
    2584                 :             :  */
    2585                 :             : int
    2586                 :           0 : PQsendClosePortal(PGconn *conn, const char *portal)
    2587                 :             : {
    2588                 :           0 :         return PQsendTypedCommand(conn, PqMsg_Close, 'P', portal);
    2589                 :             : }
    2590                 :             : 
    2591                 :             : /*
    2592                 :             :  * PQsendTypedCommand
    2593                 :             :  *       Common code to send a Describe or Close command
    2594                 :             :  *
    2595                 :             :  * Available options for "command" are
    2596                 :             :  *       PqMsg_Close for Close; or
    2597                 :             :  *       PqMsg_Describe for Describe.
    2598                 :             :  *
    2599                 :             :  * Available options for "type" are
    2600                 :             :  *       'S' to run a command on a prepared statement; or
    2601                 :             :  *       'P' to run a command on a portal.
    2602                 :             :  *
    2603                 :             :  * Returns 1 on success and 0 on failure.
    2604                 :             :  */
    2605                 :             : static int
    2606                 :          15 : PQsendTypedCommand(PGconn *conn, char command, char type, const char *target)
    2607                 :             : {
    2608                 :          15 :         PGcmdQueueEntry *entry = NULL;
    2609                 :             : 
    2610                 :             :         /* Treat null target as empty string */
    2611         [ +  - ]:          15 :         if (!target)
    2612                 :           0 :                 target = "";
    2613                 :             : 
    2614         [ +  - ]:          15 :         if (!PQsendQueryStart(conn, true))
    2615                 :           0 :                 return 0;
    2616                 :             : 
    2617                 :          15 :         entry = pqAllocCmdQueueEntry(conn);
    2618         [ +  - ]:          15 :         if (entry == NULL)
    2619                 :           0 :                 return 0;                               /* error msg already set */
    2620                 :             : 
    2621                 :             :         /* construct the Close message */
    2622         [ +  - ]:          15 :         if (pqPutMsgStart(command, conn) < 0 ||
    2623         [ +  - ]:          15 :                 pqPutc(type, conn) < 0 ||
    2624   [ +  -  -  + ]:          15 :                 pqPuts(target, conn) < 0 ||
    2625                 :          15 :                 pqPutMsgEnd(conn) < 0)
    2626                 :           0 :                 goto sendFailed;
    2627                 :             : 
    2628                 :             :         /* construct the Sync message */
    2629         [ +  + ]:          15 :         if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    2630                 :             :         {
    2631   [ +  -  -  + ]:          12 :                 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    2632                 :          12 :                         pqPutMsgEnd(conn) < 0)
    2633                 :           0 :                         goto sendFailed;
    2634                 :          12 :         }
    2635                 :             : 
    2636                 :             :         /* remember if we are doing a Close or a Describe */
    2637         [ +  + ]:          15 :         if (command == PqMsg_Close)
    2638                 :             :         {
    2639                 :           6 :                 entry->queryclass = PGQUERY_CLOSE;
    2640                 :           6 :         }
    2641         [ +  - ]:           9 :         else if (command == PqMsg_Describe)
    2642                 :             :         {
    2643                 :           9 :                 entry->queryclass = PGQUERY_DESCRIBE;
    2644                 :           9 :         }
    2645                 :             :         else
    2646                 :             :         {
    2647                 :           0 :                 libpq_append_conn_error(conn, "unrecognized message type \"%c\"", command);
    2648                 :           0 :                 goto sendFailed;
    2649                 :             :         }
    2650                 :             : 
    2651                 :             :         /*
    2652                 :             :          * Give the data a push (in pipeline mode, only if we're past the size
    2653                 :             :          * threshold).  In nonblock mode, don't complain if we're unable to send
    2654                 :             :          * it all; PQgetResult() will do any additional flushing needed.
    2655                 :             :          */
    2656         [ +  - ]:          15 :         if (pqPipelineFlush(conn) < 0)
    2657                 :           0 :                 goto sendFailed;
    2658                 :             : 
    2659                 :             :         /* OK, it's launched! */
    2660                 :          15 :         pqAppendCmdQueueEntry(conn, entry);
    2661                 :             : 
    2662                 :          15 :         return 1;
    2663                 :             : 
    2664                 :             : sendFailed:
    2665                 :           0 :         pqRecycleCmdQueueEntry(conn, entry);
    2666                 :             :         /* error message should be set up already */
    2667                 :           0 :         return 0;
    2668                 :          15 : }
    2669                 :             : 
    2670                 :             : /*
    2671                 :             :  * PQnotifies
    2672                 :             :  *        returns a PGnotify* structure of the latest async notification
    2673                 :             :  * that has not yet been handled
    2674                 :             :  *
    2675                 :             :  * returns NULL, if there is currently
    2676                 :             :  * no unhandled async notification from the backend
    2677                 :             :  *
    2678                 :             :  * the CALLER is responsible for FREE'ing the structure returned
    2679                 :             :  *
    2680                 :             :  * Note that this function does not read any new data from the socket;
    2681                 :             :  * so usually, caller should call PQconsumeInput() first.
    2682                 :             :  */
    2683                 :             : PGnotify *
    2684                 :       51039 : PQnotifies(PGconn *conn)
    2685                 :             : {
    2686                 :       51039 :         PGnotify   *event;
    2687                 :             : 
    2688         [ +  - ]:       51039 :         if (!conn)
    2689                 :           0 :                 return NULL;
    2690                 :             : 
    2691                 :             :         /* Parse any available data to see if we can extract NOTIFY messages. */
    2692                 :       51039 :         parseInput(conn);
    2693                 :             : 
    2694                 :       51039 :         event = conn->notifyHead;
    2695         [ +  - ]:       51039 :         if (event)
    2696                 :             :         {
    2697                 :           0 :                 conn->notifyHead = event->next;
    2698         [ #  # ]:           0 :                 if (!conn->notifyHead)
    2699                 :           0 :                         conn->notifyTail = NULL;
    2700                 :           0 :                 event->next = NULL;          /* don't let app see the internal state */
    2701                 :           0 :         }
    2702                 :       51039 :         return event;
    2703                 :       51039 : }
    2704                 :             : 
    2705                 :             : /*
    2706                 :             :  * PQputCopyData - send some data to the backend during COPY IN or COPY BOTH
    2707                 :             :  *
    2708                 :             :  * Returns 1 if successful, 0 if data could not be sent (only possible
    2709                 :             :  * in nonblock mode), or -1 if an error occurs.
    2710                 :             :  */
    2711                 :             : int
    2712                 :         131 : PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
    2713                 :             : {
    2714         [ +  - ]:         131 :         if (!conn)
    2715                 :           0 :                 return -1;
    2716   [ -  +  #  # ]:         131 :         if (conn->asyncStatus != PGASYNC_COPY_IN &&
    2717                 :           0 :                 conn->asyncStatus != PGASYNC_COPY_BOTH)
    2718                 :             :         {
    2719                 :           0 :                 libpq_append_conn_error(conn, "no COPY in progress");
    2720                 :           0 :                 return -1;
    2721                 :             :         }
    2722                 :             : 
    2723                 :             :         /*
    2724                 :             :          * Process any NOTICE or NOTIFY messages that might be pending in the
    2725                 :             :          * input buffer.  Since the server might generate many notices during the
    2726                 :             :          * COPY, we want to clean those out reasonably promptly to prevent
    2727                 :             :          * indefinite expansion of the input buffer.  (Note: the actual read of
    2728                 :             :          * input data into the input buffer happens down inside pqSendSome, but
    2729                 :             :          * it's not authorized to get rid of the data again.)
    2730                 :             :          */
    2731                 :         131 :         parseInput(conn);
    2732                 :             : 
    2733         [ -  + ]:         131 :         if (nbytes > 0)
    2734                 :             :         {
    2735                 :             :                 /*
    2736                 :             :                  * Try to flush any previously sent data in preference to growing the
    2737                 :             :                  * output buffer.  If we can't enlarge the buffer enough to hold the
    2738                 :             :                  * data, return 0 in the nonblock case, else hard error. (For
    2739                 :             :                  * simplicity, always assume 5 bytes of overhead.)
    2740                 :             :                  */
    2741         [ +  - ]:         131 :                 if ((conn->outBufSize - conn->outCount - 5) < nbytes)
    2742                 :             :                 {
    2743         [ #  # ]:           0 :                         if (pqFlush(conn) < 0)
    2744                 :           0 :                                 return -1;
    2745   [ #  #  #  # ]:           0 :                         if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes,
    2746                 :           0 :                                                                           conn))
    2747                 :           0 :                                 return pqIsnonblocking(conn) ? 0 : -1;
    2748                 :           0 :                 }
    2749                 :             :                 /* Send the data (too simple to delegate to fe-protocol files) */
    2750         [ +  - ]:         131 :                 if (pqPutMsgStart(PqMsg_CopyData, conn) < 0 ||
    2751   [ +  -  -  + ]:         131 :                         pqPutnchar(buffer, nbytes, conn) < 0 ||
    2752                 :         131 :                         pqPutMsgEnd(conn) < 0)
    2753                 :           0 :                         return -1;
    2754                 :         131 :         }
    2755                 :         131 :         return 1;
    2756                 :         131 : }
    2757                 :             : 
    2758                 :             : /*
    2759                 :             :  * PQputCopyEnd - send EOF indication to the backend during COPY IN
    2760                 :             :  *
    2761                 :             :  * After calling this, use PQgetResult() to check command completion status.
    2762                 :             :  *
    2763                 :             :  * Returns 1 if successful, or -1 if an error occurs.
    2764                 :             :  */
    2765                 :             : int
    2766                 :         132 : PQputCopyEnd(PGconn *conn, const char *errormsg)
    2767                 :             : {
    2768         [ +  - ]:         132 :         if (!conn)
    2769                 :           0 :                 return -1;
    2770   [ -  +  #  # ]:         132 :         if (conn->asyncStatus != PGASYNC_COPY_IN &&
    2771                 :           0 :                 conn->asyncStatus != PGASYNC_COPY_BOTH)
    2772                 :             :         {
    2773                 :           0 :                 libpq_append_conn_error(conn, "no COPY in progress");
    2774                 :           0 :                 return -1;
    2775                 :             :         }
    2776                 :             : 
    2777                 :             :         /*
    2778                 :             :          * Send the COPY END indicator.  This is simple enough that we don't
    2779                 :             :          * bother delegating it to the fe-protocol files.
    2780                 :             :          */
    2781         [ -  + ]:         132 :         if (errormsg)
    2782                 :             :         {
    2783                 :             :                 /* Send COPY FAIL */
    2784         [ #  # ]:           0 :                 if (pqPutMsgStart(PqMsg_CopyFail, conn) < 0 ||
    2785   [ #  #  #  # ]:           0 :                         pqPuts(errormsg, conn) < 0 ||
    2786                 :           0 :                         pqPutMsgEnd(conn) < 0)
    2787                 :           0 :                         return -1;
    2788                 :           0 :         }
    2789                 :             :         else
    2790                 :             :         {
    2791                 :             :                 /* Send COPY DONE */
    2792   [ +  -  -  + ]:         132 :                 if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
    2793                 :         132 :                         pqPutMsgEnd(conn) < 0)
    2794                 :           0 :                         return -1;
    2795                 :             :         }
    2796                 :             : 
    2797                 :             :         /*
    2798                 :             :          * If we sent the COPY command in extended-query mode, we must issue a
    2799                 :             :          * Sync as well.
    2800                 :             :          */
    2801   [ +  -  +  - ]:         132 :         if (conn->cmd_queue_head &&
    2802                 :         132 :                 conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
    2803                 :             :         {
    2804   [ #  #  #  # ]:           0 :                 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    2805                 :           0 :                         pqPutMsgEnd(conn) < 0)
    2806                 :           0 :                         return -1;
    2807                 :           0 :         }
    2808                 :             : 
    2809                 :             :         /* Return to active duty */
    2810         [ -  + ]:         132 :         if (conn->asyncStatus == PGASYNC_COPY_BOTH)
    2811                 :           0 :                 conn->asyncStatus = PGASYNC_COPY_OUT;
    2812                 :             :         else
    2813                 :         132 :                 conn->asyncStatus = PGASYNC_BUSY;
    2814                 :             : 
    2815                 :             :         /* Try to flush data */
    2816         [ +  - ]:         132 :         if (pqFlush(conn) < 0)
    2817                 :           0 :                 return -1;
    2818                 :             : 
    2819                 :         132 :         return 1;
    2820                 :         132 : }
    2821                 :             : 
    2822                 :             : /*
    2823                 :             :  * PQgetCopyData - read a row of data from the backend during COPY OUT
    2824                 :             :  * or COPY BOTH
    2825                 :             :  *
    2826                 :             :  * If successful, sets *buffer to point to a malloc'd row of data, and
    2827                 :             :  * returns row length (always > 0) as result.
    2828                 :             :  * Returns 0 if no row available yet (only possible if async is true),
    2829                 :             :  * -1 if end of copy (consult PQgetResult), or -2 if error (consult
    2830                 :             :  * PQerrorMessage).
    2831                 :             :  */
    2832                 :             : int
    2833                 :         410 : PQgetCopyData(PGconn *conn, char **buffer, int async)
    2834                 :             : {
    2835                 :         410 :         *buffer = NULL;                         /* for all failure cases */
    2836         [ +  - ]:         410 :         if (!conn)
    2837                 :           0 :                 return -2;
    2838   [ -  +  #  # ]:         410 :         if (conn->asyncStatus != PGASYNC_COPY_OUT &&
    2839                 :           0 :                 conn->asyncStatus != PGASYNC_COPY_BOTH)
    2840                 :             :         {
    2841                 :           0 :                 libpq_append_conn_error(conn, "no COPY in progress");
    2842                 :           0 :                 return -2;
    2843                 :             :         }
    2844                 :         410 :         return pqGetCopyData3(conn, buffer, async);
    2845                 :         410 : }
    2846                 :             : 
    2847                 :             : /*
    2848                 :             :  * PQgetline - gets a newline-terminated string from the backend.
    2849                 :             :  *
    2850                 :             :  * Chiefly here so that applications can use "COPY <rel> to stdout"
    2851                 :             :  * and read the output string.  Returns a null-terminated string in `buffer`.
    2852                 :             :  *
    2853                 :             :  * XXX this routine is now deprecated, because it can't handle binary data.
    2854                 :             :  * If called during a COPY BINARY we return EOF.
    2855                 :             :  *
    2856                 :             :  * PQgetline reads up to `length`-1 characters (like fgets(3)) but strips
    2857                 :             :  * the terminating \n (like gets(3)).
    2858                 :             :  *
    2859                 :             :  * CAUTION: the caller is responsible for detecting the end-of-copy signal
    2860                 :             :  * (a line containing just "\.") when using this routine.
    2861                 :             :  *
    2862                 :             :  * RETURNS:
    2863                 :             :  *              EOF if error (eg, invalid arguments are given)
    2864                 :             :  *              0 if EOL is reached (i.e., \n has been read)
    2865                 :             :  *                              (this is required for backward-compatibility -- this
    2866                 :             :  *                               routine used to always return EOF or 0, assuming that
    2867                 :             :  *                               the line ended within `length` bytes.)
    2868                 :             :  *              1 in other cases (i.e., the buffer was filled before \n is reached)
    2869                 :             :  */
    2870                 :             : int
    2871                 :           0 : PQgetline(PGconn *conn, char *buffer, int length)
    2872                 :             : {
    2873   [ #  #  #  # ]:           0 :         if (!buffer || length <= 0)
    2874                 :           0 :                 return EOF;
    2875                 :           0 :         *buffer = '\0';
    2876                 :             :         /* length must be at least 3 to hold the \. terminator! */
    2877         [ #  # ]:           0 :         if (length < 3)
    2878                 :           0 :                 return EOF;
    2879                 :             : 
    2880         [ #  # ]:           0 :         if (!conn)
    2881                 :           0 :                 return EOF;
    2882                 :             : 
    2883                 :           0 :         return pqGetline3(conn, buffer, length);
    2884                 :           0 : }
    2885                 :             : 
    2886                 :             : /*
    2887                 :             :  * PQgetlineAsync - gets a COPY data row without blocking.
    2888                 :             :  *
    2889                 :             :  * This routine is for applications that want to do "COPY <rel> to stdout"
    2890                 :             :  * asynchronously, that is without blocking.  Having issued the COPY command
    2891                 :             :  * and gotten a PGRES_COPY_OUT response, the app should call PQconsumeInput
    2892                 :             :  * and this routine until the end-of-data signal is detected.  Unlike
    2893                 :             :  * PQgetline, this routine takes responsibility for detecting end-of-data.
    2894                 :             :  *
    2895                 :             :  * On each call, PQgetlineAsync will return data if a complete data row
    2896                 :             :  * is available in libpq's input buffer.  Otherwise, no data is returned
    2897                 :             :  * until the rest of the row arrives.
    2898                 :             :  *
    2899                 :             :  * If -1 is returned, the end-of-data signal has been recognized (and removed
    2900                 :             :  * from libpq's input buffer).  The caller *must* next call PQendcopy and
    2901                 :             :  * then return to normal processing.
    2902                 :             :  *
    2903                 :             :  * RETURNS:
    2904                 :             :  *       -1    if the end-of-copy-data marker has been recognized
    2905                 :             :  *       0         if no data is available
    2906                 :             :  *       >0    the number of bytes returned.
    2907                 :             :  *
    2908                 :             :  * The data returned will not extend beyond a data-row boundary.  If possible
    2909                 :             :  * a whole row will be returned at one time.  But if the buffer offered by
    2910                 :             :  * the caller is too small to hold a row sent by the backend, then a partial
    2911                 :             :  * data row will be returned.  In text mode this can be detected by testing
    2912                 :             :  * whether the last returned byte is '\n' or not.
    2913                 :             :  *
    2914                 :             :  * The returned data is *not* null-terminated.
    2915                 :             :  */
    2916                 :             : 
    2917                 :             : int
    2918                 :           0 : PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
    2919                 :             : {
    2920         [ #  # ]:           0 :         if (!conn)
    2921                 :           0 :                 return -1;
    2922                 :             : 
    2923                 :           0 :         return pqGetlineAsync3(conn, buffer, bufsize);
    2924                 :           0 : }
    2925                 :             : 
    2926                 :             : /*
    2927                 :             :  * PQputline -- sends a string to the backend during COPY IN.
    2928                 :             :  * Returns 0 if OK, EOF if not.
    2929                 :             :  *
    2930                 :             :  * This is deprecated primarily because the return convention doesn't allow
    2931                 :             :  * caller to tell the difference between a hard error and a nonblock-mode
    2932                 :             :  * send failure.
    2933                 :             :  */
    2934                 :             : int
    2935                 :           0 : PQputline(PGconn *conn, const char *string)
    2936                 :             : {
    2937                 :           0 :         return PQputnbytes(conn, string, strlen(string));
    2938                 :             : }
    2939                 :             : 
    2940                 :             : /*
    2941                 :             :  * PQputnbytes -- like PQputline, but buffer need not be null-terminated.
    2942                 :             :  * Returns 0 if OK, EOF if not.
    2943                 :             :  */
    2944                 :             : int
    2945                 :           0 : PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
    2946                 :             : {
    2947         [ #  # ]:           0 :         if (PQputCopyData(conn, buffer, nbytes) > 0)
    2948                 :           0 :                 return 0;
    2949                 :             :         else
    2950                 :           0 :                 return EOF;
    2951                 :           0 : }
    2952                 :             : 
    2953                 :             : /*
    2954                 :             :  * PQendcopy
    2955                 :             :  *              After completing the data transfer portion of a copy in/out,
    2956                 :             :  *              the application must call this routine to finish the command protocol.
    2957                 :             :  *
    2958                 :             :  * This is deprecated; it's cleaner to use PQgetResult to get the transfer
    2959                 :             :  * status.
    2960                 :             :  *
    2961                 :             :  * RETURNS:
    2962                 :             :  *              0 on success
    2963                 :             :  *              1 on failure
    2964                 :             :  */
    2965                 :             : int
    2966                 :           0 : PQendcopy(PGconn *conn)
    2967                 :             : {
    2968         [ #  # ]:           0 :         if (!conn)
    2969                 :           0 :                 return 0;
    2970                 :             : 
    2971                 :           0 :         return pqEndcopy3(conn);
    2972                 :           0 : }
    2973                 :             : 
    2974                 :             : 
    2975                 :             : /* ----------------
    2976                 :             :  *              PQfn -  Send a function call to the POSTGRES backend.
    2977                 :             :  *
    2978                 :             :  *              conn                    : backend connection
    2979                 :             :  *              fnid                    : OID of function to be called
    2980                 :             :  *              result_buf              : pointer to result buffer
    2981                 :             :  *              result_len              : actual length of result is returned here
    2982                 :             :  *              result_is_int   : If the result is an integer, this must be 1,
    2983                 :             :  *                                                otherwise this should be 0
    2984                 :             :  *              args                    : pointer to an array of function arguments
    2985                 :             :  *                                                (each has length, if integer, and value/pointer)
    2986                 :             :  *              nargs                   : # of arguments in args array.
    2987                 :             :  *
    2988                 :             :  * RETURNS
    2989                 :             :  *              PGresult with status = PGRES_COMMAND_OK if successful.
    2990                 :             :  *                      *result_len is > 0 if there is a return value, 0 if not.
    2991                 :             :  *              PGresult with status = PGRES_FATAL_ERROR if backend returns an error.
    2992                 :             :  *              NULL on communications failure.  conn->errorMessage will be set.
    2993                 :             :  * ----------------
    2994                 :             :  */
    2995                 :             : 
    2996                 :             : PGresult *
    2997                 :         259 : PQfn(PGconn *conn,
    2998                 :             :          int fnid,
    2999                 :             :          int *result_buf,
    3000                 :             :          int *result_len,
    3001                 :             :          int result_is_int,
    3002                 :             :          const PQArgBlock *args,
    3003                 :             :          int nargs)
    3004                 :             : {
    3005                 :         259 :         *result_len = 0;
    3006                 :             : 
    3007         [ +  - ]:         259 :         if (!conn)
    3008                 :           0 :                 return NULL;
    3009                 :             : 
    3010                 :             :         /*
    3011                 :             :          * Since this is the beginning of a query cycle, reset the error state.
    3012                 :             :          * However, in pipeline mode with something already queued, the error
    3013                 :             :          * buffer belongs to that command and we shouldn't clear it.
    3014                 :             :          */
    3015         [ -  + ]:         259 :         if (conn->cmd_queue_head == NULL)
    3016                 :         259 :                 pqClearConnErrorState(conn);
    3017                 :             : 
    3018         [ -  + ]:         259 :         if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    3019                 :             :         {
    3020                 :           0 :                 libpq_append_conn_error(conn, "%s not allowed in pipeline mode", "PQfn");
    3021                 :           0 :                 return NULL;
    3022                 :             :         }
    3023                 :             : 
    3024   [ +  -  +  -  :         518 :         if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
                   -  + ]
    3025         [ +  - ]:         259 :                 pgHavePendingResult(conn))
    3026                 :             :         {
    3027                 :           0 :                 libpq_append_conn_error(conn, "connection in wrong state");
    3028                 :           0 :                 return NULL;
    3029                 :             :         }
    3030                 :             : 
    3031                 :         518 :         return pqFunctionCall3(conn, fnid,
    3032                 :         259 :                                                    result_buf, result_len,
    3033                 :         259 :                                                    result_is_int,
    3034                 :         259 :                                                    args, nargs);
    3035                 :         259 : }
    3036                 :             : 
    3037                 :             : /* ====== Pipeline mode support ======== */
    3038                 :             : 
    3039                 :             : /*
    3040                 :             :  * PQenterPipelineMode
    3041                 :             :  *              Put an idle connection in pipeline mode.
    3042                 :             :  *
    3043                 :             :  * Returns 1 on success. On failure, errorMessage is set and 0 is returned.
    3044                 :             :  *
    3045                 :             :  * Commands submitted after this can be pipelined on the connection;
    3046                 :             :  * there's no requirement to wait for one to finish before the next is
    3047                 :             :  * dispatched.
    3048                 :             :  *
    3049                 :             :  * Queuing of a new query or syncing during COPY is not allowed.
    3050                 :             :  *
    3051                 :             :  * A set of commands is terminated by a PQpipelineSync.  Multiple sync
    3052                 :             :  * points can be established while in pipeline mode.  Pipeline mode can
    3053                 :             :  * be exited by calling PQexitPipelineMode() once all results are processed.
    3054                 :             :  *
    3055                 :             :  * This doesn't actually send anything on the wire, it just puts libpq
    3056                 :             :  * into a state where it can pipeline work.
    3057                 :             :  */
    3058                 :             : int
    3059                 :          47 : PQenterPipelineMode(PGconn *conn)
    3060                 :             : {
    3061         [ +  - ]:          47 :         if (!conn)
    3062                 :           0 :                 return 0;
    3063                 :             : 
    3064                 :             :         /* succeed with no action if already in pipeline mode */
    3065         [ +  + ]:          47 :         if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    3066                 :           1 :                 return 1;
    3067                 :             : 
    3068         [ -  + ]:          46 :         if (conn->asyncStatus != PGASYNC_IDLE)
    3069                 :             :         {
    3070                 :           0 :                 libpq_append_conn_error(conn, "cannot enter pipeline mode, connection not idle");
    3071                 :           0 :                 return 0;
    3072                 :             :         }
    3073                 :             : 
    3074                 :          46 :         conn->pipelineStatus = PQ_PIPELINE_ON;
    3075                 :             : 
    3076                 :          46 :         return 1;
    3077                 :          47 : }
    3078                 :             : 
    3079                 :             : /*
    3080                 :             :  * PQexitPipelineMode
    3081                 :             :  *              End pipeline mode and return to normal command mode.
    3082                 :             :  *
    3083                 :             :  * Returns 1 in success (pipeline mode successfully ended, or not in pipeline
    3084                 :             :  * mode).
    3085                 :             :  *
    3086                 :             :  * Returns 0 if in pipeline mode and cannot be ended yet.  Error message will
    3087                 :             :  * be set.
    3088                 :             :  */
    3089                 :             : int
    3090                 :          46 : PQexitPipelineMode(PGconn *conn)
    3091                 :             : {
    3092         [ +  - ]:          46 :         if (!conn)
    3093                 :           0 :                 return 0;
    3094                 :             : 
    3095         [ -  + ]:          46 :         if (conn->pipelineStatus == PQ_PIPELINE_OFF &&
    3096         [ #  # ]:           0 :                 (conn->asyncStatus == PGASYNC_IDLE ||
    3097         [ #  # ]:           0 :                  conn->asyncStatus == PGASYNC_PIPELINE_IDLE) &&
    3098                 :           0 :                 conn->cmd_queue_head == NULL)
    3099                 :           0 :                 return 1;
    3100                 :             : 
    3101   [ -  -  -  +  :          46 :         switch (conn->asyncStatus)
                      - ]
    3102                 :             :         {
    3103                 :             :                 case PGASYNC_READY:
    3104                 :             :                 case PGASYNC_READY_MORE:
    3105                 :             :                         /* there are some uncollected results */
    3106                 :           0 :                         libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results");
    3107                 :           0 :                         return 0;
    3108                 :             : 
    3109                 :             :                 case PGASYNC_BUSY:
    3110                 :           0 :                         libpq_append_conn_error(conn, "cannot exit pipeline mode while busy");
    3111                 :           0 :                         return 0;
    3112                 :             : 
    3113                 :             :                 case PGASYNC_IDLE:
    3114                 :             :                 case PGASYNC_PIPELINE_IDLE:
    3115                 :             :                         /* OK */
    3116                 :          46 :                         break;
    3117                 :             : 
    3118                 :             :                 case PGASYNC_COPY_IN:
    3119                 :             :                 case PGASYNC_COPY_OUT:
    3120                 :             :                 case PGASYNC_COPY_BOTH:
    3121                 :           0 :                         libpq_append_conn_error(conn, "cannot exit pipeline mode while in COPY");
    3122                 :           0 :         }
    3123                 :             : 
    3124                 :             :         /* still work to process */
    3125         [ -  + ]:          46 :         if (conn->cmd_queue_head != NULL)
    3126                 :             :         {
    3127                 :           0 :                 libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results");
    3128                 :           0 :                 return 0;
    3129                 :             :         }
    3130                 :             : 
    3131                 :          46 :         conn->pipelineStatus = PQ_PIPELINE_OFF;
    3132                 :          46 :         conn->asyncStatus = PGASYNC_IDLE;
    3133                 :             : 
    3134                 :             :         /* Flush any pending data in out buffer */
    3135         [ -  + ]:          46 :         if (pqFlush(conn) < 0)
    3136                 :           0 :                 return 0;                               /* error message is setup already */
    3137                 :          46 :         return 1;
    3138                 :          46 : }
    3139                 :             : 
    3140                 :             : /*
    3141                 :             :  * pqCommandQueueAdvance
    3142                 :             :  *              Remove one query from the command queue, if appropriate.
    3143                 :             :  *
    3144                 :             :  * If we have received all results corresponding to the head element
    3145                 :             :  * in the command queue, remove it.
    3146                 :             :  *
    3147                 :             :  * In simple query protocol we must not advance the command queue until the
    3148                 :             :  * ReadyForQuery message has been received.  This is because in simple mode a
    3149                 :             :  * command can have multiple queries, and we must process result for all of
    3150                 :             :  * them before moving on to the next command.
    3151                 :             :  *
    3152                 :             :  * Another consideration is synchronization during error processing in
    3153                 :             :  * extended query protocol: we refuse to advance the queue past a SYNC queue
    3154                 :             :  * element, unless the result we've received is also a SYNC.  In particular
    3155                 :             :  * this protects us from advancing when an error is received at an
    3156                 :             :  * inappropriate moment.
    3157                 :             :  */
    3158                 :             : void
    3159                 :      116519 : pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
    3160                 :             : {
    3161                 :      116519 :         PGcmdQueueEntry *prevquery;
    3162                 :             : 
    3163         [ +  + ]:      116519 :         if (conn->cmd_queue_head == NULL)
    3164                 :         361 :                 return;
    3165                 :             : 
    3166                 :             :         /*
    3167                 :             :          * If processing a query of simple query protocol, we only advance the
    3168                 :             :          * queue when we receive the ReadyForQuery message for it.
    3169                 :             :          */
    3170   [ +  +  +  + ]:      116158 :         if (conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE && !isReadyForQuery)
    3171                 :       58019 :                 return;
    3172                 :             : 
    3173                 :             :         /*
    3174                 :             :          * If we're waiting for a SYNC, don't advance the queue until we get one.
    3175                 :             :          */
    3176   [ +  +  +  - ]:       58139 :         if (conn->cmd_queue_head->queryclass == PGQUERY_SYNC && !gotSync)
    3177                 :           0 :                 return;
    3178                 :             : 
    3179                 :             :         /* delink element from queue */
    3180                 :       58139 :         prevquery = conn->cmd_queue_head;
    3181                 :       58139 :         conn->cmd_queue_head = conn->cmd_queue_head->next;
    3182                 :             : 
    3183                 :             :         /* If the queue is now empty, reset the tail too */
    3184         [ +  + ]:       58139 :         if (conn->cmd_queue_head == NULL)
    3185                 :       58010 :                 conn->cmd_queue_tail = NULL;
    3186                 :             : 
    3187                 :             :         /* and make the queue element recyclable */
    3188                 :       58139 :         prevquery->next = NULL;
    3189                 :       58139 :         pqRecycleCmdQueueEntry(conn, prevquery);
    3190         [ -  + ]:      116519 : }
    3191                 :             : 
    3192                 :             : /*
    3193                 :             :  * pqPipelineProcessQueue: subroutine for PQgetResult
    3194                 :             :  *              In pipeline mode, start processing the results of the next query in the queue.
    3195                 :             :  */
    3196                 :             : static void
    3197                 :         189 : pqPipelineProcessQueue(PGconn *conn)
    3198                 :             : {
    3199   [ -  -  +  + ]:         189 :         switch (conn->asyncStatus)
    3200                 :             :         {
    3201                 :             :                 case PGASYNC_COPY_IN:
    3202                 :             :                 case PGASYNC_COPY_OUT:
    3203                 :             :                 case PGASYNC_COPY_BOTH:
    3204                 :             :                 case PGASYNC_READY:
    3205                 :             :                 case PGASYNC_READY_MORE:
    3206                 :             :                 case PGASYNC_BUSY:
    3207                 :             :                         /* client still has to process current query or results */
    3208                 :           0 :                         return;
    3209                 :             : 
    3210                 :             :                 case PGASYNC_IDLE:
    3211                 :             : 
    3212                 :             :                         /*
    3213                 :             :                          * If we're in IDLE mode and there's some command in the queue,
    3214                 :             :                          * get us into PIPELINE_IDLE mode and process normally.  Otherwise
    3215                 :             :                          * there's nothing for us to do.
    3216                 :             :                          */
    3217         [ +  - ]:           3 :                         if (conn->cmd_queue_head != NULL)
    3218                 :             :                         {
    3219                 :           3 :                                 conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
    3220                 :           3 :                                 break;
    3221                 :             :                         }
    3222                 :           0 :                         return;
    3223                 :             : 
    3224                 :             :                 case PGASYNC_PIPELINE_IDLE:
    3225         [ +  - ]:         186 :                         Assert(conn->pipelineStatus != PQ_PIPELINE_OFF);
    3226                 :             :                         /* next query please */
    3227                 :         186 :                         break;
    3228                 :             :         }
    3229                 :             : 
    3230                 :             :         /*
    3231                 :             :          * Reset partial-result mode.  (Client has to set it up for each query, if
    3232                 :             :          * desired.)
    3233                 :             :          */
    3234                 :         189 :         conn->partialResMode = false;
    3235                 :         189 :         conn->singleRowMode = false;
    3236                 :         189 :         conn->maxChunkSize = 0;
    3237                 :             : 
    3238                 :             :         /*
    3239                 :             :          * If there are no further commands to process in the queue, get us in
    3240                 :             :          * "real idle" mode now.
    3241                 :             :          */
    3242         [ +  + ]:         189 :         if (conn->cmd_queue_head == NULL)
    3243                 :             :         {
    3244                 :          57 :                 conn->asyncStatus = PGASYNC_IDLE;
    3245                 :          57 :                 return;
    3246                 :             :         }
    3247                 :             : 
    3248                 :             :         /*
    3249                 :             :          * Reset the error state.  This and the next couple of steps correspond to
    3250                 :             :          * what PQsendQueryStart didn't do for this query.
    3251                 :             :          */
    3252                 :         132 :         pqClearConnErrorState(conn);
    3253                 :             : 
    3254                 :             :         /* Initialize async result-accumulation state */
    3255                 :         132 :         pqClearAsyncResult(conn);
    3256                 :             : 
    3257   [ +  +  +  + ]:         132 :         if (conn->pipelineStatus == PQ_PIPELINE_ABORTED &&
    3258                 :          35 :                 conn->cmd_queue_head->queryclass != PGQUERY_SYNC)
    3259                 :             :         {
    3260                 :             :                 /*
    3261                 :             :                  * In an aborted pipeline we don't get anything from the server for
    3262                 :             :                  * each result; we're just discarding commands from the queue until we
    3263                 :             :                  * get to the next sync from the server.
    3264                 :             :                  *
    3265                 :             :                  * The PGRES_PIPELINE_ABORTED results tell the client that its queries
    3266                 :             :                  * got aborted.
    3267                 :             :                  */
    3268                 :          22 :                 conn->result = PQmakeEmptyPGresult(conn, PGRES_PIPELINE_ABORTED);
    3269         [ +  - ]:          22 :                 if (!conn->result)
    3270                 :             :                 {
    3271                 :           0 :                         libpq_append_conn_error(conn, "out of memory");
    3272                 :           0 :                         pqSaveErrorResult(conn);
    3273                 :           0 :                         return;
    3274                 :             :                 }
    3275                 :          22 :                 conn->asyncStatus = PGASYNC_READY;
    3276                 :          22 :         }
    3277                 :             :         else
    3278                 :             :         {
    3279                 :             :                 /* allow parsing to continue */
    3280                 :         110 :                 conn->asyncStatus = PGASYNC_BUSY;
    3281                 :             :         }
    3282                 :         189 : }
    3283                 :             : 
    3284                 :             : /*
    3285                 :             :  * PQpipelineSync
    3286                 :             :  *              Send a Sync message as part of a pipeline, and flush to server
    3287                 :             :  */
    3288                 :             : int
    3289                 :          47 : PQpipelineSync(PGconn *conn)
    3290                 :             : {
    3291                 :          47 :         return pqPipelineSyncInternal(conn, true);
    3292                 :             : }
    3293                 :             : 
    3294                 :             : /*
    3295                 :             :  * PQsendPipelineSync
    3296                 :             :  *              Send a Sync message as part of a pipeline, without flushing to server
    3297                 :             :  */
    3298                 :             : int
    3299                 :          17 : PQsendPipelineSync(PGconn *conn)
    3300                 :             : {
    3301                 :          17 :         return pqPipelineSyncInternal(conn, false);
    3302                 :             : }
    3303                 :             : 
    3304                 :             : /*
    3305                 :             :  * Workhorse function for PQpipelineSync and PQsendPipelineSync.
    3306                 :             :  *
    3307                 :             :  * immediate_flush controls if the flush happens immediately after sending the
    3308                 :             :  * Sync message or not.
    3309                 :             :  */
    3310                 :             : static int
    3311                 :          64 : pqPipelineSyncInternal(PGconn *conn, bool immediate_flush)
    3312                 :             : {
    3313                 :          64 :         PGcmdQueueEntry *entry;
    3314                 :             : 
    3315         [ +  - ]:          64 :         if (!conn)
    3316                 :           0 :                 return 0;
    3317                 :             : 
    3318         [ +  + ]:          64 :         if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    3319                 :             :         {
    3320                 :           1 :                 libpq_append_conn_error(conn, "cannot send pipeline when not in pipeline mode");
    3321                 :           1 :                 return 0;
    3322                 :             :         }
    3323                 :             : 
    3324      [ +  -  - ]:          63 :         switch (conn->asyncStatus)
    3325                 :             :         {
    3326                 :             :                 case PGASYNC_COPY_IN:
    3327                 :             :                 case PGASYNC_COPY_OUT:
    3328                 :             :                 case PGASYNC_COPY_BOTH:
    3329                 :             :                         /* should be unreachable */
    3330                 :           0 :                         appendPQExpBufferStr(&conn->errorMessage,
    3331                 :             :                                                                  "internal error: cannot send pipeline while in COPY\n");
    3332                 :           0 :                         return 0;
    3333                 :             :                 case PGASYNC_READY:
    3334                 :             :                 case PGASYNC_READY_MORE:
    3335                 :             :                 case PGASYNC_BUSY:
    3336                 :             :                 case PGASYNC_IDLE:
    3337                 :             :                 case PGASYNC_PIPELINE_IDLE:
    3338                 :             :                         /* OK to send sync */
    3339                 :          63 :                         break;
    3340                 :             :         }
    3341                 :             : 
    3342                 :          63 :         entry = pqAllocCmdQueueEntry(conn);
    3343         [ +  - ]:          63 :         if (entry == NULL)
    3344                 :           0 :                 return 0;                               /* error msg already set */
    3345                 :             : 
    3346                 :          63 :         entry->queryclass = PGQUERY_SYNC;
    3347                 :          63 :         entry->query = NULL;
    3348                 :             : 
    3349                 :             :         /* construct the Sync message */
    3350   [ +  -  -  + ]:          63 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    3351                 :          63 :                 pqPutMsgEnd(conn) < 0)
    3352                 :           0 :                 goto sendFailed;
    3353                 :             : 
    3354                 :             :         /*
    3355                 :             :          * Give the data a push.  In nonblock mode, don't complain if we're unable
    3356                 :             :          * to send it all; PQgetResult() will do any additional flushing needed.
    3357                 :             :          * If immediate_flush is disabled, the data is pushed if we are past the
    3358                 :             :          * size threshold.
    3359                 :             :          */
    3360         [ +  + ]:          63 :         if (immediate_flush)
    3361                 :             :         {
    3362         [ +  - ]:          46 :                 if (pqFlush(conn) < 0)
    3363                 :           0 :                         goto sendFailed;
    3364                 :          46 :         }
    3365                 :             :         else
    3366                 :             :         {
    3367         [ +  - ]:          17 :                 if (pqPipelineFlush(conn) < 0)
    3368                 :           0 :                         goto sendFailed;
    3369                 :             :         }
    3370                 :             : 
    3371                 :             :         /* OK, it's launched! */
    3372                 :          63 :         pqAppendCmdQueueEntry(conn, entry);
    3373                 :             : 
    3374                 :          63 :         return 1;
    3375                 :             : 
    3376                 :             : sendFailed:
    3377                 :           0 :         pqRecycleCmdQueueEntry(conn, entry);
    3378                 :             :         /* error message should be set up already */
    3379                 :           0 :         return 0;
    3380                 :          64 : }
    3381                 :             : 
    3382                 :             : /*
    3383                 :             :  * PQsendFlushRequest
    3384                 :             :  *              Send request for server to flush its buffer.  Useful in pipeline
    3385                 :             :  *              mode when a sync point is not desired.
    3386                 :             :  */
    3387                 :             : int
    3388                 :           9 : PQsendFlushRequest(PGconn *conn)
    3389                 :             : {
    3390         [ +  - ]:           9 :         if (!conn)
    3391                 :           0 :                 return 0;
    3392                 :             : 
    3393                 :             :         /* Don't try to send if we know there's no live connection. */
    3394         [ -  + ]:           9 :         if (conn->status != CONNECTION_OK)
    3395                 :             :         {
    3396                 :           0 :                 libpq_append_conn_error(conn, "no connection to the server");
    3397                 :           0 :                 return 0;
    3398                 :             :         }
    3399                 :             : 
    3400                 :             :         /* Can't send while already busy, either, unless enqueuing for later */
    3401   [ +  -  +  - ]:           9 :         if (conn->asyncStatus != PGASYNC_IDLE &&
    3402                 :           9 :                 conn->pipelineStatus == PQ_PIPELINE_OFF)
    3403                 :             :         {
    3404                 :           0 :                 libpq_append_conn_error(conn, "another command is already in progress");
    3405                 :           0 :                 return 0;
    3406                 :             :         }
    3407                 :             : 
    3408   [ +  -  -  + ]:           9 :         if (pqPutMsgStart(PqMsg_Flush, conn) < 0 ||
    3409                 :           9 :                 pqPutMsgEnd(conn) < 0)
    3410                 :             :         {
    3411                 :           0 :                 return 0;
    3412                 :             :         }
    3413                 :             : 
    3414                 :             :         /*
    3415                 :             :          * Give the data a push (in pipeline mode, only if we're past the size
    3416                 :             :          * threshold).  In nonblock mode, don't complain if we're unable to send
    3417                 :             :          * it all; PQgetResult() will do any additional flushing needed.
    3418                 :             :          */
    3419         [ +  - ]:           9 :         if (pqPipelineFlush(conn) < 0)
    3420                 :           0 :                 return 0;
    3421                 :             : 
    3422                 :           9 :         return 1;
    3423                 :           9 : }
    3424                 :             : 
    3425                 :             : /* ====== accessor funcs for PGresult ======== */
    3426                 :             : 
    3427                 :             : ExecStatusType
    3428                 :      293618 : PQresultStatus(const PGresult *res)
    3429                 :             : {
    3430         [ +  + ]:      293618 :         if (!res)
    3431                 :          38 :                 return PGRES_FATAL_ERROR;
    3432                 :      293580 :         return res->resultStatus;
    3433                 :      293618 : }
    3434                 :             : 
    3435                 :             : char *
    3436                 :           0 : PQresStatus(ExecStatusType status)
    3437                 :             : {
    3438         [ #  # ]:           0 :         if ((unsigned int) status >= lengthof(pgresStatus))
    3439                 :           0 :                 return libpq_gettext("invalid ExecStatusType code");
    3440                 :           0 :         return pgresStatus[status];
    3441                 :           0 : }
    3442                 :             : 
    3443                 :             : char *
    3444                 :        9600 : PQresultErrorMessage(const PGresult *res)
    3445                 :             : {
    3446   [ +  -  -  + ]:        9600 :         if (!res || !res->errMsg)
    3447                 :           0 :                 return "";
    3448                 :        9600 :         return res->errMsg;
    3449                 :        9600 : }
    3450                 :             : 
    3451                 :             : char *
    3452                 :           0 : PQresultVerboseErrorMessage(const PGresult *res,
    3453                 :             :                                                         PGVerbosity verbosity,
    3454                 :             :                                                         PGContextVisibility show_context)
    3455                 :             : {
    3456                 :           0 :         PQExpBufferData workBuf;
    3457                 :             : 
    3458                 :             :         /*
    3459                 :             :          * Because the caller is expected to free the result string, we must
    3460                 :             :          * strdup any constant result.  We use plain strdup and document that
    3461                 :             :          * callers should expect NULL if out-of-memory.
    3462                 :             :          */
    3463   [ #  #  #  # ]:           0 :         if (!res ||
    3464         [ #  # ]:           0 :                 (res->resultStatus != PGRES_FATAL_ERROR &&
    3465                 :           0 :                  res->resultStatus != PGRES_NONFATAL_ERROR))
    3466                 :           0 :                 return strdup(libpq_gettext("PGresult is not an error result\n"));
    3467                 :             : 
    3468                 :           0 :         initPQExpBuffer(&workBuf);
    3469                 :             : 
    3470                 :           0 :         pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
    3471                 :             : 
    3472                 :             :         /* If insufficient memory to format the message, fail cleanly */
    3473         [ #  # ]:           0 :         if (PQExpBufferDataBroken(workBuf))
    3474                 :             :         {
    3475                 :           0 :                 termPQExpBuffer(&workBuf);
    3476                 :           0 :                 return strdup(libpq_gettext("out of memory\n"));
    3477                 :             :         }
    3478                 :             : 
    3479                 :           0 :         return workBuf.data;
    3480                 :           0 : }
    3481                 :             : 
    3482                 :             : char *
    3483                 :       85884 : PQresultErrorField(const PGresult *res, int fieldcode)
    3484                 :             : {
    3485                 :       85884 :         PGMessageField *pfield;
    3486                 :             : 
    3487         [ +  + ]:       85884 :         if (!res)
    3488                 :           6 :                 return NULL;
    3489         [ +  + ]:      641675 :         for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
    3490                 :             :         {
    3491         [ +  + ]:      593051 :                 if (pfield->code == fieldcode)
    3492                 :       37254 :                         return pfield->contents;
    3493                 :      555797 :         }
    3494                 :       48624 :         return NULL;
    3495                 :       85884 : }
    3496                 :             : 
    3497                 :             : int
    3498                 :       29274 : PQntuples(const PGresult *res)
    3499                 :             : {
    3500         [ +  - ]:       29274 :         if (!res)
    3501                 :           0 :                 return 0;
    3502                 :       29274 :         return res->ntups;
    3503                 :       29274 : }
    3504                 :             : 
    3505                 :             : int
    3506                 :       19424 : PQnfields(const PGresult *res)
    3507                 :             : {
    3508         [ +  - ]:       19424 :         if (!res)
    3509                 :           0 :                 return 0;
    3510                 :       19424 :         return res->numAttributes;
    3511                 :       19424 : }
    3512                 :             : 
    3513                 :             : int
    3514                 :         132 : PQbinaryTuples(const PGresult *res)
    3515                 :             : {
    3516         [ +  - ]:         132 :         if (!res)
    3517                 :           0 :                 return 0;
    3518                 :         132 :         return res->binary;
    3519                 :         132 : }
    3520                 :             : 
    3521                 :             : /*
    3522                 :             :  * Helper routines to range-check field numbers and tuple numbers.
    3523                 :             :  * Return true if OK, false if not
    3524                 :             :  */
    3525                 :             : 
    3526                 :             : static int
    3527                 :      223655 : check_field_number(const PGresult *res, int field_num)
    3528                 :             : {
    3529         [ +  - ]:      223655 :         if (!res)
    3530                 :           0 :                 return false;                   /* no way to display error message... */
    3531   [ +  -  -  + ]:      223655 :         if (field_num < 0 || field_num >= res->numAttributes)
    3532                 :             :         {
    3533                 :           0 :                 pqInternalNotice(&res->noticeHooks,
    3534                 :             :                                                  "column number %d is out of range 0..%d",
    3535                 :           0 :                                                  field_num, res->numAttributes - 1);
    3536                 :           0 :                 return false;
    3537                 :             :         }
    3538                 :      223655 :         return true;
    3539                 :      223655 : }
    3540                 :             : 
    3541                 :             : static int
    3542                 :      357171 : check_tuple_field_number(const PGresult *res,
    3543                 :             :                                                  int tup_num, int field_num)
    3544                 :             : {
    3545         [ +  - ]:      357171 :         if (!res)
    3546                 :           0 :                 return false;                   /* no way to display error message... */
    3547   [ +  -  -  + ]:      357171 :         if (tup_num < 0 || tup_num >= res->ntups)
    3548                 :             :         {
    3549                 :           0 :                 pqInternalNotice(&res->noticeHooks,
    3550                 :             :                                                  "row number %d is out of range 0..%d",
    3551                 :           0 :                                                  tup_num, res->ntups - 1);
    3552                 :           0 :                 return false;
    3553                 :             :         }
    3554   [ +  -  -  + ]:      357171 :         if (field_num < 0 || field_num >= res->numAttributes)
    3555                 :             :         {
    3556                 :           0 :                 pqInternalNotice(&res->noticeHooks,
    3557                 :             :                                                  "column number %d is out of range 0..%d",
    3558                 :           0 :                                                  field_num, res->numAttributes - 1);
    3559                 :           0 :                 return false;
    3560                 :             :         }
    3561                 :      357171 :         return true;
    3562                 :      357171 : }
    3563                 :             : 
    3564                 :             : static int
    3565                 :           0 : check_param_number(const PGresult *res, int param_num)
    3566                 :             : {
    3567         [ #  # ]:           0 :         if (!res)
    3568                 :           0 :                 return false;                   /* no way to display error message... */
    3569   [ #  #  #  # ]:           0 :         if (param_num < 0 || param_num >= res->numParameters)
    3570                 :             :         {
    3571                 :           0 :                 pqInternalNotice(&res->noticeHooks,
    3572                 :             :                                                  "parameter number %d is out of range 0..%d",
    3573                 :           0 :                                                  param_num, res->numParameters - 1);
    3574                 :           0 :                 return false;
    3575                 :             :         }
    3576                 :             : 
    3577                 :           0 :         return true;
    3578                 :           0 : }
    3579                 :             : 
    3580                 :             : /*
    3581                 :             :  * returns NULL if the field_num is invalid
    3582                 :             :  */
    3583                 :             : char *
    3584                 :       35011 : PQfname(const PGresult *res, int field_num)
    3585                 :             : {
    3586         [ +  - ]:       35011 :         if (!check_field_number(res, field_num))
    3587                 :           0 :                 return NULL;
    3588         [ +  - ]:       35011 :         if (res->attDescs)
    3589                 :       35011 :                 return res->attDescs[field_num].name;
    3590                 :             :         else
    3591                 :           0 :                 return NULL;
    3592                 :       35011 : }
    3593                 :             : 
    3594                 :             : /*
    3595                 :             :  * PQfnumber: find column number given column name
    3596                 :             :  *
    3597                 :             :  * The column name is parsed as if it were in a SQL statement, including
    3598                 :             :  * case-folding and double-quote processing.  But note a possible gotcha:
    3599                 :             :  * downcasing in the frontend might follow different locale rules than
    3600                 :             :  * downcasing in the backend...
    3601                 :             :  *
    3602                 :             :  * Returns -1 if no match.  In the present backend it is also possible
    3603                 :             :  * to have multiple matches, in which case the first one is found.
    3604                 :             :  */
    3605                 :             : int
    3606                 :         164 : PQfnumber(const PGresult *res, const char *field_name)
    3607                 :             : {
    3608                 :         164 :         char       *field_case;
    3609                 :         164 :         bool            in_quotes;
    3610                 :         164 :         bool            all_lower = true;
    3611                 :         164 :         const char *iptr;
    3612                 :         164 :         char       *optr;
    3613                 :         164 :         int                     i;
    3614                 :             : 
    3615         [ +  - ]:         164 :         if (!res)
    3616                 :           0 :                 return -1;
    3617                 :             : 
    3618                 :             :         /*
    3619                 :             :          * Note: it is correct to reject a zero-length input string; the proper
    3620                 :             :          * input to match a zero-length field name would be "".
    3621                 :             :          */
    3622         [ +  - ]:         164 :         if (field_name == NULL ||
    3623   [ +  -  -  + ]:         164 :                 field_name[0] == '\0' ||
    3624                 :         164 :                 res->attDescs == NULL)
    3625                 :           0 :                 return -1;
    3626                 :             : 
    3627                 :             :         /*
    3628                 :             :          * Check if we can avoid the strdup() and related work because the
    3629                 :             :          * passed-in string wouldn't be changed before we do the check anyway.
    3630                 :             :          */
    3631         [ +  + ]:        1332 :         for (iptr = field_name; *iptr; iptr++)
    3632                 :             :         {
    3633                 :        1168 :                 char            c = *iptr;
    3634                 :             : 
    3635   [ +  -  -  + ]:        1168 :                 if (c == '"' || c != pg_tolower((unsigned char) c))
    3636                 :             :                 {
    3637                 :           0 :                         all_lower = false;
    3638                 :           0 :                         break;
    3639                 :             :                 }
    3640      [ -  -  + ]:        1168 :         }
    3641                 :             : 
    3642         [ -  + ]:         164 :         if (all_lower)
    3643         [ +  - ]:         392 :                 for (i = 0; i < res->numAttributes; i++)
    3644         [ +  + ]:         392 :                         if (strcmp(field_name, res->attDescs[i].name) == 0)
    3645                 :         164 :                                 return i;
    3646                 :             : 
    3647                 :             :         /* Fall through to the normal check if that didn't work out. */
    3648                 :             : 
    3649                 :             :         /*
    3650                 :             :          * Note: this code will not reject partially quoted strings, eg
    3651                 :             :          * foo"BAR"foo will become fooBARfoo when it probably ought to be an error
    3652                 :             :          * condition.
    3653                 :             :          */
    3654                 :           0 :         field_case = strdup(field_name);
    3655         [ #  # ]:           0 :         if (field_case == NULL)
    3656                 :           0 :                 return -1;                              /* grotty */
    3657                 :             : 
    3658                 :           0 :         in_quotes = false;
    3659                 :           0 :         optr = field_case;
    3660         [ #  # ]:           0 :         for (iptr = field_case; *iptr; iptr++)
    3661                 :             :         {
    3662                 :           0 :                 char            c = *iptr;
    3663                 :             : 
    3664         [ #  # ]:           0 :                 if (in_quotes)
    3665                 :             :                 {
    3666         [ #  # ]:           0 :                         if (c == '"')
    3667                 :             :                         {
    3668         [ #  # ]:           0 :                                 if (iptr[1] == '"')
    3669                 :             :                                 {
    3670                 :             :                                         /* doubled quotes become a single quote */
    3671                 :           0 :                                         *optr++ = '"';
    3672                 :           0 :                                         iptr++;
    3673                 :           0 :                                 }
    3674                 :             :                                 else
    3675                 :           0 :                                         in_quotes = false;
    3676                 :           0 :                         }
    3677                 :             :                         else
    3678                 :           0 :                                 *optr++ = c;
    3679                 :           0 :                 }
    3680         [ #  # ]:           0 :                 else if (c == '"')
    3681                 :           0 :                         in_quotes = true;
    3682                 :             :                 else
    3683                 :             :                 {
    3684                 :           0 :                         c = pg_tolower((unsigned char) c);
    3685                 :           0 :                         *optr++ = c;
    3686                 :             :                 }
    3687                 :           0 :         }
    3688                 :           0 :         *optr = '\0';
    3689                 :             : 
    3690         [ #  # ]:           0 :         for (i = 0; i < res->numAttributes; i++)
    3691                 :             :         {
    3692         [ #  # ]:           0 :                 if (strcmp(field_case, res->attDescs[i].name) == 0)
    3693                 :             :                 {
    3694                 :           0 :                         free(field_case);
    3695                 :           0 :                         return i;
    3696                 :             :                 }
    3697                 :           0 :         }
    3698                 :           0 :         free(field_case);
    3699                 :           0 :         return -1;
    3700                 :         164 : }
    3701                 :             : 
    3702                 :             : Oid
    3703                 :           0 : PQftable(const PGresult *res, int field_num)
    3704                 :             : {
    3705         [ #  # ]:           0 :         if (!check_field_number(res, field_num))
    3706                 :           0 :                 return InvalidOid;
    3707         [ #  # ]:           0 :         if (res->attDescs)
    3708                 :           0 :                 return res->attDescs[field_num].tableid;
    3709                 :             :         else
    3710                 :           0 :                 return InvalidOid;
    3711                 :           0 : }
    3712                 :             : 
    3713                 :             : int
    3714                 :           0 : PQftablecol(const PGresult *res, int field_num)
    3715                 :             : {
    3716         [ #  # ]:           0 :         if (!check_field_number(res, field_num))
    3717                 :           0 :                 return 0;
    3718         [ #  # ]:           0 :         if (res->attDescs)
    3719                 :           0 :                 return res->attDescs[field_num].columnid;
    3720                 :             :         else
    3721                 :           0 :                 return 0;
    3722                 :           0 : }
    3723                 :             : 
    3724                 :             : int
    3725                 :           0 : PQfformat(const PGresult *res, int field_num)
    3726                 :             : {
    3727         [ #  # ]:           0 :         if (!check_field_number(res, field_num))
    3728                 :           0 :                 return 0;
    3729         [ #  # ]:           0 :         if (res->attDescs)
    3730                 :           0 :                 return res->attDescs[field_num].format;
    3731                 :             :         else
    3732                 :           0 :                 return 0;
    3733                 :           0 : }
    3734                 :             : 
    3735                 :             : Oid
    3736                 :      188623 : PQftype(const PGresult *res, int field_num)
    3737                 :             : {
    3738         [ +  - ]:      188623 :         if (!check_field_number(res, field_num))
    3739                 :           0 :                 return InvalidOid;
    3740         [ +  - ]:      188623 :         if (res->attDescs)
    3741                 :      188623 :                 return res->attDescs[field_num].typid;
    3742                 :             :         else
    3743                 :           0 :                 return InvalidOid;
    3744                 :      188623 : }
    3745                 :             : 
    3746                 :             : int
    3747                 :           0 : PQfsize(const PGresult *res, int field_num)
    3748                 :             : {
    3749         [ #  # ]:           0 :         if (!check_field_number(res, field_num))
    3750                 :           0 :                 return 0;
    3751         [ #  # ]:           0 :         if (res->attDescs)
    3752                 :           0 :                 return res->attDescs[field_num].typlen;
    3753                 :             :         else
    3754                 :           0 :                 return 0;
    3755                 :           0 : }
    3756                 :             : 
    3757                 :             : int
    3758                 :          21 : PQfmod(const PGresult *res, int field_num)
    3759                 :             : {
    3760         [ +  - ]:          21 :         if (!check_field_number(res, field_num))
    3761                 :           0 :                 return 0;
    3762         [ +  - ]:          21 :         if (res->attDescs)
    3763                 :          21 :                 return res->attDescs[field_num].atttypmod;
    3764                 :             :         else
    3765                 :           0 :                 return 0;
    3766                 :          21 : }
    3767                 :             : 
    3768                 :             : char *
    3769                 :       88406 : PQcmdStatus(PGresult *res)
    3770                 :             : {
    3771         [ +  - ]:       88406 :         if (!res)
    3772                 :           0 :                 return NULL;
    3773                 :       88406 :         return res->cmdStatus;
    3774                 :       88406 : }
    3775                 :             : 
    3776                 :             : /*
    3777                 :             :  * PQoidStatus -
    3778                 :             :  *      if the last command was an INSERT, return the oid string
    3779                 :             :  *      if not, return ""
    3780                 :             :  */
    3781                 :             : char *
    3782                 :           0 : PQoidStatus(const PGresult *res)
    3783                 :             : {
    3784                 :             :         /*
    3785                 :             :          * This must be enough to hold the result. Don't laugh, this is better
    3786                 :             :          * than what this function used to do.
    3787                 :             :          */
    3788                 :             :         static char buf[24];
    3789                 :             : 
    3790                 :           0 :         size_t          len;
    3791                 :             : 
    3792   [ #  #  #  # ]:           0 :         if (!res || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
    3793                 :           0 :                 return "";
    3794                 :             : 
    3795                 :           0 :         len = strspn(res->cmdStatus + 7, "0123456789");
    3796         [ #  # ]:           0 :         if (len > sizeof(buf) - 1)
    3797                 :           0 :                 len = sizeof(buf) - 1;
    3798                 :           0 :         memcpy(buf, res->cmdStatus + 7, len);
    3799                 :           0 :         buf[len] = '\0';
    3800                 :             : 
    3801                 :           0 :         return buf;
    3802                 :           0 : }
    3803                 :             : 
    3804                 :             : /*
    3805                 :             :  * PQoidValue -
    3806                 :             :  *      a perhaps preferable form of the above which just returns
    3807                 :             :  *      an Oid type
    3808                 :             :  */
    3809                 :             : Oid
    3810                 :       25582 : PQoidValue(const PGresult *res)
    3811                 :             : {
    3812                 :       25582 :         char       *endptr = NULL;
    3813                 :       25582 :         unsigned long result;
    3814                 :             : 
    3815         [ +  - ]:       25582 :         if (!res ||
    3816         [ +  + ]:       25582 :                 strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
    3817   [ +  -  -  + ]:        4474 :                 res->cmdStatus[7] < '0' ||
    3818                 :        4474 :                 res->cmdStatus[7] > '9')
    3819                 :       21108 :                 return InvalidOid;
    3820                 :             : 
    3821                 :        4474 :         result = strtoul(res->cmdStatus + 7, &endptr, 10);
    3822                 :             : 
    3823   [ +  -  -  +  :        4474 :         if (!endptr || (*endptr != ' ' && *endptr != '\0'))
                   #  # ]
    3824                 :           0 :                 return InvalidOid;
    3825                 :             :         else
    3826                 :        4474 :                 return (Oid) result;
    3827                 :       25582 : }
    3828                 :             : 
    3829                 :             : 
    3830                 :             : /*
    3831                 :             :  * PQcmdTuples -
    3832                 :             :  *      If the last command was INSERT/UPDATE/DELETE/MERGE/MOVE/FETCH/COPY,
    3833                 :             :  *      return a string containing the number of inserted/affected tuples.
    3834                 :             :  *      If not, return "".
    3835                 :             :  *
    3836                 :             :  *      XXX: this should probably return an int
    3837                 :             :  */
    3838                 :             : char *
    3839                 :       44050 : PQcmdTuples(PGresult *res)
    3840                 :             : {
    3841                 :       44050 :         char       *p,
    3842                 :             :                            *c;
    3843                 :             : 
    3844         [ +  + ]:       44050 :         if (!res)
    3845                 :          80 :                 return "";
    3846                 :             : 
    3847         [ +  + ]:       43970 :         if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
    3848                 :             :         {
    3849                 :        4445 :                 p = res->cmdStatus + 7;
    3850                 :             :                 /* INSERT: skip oid and space */
    3851   [ -  +  +  + ]:        8890 :                 while (*p && *p != ' ')
    3852                 :        4445 :                         p++;
    3853         [ +  - ]:        4445 :                 if (*p == 0)
    3854                 :           0 :                         goto interpret_error;   /* no space? */
    3855                 :        4445 :                 p++;
    3856                 :        4445 :         }
    3857         [ +  + ]:       39525 :         else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
    3858   [ +  +  +  + ]:       23537 :                          strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
    3859                 :       23172 :                          strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
    3860                 :       17001 :                 p = res->cmdStatus + 7;
    3861   [ +  +  +  + ]:       22524 :         else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0 ||
    3862                 :       22296 :                          strncmp(res->cmdStatus, "MERGE ", 6) == 0)
    3863                 :         391 :                 p = res->cmdStatus + 6;
    3864   [ +  +  +  + ]:       22133 :         else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
    3865                 :       22125 :                          strncmp(res->cmdStatus, "COPY ", 5) == 0)
    3866                 :         157 :                 p = res->cmdStatus + 5;
    3867                 :             :         else
    3868                 :       21976 :                 return "";
    3869                 :             : 
    3870                 :             :         /* check that we have an integer (at least one digit, nothing else) */
    3871         [ +  + ]:       46400 :         for (c = p; *c; c++)
    3872                 :             :         {
    3873         [ -  + ]:       24406 :                 if (!isdigit((unsigned char) *c))
    3874                 :           0 :                         goto interpret_error;
    3875                 :       24406 :         }
    3876         [ +  - ]:       21994 :         if (c == p)
    3877                 :           0 :                 goto interpret_error;
    3878                 :             : 
    3879                 :       21994 :         return p;
    3880                 :             : 
    3881                 :             : interpret_error:
    3882                 :           0 :         pqInternalNotice(&res->noticeHooks,
    3883                 :             :                                          "could not interpret result from server: %s",
    3884                 :           0 :                                          res->cmdStatus);
    3885                 :           0 :         return "";
    3886                 :       44050 : }
    3887                 :             : 
    3888                 :             : /*
    3889                 :             :  * PQgetvalue:
    3890                 :             :  *      return the value of field 'field_num' of row 'tup_num'
    3891                 :             :  */
    3892                 :             : char *
    3893                 :      189541 : PQgetvalue(const PGresult *res, int tup_num, int field_num)
    3894                 :             : {
    3895         [ +  - ]:      189541 :         if (!check_tuple_field_number(res, tup_num, field_num))
    3896                 :           0 :                 return NULL;
    3897                 :      189541 :         return res->tuples[tup_num][field_num].value;
    3898                 :      189541 : }
    3899                 :             : 
    3900                 :             : /* PQgetlength:
    3901                 :             :  *      returns the actual length of a field value in bytes.
    3902                 :             :  */
    3903                 :             : int
    3904                 :           0 : PQgetlength(const PGresult *res, int tup_num, int field_num)
    3905                 :             : {
    3906         [ #  # ]:           0 :         if (!check_tuple_field_number(res, tup_num, field_num))
    3907                 :           0 :                 return 0;
    3908         [ #  # ]:           0 :         if (res->tuples[tup_num][field_num].len != NULL_LEN)
    3909                 :           0 :                 return res->tuples[tup_num][field_num].len;
    3910                 :             :         else
    3911                 :           0 :                 return 0;
    3912                 :           0 : }
    3913                 :             : 
    3914                 :             : /* PQgetisnull:
    3915                 :             :  *      returns the null status of a field value.
    3916                 :             :  */
    3917                 :             : int
    3918                 :      167630 : PQgetisnull(const PGresult *res, int tup_num, int field_num)
    3919                 :             : {
    3920         [ +  - ]:      167630 :         if (!check_tuple_field_number(res, tup_num, field_num))
    3921                 :           0 :                 return 1;                               /* pretend it is null */
    3922         [ +  + ]:      167630 :         if (res->tuples[tup_num][field_num].len == NULL_LEN)
    3923                 :        9409 :                 return 1;
    3924                 :             :         else
    3925                 :      158221 :                 return 0;
    3926                 :      167630 : }
    3927                 :             : 
    3928                 :             : /* PQnparams:
    3929                 :             :  *      returns the number of input parameters of a prepared statement.
    3930                 :             :  */
    3931                 :             : int
    3932                 :           0 : PQnparams(const PGresult *res)
    3933                 :             : {
    3934         [ #  # ]:           0 :         if (!res)
    3935                 :           0 :                 return 0;
    3936                 :           0 :         return res->numParameters;
    3937                 :           0 : }
    3938                 :             : 
    3939                 :             : /* PQparamtype:
    3940                 :             :  *      returns type Oid of the specified statement parameter.
    3941                 :             :  */
    3942                 :             : Oid
    3943                 :           0 : PQparamtype(const PGresult *res, int param_num)
    3944                 :             : {
    3945         [ #  # ]:           0 :         if (!check_param_number(res, param_num))
    3946                 :           0 :                 return InvalidOid;
    3947         [ #  # ]:           0 :         if (res->paramDescs)
    3948                 :           0 :                 return res->paramDescs[param_num].typid;
    3949                 :             :         else
    3950                 :           0 :                 return InvalidOid;
    3951                 :           0 : }
    3952                 :             : 
    3953                 :             : 
    3954                 :             : /* PQsetnonblocking:
    3955                 :             :  *      sets the PGconn's database connection non-blocking if the arg is true
    3956                 :             :  *      or makes it blocking if the arg is false, this will not protect
    3957                 :             :  *      you from PQexec(), you'll only be safe when using the non-blocking API.
    3958                 :             :  *      Needs to be called only on a connected database connection.
    3959                 :             :  */
    3960                 :             : int
    3961                 :           0 : PQsetnonblocking(PGconn *conn, int arg)
    3962                 :             : {
    3963                 :           0 :         bool            barg;
    3964                 :             : 
    3965   [ #  #  #  # ]:           0 :         if (!conn || conn->status == CONNECTION_BAD)
    3966                 :           0 :                 return -1;
    3967                 :             : 
    3968                 :           0 :         barg = (arg ? true : false);
    3969                 :             : 
    3970                 :             :         /* early out if the socket is already in the state requested */
    3971         [ #  # ]:           0 :         if (barg == conn->nonblocking)
    3972                 :           0 :                 return 0;
    3973                 :             : 
    3974                 :             :         /*
    3975                 :             :          * to guarantee constancy for flushing/query/result-polling behavior we
    3976                 :             :          * need to flush the send queue at this point in order to guarantee proper
    3977                 :             :          * behavior. this is ok because either they are making a transition _from_
    3978                 :             :          * or _to_ blocking mode, either way we can block them.
    3979                 :             :          *
    3980                 :             :          * Clear error state in case pqFlush adds to it, unless we're actively
    3981                 :             :          * pipelining, in which case it seems best not to.
    3982                 :             :          */
    3983         [ #  # ]:           0 :         if (conn->cmd_queue_head == NULL)
    3984                 :           0 :                 pqClearConnErrorState(conn);
    3985                 :             : 
    3986                 :             :         /* if we are going from blocking to non-blocking flush here */
    3987         [ #  # ]:           0 :         if (pqFlush(conn))
    3988                 :           0 :                 return -1;
    3989                 :             : 
    3990                 :           0 :         conn->nonblocking = barg;
    3991                 :             : 
    3992                 :           0 :         return 0;
    3993                 :           0 : }
    3994                 :             : 
    3995                 :             : /*
    3996                 :             :  * return the blocking status of the database connection
    3997                 :             :  *              true == nonblocking, false == blocking
    3998                 :             :  */
    3999                 :             : int
    4000                 :           0 : PQisnonblocking(const PGconn *conn)
    4001                 :             : {
    4002   [ #  #  #  # ]:           0 :         if (!conn || conn->status == CONNECTION_BAD)
    4003                 :           0 :                 return false;
    4004                 :           0 :         return pqIsnonblocking(conn);
    4005                 :           0 : }
    4006                 :             : 
    4007                 :             : /* libpq is thread-safe? */
    4008                 :             : int
    4009                 :           0 : PQisthreadsafe(void)
    4010                 :             : {
    4011                 :           0 :         return true;
    4012                 :             : }
    4013                 :             : 
    4014                 :             : 
    4015                 :             : /* try to force data out, really only useful for non-blocking users */
    4016                 :             : int
    4017                 :           3 : PQflush(PGconn *conn)
    4018                 :             : {
    4019   [ +  -  -  + ]:           3 :         if (!conn || conn->status == CONNECTION_BAD)
    4020                 :           0 :                 return -1;
    4021                 :           3 :         return pqFlush(conn);
    4022                 :           3 : }
    4023                 :             : 
    4024                 :             : /*
    4025                 :             :  * pqPipelineFlush
    4026                 :             :  *
    4027                 :             :  * In pipeline mode, data will be flushed only when the out buffer reaches the
    4028                 :             :  * threshold value.  In non-pipeline mode, it behaves as stock pqFlush.
    4029                 :             :  *
    4030                 :             :  * Returns 0 on success.
    4031                 :             :  */
    4032                 :             : static int
    4033                 :         194 : pqPipelineFlush(PGconn *conn)
    4034                 :             : {
    4035   [ +  +  -  + ]:         194 :         if ((conn->pipelineStatus != PQ_PIPELINE_ON) ||
    4036                 :         143 :                 (conn->outCount >= OUTBUFFER_THRESHOLD))
    4037                 :          51 :                 return pqFlush(conn);
    4038                 :         143 :         return 0;
    4039                 :         194 : }
    4040                 :             : 
    4041                 :             : 
    4042                 :             : /*
    4043                 :             :  *              PQfreemem - safely frees memory allocated
    4044                 :             :  *
    4045                 :             :  * Needed mostly by Win32, unless multithreaded DLL (/MD in VC6)
    4046                 :             :  * Used for freeing memory from PQescapeBytea()/PQunescapeBytea()
    4047                 :             :  */
    4048                 :             : void
    4049                 :         463 : PQfreemem(void *ptr)
    4050                 :             : {
    4051                 :         463 :         free(ptr);
    4052                 :         463 : }
    4053                 :             : 
    4054                 :             : /*
    4055                 :             :  * PQfreeNotify - free's the memory associated with a PGnotify
    4056                 :             :  *
    4057                 :             :  * This function is here only for binary backward compatibility.
    4058                 :             :  * New code should use PQfreemem().  A macro will automatically map
    4059                 :             :  * calls to PQfreemem.  It should be removed in the future.  bjm 2003-03-24
    4060                 :             :  */
    4061                 :             : 
    4062                 :             : #undef PQfreeNotify
    4063                 :             : void            PQfreeNotify(PGnotify *notify);
    4064                 :             : 
    4065                 :             : void
    4066                 :           0 : PQfreeNotify(PGnotify *notify)
    4067                 :             : {
    4068                 :           0 :         PQfreemem(notify);
    4069                 :           0 : }
    4070                 :             : 
    4071                 :             : 
    4072                 :             : /*
    4073                 :             :  * Escaping arbitrary strings to get valid SQL literal strings.
    4074                 :             :  *
    4075                 :             :  * Replaces "'" with "''", and if not std_strings, replaces "\" with "\\".
    4076                 :             :  *
    4077                 :             :  * length is the length of the source string.  (Note: if a terminating NUL
    4078                 :             :  * is encountered sooner, PQescapeString stops short of "length"; the behavior
    4079                 :             :  * is thus rather like strncpy.)
    4080                 :             :  *
    4081                 :             :  * For safety the buffer at "to" must be at least 2*length + 1 bytes long.
    4082                 :             :  * A terminating NUL character is added to the output string, whether the
    4083                 :             :  * input is NUL-terminated or not.
    4084                 :             :  *
    4085                 :             :  * Returns the actual length of the output (not counting the terminating NUL).
    4086                 :             :  */
    4087                 :             : static size_t
    4088                 :        1381 : PQescapeStringInternal(PGconn *conn,
    4089                 :             :                                            char *to, const char *from, size_t length,
    4090                 :             :                                            int *error,
    4091                 :             :                                            int encoding, bool std_strings)
    4092                 :             : {
    4093                 :        1381 :         const char *source = from;
    4094                 :        1381 :         char       *target = to;
    4095                 :        1381 :         size_t          remaining = strnlen(from, length);
    4096                 :        1381 :         bool            already_complained = false;
    4097                 :             : 
    4098         [ -  + ]:        1381 :         if (error)
    4099                 :           0 :                 *error = 0;
    4100                 :             : 
    4101         [ +  + ]:       25093 :         while (remaining > 0)
    4102                 :             :         {
    4103                 :       23712 :                 char            c = *source;
    4104                 :       23712 :                 int                     charlen;
    4105                 :       23712 :                 int                     i;
    4106                 :             : 
    4107                 :             :                 /* Fast path for plain ASCII */
    4108         [ -  + ]:       23712 :                 if (!IS_HIGHBIT_SET(c))
    4109                 :             :                 {
    4110                 :             :                         /* Apply quoting if needed */
    4111   [ +  -  +  +  :       23712 :                         if (SQL_STR_DOUBLE(c, !std_strings))
                   +  - ]
    4112                 :           0 :                                 *target++ = c;
    4113                 :             :                         /* Copy the character */
    4114                 :       23712 :                         *target++ = c;
    4115                 :       23712 :                         source++;
    4116                 :       23712 :                         remaining--;
    4117                 :       23712 :                         continue;
    4118                 :             :                 }
    4119                 :             : 
    4120                 :             :                 /* Slow path for possible multibyte characters */
    4121                 :           0 :                 charlen = pg_encoding_mblen_or_incomplete(encoding,
    4122                 :           0 :                                                                                                   source, remaining);
    4123                 :             : 
    4124   [ #  #  #  # ]:           0 :                 if (remaining < charlen ||
    4125                 :           0 :                         pg_encoding_verifymbchar(encoding, source, charlen) == -1)
    4126                 :             :                 {
    4127                 :             :                         /*
    4128                 :             :                          * Multibyte character is invalid.  It's important to verify that
    4129                 :             :                          * as invalid multibyte characters could e.g. be used to "skip"
    4130                 :             :                          * over quote characters, e.g. when parsing
    4131                 :             :                          * character-by-character.
    4132                 :             :                          *
    4133                 :             :                          * Report an error if possible, and replace the character's first
    4134                 :             :                          * byte with an invalid sequence. The invalid sequence ensures
    4135                 :             :                          * that the escaped string will trigger an error on the
    4136                 :             :                          * server-side, even if we can't directly report an error here.
    4137                 :             :                          *
    4138                 :             :                          * This isn't *that* crucial when we can report an error to the
    4139                 :             :                          * caller; but if we can't or the caller ignores it, the caller
    4140                 :             :                          * will use this string unmodified and it needs to be safe for
    4141                 :             :                          * parsing.
    4142                 :             :                          *
    4143                 :             :                          * We know there's enough space for the invalid sequence because
    4144                 :             :                          * the "to" buffer needs to be at least 2 * length + 1 long, and
    4145                 :             :                          * at worst we're replacing a single input byte with two invalid
    4146                 :             :                          * bytes.
    4147                 :             :                          *
    4148                 :             :                          * It would be a bit faster to verify the whole string the first
    4149                 :             :                          * time we encounter a set highbit, but this way we can replace
    4150                 :             :                          * just the invalid data, which probably makes it easier for users
    4151                 :             :                          * to find the invalidly encoded portion of a larger string.
    4152                 :             :                          */
    4153         [ #  # ]:           0 :                         if (error)
    4154                 :           0 :                                 *error = 1;
    4155   [ #  #  #  # ]:           0 :                         if (conn && !already_complained)
    4156                 :             :                         {
    4157         [ #  # ]:           0 :                                 if (remaining < charlen)
    4158                 :           0 :                                         libpq_append_conn_error(conn, "incomplete multibyte character");
    4159                 :             :                                 else
    4160                 :           0 :                                         libpq_append_conn_error(conn, "invalid multibyte character");
    4161                 :             :                                 /* Issue a complaint only once per string */
    4162                 :           0 :                                 already_complained = true;
    4163                 :           0 :                         }
    4164                 :             : 
    4165                 :           0 :                         pg_encoding_set_invalid(encoding, target);
    4166                 :           0 :                         target += 2;
    4167                 :             : 
    4168                 :             :                         /*
    4169                 :             :                          * Handle the following bytes as if this byte didn't exist. That's
    4170                 :             :                          * safer in case the subsequent bytes contain important characters
    4171                 :             :                          * for the caller (e.g. '>' in html).
    4172                 :             :                          */
    4173                 :           0 :                         source++;
    4174                 :           0 :                         remaining--;
    4175                 :           0 :                 }
    4176                 :             :                 else
    4177                 :             :                 {
    4178                 :             :                         /* Copy the character */
    4179         [ #  # ]:           0 :                         for (i = 0; i < charlen; i++)
    4180                 :             :                         {
    4181                 :           0 :                                 *target++ = *source++;
    4182                 :           0 :                                 remaining--;
    4183                 :           0 :                         }
    4184                 :             :                 }
    4185      [ -  +  - ]:       23712 :         }
    4186                 :             : 
    4187                 :             :         /* Write the terminating NUL character. */
    4188                 :        1381 :         *target = '\0';
    4189                 :             : 
    4190                 :        2762 :         return target - to;
    4191                 :        1381 : }
    4192                 :             : 
    4193                 :             : size_t
    4194                 :        1381 : PQescapeStringConn(PGconn *conn,
    4195                 :             :                                    char *to, const char *from, size_t length,
    4196                 :             :                                    int *error)
    4197                 :             : {
    4198         [ +  - ]:        1381 :         if (!conn)
    4199                 :             :         {
    4200                 :             :                 /* force empty-string result */
    4201                 :           0 :                 *to = '\0';
    4202         [ #  # ]:           0 :                 if (error)
    4203                 :           0 :                         *error = 1;
    4204                 :           0 :                 return 0;
    4205                 :             :         }
    4206                 :             : 
    4207         [ -  + ]:        1381 :         if (conn->cmd_queue_head == NULL)
    4208                 :        1381 :                 pqClearConnErrorState(conn);
    4209                 :             : 
    4210                 :        2762 :         return PQescapeStringInternal(conn, to, from, length, error,
    4211                 :        1381 :                                                                   conn->client_encoding,
    4212                 :        1381 :                                                                   conn->std_strings);
    4213                 :        1381 : }
    4214                 :             : 
    4215                 :             : size_t
    4216                 :           0 : PQescapeString(char *to, const char *from, size_t length)
    4217                 :             : {
    4218                 :           0 :         return PQescapeStringInternal(NULL, to, from, length, NULL,
    4219                 :           0 :                                                                   static_client_encoding,
    4220                 :           0 :                                                                   static_std_strings);
    4221                 :             : }
    4222                 :             : 
    4223                 :             : 
    4224                 :             : /*
    4225                 :             :  * Escape arbitrary strings.  If as_ident is true, we escape the result
    4226                 :             :  * as an identifier; if false, as a literal.  The result is returned in
    4227                 :             :  * a newly allocated buffer.  If we fail due to an encoding violation or out
    4228                 :             :  * of memory condition, we return NULL, storing an error message into conn.
    4229                 :             :  */
    4230                 :             : static char *
    4231                 :         139 : PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
    4232                 :             : {
    4233                 :         139 :         const char *s;
    4234                 :         139 :         char       *result;
    4235                 :         139 :         char       *rp;
    4236                 :         139 :         size_t          num_quotes = 0; /* single or double, depending on as_ident */
    4237                 :         139 :         size_t          num_backslashes = 0;
    4238                 :         139 :         size_t          input_len = strnlen(str, len);
    4239                 :         139 :         size_t          result_size;
    4240                 :         139 :         char            quote_char = as_ident ? '"' : '\'';
    4241                 :         139 :         bool            validated_mb = false;
    4242                 :             : 
    4243                 :             :         /* We must have a connection, else fail immediately. */
    4244         [ +  - ]:         139 :         if (!conn)
    4245                 :           0 :                 return NULL;
    4246                 :             : 
    4247         [ -  + ]:         139 :         if (conn->cmd_queue_head == NULL)
    4248                 :         139 :                 pqClearConnErrorState(conn);
    4249                 :             : 
    4250                 :             :         /*
    4251                 :             :          * Scan the string for characters that must be escaped and for invalidly
    4252                 :             :          * encoded data.
    4253                 :             :          */
    4254                 :         139 :         s = str;
    4255   [ +  +  -  + ]:      104682 :         for (size_t remaining = input_len; remaining > 0; remaining--, s++)
    4256                 :             :         {
    4257         [ +  + ]:      104543 :                 if (*s == quote_char)
    4258                 :           4 :                         ++num_quotes;
    4259         [ +  + ]:      104539 :                 else if (*s == '\\')
    4260                 :           2 :                         ++num_backslashes;
    4261         [ +  - ]:      104537 :                 else if (IS_HIGHBIT_SET(*s))
    4262                 :             :                 {
    4263                 :           0 :                         int                     charlen;
    4264                 :             : 
    4265                 :             :                         /* Slow path for possible multibyte characters */
    4266                 :           0 :                         charlen = pg_encoding_mblen_or_incomplete(conn->client_encoding,
    4267                 :           0 :                                                                                                           s, remaining);
    4268                 :             : 
    4269         [ #  # ]:           0 :                         if (charlen > remaining)
    4270                 :             :                         {
    4271                 :             :                                 /* Multibyte character overruns allowable length. */
    4272                 :           0 :                                 libpq_append_conn_error(conn, "incomplete multibyte character");
    4273                 :           0 :                                 return NULL;
    4274                 :             :                         }
    4275                 :             : 
    4276                 :             :                         /*
    4277                 :             :                          * If we haven't already, check that multibyte characters are
    4278                 :             :                          * valid. It's important to verify that as invalid multi-byte
    4279                 :             :                          * characters could e.g. be used to "skip" over quote characters,
    4280                 :             :                          * e.g. when parsing character-by-character.
    4281                 :             :                          *
    4282                 :             :                          * We check validity once, for the whole remainder of the string,
    4283                 :             :                          * when we first encounter any multi-byte character. Some
    4284                 :             :                          * encodings have optimized implementations for longer strings.
    4285                 :             :                          */
    4286         [ #  # ]:           0 :                         if (!validated_mb)
    4287                 :             :                         {
    4288                 :           0 :                                 if (pg_encoding_verifymbstr(conn->client_encoding, s, remaining)
    4289         [ #  # ]:           0 :                                         != remaining)
    4290                 :             :                                 {
    4291                 :           0 :                                         libpq_append_conn_error(conn, "invalid multibyte character");
    4292                 :           0 :                                         return NULL;
    4293                 :             :                                 }
    4294                 :           0 :                                 validated_mb = true;
    4295                 :           0 :                         }
    4296                 :             : 
    4297                 :             :                         /* Adjust s, bearing in mind that for loop will increment it. */
    4298                 :           0 :                         s += charlen - 1;
    4299                 :           0 :                         remaining -= charlen - 1;
    4300         [ #  # ]:           0 :                 }
    4301                 :      104543 :         }
    4302                 :             : 
    4303                 :             :         /*
    4304                 :             :          * Allocate output buffer. Protect against overflow, in case the caller
    4305                 :             :          * has allocated a large fraction of the available size_t.
    4306                 :             :          */
    4307   [ +  -  -  + ]:         139 :         if (pg_add_size_overflow(input_len, num_quotes, &result_size) ||
    4308                 :         139 :                 pg_add_size_overflow(result_size, 3, &result_size)) /* two quotes plus a NUL */
    4309                 :           0 :                 goto overflow;
    4310                 :             : 
    4311   [ +  +  +  + ]:         139 :         if (!as_ident && num_backslashes > 0)
    4312                 :             :         {
    4313   [ +  -  -  + ]:           2 :                 if (pg_add_size_overflow(result_size, num_backslashes, &result_size) ||
    4314                 :           2 :                         pg_add_size_overflow(result_size, 2, &result_size)) /* for " E" prefix */
    4315                 :           0 :                         goto overflow;
    4316                 :           2 :         }
    4317                 :             : 
    4318                 :         139 :         result = rp = (char *) malloc(result_size);
    4319         [ +  - ]:         139 :         if (rp == NULL)
    4320                 :             :         {
    4321                 :           0 :                 libpq_append_conn_error(conn, "out of memory");
    4322                 :           0 :                 return NULL;
    4323                 :             :         }
    4324                 :             : 
    4325                 :             :         /*
    4326                 :             :          * If we are escaping a literal that contains backslashes, we use the
    4327                 :             :          * escape string syntax so that the result is correct under either value
    4328                 :             :          * of standard_conforming_strings.  We also emit a leading space in this
    4329                 :             :          * case, to guard against the possibility that the result might be
    4330                 :             :          * interpolated immediately following an identifier.
    4331                 :             :          */
    4332   [ +  +  +  + ]:         139 :         if (!as_ident && num_backslashes > 0)
    4333                 :             :         {
    4334                 :           2 :                 *rp++ = ' ';
    4335                 :           2 :                 *rp++ = 'E';
    4336                 :           2 :         }
    4337                 :             : 
    4338                 :             :         /* Opening quote. */
    4339                 :         139 :         *rp++ = quote_char;
    4340                 :             : 
    4341                 :             :         /*
    4342                 :             :          * Use fast path if possible.
    4343                 :             :          *
    4344                 :             :          * We've already verified that the input string is well-formed in the
    4345                 :             :          * current encoding.  If it contains no quotes and, in the case of
    4346                 :             :          * literal-escaping, no backslashes, then we can just copy it directly to
    4347                 :             :          * the output buffer, adding the necessary quotes.
    4348                 :             :          *
    4349                 :             :          * If not, we must rescan the input and process each character
    4350                 :             :          * individually.
    4351                 :             :          */
    4352   [ +  +  +  +  :         139 :         if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
                   -  + ]
    4353                 :             :         {
    4354                 :         136 :                 memcpy(rp, str, input_len);
    4355                 :         136 :                 rp += input_len;
    4356                 :         136 :         }
    4357                 :             :         else
    4358                 :             :         {
    4359                 :           3 :                 s = str;
    4360         [ +  + ]:         304 :                 for (size_t remaining = input_len; remaining > 0; remaining--, s++)
    4361                 :             :                 {
    4362   [ +  +  +  -  :         301 :                         if (*s == quote_char || (!as_ident && *s == '\\'))
                   +  + ]
    4363                 :             :                         {
    4364                 :           6 :                                 *rp++ = *s;
    4365                 :           6 :                                 *rp++ = *s;
    4366                 :           6 :                         }
    4367         [ -  + ]:         295 :                         else if (!IS_HIGHBIT_SET(*s))
    4368                 :         295 :                                 *rp++ = *s;
    4369                 :             :                         else
    4370                 :             :                         {
    4371                 :           0 :                                 int                     i = pg_encoding_mblen(conn->client_encoding, s);
    4372                 :             : 
    4373                 :           0 :                                 while (1)
    4374                 :             :                                 {
    4375                 :           0 :                                         *rp++ = *s;
    4376         [ #  # ]:           0 :                                         if (--i == 0)
    4377                 :           0 :                                                 break;
    4378                 :           0 :                                         remaining--;
    4379                 :           0 :                                         ++s;            /* for loop will provide the final increment */
    4380                 :             :                                 }
    4381                 :           0 :                         }
    4382                 :         301 :                 }
    4383                 :             :         }
    4384                 :             : 
    4385                 :             :         /* Closing quote and terminating NUL. */
    4386                 :         139 :         *rp++ = quote_char;
    4387                 :         139 :         *rp = '\0';
    4388                 :             : 
    4389                 :         139 :         return result;
    4390                 :             : 
    4391                 :             : overflow:
    4392                 :           0 :         libpq_append_conn_error(conn,
    4393                 :             :                                                         "escaped string size exceeds the maximum allowed (%zu)",
    4394                 :             :                                                         SIZE_MAX);
    4395                 :           0 :         return NULL;
    4396                 :         139 : }
    4397                 :             : 
    4398                 :             : char *
    4399                 :         135 : PQescapeLiteral(PGconn *conn, const char *str, size_t len)
    4400                 :             : {
    4401                 :         135 :         return PQescapeInternal(conn, str, len, false);
    4402                 :             : }
    4403                 :             : 
    4404                 :             : char *
    4405                 :           4 : PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
    4406                 :             : {
    4407                 :           4 :         return PQescapeInternal(conn, str, len, true);
    4408                 :             : }
    4409                 :             : 
    4410                 :             : /* HEX encoding support for bytea */
    4411                 :             : static const char hextbl[] = "0123456789abcdef";
    4412                 :             : 
    4413                 :             : static const int8 hexlookup[128] = {
    4414                 :             :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4415                 :             :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4416                 :             :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4417                 :             :         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
    4418                 :             :         -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4419                 :             :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4420                 :             :         -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4421                 :             :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    4422                 :             : };
    4423                 :             : 
    4424                 :             : static inline char
    4425                 :           0 : get_hex(char c)
    4426                 :             : {
    4427                 :           0 :         int                     res = -1;
    4428                 :             : 
    4429   [ #  #  #  # ]:           0 :         if (c > 0 && c < 127)
    4430                 :           0 :                 res = hexlookup[(unsigned char) c];
    4431                 :             : 
    4432                 :           0 :         return (char) res;
    4433                 :           0 : }
    4434                 :             : 
    4435                 :             : 
    4436                 :             : /*
    4437                 :             :  *              PQescapeBytea   - converts from binary string to the
    4438                 :             :  *              minimal encoding necessary to include the string in an SQL
    4439                 :             :  *              INSERT statement with a bytea type column as the target.
    4440                 :             :  *
    4441                 :             :  *              We can use either hex or escape (traditional) encoding.
    4442                 :             :  *              In escape mode, the following transformations are applied:
    4443                 :             :  *              '\0' == ASCII  0 == \000
    4444                 :             :  *              '\'' == ASCII 39 == ''
    4445                 :             :  *              '\\' == ASCII 92 == \\
    4446                 :             :  *              anything < 0x20, or > 0x7e ---> \ooo
    4447                 :             :  *                                                                              (where ooo is an octal expression)
    4448                 :             :  *
    4449                 :             :  *              If not std_strings, all backslashes sent to the output are doubled.
    4450                 :             :  */
    4451                 :             : static unsigned char *
    4452                 :           0 : PQescapeByteaInternal(PGconn *conn,
    4453                 :             :                                           const unsigned char *from, size_t from_length,
    4454                 :             :                                           size_t *to_length, bool std_strings, bool use_hex)
    4455                 :             : {
    4456                 :           0 :         const unsigned char *vp;
    4457                 :           0 :         unsigned char *rp;
    4458                 :           0 :         unsigned char *result;
    4459                 :           0 :         size_t          i;
    4460                 :           0 :         size_t          len;
    4461                 :           0 :         const size_t bslash_len = (std_strings ? 1 : 2);
    4462                 :             : 
    4463                 :             :         /*
    4464                 :             :          * Calculate the escaped length, watching for overflow as we do with
    4465                 :             :          * PQescapeInternal(). The following code relies on a small constant
    4466                 :             :          * bslash_len so that small additions and multiplications don't need their
    4467                 :             :          * own overflow checks.
    4468                 :             :          *
    4469                 :             :          * Start with the empty string, which has 1 char ('\0').
    4470                 :             :          */
    4471                 :           0 :         len = 1;
    4472                 :             : 
    4473         [ #  # ]:           0 :         if (use_hex)
    4474                 :             :         {
    4475                 :             :                 /* We prepend "\x" and double each input character. */
    4476         [ #  # ]:           0 :                 if (pg_add_size_overflow(len, bslash_len + 1, &len) ||
    4477   [ #  #  #  # ]:           0 :                         pg_add_size_overflow(len, from_length, &len) ||
    4478                 :           0 :                         pg_add_size_overflow(len, from_length, &len))
    4479                 :           0 :                         goto overflow;
    4480                 :           0 :         }
    4481                 :             :         else
    4482                 :             :         {
    4483                 :           0 :                 vp = from;
    4484         [ #  # ]:           0 :                 for (i = from_length; i > 0; i--, vp++)
    4485                 :             :                 {
    4486   [ #  #  #  # ]:           0 :                         if (*vp < 0x20 || *vp > 0x7e)
    4487                 :             :                         {
    4488         [ #  # ]:           0 :                                 if (pg_add_size_overflow(len, bslash_len + 3, &len))        /* octal "\ooo" */
    4489                 :           0 :                                         goto overflow;
    4490                 :           0 :                         }
    4491         [ #  # ]:           0 :                         else if (*vp == '\'')
    4492                 :             :                         {
    4493         [ #  # ]:           0 :                                 if (pg_add_size_overflow(len, 2, &len)) /* double each quote */
    4494                 :           0 :                                         goto overflow;
    4495                 :           0 :                         }
    4496         [ #  # ]:           0 :                         else if (*vp == '\\')
    4497                 :             :                         {
    4498         [ #  # ]:           0 :                                 if (pg_add_size_overflow(len, bslash_len * 2, &len))        /* double each backslash */
    4499                 :           0 :                                         goto overflow;
    4500                 :           0 :                         }
    4501                 :             :                         else
    4502                 :             :                         {
    4503         [ #  # ]:           0 :                                 if (pg_add_size_overflow(len, 1, &len))
    4504                 :           0 :                                         goto overflow;
    4505                 :             :                         }
    4506                 :           0 :                 }
    4507                 :             :         }
    4508                 :             : 
    4509                 :           0 :         *to_length = len;
    4510                 :           0 :         rp = result = (unsigned char *) malloc(len);
    4511         [ #  # ]:           0 :         if (rp == NULL)
    4512                 :             :         {
    4513         [ #  # ]:           0 :                 if (conn)
    4514                 :           0 :                         libpq_append_conn_error(conn, "out of memory");
    4515                 :           0 :                 return NULL;
    4516                 :             :         }
    4517                 :             : 
    4518         [ #  # ]:           0 :         if (use_hex)
    4519                 :             :         {
    4520         [ #  # ]:           0 :                 if (!std_strings)
    4521                 :           0 :                         *rp++ = '\\';
    4522                 :           0 :                 *rp++ = '\\';
    4523                 :           0 :                 *rp++ = 'x';
    4524                 :           0 :         }
    4525                 :             : 
    4526                 :           0 :         vp = from;
    4527         [ #  # ]:           0 :         for (i = from_length; i > 0; i--, vp++)
    4528                 :             :         {
    4529                 :           0 :                 unsigned char c = *vp;
    4530                 :             : 
    4531         [ #  # ]:           0 :                 if (use_hex)
    4532                 :             :                 {
    4533                 :           0 :                         *rp++ = hextbl[(c >> 4) & 0xF];
    4534                 :           0 :                         *rp++ = hextbl[c & 0xF];
    4535                 :           0 :                 }
    4536   [ #  #  #  # ]:           0 :                 else if (c < 0x20 || c > 0x7e)
    4537                 :             :                 {
    4538         [ #  # ]:           0 :                         if (!std_strings)
    4539                 :           0 :                                 *rp++ = '\\';
    4540                 :           0 :                         *rp++ = '\\';
    4541                 :           0 :                         *rp++ = (c >> 6) + '0';
    4542                 :           0 :                         *rp++ = ((c >> 3) & 07) + '0';
    4543                 :           0 :                         *rp++ = (c & 07) + '0';
    4544                 :           0 :                 }
    4545         [ #  # ]:           0 :                 else if (c == '\'')
    4546                 :             :                 {
    4547                 :           0 :                         *rp++ = '\'';
    4548                 :           0 :                         *rp++ = '\'';
    4549                 :           0 :                 }
    4550         [ #  # ]:           0 :                 else if (c == '\\')
    4551                 :             :                 {
    4552         [ #  # ]:           0 :                         if (!std_strings)
    4553                 :             :                         {
    4554                 :           0 :                                 *rp++ = '\\';
    4555                 :           0 :                                 *rp++ = '\\';
    4556                 :           0 :                         }
    4557                 :           0 :                         *rp++ = '\\';
    4558                 :           0 :                         *rp++ = '\\';
    4559                 :           0 :                 }
    4560                 :             :                 else
    4561                 :           0 :                         *rp++ = c;
    4562                 :           0 :         }
    4563                 :           0 :         *rp = '\0';
    4564                 :             : 
    4565                 :           0 :         return result;
    4566                 :             : 
    4567                 :             : overflow:
    4568         [ #  # ]:           0 :         if (conn)
    4569                 :           0 :                 libpq_append_conn_error(conn,
    4570                 :             :                                                                 "escaped bytea size exceeds the maximum allowed (%zu)",
    4571                 :             :                                                                 SIZE_MAX);
    4572                 :           0 :         return NULL;
    4573                 :           0 : }
    4574                 :             : 
    4575                 :             : unsigned char *
    4576                 :           0 : PQescapeByteaConn(PGconn *conn,
    4577                 :             :                                   const unsigned char *from, size_t from_length,
    4578                 :             :                                   size_t *to_length)
    4579                 :             : {
    4580         [ #  # ]:           0 :         if (!conn)
    4581                 :           0 :                 return NULL;
    4582                 :             : 
    4583         [ #  # ]:           0 :         if (conn->cmd_queue_head == NULL)
    4584                 :           0 :                 pqClearConnErrorState(conn);
    4585                 :             : 
    4586                 :           0 :         return PQescapeByteaInternal(conn, from, from_length, to_length,
    4587                 :           0 :                                                                  conn->std_strings,
    4588                 :           0 :                                                                  (conn->sversion >= 90000));
    4589                 :           0 : }
    4590                 :             : 
    4591                 :             : unsigned char *
    4592                 :           0 : PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
    4593                 :             : {
    4594                 :           0 :         return PQescapeByteaInternal(NULL, from, from_length, to_length,
    4595                 :           0 :                                                                  static_std_strings,
    4596                 :             :                                                                  false /* can't use hex */ );
    4597                 :             : }
    4598                 :             : 
    4599                 :             : 
    4600                 :             : #define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
    4601                 :             : #define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
    4602                 :             : #define OCTVAL(CH) ((CH) - '0')
    4603                 :             : 
    4604                 :             : /*
    4605                 :             :  *              PQunescapeBytea - converts the null terminated string representation
    4606                 :             :  *              of a bytea, strtext, into binary, filling a buffer. It returns a
    4607                 :             :  *              pointer to the buffer (or NULL on error), and the size of the
    4608                 :             :  *              buffer in retbuflen. The pointer may subsequently be used as an
    4609                 :             :  *              argument to the function PQfreemem.
    4610                 :             :  *
    4611                 :             :  *              The following transformations are made:
    4612                 :             :  *              \\       == ASCII 92 == \
    4613                 :             :  *              \ooo == a byte whose value = ooo (ooo is an octal number)
    4614                 :             :  *              \x       == x (x is any character not matched by the above transformations)
    4615                 :             :  */
    4616                 :             : unsigned char *
    4617                 :           0 : PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
    4618                 :             : {
    4619                 :           0 :         size_t          strtextlen,
    4620                 :             :                                 buflen;
    4621                 :           0 :         unsigned char *buffer,
    4622                 :             :                            *tmpbuf;
    4623                 :           0 :         size_t          i,
    4624                 :             :                                 j;
    4625                 :             : 
    4626         [ #  # ]:           0 :         if (strtext == NULL)
    4627                 :           0 :                 return NULL;
    4628                 :             : 
    4629                 :           0 :         strtextlen = strlen((const char *) strtext);
    4630                 :             : 
    4631   [ #  #  #  # ]:           0 :         if (strtext[0] == '\\' && strtext[1] == 'x')
    4632                 :             :         {
    4633                 :           0 :                 const unsigned char *s;
    4634                 :           0 :                 unsigned char *p;
    4635                 :             : 
    4636                 :           0 :                 buflen = (strtextlen - 2) / 2;
    4637                 :             :                 /* Avoid unportable malloc(0) */
    4638         [ #  # ]:           0 :                 buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1);
    4639         [ #  # ]:           0 :                 if (buffer == NULL)
    4640                 :           0 :                         return NULL;
    4641                 :             : 
    4642                 :           0 :                 s = strtext + 2;
    4643                 :           0 :                 p = buffer;
    4644         [ #  # ]:           0 :                 while (*s)
    4645                 :             :                 {
    4646                 :           0 :                         char            v1,
    4647                 :             :                                                 v2;
    4648                 :             : 
    4649                 :             :                         /*
    4650                 :             :                          * Bad input is silently ignored.  Note that this includes
    4651                 :             :                          * whitespace between hex pairs, which is allowed by byteain.
    4652                 :             :                          */
    4653                 :           0 :                         v1 = get_hex(*s++);
    4654   [ #  #  #  # ]:           0 :                         if (!*s || v1 == (char) -1)
    4655                 :           0 :                                 continue;
    4656                 :           0 :                         v2 = get_hex(*s++);
    4657         [ #  # ]:           0 :                         if (v2 != (char) -1)
    4658                 :           0 :                                 *p++ = (v1 << 4) | v2;
    4659      [ #  #  # ]:           0 :                 }
    4660                 :             : 
    4661                 :           0 :                 buflen = p - buffer;
    4662         [ #  # ]:           0 :         }
    4663                 :             :         else
    4664                 :             :         {
    4665                 :             :                 /*
    4666                 :             :                  * Length of input is max length of output, but add one to avoid
    4667                 :             :                  * unportable malloc(0) if input is zero-length.
    4668                 :             :                  */
    4669                 :           0 :                 buffer = (unsigned char *) malloc(strtextlen + 1);
    4670         [ #  # ]:           0 :                 if (buffer == NULL)
    4671                 :           0 :                         return NULL;
    4672                 :             : 
    4673         [ #  # ]:           0 :                 for (i = j = 0; i < strtextlen;)
    4674                 :             :                 {
    4675         [ #  # ]:           0 :                         switch (strtext[i])
    4676                 :             :                         {
    4677                 :             :                                 case '\\':
    4678                 :           0 :                                         i++;
    4679         [ #  # ]:           0 :                                         if (strtext[i] == '\\')
    4680                 :           0 :                                                 buffer[j++] = strtext[i++];
    4681                 :             :                                         else
    4682                 :             :                                         {
    4683   [ #  #  #  # ]:           0 :                                                 if ((ISFIRSTOCTDIGIT(strtext[i])) &&
    4684   [ #  #  #  #  :           0 :                                                         (ISOCTDIGIT(strtext[i + 1])) &&
                   #  # ]
    4685         [ #  # ]:           0 :                                                         (ISOCTDIGIT(strtext[i + 2])))
    4686                 :             :                                                 {
    4687                 :           0 :                                                         int                     byte;
    4688                 :             : 
    4689                 :           0 :                                                         byte = OCTVAL(strtext[i++]);
    4690                 :           0 :                                                         byte = (byte << 3) + OCTVAL(strtext[i++]);
    4691                 :           0 :                                                         byte = (byte << 3) + OCTVAL(strtext[i++]);
    4692                 :           0 :                                                         buffer[j++] = byte;
    4693                 :           0 :                                                 }
    4694                 :             :                                         }
    4695                 :             : 
    4696                 :             :                                         /*
    4697                 :             :                                          * Note: if we see '\' followed by something that isn't a
    4698                 :             :                                          * recognized escape sequence, we loop around having done
    4699                 :             :                                          * nothing except advance i.  Therefore the something will
    4700                 :             :                                          * be emitted as ordinary data on the next cycle. Corner
    4701                 :             :                                          * case: '\' at end of string will just be discarded.
    4702                 :             :                                          */
    4703                 :           0 :                                         break;
    4704                 :             : 
    4705                 :             :                                 default:
    4706                 :           0 :                                         buffer[j++] = strtext[i++];
    4707                 :           0 :                                         break;
    4708                 :             :                         }
    4709                 :             :                 }
    4710                 :           0 :                 buflen = j;                             /* buflen is the length of the dequoted data */
    4711                 :             :         }
    4712                 :             : 
    4713                 :             :         /* Shrink the buffer to be no larger than necessary */
    4714                 :             :         /* +1 avoids unportable behavior when buflen==0 */
    4715                 :           0 :         tmpbuf = realloc(buffer, buflen + 1);
    4716                 :             : 
    4717                 :             :         /* It would only be a very brain-dead realloc that could fail, but... */
    4718         [ #  # ]:           0 :         if (!tmpbuf)
    4719                 :             :         {
    4720                 :           0 :                 free(buffer);
    4721                 :           0 :                 return NULL;
    4722                 :             :         }
    4723                 :             : 
    4724                 :           0 :         *retbuflen = buflen;
    4725                 :           0 :         return tmpbuf;
    4726                 :           0 : }
        

Generated by: LCOV version 2.3.2-1