LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-exec.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 62.0 % 1622 1006
Test Date: 2026-03-03 23:14:44 Functions: 83.1 % 118 98
Legend: Lines:     hit not hit

            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      2053147 : PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
     161              : {
     162              :     PGresult   *result;
     163              : 
     164      2053147 :     result = (PGresult *) malloc(sizeof(PGresult));
     165      2053147 :     if (!result)
     166            0 :         return NULL;
     167              : 
     168      2053147 :     result->ntups = 0;
     169      2053147 :     result->numAttributes = 0;
     170      2053147 :     result->attDescs = NULL;
     171      2053147 :     result->tuples = NULL;
     172      2053147 :     result->tupArrSize = 0;
     173      2053147 :     result->numParameters = 0;
     174      2053147 :     result->paramDescs = NULL;
     175      2053147 :     result->resultStatus = status;
     176      2053147 :     result->cmdStatus[0] = '\0';
     177      2053147 :     result->binary = 0;
     178      2053147 :     result->events = NULL;
     179      2053147 :     result->nEvents = 0;
     180      2053147 :     result->errMsg = NULL;
     181      2053147 :     result->errFields = NULL;
     182      2053147 :     result->errQuery = NULL;
     183      2053147 :     result->null_field[0] = '\0';
     184      2053147 :     result->curBlock = NULL;
     185      2053147 :     result->curOffset = 0;
     186      2053147 :     result->spaceLeft = 0;
     187      2053147 :     result->memorySize = sizeof(PGresult);
     188              : 
     189      2053147 :     if (conn)
     190              :     {
     191              :         /* copy connection data we might need for operations on PGresult */
     192       450551 :         result->noticeHooks = conn->noticeHooks;
     193       450551 :         result->client_encoding = conn->client_encoding;
     194              : 
     195              :         /* consider copying conn's errorMessage */
     196       450551 :         switch (status)
     197              :         {
     198       450031 :             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       450031 :                 break;
     208          520 :             default:
     209              :                 /* we intentionally do not use or modify errorReported here */
     210          520 :                 pqSetResultError(result, &conn->errorMessage, 0);
     211          520 :                 break;
     212              :         }
     213              : 
     214              :         /* copy events last; result must be valid if we need to PQclear */
     215       450551 :         if (conn->nEvents > 0)
     216              :         {
     217            0 :             result->events = dupEvents(conn->events, conn->nEvents,
     218              :                                        &result->memorySize);
     219            0 :             if (!result->events)
     220              :             {
     221            0 :                 PQclear(result);
     222            0 :                 return NULL;
     223              :             }
     224            0 :             result->nEvents = conn->nEvents;
     225              :         }
     226              :     }
     227              :     else
     228              :     {
     229              :         /* defaults... */
     230      1602596 :         result->noticeHooks.noticeRec = NULL;
     231      1602596 :         result->noticeHooks.noticeRecArg = NULL;
     232      1602596 :         result->noticeHooks.noticeProc = NULL;
     233      1602596 :         result->noticeHooks.noticeProcArg = NULL;
     234      1602596 :         result->client_encoding = PG_SQL_ASCII;
     235              :     }
     236              : 
     237      2053147 :     return result;
     238              : }
     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         2562 : PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
     251              : {
     252              :     int         i;
     253              : 
     254              :     /* Fail if argument is NULL or OOM_result */
     255         2562 :     if (!res || (const PGresult *) res == &OOM_result)
     256            0 :         return false;
     257              : 
     258              :     /* If attrs already exist, they cannot be overwritten. */
     259         2562 :     if (res->numAttributes > 0)
     260            0 :         return false;
     261              : 
     262              :     /* ignore no-op request */
     263         2562 :     if (numAttributes <= 0 || !attDescs)
     264            0 :         return true;
     265              : 
     266         2562 :     res->attDescs = (PGresAttDesc *)
     267         2562 :         PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
     268              : 
     269         2562 :     if (!res->attDescs)
     270            0 :         return false;
     271              : 
     272         2562 :     res->numAttributes = numAttributes;
     273         2562 :     memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
     274              : 
     275              :     /* deep-copy the attribute names, and determine format */
     276         2562 :     res->binary = 1;
     277        10112 :     for (i = 0; i < res->numAttributes; i++)
     278              :     {
     279         7550 :         if (res->attDescs[i].name)
     280         7550 :             res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
     281              :         else
     282            0 :             res->attDescs[i].name = res->null_field;
     283              : 
     284         7550 :         if (!res->attDescs[i].name)
     285            0 :             return false;
     286              : 
     287         7550 :         if (res->attDescs[i].format == 0)
     288          503 :             res->binary = 0;
     289              :     }
     290              : 
     291         2562 :     return true;
     292              : }
     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         2562 : PQcopyResult(const PGresult *src, int flags)
     320              : {
     321              :     PGresult   *dest;
     322              :     int         i;
     323              : 
     324         2562 :     if (!src)
     325            0 :         return NULL;
     326              : 
     327         2562 :     dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK);
     328         2562 :     if (!dest)
     329            0 :         return NULL;
     330              : 
     331              :     /* Always copy these over.  Is cmdStatus really useful here? */
     332         2562 :     dest->client_encoding = src->client_encoding;
     333         2562 :     strcpy(dest->cmdStatus, src->cmdStatus);
     334              : 
     335              :     /* Wants attrs? */
     336         2562 :     if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
     337              :     {
     338         2562 :         if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs))
     339              :         {
     340            0 :             PQclear(dest);
     341            0 :             return NULL;
     342              :         }
     343              :     }
     344              : 
     345              :     /* Wants to copy tuples? */
     346         2562 :     if (flags & PG_COPYRES_TUPLES)
     347              :     {
     348              :         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              :             }
     363              :         }
     364              :     }
     365              : 
     366              :     /* Wants to copy notice hooks? */
     367         2562 :     if (flags & PG_COPYRES_NOTICEHOOKS)
     368         2562 :         dest->noticeHooks = src->noticeHooks;
     369              : 
     370              :     /* Wants to copy PGEvents? */
     371         2562 :     if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
     372              :     {
     373            0 :         dest->events = dupEvents(src->events, src->nEvents,
     374              :                                  &dest->memorySize);
     375            0 :         if (!dest->events)
     376              :         {
     377            0 :             PQclear(dest);
     378            0 :             return NULL;
     379              :         }
     380            0 :         dest->nEvents = src->nEvents;
     381              :     }
     382              : 
     383              :     /* Okay, trigger PGEVT_RESULTCOPY event */
     384         2562 :     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              :             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              :         }
     397              :     }
     398              : 
     399         2562 :     return dest;
     400              : }
     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              :     PGEvent    *newEvents;
     412              :     size_t      msize;
     413              :     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              :     }
     439              : 
     440            0 :     *memSize += msize;
     441            0 :     return newEvents;
     442              : }
     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              :     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              :                          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              :         PGresAttValue *tup;
     479              :         int         i;
     480              : 
     481              :         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              :         }
     494              : 
     495              :         /* add it to the array */
     496            0 :         if (!pqAddTuple(res, tup, &errmsg))
     497            0 :             goto fail;
     498              :     }
     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              :     }
     508            0 :     else if (len <= 0)
     509              :     {
     510            0 :         attval->len = 0;
     511            0 :         attval->value = res->null_field;
     512              :     }
     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            0 : 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              : }
     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         2562 : PQresultAlloc(PGresult *res, size_t nBytes)
     545              : {
     546              :     /* Fail if argument is NULL or OOM_result */
     547         2562 :     if (!res || (const PGresult *) res == &OOM_result)
     548            0 :         return NULL;
     549              : 
     550         2562 :     return pqResultAlloc(res, nBytes, true);
     551              : }
     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     27773394 : pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
     565              : {
     566              :     char       *space;
     567              :     PGresult_data *block;
     568              : 
     569     27773394 :     if (!res)
     570            0 :         return NULL;
     571              : 
     572     27773394 :     if (nBytes <= 0)
     573          232 :         return res->null_field;
     574              : 
     575              :     /*
     576              :      * If alignment is needed, round up the current position to an alignment
     577              :      * boundary.
     578              :      */
     579     27773162 :     if (isBinary)
     580              :     {
     581      5400994 :         int         offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
     582              : 
     583      5400994 :         if (offset)
     584              :         {
     585      4019183 :             res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
     586      4019183 :             res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
     587              :         }
     588              :     }
     589              : 
     590              :     /* If there's enough space in the current block, no problem. */
     591     27773162 :     if (nBytes <= (size_t) res->spaceLeft)
     592              :     {
     593     27233642 :         space = res->curBlock->space + res->curOffset;
     594     27233642 :         res->curOffset += nBytes;
     595     27233642 :         res->spaceLeft -= nBytes;
     596     27233642 :         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       539520 :     if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
     606              :     {
     607              :         size_t      alloc_size;
     608              : 
     609              :         /* Don't wrap around with overly large requests. */
     610         2722 :         if (nBytes > SIZE_MAX - PGRESULT_BLOCK_OVERHEAD)
     611            0 :             return NULL;
     612              : 
     613         2722 :         alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
     614         2722 :         block = (PGresult_data *) malloc(alloc_size);
     615         2722 :         if (!block)
     616            0 :             return NULL;
     617         2722 :         res->memorySize += alloc_size;
     618         2722 :         space = block->space + PGRESULT_BLOCK_OVERHEAD;
     619         2722 :         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         2435 :             block->next = res->curBlock->next;
     626         2435 :             res->curBlock->next = block;
     627              :         }
     628              :         else
     629              :         {
     630              :             /* Must set up the new block as the first active block. */
     631          287 :             block->next = NULL;
     632          287 :             res->curBlock = block;
     633          287 :             res->spaceLeft = 0; /* be sure it's marked full */
     634              :         }
     635         2722 :         return space;
     636              :     }
     637              : 
     638              :     /* Otherwise, start a new block. */
     639       536798 :     block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
     640       536798 :     if (!block)
     641            0 :         return NULL;
     642       536798 :     res->memorySize += PGRESULT_DATA_BLOCKSIZE;
     643       536798 :     block->next = res->curBlock;
     644       536798 :     res->curBlock = block;
     645       536798 :     if (isBinary)
     646              :     {
     647              :         /* object needs full alignment */
     648       493502 :         res->curOffset = PGRESULT_BLOCK_OVERHEAD;
     649       493502 :         res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
     650              :     }
     651              :     else
     652              :     {
     653              :         /* we can cram it right after the overhead pointer */
     654        43296 :         res->curOffset = sizeof(PGresult_data);
     655        43296 :         res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
     656              :     }
     657              : 
     658       536798 :     space = block->space + res->curOffset;
     659       536798 :     res->curOffset += nBytes;
     660       536798 :     res->spaceLeft -= nBytes;
     661       536798 :     return space;
     662              : }
     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              : }
     675              : 
     676              : /*
     677              :  * pqResultStrdup -
     678              :  *      Like strdup, but the space is subsidiary PGresult space.
     679              :  */
     680              : char *
     681       590486 : pqResultStrdup(PGresult *res, const char *str)
     682              : {
     683       590486 :     char       *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
     684              : 
     685       590486 :     if (space)
     686       590486 :         strcpy(space, str);
     687       590486 :     return space;
     688              : }
     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        23683 : pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
     699              : {
     700              :     char       *msg;
     701              : 
     702        23683 :     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        23683 :     if (!PQExpBufferBroken(errorMessage))
     713        23683 :         msg = pqResultStrdup(res, errorMessage->data + offset);
     714              :     else
     715            0 :         msg = NULL;
     716        23683 :     if (msg)
     717        23683 :         res->errMsg = msg;
     718              :     else
     719            0 :         res->errMsg = libpq_gettext("out of memory\n");
     720              : }
     721              : 
     722              : /*
     723              :  * PQclear -
     724              :  *    free's the memory associated with a PGresult
     725              :  */
     726              : void
     727      2980273 : PQclear(PGresult *res)
     728              : {
     729              :     PGresult_data *block;
     730              :     int         i;
     731              : 
     732              :     /* As a convenience, do nothing for a NULL pointer */
     733      2980273 :     if (!res)
     734       928781 :         return;
     735              :     /* Also, do nothing if the argument is OOM_result */
     736      2051492 :     if ((const PGresult *) res == &OOM_result)
     737            0 :         return;
     738              : 
     739              :     /* Close down any events we may have */
     740      2051492 :     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              :             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              :         }
     751            0 :         free(res->events[i].name);
     752              :     }
     753              : 
     754      2051492 :     free(res->events);
     755              : 
     756              :     /* Free all the subsidiary blocks */
     757      2589267 :     while ((block = res->curBlock) != NULL)
     758              :     {
     759       537775 :         res->curBlock = block->next;
     760       537775 :         free(block);
     761              :     }
     762              : 
     763              :     /* Free the top-level tuple pointer array */
     764      2051492 :     free(res->tuples);
     765              : 
     766              :     /* zero out the pointer fields to catch programming errors */
     767      2051492 :     res->attDescs = NULL;
     768      2051492 :     res->tuples = NULL;
     769      2051492 :     res->paramDescs = NULL;
     770      2051492 :     res->errFields = NULL;
     771      2051492 :     res->events = NULL;
     772      2051492 :     res->nEvents = 0;
     773              :     /* res->curBlock was zeroed out earlier */
     774              : 
     775              :     /* Free the PGresult structure itself */
     776      2051492 :     free(res);
     777              : }
     778              : 
     779              : /*
     780              :  * Handy subroutine to deallocate any partially constructed async result.
     781              :  *
     782              :  * Any "saved" result gets cleared too.
     783              :  */
     784              : void
     785       416357 : pqClearAsyncResult(PGconn *conn)
     786              : {
     787       416357 :     PQclear(conn->result);
     788       416357 :     conn->result = NULL;
     789       416357 :     conn->error_result = false;
     790       416357 :     PQclear(conn->saved_result);
     791       416357 :     conn->saved_result = NULL;
     792       416357 : }
     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           61 : pqSaveErrorResult(PGconn *conn)
     810              : {
     811              :     /* Drop any pending result ... */
     812           61 :     pqClearAsyncResult(conn);
     813              :     /* ... and set flag to remember to make an error result later */
     814           61 :     conn->error_result = true;
     815           61 : }
     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            4 : 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            4 :     if (conn->write_err_msg)
     834              :     {
     835            4 :         appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg);
     836              :         /* Avoid possibly appending the same message twice */
     837            4 :         conn->write_err_msg[0] = '\0';
     838              :     }
     839              :     else
     840            0 :         libpq_append_conn_error(conn, "write to server failed");
     841              : 
     842            4 :     pqSaveErrorResult(conn);
     843            4 : }
     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       369695 : pqPrepareAsyncResult(PGconn *conn)
     858              : {
     859              :     PGresult   *res;
     860              : 
     861       369695 :     res = conn->result;
     862       369695 :     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       369634 :         if (res->resultStatus == PGRES_FATAL_ERROR)
     870        22843 :             conn->errorReported = conn->errorMessage.len;
     871              :     }
     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           61 :         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           61 :         if (conn->errorReported < 0 ||
     884           61 :             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           61 :         res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
     893           61 :         if (res)
     894              :         {
     895              :             /*
     896              :              * Report whatever new error text we have, and advance
     897              :              * errorReported.
     898              :              */
     899           61 :             res->resultStatus = PGRES_FATAL_ERROR;
     900           61 :             pqSetResultError(res, &conn->errorMessage, conn->errorReported);
     901           61 :             conn->errorReported = conn->errorMessage.len;
     902              :         }
     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       369695 :     conn->result = conn->saved_result;
     928       369695 :     conn->error_result = false; /* saved_result is never an error */
     929       369695 :     conn->saved_result = NULL;
     930              : 
     931       369695 :     return res;
     932              : }
     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              :     char        msgBuf[1024];
     947              :     va_list     args;
     948              :     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              : }
     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      4405953 : pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
    1000              : {
    1001      4405953 :     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              :         int         newSize;
    1015              :         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       150282 :         if (res->tupArrSize <= INT_MAX / 2)
    1022       150282 :             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       150282 :         if (res->tuples == NULL)
    1045              :             newTuples = (PGresAttValue **)
    1046       141772 :                 malloc(newSize * sizeof(PGresAttValue *));
    1047              :         else
    1048              :             newTuples = (PGresAttValue **)
    1049         8510 :                 realloc(res->tuples, newSize * sizeof(PGresAttValue *));
    1050       150282 :         if (!newTuples)
    1051            0 :             return false;       /* malloc or realloc failed */
    1052       150282 :         res->memorySize +=
    1053       150282 :             (newSize - res->tupArrSize) * sizeof(PGresAttValue *);
    1054       150282 :         res->tupArrSize = newSize;
    1055       150282 :         res->tuples = newTuples;
    1056              :     }
    1057      4405953 :     res->tuples[res->ntups] = tup;
    1058      4405953 :     res->ntups++;
    1059      4405953 :     return true;
    1060              : }
    1061              : 
    1062              : /*
    1063              :  * pqSaveMessageField - save one field of an error or notice message
    1064              :  */
    1065              : void
    1066       810724 : pqSaveMessageField(PGresult *res, char code, const char *value)
    1067              : {
    1068              :     PGMessageField *pfield;
    1069              : 
    1070              :     pfield = (PGMessageField *)
    1071       810724 :         pqResultAlloc(res,
    1072              :                       offsetof(PGMessageField, contents) +
    1073       810724 :                       strlen(value) + 1,
    1074              :                       true);
    1075       810724 :     if (!pfield)
    1076            0 :         return;                 /* out of memory? */
    1077       810724 :     pfield->code = code;
    1078       810724 :     strcpy(pfield->contents, value);
    1079       810724 :     pfield->next = res->errFields;
    1080       810724 :     res->errFields = pfield;
    1081              : }
    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       220726 : pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
    1092              : {
    1093              :     pgParameterStatus *pstatus;
    1094              :     pgParameterStatus *prev;
    1095              : 
    1096              :     /*
    1097              :      * Forget any old information about the parameter
    1098              :      */
    1099       220726 :     for (pstatus = conn->pstatus, prev = NULL;
    1100      1752809 :          pstatus != NULL;
    1101      1532083 :          prev = pstatus, pstatus = pstatus->next)
    1102              :     {
    1103      1539569 :         if (strcmp(pstatus->name, name) == 0)
    1104              :         {
    1105         7486 :             if (prev)
    1106         5212 :                 prev->next = pstatus->next;
    1107              :             else
    1108         2274 :                 conn->pstatus = pstatus->next;
    1109         7486 :             free(pstatus);      /* frees name and value strings too */
    1110         7486 :             break;
    1111              :         }
    1112              :     }
    1113              : 
    1114              :     /*
    1115              :      * Store new info as a single malloc block
    1116              :      */
    1117       220726 :     pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
    1118       220726 :                                            strlen(name) + strlen(value) + 2);
    1119       220726 :     if (pstatus)
    1120              :     {
    1121              :         char       *ptr;
    1122              : 
    1123       220726 :         ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
    1124       220726 :         pstatus->name = ptr;
    1125       220726 :         strcpy(ptr, name);
    1126       220726 :         ptr += strlen(name) + 1;
    1127       220726 :         pstatus->value = ptr;
    1128       220726 :         strcpy(ptr, value);
    1129       220726 :         pstatus->next = conn->pstatus;
    1130       220726 :         conn->pstatus = pstatus;
    1131              :     }
    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       220726 :     if (strcmp(name, "client_encoding") == 0)
    1146              :     {
    1147        14249 :         conn->client_encoding = pg_char_to_encoding(value);
    1148              :         /* if we don't recognize the encoding name, fall back to SQL_ASCII */
    1149        14249 :         if (conn->client_encoding < 0)
    1150            0 :             conn->client_encoding = PG_SQL_ASCII;
    1151        14249 :         static_client_encoding = conn->client_encoding;
    1152              :     }
    1153       206477 :     else if (strcmp(name, "standard_conforming_strings") == 0)
    1154              :     {
    1155        14216 :         conn->std_strings = (strcmp(value, "on") == 0);
    1156        14216 :         static_std_strings = conn->std_strings;
    1157              :     }
    1158       192261 :     else if (strcmp(name, "server_version") == 0)
    1159              :     {
    1160              :         /* We convert the server version to numeric form. */
    1161              :         int         cnt;
    1162              :         int         vmaj,
    1163              :                     vmin,
    1164              :                     vrev;
    1165              : 
    1166        14216 :         cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
    1167              : 
    1168        14216 :         if (cnt == 3)
    1169              :         {
    1170              :             /* old style, e.g. 9.6.1 */
    1171            0 :             conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
    1172              :         }
    1173        14216 :         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              :             }
    1180              :             else
    1181              :             {
    1182              :                 /* old style without minor version, e.g. 9.6devel */
    1183            0 :                 conn->sversion = (100 * vmaj + vmin) * 100;
    1184              :             }
    1185              :         }
    1186        14216 :         else if (cnt == 1)
    1187              :         {
    1188              :             /* new style without minor version, e.g. 10devel */
    1189        14216 :             conn->sversion = 100 * 100 * vmaj;
    1190              :         }
    1191              :         else
    1192            0 :             conn->sversion = 0; /* unknown */
    1193              :     }
    1194       178045 :     else if (strcmp(name, "default_transaction_read_only") == 0)
    1195              :     {
    1196        14236 :         conn->default_transaction_read_only =
    1197        14236 :             (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
    1198              :     }
    1199       163809 :     else if (strcmp(name, "in_hot_standby") == 0)
    1200              :     {
    1201        14225 :         conn->in_hot_standby =
    1202        14225 :             (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
    1203              :     }
    1204       149584 :     else if (strcmp(name, "scram_iterations") == 0)
    1205              :     {
    1206        14222 :         conn->scram_sha_256_iterations = atoi(value);
    1207              :     }
    1208              : 
    1209       220726 :     return 1;
    1210              : }
    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      4405953 : pqRowProcessor(PGconn *conn, const char **errmsgp)
    1224              : {
    1225      4405953 :     PGresult   *res = conn->result;
    1226      4405953 :     int         nfields = res->numAttributes;
    1227      4405953 :     const PGdataValue *columns = conn->rowBuf;
    1228              :     PGresAttValue *tup;
    1229              :     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      4405953 :     if (conn->partialResMode && conn->saved_result == NULL)
    1240              :     {
    1241              :         /* Copy everything that should be in the result at this point */
    1242         2562 :         res = PQcopyResult(res,
    1243              :                            PG_COPYRES_ATTRS | PG_COPYRES_EVENTS |
    1244              :                            PG_COPYRES_NOTICEHOOKS);
    1245         2562 :         if (!res)
    1246            0 :             return 0;
    1247              :         /* Change result status to appropriate special value */
    1248         2562 :         res->resultStatus = (conn->singleRowMode ? PGRES_SINGLE_TUPLE : PGRES_TUPLES_CHUNK);
    1249              :         /* And stash it as the active result */
    1250         2562 :         conn->saved_result = conn->result;
    1251         2562 :         conn->result = res;
    1252              :     }
    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              :     tup = (PGresAttValue *)
    1264      4405953 :         pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
    1265      4405953 :     if (tup == NULL)
    1266            0 :         return 0;
    1267              : 
    1268     27433193 :     for (i = 0; i < nfields; i++)
    1269              :     {
    1270     23027240 :         int         clen = columns[i].len;
    1271              : 
    1272     23027240 :         if (clen < 0)
    1273              :         {
    1274              :             /* null field */
    1275      1238486 :             tup[i].len = NULL_LEN;
    1276      1238486 :             tup[i].value = res->null_field;
    1277              :         }
    1278              :         else
    1279              :         {
    1280     21788754 :             bool        isbinary = (res->attDescs[i].format != 0);
    1281              :             char       *val;
    1282              : 
    1283     21788754 :             val = (char *) pqResultAlloc(res, (size_t) clen + 1, isbinary);
    1284     21788754 :             if (val == NULL)
    1285            0 :                 return 0;
    1286              : 
    1287              :             /* copy and zero-terminate the data (even if it's binary) */
    1288     21788754 :             memcpy(val, columns[i].value, clen);
    1289     21788754 :             val[clen] = '\0';
    1290              : 
    1291     21788754 :             tup[i].len = clen;
    1292     21788754 :             tup[i].value = val;
    1293              :         }
    1294              :     }
    1295              : 
    1296              :     /* And add the tuple to the PGresult's tuple array */
    1297      4405953 :     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      4405953 :     if (conn->partialResMode && res->ntups >= conn->maxChunkSize)
    1305         2549 :         conn->asyncStatus = PGASYNC_READY_MORE;
    1306              : 
    1307      4405953 :     return 1;
    1308              : }
    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       340439 : pqAllocCmdQueueEntry(PGconn *conn)
    1324              : {
    1325              :     PGcmdQueueEntry *entry;
    1326              : 
    1327       340439 :     if (conn->cmd_queue_recycle == NULL)
    1328              :     {
    1329        14869 :         entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry));
    1330        14869 :         if (entry == NULL)
    1331              :         {
    1332            0 :             libpq_append_conn_error(conn, "out of memory");
    1333            0 :             return NULL;
    1334              :         }
    1335              :     }
    1336              :     else
    1337              :     {
    1338       325570 :         entry = conn->cmd_queue_recycle;
    1339       325570 :         conn->cmd_queue_recycle = entry->next;
    1340              :     }
    1341       340439 :     entry->next = NULL;
    1342       340439 :     entry->query = NULL;
    1343              : 
    1344       340439 :     return entry;
    1345              : }
    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       340439 : pqAppendCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
    1357              : {
    1358              :     Assert(entry->next == NULL);
    1359              : 
    1360       340439 :     if (conn->cmd_queue_head == NULL)
    1361       338168 :         conn->cmd_queue_head = entry;
    1362              :     else
    1363         2271 :         conn->cmd_queue_tail->next = entry;
    1364              : 
    1365       340439 :     conn->cmd_queue_tail = entry;
    1366              : 
    1367       340439 :     switch (conn->pipelineStatus)
    1368              :     {
    1369       340415 :         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       340415 :             if (conn->asyncStatus == PGASYNC_IDLE)
    1379       338159 :                 conn->asyncStatus = PGASYNC_BUSY;
    1380       340415 :             break;
    1381              : 
    1382           24 :         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           24 :             if (conn->asyncStatus == PGASYNC_IDLE ||
    1392           15 :                 conn->asyncStatus == PGASYNC_PIPELINE_IDLE)
    1393            9 :                 pqPipelineProcessQueue(conn);
    1394           24 :             break;
    1395              :     }
    1396       340439 : }
    1397              : 
    1398              : /*
    1399              :  * pqRecycleCmdQueueEntry
    1400              :  *      Push a command queue entry onto the freelist.
    1401              :  */
    1402              : static void
    1403       339241 : pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
    1404              : {
    1405       339241 :     if (entry == NULL)
    1406            0 :         return;
    1407              : 
    1408              :     /* recyclable entries should not have a follow-on command */
    1409              :     Assert(entry->next == NULL);
    1410              : 
    1411       339241 :     if (entry->query)
    1412              :     {
    1413       331087 :         free(entry->query);
    1414       331087 :         entry->query = NULL;
    1415              :     }
    1416              : 
    1417       339241 :     entry->next = conn->cmd_queue_recycle;
    1418       339241 :     conn->cmd_queue_recycle = entry;
    1419              : }
    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       326630 : PQsendQuery(PGconn *conn, const char *query)
    1434              : {
    1435       326630 :     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       326630 : PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
    1446              : {
    1447       326630 :     PGcmdQueueEntry *entry = NULL;
    1448              : 
    1449       326630 :     if (!PQsendQueryStart(conn, newQuery))
    1450            0 :         return 0;
    1451              : 
    1452              :     /* check the argument */
    1453       326630 :     if (!query)
    1454              :     {
    1455            0 :         libpq_append_conn_error(conn, "command string is a null pointer");
    1456            0 :         return 0;
    1457              :     }
    1458              : 
    1459       326630 :     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    1460              :     {
    1461            1 :         libpq_append_conn_error(conn, "%s not allowed in pipeline mode",
    1462              :                                 "PQsendQuery");
    1463            1 :         return 0;
    1464              :     }
    1465              : 
    1466       326629 :     entry = pqAllocCmdQueueEntry(conn);
    1467       326629 :     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       653258 :     if (pqPutMsgStart(PqMsg_Query, conn) < 0 ||
    1473       653258 :         pqPuts(query, conn) < 0 ||
    1474       326629 :         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       326629 :     entry->queryclass = PGQUERY_SIMPLE;
    1483              :     /* and remember the query text too, if possible */
    1484       326629 :     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       326629 :     if (pqFlush(conn) < 0)
    1491            0 :         goto sendFailed;
    1492              : 
    1493              :     /* OK, it's launched! */
    1494       326629 :     pqAppendCmdQueueEntry(conn, entry);
    1495              : 
    1496       326629 :     return 1;
    1497              : 
    1498            0 : sendFailed:
    1499            0 :     pqRecycleCmdQueueEntry(conn, entry);
    1500              :     /* error message should be set up already */
    1501            0 :     return 0;
    1502              : }
    1503              : 
    1504              : /*
    1505              :  * PQsendQueryParams
    1506              :  *      Like PQsendQuery, but use extended query protocol so we can pass parameters
    1507              :  */
    1508              : int
    1509         3395 : 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         3395 :     if (!PQsendQueryStart(conn, true))
    1519            0 :         return 0;
    1520              : 
    1521              :     /* check the arguments */
    1522         3395 :     if (!command)
    1523              :     {
    1524            0 :         libpq_append_conn_error(conn, "command string is a null pointer");
    1525            0 :         return 0;
    1526              :     }
    1527         3395 :     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         3395 :     return PQsendQueryGuts(conn,
    1535              :                            command,
    1536              :                            "",    /* use unnamed statement */
    1537              :                            nParams,
    1538              :                            paramTypes,
    1539              :                            paramValues,
    1540              :                            paramLengths,
    1541              :                            paramFormats,
    1542              :                            resultFormat);
    1543              : }
    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         2253 : PQsendPrepare(PGconn *conn,
    1554              :               const char *stmtName, const char *query,
    1555              :               int nParams, const Oid *paramTypes)
    1556              : {
    1557         2253 :     PGcmdQueueEntry *entry = NULL;
    1558              : 
    1559         2253 :     if (!PQsendQueryStart(conn, true))
    1560            0 :         return 0;
    1561              : 
    1562              :     /* check the arguments */
    1563         2253 :     if (!stmtName)
    1564              :     {
    1565            0 :         libpq_append_conn_error(conn, "statement name is a null pointer");
    1566            0 :         return 0;
    1567              :     }
    1568         2253 :     if (!query)
    1569              :     {
    1570            0 :         libpq_append_conn_error(conn, "command string is a null pointer");
    1571            0 :         return 0;
    1572              :     }
    1573         2253 :     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         2253 :     entry = pqAllocCmdQueueEntry(conn);
    1581         2253 :     if (entry == NULL)
    1582            0 :         return 0;               /* error msg already set */
    1583              : 
    1584              :     /* construct the Parse message */
    1585         4506 :     if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
    1586         4506 :         pqPuts(stmtName, conn) < 0 ||
    1587         2253 :         pqPuts(query, conn) < 0)
    1588            0 :         goto sendFailed;
    1589              : 
    1590         2253 :     if (nParams > 0 && paramTypes)
    1591            3 :     {
    1592              :         int         i;
    1593              : 
    1594            3 :         if (pqPutInt(nParams, 2, conn) < 0)
    1595            0 :             goto sendFailed;
    1596            8 :         for (i = 0; i < nParams; i++)
    1597              :         {
    1598            5 :             if (pqPutInt(paramTypes[i], 4, conn) < 0)
    1599            0 :                 goto sendFailed;
    1600              :         }
    1601              :     }
    1602              :     else
    1603              :     {
    1604         2250 :         if (pqPutInt(0, 2, conn) < 0)
    1605            0 :             goto sendFailed;
    1606              :     }
    1607         2253 :     if (pqPutMsgEnd(conn) < 0)
    1608            0 :         goto sendFailed;
    1609              : 
    1610              :     /* Add a Sync, unless in pipeline mode. */
    1611         2253 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    1612              :     {
    1613         4434 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    1614         2217 :             pqPutMsgEnd(conn) < 0)
    1615            0 :             goto sendFailed;
    1616              :     }
    1617              : 
    1618              :     /* remember we are doing just a Parse */
    1619         2253 :     entry->queryclass = PGQUERY_PREPARE;
    1620              : 
    1621              :     /* and remember the query text too, if possible */
    1622              :     /* if insufficient memory, query just winds up NULL */
    1623         2253 :     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         2253 :     if (pqPipelineFlush(conn) < 0)
    1631            0 :         goto sendFailed;
    1632              : 
    1633              :     /* OK, it's launched! */
    1634         2253 :     pqAppendCmdQueueEntry(conn, entry);
    1635              : 
    1636         2253 :     return 1;
    1637              : 
    1638            0 : sendFailed:
    1639            0 :     pqRecycleCmdQueueEntry(conn, entry);
    1640              :     /* error message should be set up already */
    1641            0 :     return 0;
    1642              : }
    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         7792 : 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         7792 :     if (!PQsendQueryStart(conn, true))
    1659            0 :         return 0;
    1660              : 
    1661              :     /* check the arguments */
    1662         7792 :     if (!stmtName)
    1663              :     {
    1664            0 :         libpq_append_conn_error(conn, "statement name is a null pointer");
    1665            0 :         return 0;
    1666              :     }
    1667         7792 :     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         7792 :     return PQsendQueryGuts(conn,
    1675              :                            NULL,    /* no command to parse */
    1676              :                            stmtName,
    1677              :                            nParams,
    1678              :                            NULL,    /* no param types */
    1679              :                            paramValues,
    1680              :                            paramLengths,
    1681              :                            paramFormats,
    1682              :                            resultFormat);
    1683              : }
    1684              : 
    1685              : /*
    1686              :  * PQsendQueryStart
    1687              :  *  Common startup code for PQsendQuery and sibling routines
    1688              :  */
    1689              : static bool
    1690       340166 : PQsendQueryStart(PGconn *conn, bool newQuery)
    1691              : {
    1692       340166 :     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       340166 :     if (newQuery && conn->cmd_queue_head == NULL)
    1701       338137 :         pqClearConnErrorState(conn);
    1702              : 
    1703              :     /* Don't try to send if we know there's no live connection. */
    1704       340166 :     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       340166 :     if (conn->asyncStatus != PGASYNC_IDLE &&
    1712         2029 :         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       340166 :     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         2249 :         switch (conn->asyncStatus)
    1732              :         {
    1733         2249 :             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         2249 :                 break;
    1740              : 
    1741            0 :             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              :     }
    1748              :     else
    1749              :     {
    1750              :         /*
    1751              :          * This command's results will come in immediately. Initialize async
    1752              :          * result-accumulation state
    1753              :          */
    1754       337917 :         pqClearAsyncResult(conn);
    1755              : 
    1756              :         /* reset partial-result mode */
    1757       337917 :         conn->partialResMode = false;
    1758       337917 :         conn->singleRowMode = false;
    1759       337917 :         conn->maxChunkSize = 0;
    1760              :     }
    1761              : 
    1762              :     /* ready to send command message */
    1763       340166 :     return true;
    1764              : }
    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        11187 : 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              :     int         i;
    1785              :     PGcmdQueueEntry *entry;
    1786              : 
    1787        11187 :     entry = pqAllocCmdQueueEntry(conn);
    1788        11187 :     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        11187 :     if (command)
    1798              :     {
    1799              :         /* construct the Parse message */
    1800         6790 :         if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
    1801         6790 :             pqPuts(stmtName, conn) < 0 ||
    1802         3395 :             pqPuts(command, conn) < 0)
    1803            0 :             goto sendFailed;
    1804         3395 :         if (nParams > 0 && paramTypes)
    1805              :         {
    1806           44 :             if (pqPutInt(nParams, 2, conn) < 0)
    1807            0 :                 goto sendFailed;
    1808          112 :             for (i = 0; i < nParams; i++)
    1809              :             {
    1810           68 :                 if (pqPutInt(paramTypes[i], 4, conn) < 0)
    1811            0 :                     goto sendFailed;
    1812              :             }
    1813              :         }
    1814              :         else
    1815              :         {
    1816         3351 :             if (pqPutInt(0, 2, conn) < 0)
    1817            0 :                 goto sendFailed;
    1818              :         }
    1819         3395 :         if (pqPutMsgEnd(conn) < 0)
    1820            0 :             goto sendFailed;
    1821              :     }
    1822              : 
    1823              :     /* Construct the Bind message */
    1824        22374 :     if (pqPutMsgStart(PqMsg_Bind, conn) < 0 ||
    1825        22374 :         pqPuts("", conn) < 0 ||
    1826        11187 :         pqPuts(stmtName, conn) < 0)
    1827            0 :         goto sendFailed;
    1828              : 
    1829              :     /* Send parameter formats */
    1830        11187 :     if (nParams > 0 && paramFormats)
    1831              :     {
    1832         2562 :         if (pqPutInt(nParams, 2, conn) < 0)
    1833            0 :             goto sendFailed;
    1834         6042 :         for (i = 0; i < nParams; i++)
    1835              :         {
    1836         3480 :             if (pqPutInt(paramFormats[i], 2, conn) < 0)
    1837            0 :                 goto sendFailed;
    1838              :         }
    1839              :     }
    1840              :     else
    1841              :     {
    1842         8625 :         if (pqPutInt(0, 2, conn) < 0)
    1843            0 :             goto sendFailed;
    1844              :     }
    1845              : 
    1846        11187 :     if (pqPutInt(nParams, 2, conn) < 0)
    1847            0 :         goto sendFailed;
    1848              : 
    1849              :     /* Send parameters */
    1850        25958 :     for (i = 0; i < nParams; i++)
    1851              :     {
    1852        14771 :         if (paramValues && paramValues[i])
    1853        14162 :         {
    1854              :             int         nbytes;
    1855              : 
    1856        14162 :             if (paramFormats && paramFormats[i] != 0)
    1857              :             {
    1858              :                 /* binary parameter */
    1859           26 :                 if (paramLengths)
    1860           26 :                     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              :             }
    1867              :             else
    1868              :             {
    1869              :                 /* text parameter, do not use paramLengths */
    1870        14136 :                 nbytes = strlen(paramValues[i]);
    1871              :             }
    1872        28324 :             if (pqPutInt(nbytes, 4, conn) < 0 ||
    1873        14162 :                 pqPutnchar(paramValues[i], nbytes, conn) < 0)
    1874            0 :                 goto sendFailed;
    1875              :         }
    1876              :         else
    1877              :         {
    1878              :             /* take the param as NULL */
    1879          609 :             if (pqPutInt(-1, 4, conn) < 0)
    1880            0 :                 goto sendFailed;
    1881              :         }
    1882              :     }
    1883        22374 :     if (pqPutInt(1, 2, conn) < 0 ||
    1884        11187 :         pqPutInt(resultFormat, 2, conn))
    1885            0 :         goto sendFailed;
    1886        11187 :     if (pqPutMsgEnd(conn) < 0)
    1887            0 :         goto sendFailed;
    1888              : 
    1889              :     /* construct the Describe Portal message */
    1890        22374 :     if (pqPutMsgStart(PqMsg_Describe, conn) < 0 ||
    1891        22374 :         pqPutc('P', conn) < 0 ||
    1892        22374 :         pqPuts("", conn) < 0 ||
    1893        11187 :         pqPutMsgEnd(conn) < 0)
    1894            0 :         goto sendFailed;
    1895              : 
    1896              :     /* construct the Execute message */
    1897        22374 :     if (pqPutMsgStart(PqMsg_Execute, conn) < 0 ||
    1898        22374 :         pqPuts("", conn) < 0 ||
    1899        22374 :         pqPutInt(0, 4, conn) < 0 ||
    1900        11187 :         pqPutMsgEnd(conn) < 0)
    1901            0 :         goto sendFailed;
    1902              : 
    1903              :     /* construct the Sync message if not in pipeline mode */
    1904        11187 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    1905              :     {
    1906        17976 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    1907         8988 :             pqPutMsgEnd(conn) < 0)
    1908            0 :             goto sendFailed;
    1909              :     }
    1910              : 
    1911              :     /* remember we are using extended query protocol */
    1912        11187 :     entry->queryclass = PGQUERY_EXTENDED;
    1913              : 
    1914              :     /* and remember the query text too, if possible */
    1915              :     /* if insufficient memory, query just winds up NULL */
    1916        11187 :     if (command)
    1917         3395 :         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        11187 :     if (pqPipelineFlush(conn) < 0)
    1925            0 :         goto sendFailed;
    1926              : 
    1927              :     /* OK, it's launched! */
    1928        11187 :     pqAppendCmdQueueEntry(conn, entry);
    1929              : 
    1930        11187 :     return 1;
    1931              : 
    1932            0 : sendFailed:
    1933            0 :     pqRecycleCmdQueueEntry(conn, entry);
    1934              :     /* error message should be set up already */
    1935            0 :     return 0;
    1936              : }
    1937              : 
    1938              : /*
    1939              :  * Is it OK to change partial-result mode now?
    1940              :  */
    1941              : static bool
    1942           86 : 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           86 :     if (!conn)
    1949            0 :         return false;
    1950           86 :     if (conn->asyncStatus != PGASYNC_BUSY)
    1951            3 :         return false;
    1952           83 :     if (!conn->cmd_queue_head ||
    1953           83 :         (conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE &&
    1954           20 :          conn->cmd_queue_head->queryclass != PGQUERY_EXTENDED))
    1955            0 :         return false;
    1956           83 :     if (pgHavePendingResult(conn))
    1957            0 :         return false;
    1958           83 :     return true;
    1959              : }
    1960              : 
    1961              : /*
    1962              :  * Select row-by-row processing mode
    1963              :  */
    1964              : int
    1965           33 : PQsetSingleRowMode(PGconn *conn)
    1966              : {
    1967           33 :     if (canChangeResultMode(conn))
    1968              :     {
    1969           33 :         conn->partialResMode = true;
    1970           33 :         conn->singleRowMode = true;
    1971           33 :         conn->maxChunkSize = 1;
    1972           33 :         return 1;
    1973              :     }
    1974              :     else
    1975            0 :         return 0;
    1976              : }
    1977              : 
    1978              : /*
    1979              :  * Select chunked results processing mode
    1980              :  */
    1981              : int
    1982           53 : PQsetChunkedRowsMode(PGconn *conn, int chunkSize)
    1983              : {
    1984           53 :     if (chunkSize > 0 && canChangeResultMode(conn))
    1985              :     {
    1986           50 :         conn->partialResMode = true;
    1987           50 :         conn->singleRowMode = false;
    1988           50 :         conn->maxChunkSize = chunkSize;
    1989           50 :         return 1;
    1990              :     }
    1991              :     else
    1992            3 :         return 0;
    1993              : }
    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       476010 : PQconsumeInput(PGconn *conn)
    2002              : {
    2003       476010 :     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       476010 :     if (pqIsnonblocking(conn))
    2012              :     {
    2013            5 :         if (pqFlush(conn) < 0)
    2014            0 :             return 0;
    2015              :     }
    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       476010 :     if (pqReadData(conn) < 0)
    2024           95 :         return 0;
    2025              : 
    2026              :     /* Parsing of the data waits till later. */
    2027       475915 :     return 1;
    2028              : }
    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      1822825 : parseInput(PGconn *conn)
    2038              : {
    2039      1822825 :     pqParseInput3(conn);
    2040      1822825 : }
    2041              : 
    2042              : /*
    2043              :  * PQisBusy
    2044              :  *   Return true if PQgetResult would block waiting for input.
    2045              :  */
    2046              : 
    2047              : int
    2048       147874 : PQisBusy(PGconn *conn)
    2049              : {
    2050       147874 :     if (!conn)
    2051            0 :         return false;
    2052              : 
    2053              :     /* Parse any available data, if our state permits. */
    2054       147874 :     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       147874 :     return conn->asyncStatus == PGASYNC_BUSY && conn->status != CONNECTION_BAD;
    2065              : }
    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       820392 : PQgetResult(PGconn *conn)
    2080              : {
    2081              :     PGresult   *res;
    2082              : 
    2083       820392 :     if (!conn)
    2084            0 :         return NULL;
    2085              : 
    2086              :     /* Parse any available data, if our state permits. */
    2087       820392 :     parseInput(conn);
    2088              : 
    2089              :     /* If not ready to return something, block until we are. */
    2090      1163791 :     while (conn->asyncStatus == PGASYNC_BUSY)
    2091              :     {
    2092              :         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       343460 :         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       686920 :         if (flushResult ||
    2115       686878 :             pqWait(true, false, conn) ||
    2116       343418 :             pqReadData(conn) < 0)
    2117              :         {
    2118              :             /* Report the error saved by pqWait or pqReadData */
    2119           57 :             pqSaveErrorResult(conn);
    2120           57 :             conn->asyncStatus = PGASYNC_IDLE;
    2121           57 :             return pqPrepareAsyncResult(conn);
    2122              :         }
    2123              : 
    2124              :         /* Parse it. */
    2125       343403 :         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       343403 :         if (conn->write_failed && conn->asyncStatus == PGASYNC_BUSY)
    2132              :         {
    2133            4 :             pqSaveWriteError(conn);
    2134            4 :             conn->asyncStatus = PGASYNC_IDLE;
    2135            4 :             return pqPrepareAsyncResult(conn);
    2136              :         }
    2137              :     }
    2138              : 
    2139              :     /* Return the appropriate thing. */
    2140       820331 :     switch (conn->asyncStatus)
    2141              :     {
    2142       449318 :         case PGASYNC_IDLE:
    2143       449318 :             res = NULL;         /* query is complete */
    2144       449318 :             break;
    2145         2240 :         case PGASYNC_PIPELINE_IDLE:
    2146              :             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         2240 :             pqPipelineProcessQueue(conn);
    2155         2240 :             res = NULL;         /* query is complete */
    2156         2240 :             break;
    2157              : 
    2158       359820 :         case PGASYNC_READY:
    2159       359820 :             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       359820 :             if (conn->result)
    2170              :             {
    2171              :                 Assert(res->resultStatus == PGRES_TUPLES_CHUNK);
    2172           10 :                 break;
    2173              :             }
    2174              : 
    2175              :             /* Advance the queue as appropriate */
    2176       359810 :             pqCommandQueueAdvance(conn, false,
    2177       359810 :                                   res->resultStatus == PGRES_PIPELINE_SYNC);
    2178              : 
    2179       359810 :             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         2507 :                 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         2507 :                 if (res->resultStatus == PGRES_PIPELINE_SYNC)
    2199          266 :                     pqPipelineProcessQueue(conn);
    2200              :             }
    2201              :             else
    2202              :             {
    2203              :                 /* Set the state back to BUSY, allowing parsing to proceed. */
    2204       357303 :                 conn->asyncStatus = PGASYNC_BUSY;
    2205              :             }
    2206       359810 :             break;
    2207         2549 :         case PGASYNC_READY_MORE:
    2208         2549 :             res = pqPrepareAsyncResult(conn);
    2209              :             /* Set the state back to BUSY, allowing parsing to proceed. */
    2210         2549 :             conn->asyncStatus = PGASYNC_BUSY;
    2211         2549 :             break;
    2212          578 :         case PGASYNC_COPY_IN:
    2213          578 :             res = getCopyResult(conn, PGRES_COPY_IN);
    2214          578 :             break;
    2215         5085 :         case PGASYNC_COPY_OUT:
    2216         5085 :             res = getCopyResult(conn, PGRES_COPY_OUT);
    2217         5085 :             break;
    2218          741 :         case PGASYNC_COPY_BOTH:
    2219          741 :             res = getCopyResult(conn, PGRES_COPY_BOTH);
    2220          741 :             break;
    2221            0 :         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       820331 :     if (res && res->nEvents > 0)
    2231            0 :         (void) PQfireResultCreateEvents(conn, res);
    2232              : 
    2233       820331 :     return res;
    2234              : }
    2235              : 
    2236              : /*
    2237              :  * getCopyResult
    2238              :  *    Helper for PQgetResult: generate result for COPY-in-progress cases
    2239              :  */
    2240              : static PGresult *
    2241         6404 : 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         6404 :     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         6404 :     if (conn->result && conn->result->resultStatus == copytype)
    2260         6195 :         return pqPrepareAsyncResult(conn);
    2261              : 
    2262              :     /* Otherwise, invent a suitable PGresult */
    2263          209 :     return PQmakeEmptyPGresult(conn, copytype);
    2264              : }
    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        91127 : PQexec(PGconn *conn, const char *query)
    2280              : {
    2281        91127 :     if (!PQexecStart(conn))
    2282            1 :         return NULL;
    2283        91126 :     if (!PQsendQuery(conn, query))
    2284            0 :         return NULL;
    2285        91126 :     return PQexecFinish(conn);
    2286              : }
    2287              : 
    2288              : /*
    2289              :  * PQexecParams
    2290              :  *      Like PQexec, but use extended query protocol so we can pass parameters
    2291              :  */
    2292              : PGresult *
    2293         1490 : 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         1490 :     if (!PQexecStart(conn))
    2303            0 :         return NULL;
    2304         1490 :     if (!PQsendQueryParams(conn, command,
    2305              :                            nParams, paramTypes, paramValues, paramLengths,
    2306              :                            paramFormats, resultFormat))
    2307            0 :         return NULL;
    2308         1490 :     return PQexecFinish(conn);
    2309              : }
    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         2021 : PQprepare(PGconn *conn,
    2324              :           const char *stmtName, const char *query,
    2325              :           int nParams, const Oid *paramTypes)
    2326              : {
    2327         2021 :     if (!PQexecStart(conn))
    2328            9 :         return NULL;
    2329         2012 :     if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
    2330            0 :         return NULL;
    2331         2012 :     return PQexecFinish(conn);
    2332              : }
    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         3437 : 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         3437 :     if (!PQexecStart(conn))
    2349            0 :         return NULL;
    2350         3437 :     if (!PQsendQueryPrepared(conn, stmtName,
    2351              :                              nParams, paramValues, paramLengths,
    2352              :                              paramFormats, resultFormat))
    2353            0 :         return NULL;
    2354         3437 :     return PQexecFinish(conn);
    2355              : }
    2356              : 
    2357              : /*
    2358              :  * Common code for PQexec and sibling routines: prepare to send command
    2359              :  */
    2360              : static bool
    2361        98148 : PQexecStart(PGconn *conn)
    2362              : {
    2363              :     PGresult   *result;
    2364              : 
    2365        98148 :     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        98148 :     if (conn->cmd_queue_head == NULL)
    2374        98135 :         pqClearConnErrorState(conn);
    2375              : 
    2376        98148 :     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    2377              :     {
    2378           10 :         libpq_append_conn_error(conn, "synchronous command execution functions are not allowed in pipeline mode");
    2379           10 :         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        98138 :     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              :         }
    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              :         }
    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              :     }
    2418              : 
    2419              :     /* OK to send a command */
    2420        98138 :     return true;
    2421              : }
    2422              : 
    2423              : /*
    2424              :  * Common code for PQexec and sibling routines: wait for command result
    2425              :  */
    2426              : static PGresult *
    2427        98138 : PQexecFinish(PGconn *conn)
    2428              : {
    2429              :     PGresult   *result;
    2430              :     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        98138 :     lastResult = NULL;
    2444       209121 :     while ((result = PQgetResult(conn)) != NULL)
    2445              :     {
    2446       115429 :         PQclear(lastResult);
    2447       115429 :         lastResult = result;
    2448       115429 :         if (result->resultStatus == PGRES_COPY_IN ||
    2449       115384 :             result->resultStatus == PGRES_COPY_OUT ||
    2450       111149 :             result->resultStatus == PGRES_COPY_BOTH ||
    2451       110983 :             conn->status == CONNECTION_BAD)
    2452              :             break;
    2453              :     }
    2454              : 
    2455        98138 :     return lastResult;
    2456              : }
    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           70 : PQdescribePrepared(PGconn *conn, const char *stmt)
    2473              : {
    2474           70 :     if (!PQexecStart(conn))
    2475            0 :         return NULL;
    2476           70 :     if (!PQsendTypedCommand(conn, PqMsg_Describe, 'S', stmt))
    2477            0 :         return NULL;
    2478           70 :     return PQexecFinish(conn);
    2479              : }
    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            1 : PQdescribePortal(PGconn *conn, const char *portal)
    2492              : {
    2493            1 :     if (!PQexecStart(conn))
    2494            0 :         return NULL;
    2495            1 :     if (!PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal))
    2496            0 :         return NULL;
    2497            1 :     return PQexecFinish(conn);
    2498              : }
    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            1 : PQsendDescribePrepared(PGconn *conn, const char *stmt)
    2509              : {
    2510            1 :     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            1 : PQsendDescribePortal(PGconn *conn, const char *portal)
    2522              : {
    2523            1 :     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            1 : PQclosePrepared(PGconn *conn, const char *stmt)
    2539              : {
    2540            1 :     if (!PQexecStart(conn))
    2541            0 :         return NULL;
    2542            1 :     if (!PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt))
    2543            0 :         return NULL;
    2544            1 :     return PQexecFinish(conn);
    2545              : }
    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            1 : PQclosePortal(PGconn *conn, const char *portal)
    2557              : {
    2558            1 :     if (!PQexecStart(conn))
    2559            0 :         return NULL;
    2560            1 :     if (!PQsendTypedCommand(conn, PqMsg_Close, 'P', portal))
    2561            0 :         return NULL;
    2562            1 :     return PQexecFinish(conn);
    2563              : }
    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           20 : PQsendClosePrepared(PGconn *conn, const char *stmt)
    2574              : {
    2575           20 :     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            1 : PQsendClosePortal(PGconn *conn, const char *portal)
    2587              : {
    2588            1 :     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           96 : PQsendTypedCommand(PGconn *conn, char command, char type, const char *target)
    2607              : {
    2608           96 :     PGcmdQueueEntry *entry = NULL;
    2609              : 
    2610              :     /* Treat null target as empty string */
    2611           96 :     if (!target)
    2612            0 :         target = "";
    2613              : 
    2614           96 :     if (!PQsendQueryStart(conn, true))
    2615            0 :         return 0;
    2616              : 
    2617           96 :     entry = pqAllocCmdQueueEntry(conn);
    2618           96 :     if (entry == NULL)
    2619            0 :         return 0;               /* error msg already set */
    2620              : 
    2621              :     /* construct the Close message */
    2622          192 :     if (pqPutMsgStart(command, conn) < 0 ||
    2623          192 :         pqPutc(type, conn) < 0 ||
    2624          192 :         pqPuts(target, conn) < 0 ||
    2625           96 :         pqPutMsgEnd(conn) < 0)
    2626            0 :         goto sendFailed;
    2627              : 
    2628              :     /* construct the Sync message */
    2629           96 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    2630              :     {
    2631          166 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    2632           83 :             pqPutMsgEnd(conn) < 0)
    2633            0 :             goto sendFailed;
    2634              :     }
    2635              : 
    2636              :     /* remember if we are doing a Close or a Describe */
    2637           96 :     if (command == PqMsg_Close)
    2638              :     {
    2639           23 :         entry->queryclass = PGQUERY_CLOSE;
    2640              :     }
    2641           73 :     else if (command == PqMsg_Describe)
    2642              :     {
    2643           73 :         entry->queryclass = PGQUERY_DESCRIBE;
    2644              :     }
    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           96 :     if (pqPipelineFlush(conn) < 0)
    2657            0 :         goto sendFailed;
    2658              : 
    2659              :     /* OK, it's launched! */
    2660           96 :     pqAppendCmdQueueEntry(conn, entry);
    2661              : 
    2662           96 :     return 1;
    2663              : 
    2664            0 : sendFailed:
    2665            0 :     pqRecycleCmdQueueEntry(conn, entry);
    2666              :     /* error message should be set up already */
    2667            0 :     return 0;
    2668              : }
    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       209109 : PQnotifies(PGconn *conn)
    2685              : {
    2686              :     PGnotify   *event;
    2687              : 
    2688       209109 :     if (!conn)
    2689            0 :         return NULL;
    2690              : 
    2691              :     /* Parse any available data to see if we can extract NOTIFY messages. */
    2692       209109 :     parseInput(conn);
    2693              : 
    2694       209109 :     event = conn->notifyHead;
    2695       209109 :     if (event)
    2696              :     {
    2697           65 :         conn->notifyHead = event->next;
    2698           65 :         if (!conn->notifyHead)
    2699           26 :             conn->notifyTail = NULL;
    2700           65 :         event->next = NULL;      /* don't let app see the internal state */
    2701              :     }
    2702       209109 :     return event;
    2703              : }
    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       302047 : PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
    2713              : {
    2714       302047 :     if (!conn)
    2715            0 :         return -1;
    2716       302047 :     if (conn->asyncStatus != PGASYNC_COPY_IN &&
    2717       101345 :         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       302047 :     parseInput(conn);
    2732              : 
    2733       302047 :     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       302047 :         if ((conn->outBufSize - conn->outCount - 5) < nbytes)
    2742              :         {
    2743           23 :             if (pqFlush(conn) < 0)
    2744            0 :                 return -1;
    2745           23 :             if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes,
    2746              :                                       conn))
    2747            0 :                 return pqIsnonblocking(conn) ? 0 : -1;
    2748              :         }
    2749              :         /* Send the data (too simple to delegate to fe-protocol files) */
    2750       604094 :         if (pqPutMsgStart(PqMsg_CopyData, conn) < 0 ||
    2751       604094 :             pqPutnchar(buffer, nbytes, conn) < 0 ||
    2752       302047 :             pqPutMsgEnd(conn) < 0)
    2753            0 :             return -1;
    2754              :     }
    2755       302047 :     return 1;
    2756              : }
    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          947 : PQputCopyEnd(PGconn *conn, const char *errormsg)
    2767              : {
    2768          947 :     if (!conn)
    2769            0 :         return -1;
    2770          947 :     if (conn->asyncStatus != PGASYNC_COPY_IN &&
    2771          379 :         conn->asyncStatus != PGASYNC_COPY_BOTH)
    2772              :     {
    2773           39 :         libpq_append_conn_error(conn, "no COPY in progress");
    2774           39 :         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          908 :     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              :     }
    2789              :     else
    2790              :     {
    2791              :         /* Send COPY DONE */
    2792         1816 :         if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
    2793          908 :             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          908 :     if (conn->cmd_queue_head &&
    2802          908 :         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              :     }
    2808              : 
    2809              :     /* Return to active duty */
    2810          908 :     if (conn->asyncStatus == PGASYNC_COPY_BOTH)
    2811          340 :         conn->asyncStatus = PGASYNC_COPY_OUT;
    2812              :     else
    2813          568 :         conn->asyncStatus = PGASYNC_BUSY;
    2814              : 
    2815              :     /* Try to flush data */
    2816          908 :     if (pqFlush(conn) < 0)
    2817            0 :         return -1;
    2818              : 
    2819          908 :     return 1;
    2820              : }
    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      2769388 : PQgetCopyData(PGconn *conn, char **buffer, int async)
    2834              : {
    2835      2769388 :     *buffer = NULL;             /* for all failure cases */
    2836      2769388 :     if (!conn)
    2837            0 :         return -2;
    2838      2769388 :     if (conn->asyncStatus != PGASYNC_COPY_OUT &&
    2839       577112 :         conn->asyncStatus != PGASYNC_COPY_BOTH)
    2840              :     {
    2841            0 :         libpq_append_conn_error(conn, "no COPY in progress");
    2842            0 :         return -2;
    2843              :     }
    2844      2769388 :     return pqGetCopyData3(conn, buffer, async);
    2845              : }
    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              : }
    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              : }
    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       200028 : PQputline(PGconn *conn, const char *string)
    2936              : {
    2937       200028 :     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       200028 : PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
    2946              : {
    2947       200028 :     if (PQputCopyData(conn, buffer, nbytes) > 0)
    2948       200028 :         return 0;
    2949              :     else
    2950            0 :         return EOF;
    2951              : }
    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          193 : PQendcopy(PGconn *conn)
    2967              : {
    2968          193 :     if (!conn)
    2969            0 :         return 0;
    2970              : 
    2971          193 :     return pqEndcopy3(conn);
    2972              : }
    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         1070 : 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         1070 :     *result_len = 0;
    3006              : 
    3007         1070 :     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         1070 :     if (conn->cmd_queue_head == NULL)
    3016         1070 :         pqClearConnErrorState(conn);
    3017              : 
    3018         1070 :     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         1070 :     if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
    3025         1070 :         pgHavePendingResult(conn))
    3026              :     {
    3027            0 :         libpq_append_conn_error(conn, "connection in wrong state");
    3028            0 :         return NULL;
    3029              :     }
    3030              : 
    3031         1070 :     return pqFunctionCall3(conn, fnid,
    3032              :                            result_buf, result_len,
    3033              :                            result_is_int,
    3034              :                            args, nargs);
    3035              : }
    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          219 : PQenterPipelineMode(PGconn *conn)
    3060              : {
    3061          219 :     if (!conn)
    3062            0 :         return 0;
    3063              : 
    3064              :     /* succeed with no action if already in pipeline mode */
    3065          219 :     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    3066            4 :         return 1;
    3067              : 
    3068          215 :     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          215 :     conn->pipelineStatus = PQ_PIPELINE_ON;
    3075              : 
    3076          215 :     return 1;
    3077              : }
    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          206 : PQexitPipelineMode(PGconn *conn)
    3091              : {
    3092          206 :     if (!conn)
    3093            0 :         return 0;
    3094              : 
    3095          206 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF &&
    3096            1 :         (conn->asyncStatus == PGASYNC_IDLE ||
    3097            0 :          conn->asyncStatus == PGASYNC_PIPELINE_IDLE) &&
    3098            1 :         conn->cmd_queue_head == NULL)
    3099            1 :         return 1;
    3100              : 
    3101          205 :     switch (conn->asyncStatus)
    3102              :     {
    3103            0 :         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            5 :         case PGASYNC_BUSY:
    3110            5 :             libpq_append_conn_error(conn, "cannot exit pipeline mode while busy");
    3111            5 :             return 0;
    3112              : 
    3113          200 :         case PGASYNC_IDLE:
    3114              :         case PGASYNC_PIPELINE_IDLE:
    3115              :             /* OK */
    3116          200 :             break;
    3117              : 
    3118            0 :         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              :     }
    3123              : 
    3124              :     /* still work to process */
    3125          200 :     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          200 :     conn->pipelineStatus = PQ_PIPELINE_OFF;
    3132          200 :     conn->asyncStatus = PGASYNC_IDLE;
    3133              : 
    3134              :     /* Flush any pending data in out buffer */
    3135          200 :     if (pqFlush(conn) < 0)
    3136            0 :         return 0;               /* error message is setup already */
    3137          200 :     return 1;
    3138              : }
    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       710760 : pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
    3160              : {
    3161              :     PGcmdQueueEntry *prevquery;
    3162              : 
    3163       710760 :     if (conn->cmd_queue_head == NULL)
    3164        25526 :         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       685234 :     if (conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE && !isReadyForQuery)
    3171       345993 :         return;
    3172              : 
    3173              :     /*
    3174              :      * If we're waiting for a SYNC, don't advance the queue until we get one.
    3175              :      */
    3176       339241 :     if (conn->cmd_queue_head->queryclass == PGQUERY_SYNC && !gotSync)
    3177            0 :         return;
    3178              : 
    3179              :     /* delink element from queue */
    3180       339241 :     prevquery = conn->cmd_queue_head;
    3181       339241 :     conn->cmd_queue_head = conn->cmd_queue_head->next;
    3182              : 
    3183              :     /* If the queue is now empty, reset the tail too */
    3184       339241 :     if (conn->cmd_queue_head == NULL)
    3185       336980 :         conn->cmd_queue_tail = NULL;
    3186              : 
    3187              :     /* and make the queue element recyclable */
    3188       339241 :     prevquery->next = NULL;
    3189       339241 :     pqRecycleCmdQueueEntry(conn, prevquery);
    3190              : }
    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         2515 : pqPipelineProcessQueue(PGconn *conn)
    3198              : {
    3199         2515 :     switch (conn->asyncStatus)
    3200              :     {
    3201            0 :         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            9 :         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            9 :             if (conn->cmd_queue_head != NULL)
    3218              :             {
    3219            9 :                 conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
    3220            9 :                 break;
    3221              :             }
    3222            0 :             return;
    3223              : 
    3224         2506 :         case PGASYNC_PIPELINE_IDLE:
    3225              :             Assert(conn->pipelineStatus != PQ_PIPELINE_OFF);
    3226              :             /* next query please */
    3227         2506 :             break;
    3228              :     }
    3229              : 
    3230              :     /*
    3231              :      * Reset partial-result mode.  (Client has to set it up for each query, if
    3232              :      * desired.)
    3233              :      */
    3234         2515 :     conn->partialResMode = false;
    3235         2515 :     conn->singleRowMode = false;
    3236         2515 :     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         2515 :     if (conn->cmd_queue_head == NULL)
    3243              :     {
    3244          245 :         conn->asyncStatus = PGASYNC_IDLE;
    3245          245 :         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         2270 :     pqClearConnErrorState(conn);
    3253              : 
    3254              :     /* Initialize async result-accumulation state */
    3255         2270 :     pqClearAsyncResult(conn);
    3256              : 
    3257         2270 :     if (conn->pipelineStatus == PQ_PIPELINE_ABORTED &&
    3258          302 :         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          254 :         conn->result = PQmakeEmptyPGresult(conn, PGRES_PIPELINE_ABORTED);
    3269          254 :         if (!conn->result)
    3270              :         {
    3271            0 :             libpq_append_conn_error(conn, "out of memory");
    3272            0 :             pqSaveErrorResult(conn);
    3273            0 :             return;
    3274              :         }
    3275          254 :         conn->asyncStatus = PGASYNC_READY;
    3276              :     }
    3277              :     else
    3278              :     {
    3279              :         /* allow parsing to continue */
    3280         2016 :         conn->asyncStatus = PGASYNC_BUSY;
    3281              :     }
    3282              : }
    3283              : 
    3284              : /*
    3285              :  * PQpipelineSync
    3286              :  *      Send a Sync message as part of a pipeline, and flush to server
    3287              :  */
    3288              : int
    3289          217 : PQpipelineSync(PGconn *conn)
    3290              : {
    3291          217 :     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           60 : PQsendPipelineSync(PGconn *conn)
    3300              : {
    3301           60 :     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          277 : pqPipelineSyncInternal(PGconn *conn, bool immediate_flush)
    3312              : {
    3313              :     PGcmdQueueEntry *entry;
    3314              : 
    3315          277 :     if (!conn)
    3316            0 :         return 0;
    3317              : 
    3318          277 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    3319              :     {
    3320            3 :         libpq_append_conn_error(conn, "cannot send pipeline when not in pipeline mode");
    3321            3 :         return 0;
    3322              :     }
    3323              : 
    3324          274 :     switch (conn->asyncStatus)
    3325              :     {
    3326            0 :         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          274 :         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          274 :             break;
    3340              :     }
    3341              : 
    3342          274 :     entry = pqAllocCmdQueueEntry(conn);
    3343          274 :     if (entry == NULL)
    3344            0 :         return 0;               /* error msg already set */
    3345              : 
    3346          274 :     entry->queryclass = PGQUERY_SYNC;
    3347          274 :     entry->query = NULL;
    3348              : 
    3349              :     /* construct the Sync message */
    3350          548 :     if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    3351          274 :         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          274 :     if (immediate_flush)
    3361              :     {
    3362          214 :         if (pqFlush(conn) < 0)
    3363            0 :             goto sendFailed;
    3364              :     }
    3365              :     else
    3366              :     {
    3367           60 :         if (pqPipelineFlush(conn) < 0)
    3368            0 :             goto sendFailed;
    3369              :     }
    3370              : 
    3371              :     /* OK, it's launched! */
    3372          274 :     pqAppendCmdQueueEntry(conn, entry);
    3373              : 
    3374          274 :     return 1;
    3375              : 
    3376            0 : sendFailed:
    3377            0 :     pqRecycleCmdQueueEntry(conn, entry);
    3378              :     /* error message should be set up already */
    3379            0 :     return 0;
    3380              : }
    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           35 : PQsendFlushRequest(PGconn *conn)
    3389              : {
    3390           35 :     if (!conn)
    3391            0 :         return 0;
    3392              : 
    3393              :     /* Don't try to send if we know there's no live connection. */
    3394           35 :     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           35 :     if (conn->asyncStatus != PGASYNC_IDLE &&
    3402           35 :         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           70 :     if (pqPutMsgStart(PqMsg_Flush, conn) < 0 ||
    3409           35 :         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           35 :     if (pqPipelineFlush(conn) < 0)
    3420            0 :         return 0;
    3421              : 
    3422           35 :     return 1;
    3423              : }
    3424              : 
    3425              : /* ====== accessor funcs for PGresult ======== */
    3426              : 
    3427              : ExecStatusType
    3428      1303044 : PQresultStatus(const PGresult *res)
    3429              : {
    3430      1303044 :     if (!res)
    3431          115 :         return PGRES_FATAL_ERROR;
    3432      1302929 :     return res->resultStatus;
    3433              : }
    3434              : 
    3435              : char *
    3436           22 : PQresStatus(ExecStatusType status)
    3437              : {
    3438           22 :     if ((unsigned int) status >= lengthof(pgresStatus))
    3439            0 :         return libpq_gettext("invalid ExecStatusType code");
    3440           22 :     return pgresStatus[status];
    3441              : }
    3442              : 
    3443              : char *
    3444       101192 : PQresultErrorMessage(const PGresult *res)
    3445              : {
    3446       101192 :     if (!res || !res->errMsg)
    3447            1 :         return "";
    3448       101191 :     return res->errMsg;
    3449              : }
    3450              : 
    3451              : char *
    3452            3 : PQresultVerboseErrorMessage(const PGresult *res,
    3453              :                             PGVerbosity verbosity,
    3454              :                             PGContextVisibility show_context)
    3455              : {
    3456              :     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            3 :     if (!res ||
    3464            3 :         (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            3 :     initPQExpBuffer(&workBuf);
    3469              : 
    3470            3 :     pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
    3471              : 
    3472              :     /* If insufficient memory to format the message, fail cleanly */
    3473            3 :     if (PQExpBufferDataBroken(workBuf))
    3474              :     {
    3475            0 :         termPQExpBuffer(&workBuf);
    3476            0 :         return strdup(libpq_gettext("out of memory\n"));
    3477              :     }
    3478              : 
    3479            3 :     return workBuf.data;
    3480              : }
    3481              : 
    3482              : char *
    3483       777728 : PQresultErrorField(const PGresult *res, int fieldcode)
    3484              : {
    3485              :     PGMessageField *pfield;
    3486              : 
    3487       777728 :     if (!res)
    3488           20 :         return NULL;
    3489      5864051 :     for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
    3490              :     {
    3491      5417063 :         if (pfield->code == fieldcode)
    3492       330720 :             return pfield->contents;
    3493              :     }
    3494       446988 :     return NULL;
    3495              : }
    3496              : 
    3497              : int
    3498       210183 : PQntuples(const PGresult *res)
    3499              : {
    3500       210183 :     if (!res)
    3501         1875 :         return 0;
    3502       208308 :     return res->ntups;
    3503              : }
    3504              : 
    3505              : int
    3506       183392 : PQnfields(const PGresult *res)
    3507              : {
    3508       183392 :     if (!res)
    3509            0 :         return 0;
    3510       183392 :     return res->numAttributes;
    3511              : }
    3512              : 
    3513              : int
    3514          493 : PQbinaryTuples(const PGresult *res)
    3515              : {
    3516          493 :     if (!res)
    3517            0 :         return 0;
    3518          493 :     return res->binary;
    3519              : }
    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      2622044 : check_field_number(const PGresult *res, int field_num)
    3528              : {
    3529      2622044 :     if (!res)
    3530            0 :         return false;           /* no way to display error message... */
    3531      2622044 :     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      2622044 :     return true;
    3539              : }
    3540              : 
    3541              : static int
    3542     24949668 : check_tuple_field_number(const PGresult *res,
    3543              :                          int tup_num, int field_num)
    3544              : {
    3545     24949668 :     if (!res)
    3546            0 :         return false;           /* no way to display error message... */
    3547     24949668 :     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     24949668 :     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     24949668 :     return true;
    3562              : }
    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              : }
    3579              : 
    3580              : /*
    3581              :  * returns NULL if the field_num is invalid
    3582              :  */
    3583              : char *
    3584       145722 : PQfname(const PGresult *res, int field_num)
    3585              : {
    3586       145722 :     if (!check_field_number(res, field_num))
    3587            0 :         return NULL;
    3588       145722 :     if (res->attDescs)
    3589       145722 :         return res->attDescs[field_num].name;
    3590              :     else
    3591            0 :         return NULL;
    3592              : }
    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       263056 : PQfnumber(const PGresult *res, const char *field_name)
    3607              : {
    3608              :     char       *field_case;
    3609              :     bool        in_quotes;
    3610       263056 :     bool        all_lower = true;
    3611              :     const char *iptr;
    3612              :     char       *optr;
    3613              :     int         i;
    3614              : 
    3615       263056 :     if (!res)
    3616        15844 :         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       247212 :     if (field_name == NULL ||
    3623       247212 :         field_name[0] == '\0' ||
    3624       247212 :         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      2734982 :     for (iptr = field_name; *iptr; iptr++)
    3632              :     {
    3633      2487770 :         char        c = *iptr;
    3634              : 
    3635      2487770 :         if (c == '"' || c != pg_tolower((unsigned char) c))
    3636              :         {
    3637            0 :             all_lower = false;
    3638            0 :             break;
    3639              :         }
    3640              :     }
    3641              : 
    3642       247212 :     if (all_lower)
    3643      1927735 :         for (i = 0; i < res->numAttributes; i++)
    3644      1927735 :             if (strcmp(field_name, res->attDescs[i].name) == 0)
    3645       247212 :                 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              :                 }
    3674              :                 else
    3675            0 :                     in_quotes = false;
    3676              :             }
    3677              :             else
    3678            0 :                 *optr++ = c;
    3679              :         }
    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              :     }
    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              :     }
    3698            0 :     free(field_case);
    3699            0 :     return -1;
    3700              : }
    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              : }
    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              : }
    3723              : 
    3724              : int
    3725         6857 : PQfformat(const PGresult *res, int field_num)
    3726              : {
    3727         6857 :     if (!check_field_number(res, field_num))
    3728            0 :         return 0;
    3729         6857 :     if (res->attDescs)
    3730         6857 :         return res->attDescs[field_num].format;
    3731              :     else
    3732            0 :         return 0;
    3733              : }
    3734              : 
    3735              : Oid
    3736      2469070 : PQftype(const PGresult *res, int field_num)
    3737              : {
    3738      2469070 :     if (!check_field_number(res, field_num))
    3739            0 :         return InvalidOid;
    3740      2469070 :     if (res->attDescs)
    3741      2469070 :         return res->attDescs[field_num].typid;
    3742              :     else
    3743            0 :         return InvalidOid;
    3744              : }
    3745              : 
    3746              : int
    3747          160 : PQfsize(const PGresult *res, int field_num)
    3748              : {
    3749          160 :     if (!check_field_number(res, field_num))
    3750            0 :         return 0;
    3751          160 :     if (res->attDescs)
    3752          160 :         return res->attDescs[field_num].typlen;
    3753              :     else
    3754            0 :         return 0;
    3755              : }
    3756              : 
    3757              : int
    3758          235 : PQfmod(const PGresult *res, int field_num)
    3759              : {
    3760          235 :     if (!check_field_number(res, field_num))
    3761            0 :         return 0;
    3762          235 :     if (res->attDescs)
    3763          235 :         return res->attDescs[field_num].atttypmod;
    3764              :     else
    3765            0 :         return 0;
    3766              : }
    3767              : 
    3768              : char *
    3769       342275 : PQcmdStatus(PGresult *res)
    3770              : {
    3771       342275 :     if (!res)
    3772            0 :         return NULL;
    3773       342275 :     return res->cmdStatus;
    3774              : }
    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              :     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              : }
    3803              : 
    3804              : /*
    3805              :  * PQoidValue -
    3806              :  *  a perhaps preferable form of the above which just returns
    3807              :  *  an Oid type
    3808              :  */
    3809              : Oid
    3810        99381 : PQoidValue(const PGresult *res)
    3811              : {
    3812        99381 :     char       *endptr = NULL;
    3813              :     unsigned long result;
    3814              : 
    3815        99381 :     if (!res ||
    3816        99381 :         strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
    3817        18104 :         res->cmdStatus[7] < '0' ||
    3818        18104 :         res->cmdStatus[7] > '9')
    3819        81277 :         return InvalidOid;
    3820              : 
    3821        18104 :     result = strtoul(res->cmdStatus + 7, &endptr, 10);
    3822              : 
    3823        18104 :     if (!endptr || (*endptr != ' ' && *endptr != '\0'))
    3824            0 :         return InvalidOid;
    3825              :     else
    3826        18104 :         return (Oid) result;
    3827              : }
    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       172429 : PQcmdTuples(PGresult *res)
    3840              : {
    3841              :     char       *p,
    3842              :                *c;
    3843              : 
    3844       172429 :     if (!res)
    3845          259 :         return "";
    3846              : 
    3847       172170 :     if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
    3848              :     {
    3849        18908 :         p = res->cmdStatus + 7;
    3850              :         /* INSERT: skip oid and space */
    3851        37816 :         while (*p && *p != ' ')
    3852        18908 :             p++;
    3853        18908 :         if (*p == 0)
    3854            0 :             goto interpret_error;   /* no space? */
    3855        18908 :         p++;
    3856              :     }
    3857       153262 :     else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
    3858        88924 :              strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
    3859        87494 :              strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
    3860        68402 :         p = res->cmdStatus + 7;
    3861        84860 :     else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0 ||
    3862        84132 :              strncmp(res->cmdStatus, "MERGE ", 6) == 0)
    3863         1230 :         p = res->cmdStatus + 6;
    3864        83630 :     else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
    3865        83596 :              strncmp(res->cmdStatus, "COPY ", 5) == 0)
    3866          590 :         p = res->cmdStatus + 5;
    3867              :     else
    3868        83040 :         return "";
    3869              : 
    3870              :     /* check that we have an integer (at least one digit, nothing else) */
    3871       187976 :     for (c = p; *c; c++)
    3872              :     {
    3873        98846 :         if (!isdigit((unsigned char) *c))
    3874            0 :             goto interpret_error;
    3875              :     }
    3876        89130 :     if (c == p)
    3877            0 :         goto interpret_error;
    3878              : 
    3879        89130 :     return p;
    3880              : 
    3881            0 : interpret_error:
    3882            0 :     pqInternalNotice(&res->noticeHooks,
    3883              :                      "could not interpret result from server: %s",
    3884            0 :                      res->cmdStatus);
    3885            0 :     return "";
    3886              : }
    3887              : 
    3888              : /*
    3889              :  * PQgetvalue:
    3890              :  *  return the value of field 'field_num' of row 'tup_num'
    3891              :  */
    3892              : char *
    3893     21536653 : PQgetvalue(const PGresult *res, int tup_num, int field_num)
    3894              : {
    3895     21536653 :     if (!check_tuple_field_number(res, tup_num, field_num))
    3896            0 :         return NULL;
    3897     21536653 :     return res->tuples[tup_num][field_num].value;
    3898              : }
    3899              : 
    3900              : /* PQgetlength:
    3901              :  *  returns the actual length of a field value in bytes.
    3902              :  */
    3903              : int
    3904        20812 : PQgetlength(const PGresult *res, int tup_num, int field_num)
    3905              : {
    3906        20812 :     if (!check_tuple_field_number(res, tup_num, field_num))
    3907            0 :         return 0;
    3908        20812 :     if (res->tuples[tup_num][field_num].len != NULL_LEN)
    3909        20586 :         return res->tuples[tup_num][field_num].len;
    3910              :     else
    3911          226 :         return 0;
    3912              : }
    3913              : 
    3914              : /* PQgetisnull:
    3915              :  *  returns the null status of a field value.
    3916              :  */
    3917              : int
    3918      3392203 : PQgetisnull(const PGresult *res, int tup_num, int field_num)
    3919              : {
    3920      3392203 :     if (!check_tuple_field_number(res, tup_num, field_num))
    3921            0 :         return 1;               /* pretend it is null */
    3922      3392203 :     if (res->tuples[tup_num][field_num].len == NULL_LEN)
    3923       610784 :         return 1;
    3924              :     else
    3925      2781419 :         return 0;
    3926              : }
    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              : }
    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              : }
    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            5 : PQsetnonblocking(PGconn *conn, int arg)
    3962              : {
    3963              :     bool        barg;
    3964              : 
    3965            5 :     if (!conn || conn->status == CONNECTION_BAD)
    3966            0 :         return -1;
    3967              : 
    3968            5 :     barg = (arg ? true : false);
    3969              : 
    3970              :     /* early out if the socket is already in the state requested */
    3971            5 :     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            5 :     if (conn->cmd_queue_head == NULL)
    3984            4 :         pqClearConnErrorState(conn);
    3985              : 
    3986              :     /* if we are going from blocking to non-blocking flush here */
    3987            5 :     if (pqFlush(conn))
    3988            0 :         return -1;
    3989              : 
    3990            5 :     conn->nonblocking = barg;
    3991              : 
    3992            5 :     return 0;
    3993              : }
    3994              : 
    3995              : /*
    3996              :  * return the blocking status of the database connection
    3997              :  *      true == nonblocking, false == blocking
    3998              :  */
    3999              : int
    4000            2 : PQisnonblocking(const PGconn *conn)
    4001              : {
    4002            2 :     if (!conn || conn->status == CONNECTION_BAD)
    4003            0 :         return false;
    4004            2 :     return pqIsnonblocking(conn);
    4005              : }
    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       107852 : PQflush(PGconn *conn)
    4018              : {
    4019       107852 :     if (!conn || conn->status == CONNECTION_BAD)
    4020            0 :         return -1;
    4021       107852 :     return pqFlush(conn);
    4022              : }
    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        13631 : pqPipelineFlush(PGconn *conn)
    4034              : {
    4035        13631 :     if ((conn->pipelineStatus != PQ_PIPELINE_ON) ||
    4036         2325 :         (conn->outCount >= OUTBUFFER_THRESHOLD))
    4037        11306 :         return pqFlush(conn);
    4038         2325 :     return 0;
    4039              : }
    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      2559540 : PQfreemem(void *ptr)
    4050              : {
    4051      2559540 :     free(ptr);
    4052      2559540 : }
    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         6502 : PQescapeStringInternal(PGconn *conn,
    4089              :                        char *to, const char *from, size_t length,
    4090              :                        int *error,
    4091              :                        int encoding, bool std_strings)
    4092              : {
    4093         6502 :     const char *source = from;
    4094         6502 :     char       *target = to;
    4095         6502 :     size_t      remaining = strnlen(from, length);
    4096         6502 :     bool        already_complained = false;
    4097              : 
    4098         6502 :     if (error)
    4099           65 :         *error = 0;
    4100              : 
    4101       103124 :     while (remaining > 0)
    4102              :     {
    4103        96622 :         char        c = *source;
    4104              :         int         charlen;
    4105              :         int         i;
    4106              : 
    4107              :         /* Fast path for plain ASCII */
    4108        96622 :         if (!IS_HIGHBIT_SET(c))
    4109              :         {
    4110              :             /* Apply quoting if needed */
    4111        95744 :             if (SQL_STR_DOUBLE(c, !std_strings))
    4112           48 :                 *target++ = c;
    4113              :             /* Copy the character */
    4114        95744 :             *target++ = c;
    4115        95744 :             source++;
    4116        95744 :             remaining--;
    4117        95744 :             continue;
    4118              :         }
    4119              : 
    4120              :         /* Slow path for possible multibyte characters */
    4121          878 :         charlen = pg_encoding_mblen_or_incomplete(encoding,
    4122              :                                                   source, remaining);
    4123              : 
    4124         1700 :         if (remaining < charlen ||
    4125          822 :             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           82 :             if (error)
    4154           41 :                 *error = 1;
    4155           82 :             if (conn && !already_complained)
    4156              :             {
    4157           41 :                 if (remaining < charlen)
    4158           28 :                     libpq_append_conn_error(conn, "incomplete multibyte character");
    4159              :                 else
    4160           13 :                     libpq_append_conn_error(conn, "invalid multibyte character");
    4161              :                 /* Issue a complaint only once per string */
    4162           41 :                 already_complained = true;
    4163              :             }
    4164              : 
    4165           82 :             pg_encoding_set_invalid(encoding, target);
    4166           82 :             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           82 :             source++;
    4174           82 :             remaining--;
    4175              :         }
    4176              :         else
    4177              :         {
    4178              :             /* Copy the character */
    4179         1618 :             for (i = 0; i < charlen; i++)
    4180              :             {
    4181          822 :                 *target++ = *source++;
    4182          822 :                 remaining--;
    4183              :             }
    4184              :         }
    4185              :     }
    4186              : 
    4187              :     /* Write the terminating NUL character. */
    4188         6502 :     *target = '\0';
    4189              : 
    4190         6502 :     return target - to;
    4191              : }
    4192              : 
    4193              : size_t
    4194         6437 : PQescapeStringConn(PGconn *conn,
    4195              :                    char *to, const char *from, size_t length,
    4196              :                    int *error)
    4197              : {
    4198         6437 :     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         6437 :     if (conn->cmd_queue_head == NULL)
    4208         6437 :         pqClearConnErrorState(conn);
    4209              : 
    4210         6437 :     return PQescapeStringInternal(conn, to, from, length, error,
    4211              :                                   conn->client_encoding,
    4212         6437 :                                   conn->std_strings);
    4213              : }
    4214              : 
    4215              : size_t
    4216           65 : PQescapeString(char *to, const char *from, size_t length)
    4217              : {
    4218           65 :     return PQescapeStringInternal(NULL, to, from, length, NULL,
    4219              :                                   static_client_encoding,
    4220              :                                   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         1962 : PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
    4232              : {
    4233              :     const char *s;
    4234              :     char       *result;
    4235              :     char       *rp;
    4236         1962 :     size_t      num_quotes = 0; /* single or double, depending on as_ident */
    4237         1962 :     size_t      num_backslashes = 0;
    4238         1962 :     size_t      input_len = strnlen(str, len);
    4239              :     size_t      result_size;
    4240         1962 :     char        quote_char = as_ident ? '"' : '\'';
    4241         1962 :     bool        validated_mb = false;
    4242              : 
    4243              :     /* We must have a connection, else fail immediately. */
    4244         1962 :     if (!conn)
    4245            0 :         return NULL;
    4246              : 
    4247         1962 :     if (conn->cmd_queue_head == NULL)
    4248         1962 :         pqClearConnErrorState(conn);
    4249              : 
    4250              :     /*
    4251              :      * Scan the string for characters that must be escaped and for invalidly
    4252              :      * encoded data.
    4253              :      */
    4254         1962 :     s = str;
    4255       470702 :     for (size_t remaining = input_len; remaining > 0; remaining--, s++)
    4256              :     {
    4257       468823 :         if (*s == quote_char)
    4258           93 :             ++num_quotes;
    4259       468730 :         else if (*s == '\\')
    4260          154 :             ++num_backslashes;
    4261       468576 :         else if (IS_HIGHBIT_SET(*s))
    4262              :         {
    4263              :             int         charlen;
    4264              : 
    4265              :             /* Slow path for possible multibyte characters */
    4266          111 :             charlen = pg_encoding_mblen_or_incomplete(conn->client_encoding,
    4267              :                                                       s, remaining);
    4268              : 
    4269          111 :             if (charlen > remaining)
    4270              :             {
    4271              :                 /* Multibyte character overruns allowable length. */
    4272           57 :                 libpq_append_conn_error(conn, "incomplete multibyte character");
    4273           57 :                 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           54 :             if (!validated_mb)
    4287              :             {
    4288           54 :                 if (pg_encoding_verifymbstr(conn->client_encoding, s, remaining)
    4289              :                     != remaining)
    4290              :                 {
    4291           26 :                     libpq_append_conn_error(conn, "invalid multibyte character");
    4292           26 :                     return NULL;
    4293              :                 }
    4294           28 :                 validated_mb = true;
    4295              :             }
    4296              : 
    4297              :             /* Adjust s, bearing in mind that for loop will increment it. */
    4298           28 :             s += charlen - 1;
    4299           28 :             remaining -= charlen - 1;
    4300              :         }
    4301              :     }
    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         3758 :     if (pg_add_size_overflow(input_len, num_quotes, &result_size) ||
    4308         1879 :         pg_add_size_overflow(result_size, 3, &result_size)) /* two quotes plus a NUL */
    4309            0 :         goto overflow;
    4310              : 
    4311         1879 :     if (!as_ident && num_backslashes > 0)
    4312              :     {
    4313           56 :         if (pg_add_size_overflow(result_size, num_backslashes, &result_size) ||
    4314           28 :             pg_add_size_overflow(result_size, 2, &result_size)) /* for " E" prefix */
    4315            0 :             goto overflow;
    4316              :     }
    4317              : 
    4318         1879 :     result = rp = (char *) malloc(result_size);
    4319         1879 :     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         1879 :     if (!as_ident && num_backslashes > 0)
    4333              :     {
    4334           28 :         *rp++ = ' ';
    4335           28 :         *rp++ = 'E';
    4336              :     }
    4337              : 
    4338              :     /* Opening quote. */
    4339         1879 :     *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         1879 :     if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
    4353              :     {
    4354         1827 :         memcpy(rp, str, input_len);
    4355         1827 :         rp += input_len;
    4356              :     }
    4357              :     else
    4358              :     {
    4359           52 :         s = str;
    4360         2967 :         for (size_t remaining = input_len; remaining > 0; remaining--, s++)
    4361              :         {
    4362         2915 :             if (*s == quote_char || (!as_ident && *s == '\\'))
    4363              :             {
    4364          225 :                 *rp++ = *s;
    4365          225 :                 *rp++ = *s;
    4366              :             }
    4367         2690 :             else if (!IS_HIGHBIT_SET(*s))
    4368         2679 :                 *rp++ = *s;
    4369              :             else
    4370              :             {
    4371           11 :                 int         i = pg_encoding_mblen(conn->client_encoding, s);
    4372              : 
    4373              :                 while (1)
    4374              :                 {
    4375           21 :                     *rp++ = *s;
    4376           21 :                     if (--i == 0)
    4377           11 :                         break;
    4378           10 :                     remaining--;
    4379           10 :                     ++s;        /* for loop will provide the final increment */
    4380              :                 }
    4381              :             }
    4382              :         }
    4383              :     }
    4384              : 
    4385              :     /* Closing quote and terminating NUL. */
    4386         1879 :     *rp++ = quote_char;
    4387         1879 :     *rp = '\0';
    4388              : 
    4389         1879 :     return result;
    4390              : 
    4391            0 : 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              : }
    4397              : 
    4398              : char *
    4399         1111 : PQescapeLiteral(PGconn *conn, const char *str, size_t len)
    4400              : {
    4401         1111 :     return PQescapeInternal(conn, str, len, false);
    4402              : }
    4403              : 
    4404              : char *
    4405          851 : PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
    4406              : {
    4407          851 :     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              : }
    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              :     const unsigned char *vp;
    4457              :     unsigned char *rp;
    4458              :     unsigned char *result;
    4459              :     size_t      i;
    4460              :     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              :     }
    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              :             }
    4491            0 :             else if (*vp == '\'')
    4492              :             {
    4493            0 :                 if (pg_add_size_overflow(len, 2, &len)) /* double each quote */
    4494            0 :                     goto overflow;
    4495              :             }
    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              :             }
    4501              :             else
    4502              :             {
    4503            0 :                 if (pg_add_size_overflow(len, 1, &len))
    4504            0 :                     goto overflow;
    4505              :             }
    4506              :         }
    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              :     }
    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              :         }
    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              :         }
    4545            0 :         else if (c == '\'')
    4546              :         {
    4547            0 :             *rp++ = '\'';
    4548            0 :             *rp++ = '\'';
    4549              :         }
    4550            0 :         else if (c == '\\')
    4551              :         {
    4552            0 :             if (!std_strings)
    4553              :             {
    4554            0 :                 *rp++ = '\\';
    4555            0 :                 *rp++ = '\\';
    4556              :             }
    4557            0 :             *rp++ = '\\';
    4558            0 :             *rp++ = '\\';
    4559              :         }
    4560              :         else
    4561            0 :             *rp++ = c;
    4562              :     }
    4563            0 :     *rp = '\0';
    4564              : 
    4565            0 :     return result;
    4566              : 
    4567            0 : 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              : }
    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              : }
    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              :                                  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              :     size_t      strtextlen,
    4620              :                 buflen;
    4621              :     unsigned char *buffer,
    4622              :                *tmpbuf;
    4623              :     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            0 :     {
    4633              :         const unsigned char *s;
    4634              :         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              :             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              :         }
    4660              : 
    4661            0 :         buflen = p - buffer;
    4662              :     }
    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            0 :                 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              :                             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              :                         }
    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            0 :                 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              : }
        

Generated by: LCOV version 2.0-1