LCOV - code coverage report
Current view: top level - src/interfaces/libpq - fe-exec.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 1006 1622 62.0 %
Date: 2025-12-03 22:17:38 Functions: 98 118 83.1 %
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-2025, 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     4061582 : PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
     161             : {
     162             :     PGresult   *result;
     163             : 
     164     4061582 :     result = (PGresult *) malloc(sizeof(PGresult));
     165     4061582 :     if (!result)
     166           0 :         return NULL;
     167             : 
     168     4061582 :     result->ntups = 0;
     169     4061582 :     result->numAttributes = 0;
     170     4061582 :     result->attDescs = NULL;
     171     4061582 :     result->tuples = NULL;
     172     4061582 :     result->tupArrSize = 0;
     173     4061582 :     result->numParameters = 0;
     174     4061582 :     result->paramDescs = NULL;
     175     4061582 :     result->resultStatus = status;
     176     4061582 :     result->cmdStatus[0] = '\0';
     177     4061582 :     result->binary = 0;
     178     4061582 :     result->events = NULL;
     179     4061582 :     result->nEvents = 0;
     180     4061582 :     result->errMsg = NULL;
     181     4061582 :     result->errFields = NULL;
     182     4061582 :     result->errQuery = NULL;
     183     4061582 :     result->null_field[0] = '\0';
     184     4061582 :     result->curBlock = NULL;
     185     4061582 :     result->curOffset = 0;
     186     4061582 :     result->spaceLeft = 0;
     187     4061582 :     result->memorySize = sizeof(PGresult);
     188             : 
     189     4061582 :     if (conn)
     190             :     {
     191             :         /* copy connection data we might need for operations on PGresult */
     192      856420 :         result->noticeHooks = conn->noticeHooks;
     193      856420 :         result->client_encoding = conn->client_encoding;
     194             : 
     195             :         /* consider copying conn's errorMessage */
     196      856420 :         switch (status)
     197             :         {
     198      855380 :             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      855380 :                 break;
     208        1040 :             default:
     209             :                 /* we intentionally do not use or modify errorReported here */
     210        1040 :                 pqSetResultError(result, &conn->errorMessage, 0);
     211        1040 :                 break;
     212             :         }
     213             : 
     214             :         /* copy events last; result must be valid if we need to PQclear */
     215      856420 :         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     3205162 :         result->noticeHooks.noticeRec = NULL;
     231     3205162 :         result->noticeHooks.noticeRecArg = NULL;
     232     3205162 :         result->noticeHooks.noticeProc = NULL;
     233     3205162 :         result->noticeHooks.noticeProcArg = NULL;
     234     3205162 :         result->client_encoding = PG_SQL_ASCII;
     235             :     }
     236             : 
     237     4061582 :     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        5094 : PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
     251             : {
     252             :     int         i;
     253             : 
     254             :     /* Fail if argument is NULL or OOM_result */
     255        5094 :     if (!res || (const PGresult *) res == &OOM_result)
     256           0 :         return false;
     257             : 
     258             :     /* If attrs already exist, they cannot be overwritten. */
     259        5094 :     if (res->numAttributes > 0)
     260           0 :         return false;
     261             : 
     262             :     /* ignore no-op request */
     263        5094 :     if (numAttributes <= 0 || !attDescs)
     264           0 :         return true;
     265             : 
     266        5094 :     res->attDescs = (PGresAttDesc *)
     267        5094 :         PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
     268             : 
     269        5094 :     if (!res->attDescs)
     270           0 :         return false;
     271             : 
     272        5094 :     res->numAttributes = numAttributes;
     273        5094 :     memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
     274             : 
     275             :     /* deep-copy the attribute names, and determine format */
     276        5094 :     res->binary = 1;
     277       20104 :     for (i = 0; i < res->numAttributes; i++)
     278             :     {
     279       15010 :         if (res->attDescs[i].name)
     280       15010 :             res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
     281             :         else
     282           0 :             res->attDescs[i].name = res->null_field;
     283             : 
     284       15010 :         if (!res->attDescs[i].name)
     285           0 :             return false;
     286             : 
     287       15010 :         if (res->attDescs[i].format == 0)
     288        1006 :             res->binary = 0;
     289             :     }
     290             : 
     291        5094 :     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        5094 : PQcopyResult(const PGresult *src, int flags)
     320             : {
     321             :     PGresult   *dest;
     322             :     int         i;
     323             : 
     324        5094 :     if (!src)
     325           0 :         return NULL;
     326             : 
     327        5094 :     dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK);
     328        5094 :     if (!dest)
     329           0 :         return NULL;
     330             : 
     331             :     /* Always copy these over.  Is cmdStatus really useful here? */
     332        5094 :     dest->client_encoding = src->client_encoding;
     333        5094 :     strcpy(dest->cmdStatus, src->cmdStatus);
     334             : 
     335             :     /* Wants attrs? */
     336        5094 :     if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
     337             :     {
     338        5094 :         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        5094 :     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        5094 :     if (flags & PG_COPYRES_NOTICEHOOKS)
     368        5094 :         dest->noticeHooks = src->noticeHooks;
     369             : 
     370             :     /* Wants to copy PGEvents? */
     371        5094 :     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        5094 :     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        5094 :     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        5094 : PQresultAlloc(PGresult *res, size_t nBytes)
     545             : {
     546             :     /* Fail if argument is NULL or OOM_result */
     547        5094 :     if (!res || (const PGresult *) res == &OOM_result)
     548           0 :         return NULL;
     549             : 
     550        5094 :     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    45246322 : pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
     565             : {
     566             :     char       *space;
     567             :     PGresult_data *block;
     568             : 
     569    45246322 :     if (!res)
     570           0 :         return NULL;
     571             : 
     572    45246322 :     if (nBytes <= 0)
     573         448 :         return res->null_field;
     574             : 
     575             :     /*
     576             :      * If alignment is needed, round up the current position to an alignment
     577             :      * boundary.
     578             :      */
     579    45245874 :     if (isBinary)
     580             :     {
     581     9284160 :         int         offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
     582             : 
     583     9284160 :         if (offset)
     584             :         {
     585     6985370 :             res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
     586     6985370 :             res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
     587             :         }
     588             :     }
     589             : 
     590             :     /* If there's enough space in the current block, no problem. */
     591    45245874 :     if (nBytes <= (size_t) res->spaceLeft)
     592             :     {
     593    44294554 :         space = res->curBlock->space + res->curOffset;
     594    44294554 :         res->curOffset += nBytes;
     595    44294554 :         res->spaceLeft -= nBytes;
     596    44294554 :         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      951320 :     if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
     606             :     {
     607             :         size_t      alloc_size;
     608             : 
     609             :         /* Don't wrap around with overly large requests. */
     610        5286 :         if (nBytes > SIZE_MAX - PGRESULT_BLOCK_OVERHEAD)
     611           0 :             return NULL;
     612             : 
     613        5286 :         alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
     614        5286 :         block = (PGresult_data *) malloc(alloc_size);
     615        5286 :         if (!block)
     616           0 :             return NULL;
     617        5286 :         res->memorySize += alloc_size;
     618        5286 :         space = block->space + PGRESULT_BLOCK_OVERHEAD;
     619        5286 :         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        4838 :             block->next = res->curBlock->next;
     626        4838 :             res->curBlock->next = block;
     627             :         }
     628             :         else
     629             :         {
     630             :             /* Must set up the new block as the first active block. */
     631         448 :             block->next = NULL;
     632         448 :             res->curBlock = block;
     633         448 :             res->spaceLeft = 0; /* be sure it's marked full */
     634             :         }
     635        5286 :         return space;
     636             :     }
     637             : 
     638             :     /* Otherwise, start a new block. */
     639      946034 :     block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
     640      946034 :     if (!block)
     641           0 :         return NULL;
     642      946034 :     res->memorySize += PGRESULT_DATA_BLOCKSIZE;
     643      946034 :     block->next = res->curBlock;
     644      946034 :     res->curBlock = block;
     645      946034 :     if (isBinary)
     646             :     {
     647             :         /* object needs full alignment */
     648      876414 :         res->curOffset = PGRESULT_BLOCK_OVERHEAD;
     649      876414 :         res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
     650             :     }
     651             :     else
     652             :     {
     653             :         /* we can cram it right after the overhead pointer */
     654       69620 :         res->curOffset = sizeof(PGresult_data);
     655       69620 :         res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
     656             :     }
     657             : 
     658      946034 :     space = block->space + res->curOffset;
     659      946034 :     res->curOffset += nBytes;
     660      946034 :     res->spaceLeft -= nBytes;
     661      946034 :     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     1097696 : pqResultStrdup(PGresult *res, const char *str)
     682             : {
     683     1097696 :     char       *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
     684             : 
     685     1097696 :     if (space)
     686     1097696 :         strcpy(space, str);
     687     1097696 :     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       46700 : pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
     699             : {
     700             :     char       *msg;
     701             : 
     702       46700 :     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       46700 :     if (!PQExpBufferBroken(errorMessage))
     713       46700 :         msg = pqResultStrdup(res, errorMessage->data + offset);
     714             :     else
     715           0 :         msg = NULL;
     716       46700 :     if (msg)
     717       46700 :         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     5809876 : PQclear(PGresult *res)
     728             : {
     729             :     PGresult_data *block;
     730             :     int         i;
     731             : 
     732             :     /* As a convenience, do nothing for a NULL pointer */
     733     5809876 :     if (!res)
     734     1751546 :         return;
     735             :     /* Also, do nothing if the argument is OOM_result */
     736     4058330 :     if ((const PGresult *) res == &OOM_result)
     737           0 :         return;
     738             : 
     739             :     /* Close down any events we may have */
     740     4058330 :     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     4058330 :     free(res->events);
     755             : 
     756             :     /* Free all the subsidiary blocks */
     757     5006214 :     while ((block = res->curBlock) != NULL)
     758             :     {
     759      947884 :         res->curBlock = block->next;
     760      947884 :         free(block);
     761             :     }
     762             : 
     763             :     /* Free the top-level tuple pointer array */
     764     4058330 :     free(res->tuples);
     765             : 
     766             :     /* zero out the pointer fields to catch programming errors */
     767     4058330 :     res->attDescs = NULL;
     768     4058330 :     res->tuples = NULL;
     769     4058330 :     res->paramDescs = NULL;
     770     4058330 :     res->errFields = NULL;
     771     4058330 :     res->events = NULL;
     772     4058330 :     res->nEvents = 0;
     773             :     /* res->curBlock was zeroed out earlier */
     774             : 
     775             :     /* Free the PGresult structure itself */
     776     4058330 :     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      786324 : pqClearAsyncResult(PGconn *conn)
     786             : {
     787      786324 :     PQclear(conn->result);
     788      786324 :     conn->result = NULL;
     789      786324 :     conn->error_result = false;
     790      786324 :     PQclear(conn->saved_result);
     791      786324 :     conn->saved_result = NULL;
     792      786324 : }
     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         114 : pqSaveErrorResult(PGconn *conn)
     810             : {
     811             :     /* Drop any pending result ... */
     812         114 :     pqClearAsyncResult(conn);
     813             :     /* ... and set flag to remember to make an error result later */
     814         114 :     conn->error_result = true;
     815         114 : }
     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           8 : 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           8 :     if (conn->write_err_msg)
     834             :     {
     835           8 :         appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg);
     836             :         /* Avoid possibly appending the same message twice */
     837           8 :         conn->write_err_msg[0] = '\0';
     838             :     }
     839             :     else
     840           0 :         libpq_append_conn_error(conn, "write to server failed");
     841             : 
     842           8 :     pqSaveErrorResult(conn);
     843           8 : }
     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      695574 : pqPrepareAsyncResult(PGconn *conn)
     858             : {
     859             :     PGresult   *res;
     860             : 
     861      695574 :     res = conn->result;
     862      695574 :     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      695460 :         if (res->resultStatus == PGRES_FATAL_ERROR)
     870       44778 :             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         114 :         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         114 :         if (conn->errorReported < 0 ||
     884         114 :             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         114 :         res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
     893         114 :         if (res)
     894             :         {
     895             :             /*
     896             :              * Report whatever new error text we have, and advance
     897             :              * errorReported.
     898             :              */
     899         114 :             res->resultStatus = PGRES_FATAL_ERROR;
     900         114 :             pqSetResultError(res, &conn->errorMessage, conn->errorReported);
     901         114 :             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      695574 :     conn->result = conn->saved_result;
     928      695574 :     conn->error_result = false; /* saved_result is never an error */
     929      695574 :     conn->saved_result = NULL;
     930             : 
     931      695574 :     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     7326902 : pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
    1000             : {
    1001     7326902 :     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      282666 :         if (res->tupArrSize <= INT_MAX / 2)
    1022      282666 :             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      282666 :         if (res->tuples == NULL)
    1045             :             newTuples = (PGresAttValue **)
    1046      268824 :                 malloc(newSize * sizeof(PGresAttValue *));
    1047             :         else
    1048             :             newTuples = (PGresAttValue **)
    1049       13842 :                 realloc(res->tuples, newSize * sizeof(PGresAttValue *));
    1050      282666 :         if (!newTuples)
    1051           0 :             return false;       /* malloc or realloc failed */
    1052      282666 :         res->memorySize +=
    1053      282666 :             (newSize - res->tupArrSize) * sizeof(PGresAttValue *);
    1054      282666 :         res->tupArrSize = newSize;
    1055      282666 :         res->tuples = newTuples;
    1056             :     }
    1057     7326902 :     res->tuples[res->ntups] = tup;
    1058     7326902 :     res->ntups++;
    1059     7326902 :     return true;
    1060             : }
    1061             : 
    1062             : /*
    1063             :  * pqSaveMessageField - save one field of an error or notice message
    1064             :  */
    1065             : void
    1066     1608674 : pqSaveMessageField(PGresult *res, char code, const char *value)
    1067             : {
    1068             :     PGMessageField *pfield;
    1069             : 
    1070             :     pfield = (PGMessageField *)
    1071     1608674 :         pqResultAlloc(res,
    1072             :                       offsetof(PGMessageField, contents) +
    1073     1608674 :                       strlen(value) + 1,
    1074             :                       true);
    1075     1608674 :     if (!pfield)
    1076           0 :         return;                 /* out of memory? */
    1077     1608674 :     pfield->code = code;
    1078     1608674 :     strcpy(pfield->contents, value);
    1079     1608674 :     pfield->next = res->errFields;
    1080     1608674 :     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      423216 : 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      423216 :     for (pstatus = conn->pstatus, prev = NULL;
    1100     3360208 :          pstatus != NULL;
    1101     2936992 :          prev = pstatus, pstatus = pstatus->next)
    1102             :     {
    1103     2951278 :         if (strcmp(pstatus->name, name) == 0)
    1104             :         {
    1105       14286 :             if (prev)
    1106        9904 :                 prev->next = pstatus->next;
    1107             :             else
    1108        4382 :                 conn->pstatus = pstatus->next;
    1109       14286 :             free(pstatus);      /* frees name and value strings too */
    1110       14286 :             break;
    1111             :         }
    1112             :     }
    1113             : 
    1114             :     /*
    1115             :      * Store new info as a single malloc block
    1116             :      */
    1117      423216 :     pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
    1118      423216 :                                            strlen(name) + strlen(value) + 2);
    1119      423216 :     if (pstatus)
    1120             :     {
    1121             :         char       *ptr;
    1122             : 
    1123      423216 :         ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
    1124      423216 :         pstatus->name = ptr;
    1125      423216 :         strcpy(ptr, name);
    1126      423216 :         ptr += strlen(name) + 1;
    1127      423216 :         pstatus->value = ptr;
    1128      423216 :         strcpy(ptr, value);
    1129      423216 :         pstatus->next = conn->pstatus;
    1130      423216 :         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      423216 :     if (strcmp(name, "client_encoding") == 0)
    1146             :     {
    1147       27328 :         conn->client_encoding = pg_char_to_encoding(value);
    1148             :         /* if we don't recognize the encoding name, fall back to SQL_ASCII */
    1149       27328 :         if (conn->client_encoding < 0)
    1150           0 :             conn->client_encoding = PG_SQL_ASCII;
    1151       27328 :         static_client_encoding = conn->client_encoding;
    1152             :     }
    1153      395888 :     else if (strcmp(name, "standard_conforming_strings") == 0)
    1154             :     {
    1155       27334 :         conn->std_strings = (strcmp(value, "on") == 0);
    1156       27334 :         static_std_strings = conn->std_strings;
    1157             :     }
    1158      368554 :     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       27262 :         cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
    1167             : 
    1168       27262 :         if (cnt == 3)
    1169             :         {
    1170             :             /* old style, e.g. 9.6.1 */
    1171           0 :             conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
    1172             :         }
    1173       27262 :         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       27262 :         else if (cnt == 1)
    1187             :         {
    1188             :             /* new style without minor version, e.g. 10devel */
    1189       27262 :             conn->sversion = 100 * 100 * vmaj;
    1190             :         }
    1191             :         else
    1192           0 :             conn->sversion = 0; /* unknown */
    1193             :     }
    1194      341292 :     else if (strcmp(name, "default_transaction_read_only") == 0)
    1195             :     {
    1196       27302 :         conn->default_transaction_read_only =
    1197       27302 :             (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
    1198             :     }
    1199      313990 :     else if (strcmp(name, "in_hot_standby") == 0)
    1200             :     {
    1201       27272 :         conn->in_hot_standby =
    1202       27272 :             (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
    1203             :     }
    1204      286718 :     else if (strcmp(name, "scram_iterations") == 0)
    1205             :     {
    1206       27274 :         conn->scram_sha_256_iterations = atoi(value);
    1207             :     }
    1208             : 
    1209      423216 :     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     7326902 : pqRowProcessor(PGconn *conn, const char **errmsgp)
    1224             : {
    1225     7326902 :     PGresult   *res = conn->result;
    1226     7326902 :     int         nfields = res->numAttributes;
    1227     7326902 :     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     7326902 :     if (conn->partialResMode && conn->saved_result == NULL)
    1240             :     {
    1241             :         /* Copy everything that should be in the result at this point */
    1242        5094 :         res = PQcopyResult(res,
    1243             :                            PG_COPYRES_ATTRS | PG_COPYRES_EVENTS |
    1244             :                            PG_COPYRES_NOTICEHOOKS);
    1245        5094 :         if (!res)
    1246           0 :             return 0;
    1247             :         /* Change result status to appropriate special value */
    1248        5094 :         res->resultStatus = (conn->singleRowMode ? PGRES_SINGLE_TUPLE : PGRES_TUPLES_CHUNK);
    1249             :         /* And stash it as the active result */
    1250        5094 :         conn->saved_result = conn->result;
    1251        5094 :         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     7326902 :         pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
    1265     7326902 :     if (tup == NULL)
    1266           0 :         return 0;
    1267             : 
    1268    44305620 :     for (i = 0; i < nfields; i++)
    1269             :     {
    1270    36978718 :         int         clen = columns[i].len;
    1271             : 
    1272    36978718 :         if (clen < 0)
    1273             :         {
    1274             :             /* null field */
    1275     2100646 :             tup[i].len = NULL_LEN;
    1276     2100646 :             tup[i].value = res->null_field;
    1277             :         }
    1278             :         else
    1279             :         {
    1280    34878072 :             bool        isbinary = (res->attDescs[i].format != 0);
    1281             :             char       *val;
    1282             : 
    1283    34878072 :             val = (char *) pqResultAlloc(res, (size_t) clen + 1, isbinary);
    1284    34878072 :             if (val == NULL)
    1285           0 :                 return 0;
    1286             : 
    1287             :             /* copy and zero-terminate the data (even if it's binary) */
    1288    34878072 :             memcpy(val, columns[i].value, clen);
    1289    34878072 :             val[clen] = '\0';
    1290             : 
    1291    34878072 :             tup[i].len = clen;
    1292    34878072 :             tup[i].value = val;
    1293             :         }
    1294             :     }
    1295             : 
    1296             :     /* And add the tuple to the PGresult's tuple array */
    1297     7326902 :     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     7326902 :     if (conn->partialResMode && res->ntups >= conn->maxChunkSize)
    1305        5068 :         conn->asyncStatus = PGASYNC_READY_MORE;
    1306             : 
    1307     7326902 :     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      638082 : pqAllocCmdQueueEntry(PGconn *conn)
    1324             : {
    1325             :     PGcmdQueueEntry *entry;
    1326             : 
    1327      638082 :     if (conn->cmd_queue_recycle == NULL)
    1328             :     {
    1329       28562 :         entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry));
    1330       28562 :         if (entry == NULL)
    1331             :         {
    1332           0 :             libpq_append_conn_error(conn, "out of memory");
    1333           0 :             return NULL;
    1334             :         }
    1335             :     }
    1336             :     else
    1337             :     {
    1338      609520 :         entry = conn->cmd_queue_recycle;
    1339      609520 :         conn->cmd_queue_recycle = entry->next;
    1340             :     }
    1341      638082 :     entry->next = NULL;
    1342      638082 :     entry->query = NULL;
    1343             : 
    1344      638082 :     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      638082 : pqAppendCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
    1357             : {
    1358             :     Assert(entry->next == NULL);
    1359             : 
    1360      638082 :     if (conn->cmd_queue_head == NULL)
    1361      633542 :         conn->cmd_queue_head = entry;
    1362             :     else
    1363        4540 :         conn->cmd_queue_tail->next = entry;
    1364             : 
    1365      638082 :     conn->cmd_queue_tail = entry;
    1366             : 
    1367      638082 :     switch (conn->pipelineStatus)
    1368             :     {
    1369      637950 :         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      637950 :             if (conn->asyncStatus == PGASYNC_IDLE)
    1379      633522 :                 conn->asyncStatus = PGASYNC_BUSY;
    1380      637950 :             break;
    1381             : 
    1382         132 :         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         132 :             if (conn->asyncStatus == PGASYNC_IDLE ||
    1392         112 :                 conn->asyncStatus == PGASYNC_PIPELINE_IDLE)
    1393          20 :                 pqPipelineProcessQueue(conn);
    1394         132 :             break;
    1395             :     }
    1396      638082 : }
    1397             : 
    1398             : /*
    1399             :  * pqRecycleCmdQueueEntry
    1400             :  *      Push a command queue entry onto the freelist.
    1401             :  */
    1402             : static void
    1403      635828 : pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
    1404             : {
    1405      635828 :     if (entry == NULL)
    1406           0 :         return;
    1407             : 
    1408             :     /* recyclable entries should not have a follow-on command */
    1409             :     Assert(entry->next == NULL);
    1410             : 
    1411      635828 :     if (entry->query)
    1412             :     {
    1413      619010 :         free(entry->query);
    1414      619010 :         entry->query = NULL;
    1415             :     }
    1416             : 
    1417      635828 :     entry->next = conn->cmd_queue_recycle;
    1418      635828 :     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      609964 : PQsendQuery(PGconn *conn, const char *query)
    1434             : {
    1435      609964 :     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      609964 : PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
    1446             : {
    1447      609964 :     PGcmdQueueEntry *entry = NULL;
    1448             : 
    1449      609964 :     if (!PQsendQueryStart(conn, newQuery))
    1450           0 :         return 0;
    1451             : 
    1452             :     /* check the argument */
    1453      609964 :     if (!query)
    1454             :     {
    1455           0 :         libpq_append_conn_error(conn, "command string is a null pointer");
    1456           0 :         return 0;
    1457             :     }
    1458             : 
    1459      609964 :     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    1460             :     {
    1461           2 :         libpq_append_conn_error(conn, "%s not allowed in pipeline mode",
    1462             :                                 "PQsendQuery");
    1463           2 :         return 0;
    1464             :     }
    1465             : 
    1466      609962 :     entry = pqAllocCmdQueueEntry(conn);
    1467      609962 :     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     1219924 :     if (pqPutMsgStart(PqMsg_Query, conn) < 0 ||
    1473     1219924 :         pqPuts(query, conn) < 0 ||
    1474      609962 :         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      609962 :     entry->queryclass = PGQUERY_SIMPLE;
    1483             :     /* and remember the query text too, if possible */
    1484      609962 :     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      609962 :     if (pqFlush(conn) < 0)
    1491           0 :         goto sendFailed;
    1492             : 
    1493             :     /* OK, it's launched! */
    1494      609962 :     pqAppendCmdQueueEntry(conn, entry);
    1495             : 
    1496      609962 :     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        6782 : 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        6782 :     if (!PQsendQueryStart(conn, true))
    1519           0 :         return 0;
    1520             : 
    1521             :     /* check the arguments */
    1522        6782 :     if (!command)
    1523             :     {
    1524           0 :         libpq_append_conn_error(conn, "command string is a null pointer");
    1525           0 :         return 0;
    1526             :     }
    1527        6782 :     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        6782 :     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        4504 : PQsendPrepare(PGconn *conn,
    1554             :               const char *stmtName, const char *query,
    1555             :               int nParams, const Oid *paramTypes)
    1556             : {
    1557        4504 :     PGcmdQueueEntry *entry = NULL;
    1558             : 
    1559        4504 :     if (!PQsendQueryStart(conn, true))
    1560           0 :         return 0;
    1561             : 
    1562             :     /* check the arguments */
    1563        4504 :     if (!stmtName)
    1564             :     {
    1565           0 :         libpq_append_conn_error(conn, "statement name is a null pointer");
    1566           0 :         return 0;
    1567             :     }
    1568        4504 :     if (!query)
    1569             :     {
    1570           0 :         libpq_append_conn_error(conn, "command string is a null pointer");
    1571           0 :         return 0;
    1572             :     }
    1573        4504 :     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        4504 :     entry = pqAllocCmdQueueEntry(conn);
    1581        4504 :     if (entry == NULL)
    1582           0 :         return 0;               /* error msg already set */
    1583             : 
    1584             :     /* construct the Parse message */
    1585        9008 :     if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
    1586        9008 :         pqPuts(stmtName, conn) < 0 ||
    1587        4504 :         pqPuts(query, conn) < 0)
    1588           0 :         goto sendFailed;
    1589             : 
    1590        4504 :     if (nParams > 0 && paramTypes)
    1591           6 :     {
    1592             :         int         i;
    1593             : 
    1594           6 :         if (pqPutInt(nParams, 2, conn) < 0)
    1595           0 :             goto sendFailed;
    1596          16 :         for (i = 0; i < nParams; i++)
    1597             :         {
    1598          10 :             if (pqPutInt(paramTypes[i], 4, conn) < 0)
    1599           0 :                 goto sendFailed;
    1600             :         }
    1601             :     }
    1602             :     else
    1603             :     {
    1604        4498 :         if (pqPutInt(0, 2, conn) < 0)
    1605           0 :             goto sendFailed;
    1606             :     }
    1607        4504 :     if (pqPutMsgEnd(conn) < 0)
    1608           0 :         goto sendFailed;
    1609             : 
    1610             :     /* Add a Sync, unless in pipeline mode. */
    1611        4504 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    1612             :     {
    1613        8864 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    1614        4432 :             pqPutMsgEnd(conn) < 0)
    1615           0 :             goto sendFailed;
    1616             :     }
    1617             : 
    1618             :     /* remember we are doing just a Parse */
    1619        4504 :     entry->queryclass = PGQUERY_PREPARE;
    1620             : 
    1621             :     /* and remember the query text too, if possible */
    1622             :     /* if insufficient memory, query just winds up NULL */
    1623        4504 :     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        4504 :     if (pqPipelineFlush(conn) < 0)
    1631           0 :         goto sendFailed;
    1632             : 
    1633             :     /* OK, it's launched! */
    1634        4504 :     pqAppendCmdQueueEntry(conn, entry);
    1635             : 
    1636        4504 :     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       16094 : 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       16094 :     if (!PQsendQueryStart(conn, true))
    1659           0 :         return 0;
    1660             : 
    1661             :     /* check the arguments */
    1662       16094 :     if (!stmtName)
    1663             :     {
    1664           0 :         libpq_append_conn_error(conn, "statement name is a null pointer");
    1665           0 :         return 0;
    1666             :     }
    1667       16094 :     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       16094 :     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      637536 : PQsendQueryStart(PGconn *conn, bool newQuery)
    1691             : {
    1692      637536 :     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      637536 :     if (newQuery && conn->cmd_queue_head == NULL)
    1701      633480 :         pqClearConnErrorState(conn);
    1702             : 
    1703             :     /* Don't try to send if we know there's no live connection. */
    1704      637536 :     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      637536 :     if (conn->asyncStatus != PGASYNC_IDLE &&
    1712        4056 :         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      637536 :     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        4498 :         switch (conn->asyncStatus)
    1732             :         {
    1733        4498 :             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        4498 :                 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      633038 :         pqClearAsyncResult(conn);
    1755             : 
    1756             :         /* reset partial-result mode */
    1757      633038 :         conn->partialResMode = false;
    1758      633038 :         conn->singleRowMode = false;
    1759      633038 :         conn->maxChunkSize = 0;
    1760             :     }
    1761             : 
    1762             :     /* ready to send command message */
    1763      637536 :     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       22876 : 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       22876 :     entry = pqAllocCmdQueueEntry(conn);
    1788       22876 :     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       22876 :     if (command)
    1798             :     {
    1799             :         /* construct the Parse message */
    1800       13564 :         if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
    1801       13564 :             pqPuts(stmtName, conn) < 0 ||
    1802        6782 :             pqPuts(command, conn) < 0)
    1803           0 :             goto sendFailed;
    1804        6782 :         if (nParams > 0 && paramTypes)
    1805             :         {
    1806          88 :             if (pqPutInt(nParams, 2, conn) < 0)
    1807           0 :                 goto sendFailed;
    1808         224 :             for (i = 0; i < nParams; i++)
    1809             :             {
    1810         136 :                 if (pqPutInt(paramTypes[i], 4, conn) < 0)
    1811           0 :                     goto sendFailed;
    1812             :             }
    1813             :         }
    1814             :         else
    1815             :         {
    1816        6694 :             if (pqPutInt(0, 2, conn) < 0)
    1817           0 :                 goto sendFailed;
    1818             :         }
    1819        6782 :         if (pqPutMsgEnd(conn) < 0)
    1820           0 :             goto sendFailed;
    1821             :     }
    1822             : 
    1823             :     /* Construct the Bind message */
    1824       45752 :     if (pqPutMsgStart(PqMsg_Bind, conn) < 0 ||
    1825       45752 :         pqPuts("", conn) < 0 ||
    1826       22876 :         pqPuts(stmtName, conn) < 0)
    1827           0 :         goto sendFailed;
    1828             : 
    1829             :     /* Send parameter formats */
    1830       22876 :     if (nParams > 0 && paramFormats)
    1831             :     {
    1832        5108 :         if (pqPutInt(nParams, 2, conn) < 0)
    1833           0 :             goto sendFailed;
    1834       12036 :         for (i = 0; i < nParams; i++)
    1835             :         {
    1836        6928 :             if (pqPutInt(paramFormats[i], 2, conn) < 0)
    1837           0 :                 goto sendFailed;
    1838             :         }
    1839             :     }
    1840             :     else
    1841             :     {
    1842       17768 :         if (pqPutInt(0, 2, conn) < 0)
    1843           0 :             goto sendFailed;
    1844             :     }
    1845             : 
    1846       22876 :     if (pqPutInt(nParams, 2, conn) < 0)
    1847           0 :         goto sendFailed;
    1848             : 
    1849             :     /* Send parameters */
    1850       52898 :     for (i = 0; i < nParams; i++)
    1851             :     {
    1852       30022 :         if (paramValues && paramValues[i])
    1853       28804 :         {
    1854             :             int         nbytes;
    1855             : 
    1856       28804 :             if (paramFormats && paramFormats[i] != 0)
    1857             :             {
    1858             :                 /* binary parameter */
    1859          52 :                 if (paramLengths)
    1860          52 :                     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       28752 :                 nbytes = strlen(paramValues[i]);
    1871             :             }
    1872       57608 :             if (pqPutInt(nbytes, 4, conn) < 0 ||
    1873       28804 :                 pqPutnchar(paramValues[i], nbytes, conn) < 0)
    1874           0 :                 goto sendFailed;
    1875             :         }
    1876             :         else
    1877             :         {
    1878             :             /* take the param as NULL */
    1879        1218 :             if (pqPutInt(-1, 4, conn) < 0)
    1880           0 :                 goto sendFailed;
    1881             :         }
    1882             :     }
    1883       45752 :     if (pqPutInt(1, 2, conn) < 0 ||
    1884       22876 :         pqPutInt(resultFormat, 2, conn))
    1885           0 :         goto sendFailed;
    1886       22876 :     if (pqPutMsgEnd(conn) < 0)
    1887           0 :         goto sendFailed;
    1888             : 
    1889             :     /* construct the Describe Portal message */
    1890       45752 :     if (pqPutMsgStart(PqMsg_Describe, conn) < 0 ||
    1891       45752 :         pqPutc('P', conn) < 0 ||
    1892       45752 :         pqPuts("", conn) < 0 ||
    1893       22876 :         pqPutMsgEnd(conn) < 0)
    1894           0 :         goto sendFailed;
    1895             : 
    1896             :     /* construct the Execute message */
    1897       45752 :     if (pqPutMsgStart(PqMsg_Execute, conn) < 0 ||
    1898       45752 :         pqPuts("", conn) < 0 ||
    1899       45752 :         pqPutInt(0, 4, conn) < 0 ||
    1900       22876 :         pqPutMsgEnd(conn) < 0)
    1901           0 :         goto sendFailed;
    1902             : 
    1903             :     /* construct the Sync message if not in pipeline mode */
    1904       22876 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    1905             :     {
    1906       36956 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    1907       18478 :             pqPutMsgEnd(conn) < 0)
    1908           0 :             goto sendFailed;
    1909             :     }
    1910             : 
    1911             :     /* remember we are using extended query protocol */
    1912       22876 :     entry->queryclass = PGQUERY_EXTENDED;
    1913             : 
    1914             :     /* and remember the query text too, if possible */
    1915             :     /* if insufficient memory, query just winds up NULL */
    1916       22876 :     if (command)
    1917        6782 :         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       22876 :     if (pqPipelineFlush(conn) < 0)
    1925           0 :         goto sendFailed;
    1926             : 
    1927             :     /* OK, it's launched! */
    1928       22876 :     pqAppendCmdQueueEntry(conn, entry);
    1929             : 
    1930       22876 :     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         172 : 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         172 :     if (!conn)
    1949           0 :         return false;
    1950         172 :     if (conn->asyncStatus != PGASYNC_BUSY)
    1951           6 :         return false;
    1952         166 :     if (!conn->cmd_queue_head ||
    1953         166 :         (conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE &&
    1954          40 :          conn->cmd_queue_head->queryclass != PGQUERY_EXTENDED))
    1955           0 :         return false;
    1956         166 :     if (pgHavePendingResult(conn))
    1957           0 :         return false;
    1958         166 :     return true;
    1959             : }
    1960             : 
    1961             : /*
    1962             :  * Select row-by-row processing mode
    1963             :  */
    1964             : int
    1965          66 : PQsetSingleRowMode(PGconn *conn)
    1966             : {
    1967          66 :     if (canChangeResultMode(conn))
    1968             :     {
    1969          66 :         conn->partialResMode = true;
    1970          66 :         conn->singleRowMode = true;
    1971          66 :         conn->maxChunkSize = 1;
    1972          66 :         return 1;
    1973             :     }
    1974             :     else
    1975           0 :         return 0;
    1976             : }
    1977             : 
    1978             : /*
    1979             :  * Select chunked results processing mode
    1980             :  */
    1981             : int
    1982         106 : PQsetChunkedRowsMode(PGconn *conn, int chunkSize)
    1983             : {
    1984         106 :     if (chunkSize > 0 && canChangeResultMode(conn))
    1985             :     {
    1986         100 :         conn->partialResMode = true;
    1987         100 :         conn->singleRowMode = false;
    1988         100 :         conn->maxChunkSize = chunkSize;
    1989         100 :         return 1;
    1990             :     }
    1991             :     else
    1992           6 :         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     1052588 : PQconsumeInput(PGconn *conn)
    2002             : {
    2003     1052588 :     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     1052588 :     if (pqIsnonblocking(conn))
    2012             :     {
    2013          14 :         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     1052588 :     if (pqReadData(conn) < 0)
    2024         150 :         return 0;
    2025             : 
    2026             :     /* Parsing of the data waits till later. */
    2027     1052438 :     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     3587514 : parseInput(PGconn *conn)
    2038             : {
    2039     3587514 :     pqParseInput3(conn);
    2040     3587514 : }
    2041             : 
    2042             : /*
    2043             :  * PQisBusy
    2044             :  *   Return true if PQgetResult would block waiting for input.
    2045             :  */
    2046             : 
    2047             : int
    2048      296898 : PQisBusy(PGconn *conn)
    2049             : {
    2050      296898 :     if (!conn)
    2051           0 :         return false;
    2052             : 
    2053             :     /* Parse any available data, if our state permits. */
    2054      296898 :     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      296898 :     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     1540010 : PQgetResult(PGconn *conn)
    2080             : {
    2081             :     PGresult   *res;
    2082             : 
    2083     1540010 :     if (!conn)
    2084           0 :         return NULL;
    2085             : 
    2086             :     /* Parse any available data, if our state permits. */
    2087     1540010 :     parseInput(conn);
    2088             : 
    2089             :     /* If not ready to return something, block until we are. */
    2090     2275114 :     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      735218 :         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     1470436 :         if (flushResult ||
    2115     1470358 :             pqWait(true, false, conn) ||
    2116      735140 :             pqReadData(conn) < 0)
    2117             :         {
    2118             :             /* Report the error saved by pqWait or pqReadData */
    2119         106 :             pqSaveErrorResult(conn);
    2120         106 :             conn->asyncStatus = PGASYNC_IDLE;
    2121         106 :             return pqPrepareAsyncResult(conn);
    2122             :         }
    2123             : 
    2124             :         /* Parse it. */
    2125      735112 :         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      735112 :         if (conn->write_failed && conn->asyncStatus == PGASYNC_BUSY)
    2132             :         {
    2133           8 :             pqSaveWriteError(conn);
    2134           8 :             conn->asyncStatus = PGASYNC_IDLE;
    2135           8 :             return pqPrepareAsyncResult(conn);
    2136             :         }
    2137             :     }
    2138             : 
    2139             :     /* Return the appropriate thing. */
    2140     1539896 :     switch (conn->asyncStatus)
    2141             :     {
    2142      841688 :         case PGASYNC_IDLE:
    2143      841688 :             res = NULL;         /* query is complete */
    2144      841688 :             break;
    2145        4480 :         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        4480 :             pqPipelineProcessQueue(conn);
    2155        4480 :             res = NULL;         /* query is complete */
    2156        4480 :             break;
    2157             : 
    2158      676330 :         case PGASYNC_READY:
    2159      676330 :             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      676330 :             if (conn->result)
    2170             :             {
    2171             :                 Assert(res->resultStatus == PGRES_TUPLES_CHUNK);
    2172          20 :                 break;
    2173             :             }
    2174             : 
    2175             :             /* Advance the queue as appropriate */
    2176      676310 :             pqCommandQueueAdvance(conn, false,
    2177      676310 :                                   res->resultStatus == PGRES_PIPELINE_SYNC);
    2178             : 
    2179      676310 :             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        5014 :                 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        5014 :                 if (res->resultStatus == PGRES_PIPELINE_SYNC)
    2199         532 :                     pqPipelineProcessQueue(conn);
    2200             :             }
    2201             :             else
    2202             :             {
    2203             :                 /* Set the state back to BUSY, allowing parsing to proceed. */
    2204      671296 :                 conn->asyncStatus = PGASYNC_BUSY;
    2205             :             }
    2206      676310 :             break;
    2207        5068 :         case PGASYNC_READY_MORE:
    2208        5068 :             res = pqPrepareAsyncResult(conn);
    2209             :             /* Set the state back to BUSY, allowing parsing to proceed. */
    2210        5068 :             conn->asyncStatus = PGASYNC_BUSY;
    2211        5068 :             break;
    2212        1150 :         case PGASYNC_COPY_IN:
    2213        1150 :             res = getCopyResult(conn, PGRES_COPY_IN);
    2214        1150 :             break;
    2215        9794 :         case PGASYNC_COPY_OUT:
    2216        9794 :             res = getCopyResult(conn, PGRES_COPY_OUT);
    2217        9794 :             break;
    2218        1386 :         case PGASYNC_COPY_BOTH:
    2219        1386 :             res = getCopyResult(conn, PGRES_COPY_BOTH);
    2220        1386 :             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     1539896 :     if (res && res->nEvents > 0)
    2231           0 :         (void) PQfireResultCreateEvents(conn, res);
    2232             : 
    2233     1539896 :     return res;
    2234             : }
    2235             : 
    2236             : /*
    2237             :  * getCopyResult
    2238             :  *    Helper for PQgetResult: generate result for COPY-in-progress cases
    2239             :  */
    2240             : static PGresult *
    2241       12330 : 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       12330 :     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       12330 :     if (conn->result && conn->result->resultStatus == copytype)
    2260       11922 :         return pqPrepareAsyncResult(conn);
    2261             : 
    2262             :     /* Otherwise, invent a suitable PGresult */
    2263         408 :     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      168654 : PQexec(PGconn *conn, const char *query)
    2280             : {
    2281      168654 :     if (!PQexecStart(conn))
    2282           2 :         return NULL;
    2283      168652 :     if (!PQsendQuery(conn, query))
    2284           0 :         return NULL;
    2285      168652 :     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        2974 : 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        2974 :     if (!PQexecStart(conn))
    2303           0 :         return NULL;
    2304        2974 :     if (!PQsendQueryParams(conn, command,
    2305             :                            nParams, paramTypes, paramValues, paramLengths,
    2306             :                            paramFormats, resultFormat))
    2307           0 :         return NULL;
    2308        2974 :     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        4040 : PQprepare(PGconn *conn,
    2324             :           const char *stmtName, const char *query,
    2325             :           int nParams, const Oid *paramTypes)
    2326             : {
    2327        4040 :     if (!PQexecStart(conn))
    2328          18 :         return NULL;
    2329        4022 :     if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
    2330           0 :         return NULL;
    2331        4022 :     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        7364 : 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        7364 :     if (!PQexecStart(conn))
    2349           0 :         return NULL;
    2350        7364 :     if (!PQsendQueryPrepared(conn, stmtName,
    2351             :                              nParams, paramValues, paramLengths,
    2352             :                              paramFormats, resultFormat))
    2353           0 :         return NULL;
    2354        7364 :     return PQexecFinish(conn);
    2355             : }
    2356             : 
    2357             : /*
    2358             :  * Common code for PQexec and sibling routines: prepare to send command
    2359             :  */
    2360             : static bool
    2361      183178 : PQexecStart(PGconn *conn)
    2362             : {
    2363             :     PGresult   *result;
    2364             : 
    2365      183178 :     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      183178 :     if (conn->cmd_queue_head == NULL)
    2374      183152 :         pqClearConnErrorState(conn);
    2375             : 
    2376      183178 :     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    2377             :     {
    2378          20 :         libpq_append_conn_error(conn, "synchronous command execution functions are not allowed in pipeline mode");
    2379          20 :         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      183158 :     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      183158 :     return true;
    2421             : }
    2422             : 
    2423             : /*
    2424             :  * Common code for PQexec and sibling routines: wait for command result
    2425             :  */
    2426             : static PGresult *
    2427      183158 : 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      183158 :     lastResult = NULL;
    2444      391834 :     while ((result = PQgetResult(conn)) != NULL)
    2445             :     {
    2446      217250 :         PQclear(lastResult);
    2447      217250 :         lastResult = result;
    2448      217250 :         if (result->resultStatus == PGRES_COPY_IN ||
    2449      217108 :             result->resultStatus == PGRES_COPY_OUT ||
    2450      208992 :             result->resultStatus == PGRES_COPY_BOTH ||
    2451      208676 :             conn->status == CONNECTION_BAD)
    2452             :             break;
    2453             :     }
    2454             : 
    2455      183158 :     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         140 : PQdescribePrepared(PGconn *conn, const char *stmt)
    2473             : {
    2474         140 :     if (!PQexecStart(conn))
    2475           0 :         return NULL;
    2476         140 :     if (!PQsendTypedCommand(conn, PqMsg_Describe, 'S', stmt))
    2477           0 :         return NULL;
    2478         140 :     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           2 : PQdescribePortal(PGconn *conn, const char *portal)
    2492             : {
    2493           2 :     if (!PQexecStart(conn))
    2494           0 :         return NULL;
    2495           2 :     if (!PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal))
    2496           0 :         return NULL;
    2497           2 :     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           2 : PQsendDescribePrepared(PGconn *conn, const char *stmt)
    2509             : {
    2510           2 :     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           2 : PQsendDescribePortal(PGconn *conn, const char *portal)
    2522             : {
    2523           2 :     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           2 : PQclosePrepared(PGconn *conn, const char *stmt)
    2539             : {
    2540           2 :     if (!PQexecStart(conn))
    2541           0 :         return NULL;
    2542           2 :     if (!PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt))
    2543           0 :         return NULL;
    2544           2 :     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           2 : PQclosePortal(PGconn *conn, const char *portal)
    2557             : {
    2558           2 :     if (!PQexecStart(conn))
    2559           0 :         return NULL;
    2560           2 :     if (!PQsendTypedCommand(conn, PqMsg_Close, 'P', portal))
    2561           0 :         return NULL;
    2562           2 :     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          40 : PQsendClosePrepared(PGconn *conn, const char *stmt)
    2574             : {
    2575          40 :     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           2 : PQsendClosePortal(PGconn *conn, const char *portal)
    2587             : {
    2588           2 :     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         192 : PQsendTypedCommand(PGconn *conn, char command, char type, const char *target)
    2607             : {
    2608         192 :     PGcmdQueueEntry *entry = NULL;
    2609             : 
    2610             :     /* Treat null target as empty string */
    2611         192 :     if (!target)
    2612           0 :         target = "";
    2613             : 
    2614         192 :     if (!PQsendQueryStart(conn, true))
    2615           0 :         return 0;
    2616             : 
    2617         192 :     entry = pqAllocCmdQueueEntry(conn);
    2618         192 :     if (entry == NULL)
    2619           0 :         return 0;               /* error msg already set */
    2620             : 
    2621             :     /* construct the Close message */
    2622         384 :     if (pqPutMsgStart(command, conn) < 0 ||
    2623         384 :         pqPutc(type, conn) < 0 ||
    2624         384 :         pqPuts(target, conn) < 0 ||
    2625         192 :         pqPutMsgEnd(conn) < 0)
    2626           0 :         goto sendFailed;
    2627             : 
    2628             :     /* construct the Sync message */
    2629         192 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    2630             :     {
    2631         332 :         if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    2632         166 :             pqPutMsgEnd(conn) < 0)
    2633           0 :             goto sendFailed;
    2634             :     }
    2635             : 
    2636             :     /* remember if we are doing a Close or a Describe */
    2637         192 :     if (command == PqMsg_Close)
    2638             :     {
    2639          46 :         entry->queryclass = PGQUERY_CLOSE;
    2640             :     }
    2641         146 :     else if (command == PqMsg_Describe)
    2642             :     {
    2643         146 :         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         192 :     if (pqPipelineFlush(conn) < 0)
    2657           0 :         goto sendFailed;
    2658             : 
    2659             :     /* OK, it's launched! */
    2660         192 :     pqAppendCmdQueueEntry(conn, entry);
    2661             : 
    2662         192 :     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      389526 : PQnotifies(PGconn *conn)
    2685             : {
    2686             :     PGnotify   *event;
    2687             : 
    2688      389526 :     if (!conn)
    2689           0 :         return NULL;
    2690             : 
    2691             :     /* Parse any available data to see if we can extract NOTIFY messages. */
    2692      389526 :     parseInput(conn);
    2693             : 
    2694      389526 :     event = conn->notifyHead;
    2695      389526 :     if (event)
    2696             :     {
    2697          82 :         conn->notifyHead = event->next;
    2698          82 :         if (!conn->notifyHead)
    2699          40 :             conn->notifyTail = NULL;
    2700          82 :         event->next = NULL;      /* don't let app see the internal state */
    2701             :     }
    2702      389526 :     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      625968 : PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
    2713             : {
    2714      625968 :     if (!conn)
    2715           0 :         return -1;
    2716      625968 :     if (conn->asyncStatus != PGASYNC_COPY_IN &&
    2717      224578 :         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      625968 :     parseInput(conn);
    2732             : 
    2733      625968 :     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      625968 :         if ((conn->outBufSize - conn->outCount - 5) < nbytes)
    2742             :         {
    2743          42 :             if (pqFlush(conn) < 0)
    2744           0 :                 return -1;
    2745          42 :             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     1251936 :         if (pqPutMsgStart(PqMsg_CopyData, conn) < 0 ||
    2751     1251936 :             pqPutnchar(buffer, nbytes, conn) < 0 ||
    2752      625968 :             pqPutMsgEnd(conn) < 0)
    2753           0 :             return -1;
    2754             :     }
    2755      625968 :     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        1864 : PQputCopyEnd(PGconn *conn, const char *errormsg)
    2767             : {
    2768        1864 :     if (!conn)
    2769           0 :         return -1;
    2770        1864 :     if (conn->asyncStatus != PGASYNC_COPY_IN &&
    2771         734 :         conn->asyncStatus != PGASYNC_COPY_BOTH)
    2772             :     {
    2773          72 :         libpq_append_conn_error(conn, "no COPY in progress");
    2774          72 :         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        1792 :     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        3584 :         if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
    2793        1792 :             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        1792 :     if (conn->cmd_queue_head &&
    2802        1792 :         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        1792 :     if (conn->asyncStatus == PGASYNC_COPY_BOTH)
    2811         662 :         conn->asyncStatus = PGASYNC_COPY_OUT;
    2812             :     else
    2813        1130 :         conn->asyncStatus = PGASYNC_BUSY;
    2814             : 
    2815             :     /* Try to flush data */
    2816        1792 :     if (pqFlush(conn) < 0)
    2817           0 :         return -1;
    2818             : 
    2819        1792 :     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     5680564 : PQgetCopyData(PGconn *conn, char **buffer, int async)
    2834             : {
    2835     5680564 :     *buffer = NULL;             /* for all failure cases */
    2836     5680564 :     if (!conn)
    2837           0 :         return -2;
    2838     5680564 :     if (conn->asyncStatus != PGASYNC_COPY_OUT &&
    2839     1334536 :         conn->asyncStatus != PGASYNC_COPY_BOTH)
    2840             :     {
    2841           0 :         libpq_append_conn_error(conn, "no COPY in progress");
    2842           0 :         return -2;
    2843             :     }
    2844     5680564 :     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      400056 : PQputline(PGconn *conn, const char *string)
    2936             : {
    2937      400056 :     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      400056 : PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
    2946             : {
    2947      400056 :     if (PQputCopyData(conn, buffer, nbytes) > 0)
    2948      400056 :         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         382 : PQendcopy(PGconn *conn)
    2967             : {
    2968         382 :     if (!conn)
    2969           0 :         return 0;
    2970             : 
    2971         382 :     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        2140 : 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        2140 :     *result_len = 0;
    3006             : 
    3007        2140 :     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        2140 :     if (conn->cmd_queue_head == NULL)
    3016        2140 :         pqClearConnErrorState(conn);
    3017             : 
    3018        2140 :     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        2140 :     if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
    3025        2140 :         pgHavePendingResult(conn))
    3026             :     {
    3027           0 :         libpq_append_conn_error(conn, "connection in wrong state");
    3028           0 :         return NULL;
    3029             :     }
    3030             : 
    3031        2140 :     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         438 : PQenterPipelineMode(PGconn *conn)
    3060             : {
    3061         438 :     if (!conn)
    3062           0 :         return 0;
    3063             : 
    3064             :     /* succeed with no action if already in pipeline mode */
    3065         438 :     if (conn->pipelineStatus != PQ_PIPELINE_OFF)
    3066           8 :         return 1;
    3067             : 
    3068         430 :     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         430 :     conn->pipelineStatus = PQ_PIPELINE_ON;
    3075             : 
    3076         430 :     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         412 : PQexitPipelineMode(PGconn *conn)
    3091             : {
    3092         412 :     if (!conn)
    3093           0 :         return 0;
    3094             : 
    3095         412 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF &&
    3096           2 :         (conn->asyncStatus == PGASYNC_IDLE ||
    3097           0 :          conn->asyncStatus == PGASYNC_PIPELINE_IDLE) &&
    3098           2 :         conn->cmd_queue_head == NULL)
    3099           2 :         return 1;
    3100             : 
    3101         410 :     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          10 :         case PGASYNC_BUSY:
    3110          10 :             libpq_append_conn_error(conn, "cannot exit pipeline mode while busy");
    3111          10 :             return 0;
    3112             : 
    3113         400 :         case PGASYNC_IDLE:
    3114             :         case PGASYNC_PIPELINE_IDLE:
    3115             :             /* OK */
    3116         400 :             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         400 :     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         400 :     conn->pipelineStatus = PQ_PIPELINE_OFF;
    3132         400 :     conn->asyncStatus = PGASYNC_IDLE;
    3133             : 
    3134             :     /* Flush any pending data in out buffer */
    3135         400 :     if (pqFlush(conn) < 0)
    3136           0 :         return 0;               /* error message is setup already */
    3137         400 :     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     1334386 : pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
    3160             : {
    3161             :     PGcmdQueueEntry *prevquery;
    3162             : 
    3163     1334386 :     if (conn->cmd_queue_head == NULL)
    3164       50380 :         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     1284006 :     if (conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE && !isReadyForQuery)
    3171      648178 :         return;
    3172             : 
    3173             :     /*
    3174             :      * If we're waiting for a SYNC, don't advance the queue until we get one.
    3175             :      */
    3176      635828 :     if (conn->cmd_queue_head->queryclass == PGQUERY_SYNC && !gotSync)
    3177           0 :         return;
    3178             : 
    3179             :     /* delink element from queue */
    3180      635828 :     prevquery = conn->cmd_queue_head;
    3181      635828 :     conn->cmd_queue_head = conn->cmd_queue_head->next;
    3182             : 
    3183             :     /* If the queue is now empty, reset the tail too */
    3184      635828 :     if (conn->cmd_queue_head == NULL)
    3185      631308 :         conn->cmd_queue_tail = NULL;
    3186             : 
    3187             :     /* and make the queue element recyclable */
    3188      635828 :     prevquery->next = NULL;
    3189      635828 :     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        5032 : pqPipelineProcessQueue(PGconn *conn)
    3198             : {
    3199        5032 :     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          20 :         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          20 :             if (conn->cmd_queue_head != NULL)
    3218             :             {
    3219          20 :                 conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
    3220          20 :                 break;
    3221             :             }
    3222           0 :             return;
    3223             : 
    3224        5012 :         case PGASYNC_PIPELINE_IDLE:
    3225             :             Assert(conn->pipelineStatus != PQ_PIPELINE_OFF);
    3226             :             /* next query please */
    3227        5012 :             break;
    3228             :     }
    3229             : 
    3230             :     /*
    3231             :      * Reset partial-result mode.  (Client has to set it up for each query, if
    3232             :      * desired.)
    3233             :      */
    3234        5032 :     conn->partialResMode = false;
    3235        5032 :     conn->singleRowMode = false;
    3236        5032 :     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        5032 :     if (conn->cmd_queue_head == NULL)
    3243             :     {
    3244         492 :         conn->asyncStatus = PGASYNC_IDLE;
    3245         492 :         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        4540 :     pqClearConnErrorState(conn);
    3253             : 
    3254             :     /* Initialize async result-accumulation state */
    3255        4540 :     pqClearAsyncResult(conn);
    3256             : 
    3257        4540 :     if (conn->pipelineStatus == PQ_PIPELINE_ABORTED &&
    3258         604 :         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         508 :         conn->result = PQmakeEmptyPGresult(conn, PGRES_PIPELINE_ABORTED);
    3269         508 :         if (!conn->result)
    3270             :         {
    3271           0 :             libpq_append_conn_error(conn, "out of memory");
    3272           0 :             pqSaveErrorResult(conn);
    3273           0 :             return;
    3274             :         }
    3275         508 :         conn->asyncStatus = PGASYNC_READY;
    3276             :     }
    3277             :     else
    3278             :     {
    3279             :         /* allow parsing to continue */
    3280        4032 :         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         434 : PQpipelineSync(PGconn *conn)
    3290             : {
    3291         434 :     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         120 : PQsendPipelineSync(PGconn *conn)
    3300             : {
    3301         120 :     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         554 : pqPipelineSyncInternal(PGconn *conn, bool immediate_flush)
    3312             : {
    3313             :     PGcmdQueueEntry *entry;
    3314             : 
    3315         554 :     if (!conn)
    3316           0 :         return 0;
    3317             : 
    3318         554 :     if (conn->pipelineStatus == PQ_PIPELINE_OFF)
    3319             :     {
    3320           6 :         libpq_append_conn_error(conn, "cannot send pipeline when not in pipeline mode");
    3321           6 :         return 0;
    3322             :     }
    3323             : 
    3324         548 :     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         548 :         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         548 :             break;
    3340             :     }
    3341             : 
    3342         548 :     entry = pqAllocCmdQueueEntry(conn);
    3343         548 :     if (entry == NULL)
    3344           0 :         return 0;               /* error msg already set */
    3345             : 
    3346         548 :     entry->queryclass = PGQUERY_SYNC;
    3347         548 :     entry->query = NULL;
    3348             : 
    3349             :     /* construct the Sync message */
    3350        1096 :     if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
    3351         548 :         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         548 :     if (immediate_flush)
    3361             :     {
    3362         428 :         if (pqFlush(conn) < 0)
    3363           0 :             goto sendFailed;
    3364             :     }
    3365             :     else
    3366             :     {
    3367         120 :         if (pqPipelineFlush(conn) < 0)
    3368           0 :             goto sendFailed;
    3369             :     }
    3370             : 
    3371             :     /* OK, it's launched! */
    3372         548 :     pqAppendCmdQueueEntry(conn, entry);
    3373             : 
    3374         548 :     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          70 : PQsendFlushRequest(PGconn *conn)
    3389             : {
    3390          70 :     if (!conn)
    3391           0 :         return 0;
    3392             : 
    3393             :     /* Don't try to send if we know there's no live connection. */
    3394          70 :     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          70 :     if (conn->asyncStatus != PGASYNC_IDLE &&
    3402          70 :         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         140 :     if (pqPutMsgStart(PqMsg_Flush, conn) < 0 ||
    3409          70 :         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          70 :     if (pqPipelineFlush(conn) < 0)
    3420           0 :         return 0;
    3421             : 
    3422          70 :     return 1;
    3423             : }
    3424             : 
    3425             : /* ====== accessor funcs for PGresult ======== */
    3426             : 
    3427             : ExecStatusType
    3428     2422842 : PQresultStatus(const PGresult *res)
    3429             : {
    3430     2422842 :     if (!res)
    3431         230 :         return PGRES_FATAL_ERROR;
    3432     2422612 :     return res->resultStatus;
    3433             : }
    3434             : 
    3435             : char *
    3436          44 : PQresStatus(ExecStatusType status)
    3437             : {
    3438          44 :     if ((unsigned int) status >= lengthof(pgresStatus))
    3439           0 :         return libpq_gettext("invalid ExecStatusType code");
    3440          44 :     return pgresStatus[status];
    3441             : }
    3442             : 
    3443             : char *
    3444      200568 : PQresultErrorMessage(const PGresult *res)
    3445             : {
    3446      200568 :     if (!res || !res->errMsg)
    3447           2 :         return "";
    3448      200566 :     return res->errMsg;
    3449             : }
    3450             : 
    3451             : char *
    3452           6 : 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           6 :     if (!res ||
    3464           6 :         (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           6 :     initPQExpBuffer(&workBuf);
    3469             : 
    3470           6 :     pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
    3471             : 
    3472             :     /* If insufficient memory to format the message, fail cleanly */
    3473           6 :     if (PQExpBufferDataBroken(workBuf))
    3474             :     {
    3475           0 :         termPQExpBuffer(&workBuf);
    3476           0 :         return strdup(libpq_gettext("out of memory\n"));
    3477             :     }
    3478             : 
    3479           6 :     return workBuf.data;
    3480             : }
    3481             : 
    3482             : char *
    3483     1542084 : PQresultErrorField(const PGresult *res, int fieldcode)
    3484             : {
    3485             :     PGMessageField *pfield;
    3486             : 
    3487     1542084 :     if (!res)
    3488          40 :         return NULL;
    3489    11625768 :     for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
    3490             :     {
    3491    10739396 :         if (pfield->code == fieldcode)
    3492      655672 :             return pfield->contents;
    3493             :     }
    3494      886372 :     return NULL;
    3495             : }
    3496             : 
    3497             : int
    3498      396124 : PQntuples(const PGresult *res)
    3499             : {
    3500      396124 :     if (!res)
    3501        3718 :         return 0;
    3502      392406 :     return res->ntups;
    3503             : }
    3504             : 
    3505             : int
    3506      357044 : PQnfields(const PGresult *res)
    3507             : {
    3508      357044 :     if (!res)
    3509           0 :         return 0;
    3510      357044 :     return res->numAttributes;
    3511             : }
    3512             : 
    3513             : int
    3514         936 : PQbinaryTuples(const PGresult *res)
    3515             : {
    3516         936 :     if (!res)
    3517           0 :         return 0;
    3518         936 :     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     5167792 : check_field_number(const PGresult *res, int field_num)
    3528             : {
    3529     5167792 :     if (!res)
    3530           0 :         return false;           /* no way to display error message... */
    3531     5167792 :     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     5167792 :     return true;
    3539             : }
    3540             : 
    3541             : static int
    3542    41134870 : check_tuple_field_number(const PGresult *res,
    3543             :                          int tup_num, int field_num)
    3544             : {
    3545    41134870 :     if (!res)
    3546           0 :         return false;           /* no way to display error message... */
    3547    41134870 :     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    41134870 :     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    41134870 :     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      278484 : PQfname(const PGresult *res, int field_num)
    3585             : {
    3586      278484 :     if (!check_field_number(res, field_num))
    3587           0 :         return NULL;
    3588      278484 :     if (res->attDescs)
    3589      278484 :         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      470968 : PQfnumber(const PGresult *res, const char *field_name)
    3607             : {
    3608             :     char       *field_case;
    3609             :     bool        in_quotes;
    3610      470968 :     bool        all_lower = true;
    3611             :     const char *iptr;
    3612             :     char       *optr;
    3613             :     int         i;
    3614             : 
    3615      470968 :     if (!res)
    3616       31416 :         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      439552 :     if (field_name == NULL ||
    3623      439552 :         field_name[0] == '\0' ||
    3624      439552 :         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     4897696 :     for (iptr = field_name; *iptr; iptr++)
    3632             :     {
    3633     4458144 :         char        c = *iptr;
    3634             : 
    3635     4458144 :         if (c == '"' || c != pg_tolower((unsigned char) c))
    3636             :         {
    3637           0 :             all_lower = false;
    3638           0 :             break;
    3639             :         }
    3640             :     }
    3641             : 
    3642      439552 :     if (all_lower)
    3643     3417134 :         for (i = 0; i < res->numAttributes; i++)
    3644     3417134 :             if (strcmp(field_name, res->attDescs[i].name) == 0)
    3645      439552 :                 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       13704 : PQfformat(const PGresult *res, int field_num)
    3726             : {
    3727       13704 :     if (!check_field_number(res, field_num))
    3728           0 :         return 0;
    3729       13704 :     if (res->attDescs)
    3730       13704 :         return res->attDescs[field_num].format;
    3731             :     else
    3732           0 :         return 0;
    3733             : }
    3734             : 
    3735             : Oid
    3736     4874814 : PQftype(const PGresult *res, int field_num)
    3737             : {
    3738     4874814 :     if (!check_field_number(res, field_num))
    3739           0 :         return InvalidOid;
    3740     4874814 :     if (res->attDescs)
    3741     4874814 :         return res->attDescs[field_num].typid;
    3742             :     else
    3743           0 :         return InvalidOid;
    3744             : }
    3745             : 
    3746             : int
    3747         320 : PQfsize(const PGresult *res, int field_num)
    3748             : {
    3749         320 :     if (!check_field_number(res, field_num))
    3750           0 :         return 0;
    3751         320 :     if (res->attDescs)
    3752         320 :         return res->attDescs[field_num].typlen;
    3753             :     else
    3754           0 :         return 0;
    3755             : }
    3756             : 
    3757             : int
    3758         470 : PQfmod(const PGresult *res, int field_num)
    3759             : {
    3760         470 :     if (!check_field_number(res, field_num))
    3761           0 :         return 0;
    3762         470 :     if (res->attDescs)
    3763         470 :         return res->attDescs[field_num].atttypmod;
    3764             :     else
    3765           0 :         return 0;
    3766             : }
    3767             : 
    3768             : char *
    3769      630246 : PQcmdStatus(PGresult *res)
    3770             : {
    3771      630246 :     if (!res)
    3772           0 :         return NULL;
    3773      630246 :     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      180732 : PQoidValue(const PGresult *res)
    3811             : {
    3812      180732 :     char       *endptr = NULL;
    3813             :     unsigned long result;
    3814             : 
    3815      180732 :     if (!res ||
    3816      180732 :         strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
    3817       35312 :         res->cmdStatus[7] < '0' ||
    3818       35312 :         res->cmdStatus[7] > '9')
    3819      145420 :         return InvalidOid;
    3820             : 
    3821       35312 :     result = strtoul(res->cmdStatus + 7, &endptr, 10);
    3822             : 
    3823       35312 :     if (!endptr || (*endptr != ' ' && *endptr != '\0'))
    3824           0 :         return InvalidOid;
    3825             :     else
    3826       35312 :         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      317544 : PQcmdTuples(PGresult *res)
    3840             : {
    3841             :     char       *p,
    3842             :                *c;
    3843             : 
    3844      317544 :     if (!res)
    3845         518 :         return "";
    3846             : 
    3847      317026 :     if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
    3848             :     {
    3849       36920 :         p = res->cmdStatus + 7;
    3850             :         /* INSERT: skip oid and space */
    3851       73840 :         while (*p && *p != ' ')
    3852       36920 :             p++;
    3853       36920 :         if (*p == 0)
    3854           0 :             goto interpret_error;   /* no space? */
    3855       36920 :         p++;
    3856             :     }
    3857      280106 :     else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
    3858      159706 :              strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
    3859      156860 :              strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
    3860      128038 :         p = res->cmdStatus + 7;
    3861      152068 :     else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0 ||
    3862      150612 :              strncmp(res->cmdStatus, "MERGE ", 6) == 0)
    3863        2450 :         p = res->cmdStatus + 6;
    3864      149618 :     else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
    3865      149550 :              strncmp(res->cmdStatus, "COPY ", 5) == 0)
    3866        1136 :         p = res->cmdStatus + 5;
    3867             :     else
    3868      148482 :         return "";
    3869             : 
    3870             :     /* check that we have an integer (at least one digit, nothing else) */
    3871      356250 :     for (c = p; *c; c++)
    3872             :     {
    3873      187706 :         if (!isdigit((unsigned char) *c))
    3874           0 :             goto interpret_error;
    3875             :     }
    3876      168544 :     if (c == p)
    3877           0 :         goto interpret_error;
    3878             : 
    3879      168544 :     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    34600150 : PQgetvalue(const PGresult *res, int tup_num, int field_num)
    3894             : {
    3895    34600150 :     if (!check_tuple_field_number(res, tup_num, field_num))
    3896           0 :         return NULL;
    3897    34600150 :     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       40874 : PQgetlength(const PGresult *res, int tup_num, int field_num)
    3905             : {
    3906       40874 :     if (!check_tuple_field_number(res, tup_num, field_num))
    3907           0 :         return 0;
    3908       40874 :     if (res->tuples[tup_num][field_num].len != NULL_LEN)
    3909       40424 :         return res->tuples[tup_num][field_num].len;
    3910             :     else
    3911         450 :         return 0;
    3912             : }
    3913             : 
    3914             : /* PQgetisnull:
    3915             :  *  returns the null status of a field value.
    3916             :  */
    3917             : int
    3918     6493846 : PQgetisnull(const PGresult *res, int tup_num, int field_num)
    3919             : {
    3920     6493846 :     if (!check_tuple_field_number(res, tup_num, field_num))
    3921           0 :         return 1;               /* pretend it is null */
    3922     6493846 :     if (res->tuples[tup_num][field_num].len == NULL_LEN)
    3923     1032760 :         return 1;
    3924             :     else
    3925     5461086 :         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          10 : PQsetnonblocking(PGconn *conn, int arg)
    3962             : {
    3963             :     bool        barg;
    3964             : 
    3965          10 :     if (!conn || conn->status == CONNECTION_BAD)
    3966           0 :         return -1;
    3967             : 
    3968          10 :     barg = (arg ? true : false);
    3969             : 
    3970             :     /* early out if the socket is already in the state requested */
    3971          10 :     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          10 :     if (conn->cmd_queue_head == NULL)
    3984           8 :         pqClearConnErrorState(conn);
    3985             : 
    3986             :     /* if we are going from blocking to non-blocking flush here */
    3987          10 :     if (pqFlush(conn))
    3988           0 :         return -1;
    3989             : 
    3990          10 :     conn->nonblocking = barg;
    3991             : 
    3992          10 :     return 0;
    3993             : }
    3994             : 
    3995             : /*
    3996             :  * return the blocking status of the database connection
    3997             :  *      true == nonblocking, false == blocking
    3998             :  */
    3999             : int
    4000           4 : PQisnonblocking(const PGconn *conn)
    4001             : {
    4002           4 :     if (!conn || conn->status == CONNECTION_BAD)
    4003           0 :         return false;
    4004           4 :     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      244032 : PQflush(PGconn *conn)
    4018             : {
    4019      244032 :     if (!conn || conn->status == CONNECTION_BAD)
    4020           0 :         return -1;
    4021      244032 :     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       27762 : pqPipelineFlush(PGconn *conn)
    4034             : {
    4035       27762 :     if ((conn->pipelineStatus != PQ_PIPELINE_ON) ||
    4036        4564 :         (conn->outCount >= OUTBUFFER_THRESHOLD))
    4037       23198 :         return pqFlush(conn);
    4038        4564 :     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     5132760 : PQfreemem(void *ptr)
    4050             : {
    4051     5132760 :     free(ptr);
    4052     5132760 : }
    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       11070 : PQescapeStringInternal(PGconn *conn,
    4089             :                        char *to, const char *from, size_t length,
    4090             :                        int *error,
    4091             :                        int encoding, bool std_strings)
    4092             : {
    4093       11070 :     const char *source = from;
    4094       11070 :     char       *target = to;
    4095       11070 :     size_t      remaining = strnlen(from, length);
    4096       11070 :     bool        already_complained = false;
    4097             : 
    4098       11070 :     if (error)
    4099         130 :         *error = 0;
    4100             : 
    4101      156714 :     while (remaining > 0)
    4102             :     {
    4103      145644 :         char        c = *source;
    4104             :         int         charlen;
    4105             :         int         i;
    4106             : 
    4107             :         /* Fast path for plain ASCII */
    4108      145644 :         if (!IS_HIGHBIT_SET(c))
    4109             :         {
    4110             :             /* Apply quoting if needed */
    4111      143940 :             if (SQL_STR_DOUBLE(c, !std_strings))
    4112          98 :                 *target++ = c;
    4113             :             /* Copy the character */
    4114      143940 :             *target++ = c;
    4115      143940 :             source++;
    4116      143940 :             remaining--;
    4117      143940 :             continue;
    4118             :         }
    4119             : 
    4120             :         /* Slow path for possible multibyte characters */
    4121        1704 :         charlen = pg_encoding_mblen_or_incomplete(encoding,
    4122             :                                                   source, remaining);
    4123             : 
    4124        3296 :         if (remaining < charlen ||
    4125        1592 :             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         164 :             if (error)
    4154          82 :                 *error = 1;
    4155         164 :             if (conn && !already_complained)
    4156             :             {
    4157          82 :                 if (remaining < charlen)
    4158          56 :                     libpq_append_conn_error(conn, "incomplete multibyte character");
    4159             :                 else
    4160          26 :                     libpq_append_conn_error(conn, "invalid multibyte character");
    4161             :                 /* Issue a complaint only once per string */
    4162          82 :                 already_complained = true;
    4163             :             }
    4164             : 
    4165         164 :             pg_encoding_set_invalid(encoding, target);
    4166         164 :             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         164 :             source++;
    4174         164 :             remaining--;
    4175             :         }
    4176             :         else
    4177             :         {
    4178             :             /* Copy the character */
    4179        3132 :             for (i = 0; i < charlen; i++)
    4180             :             {
    4181        1592 :                 *target++ = *source++;
    4182        1592 :                 remaining--;
    4183             :             }
    4184             :         }
    4185             :     }
    4186             : 
    4187             :     /* Write the terminating NUL character. */
    4188       11070 :     *target = '\0';
    4189             : 
    4190       11070 :     return target - to;
    4191             : }
    4192             : 
    4193             : size_t
    4194       10940 : PQescapeStringConn(PGconn *conn,
    4195             :                    char *to, const char *from, size_t length,
    4196             :                    int *error)
    4197             : {
    4198       10940 :     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       10940 :     if (conn->cmd_queue_head == NULL)
    4208       10940 :         pqClearConnErrorState(conn);
    4209             : 
    4210       10940 :     return PQescapeStringInternal(conn, to, from, length, error,
    4211             :                                   conn->client_encoding,
    4212       10940 :                                   conn->std_strings);
    4213             : }
    4214             : 
    4215             : size_t
    4216         130 : PQescapeString(char *to, const char *from, size_t length)
    4217             : {
    4218         130 :     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        3752 : PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
    4232             : {
    4233             :     const char *s;
    4234             :     char       *result;
    4235             :     char       *rp;
    4236        3752 :     size_t      num_quotes = 0; /* single or double, depending on as_ident */
    4237        3752 :     size_t      num_backslashes = 0;
    4238        3752 :     size_t      input_len = strnlen(str, len);
    4239             :     size_t      result_size;
    4240        3752 :     char        quote_char = as_ident ? '"' : '\'';
    4241        3752 :     bool        validated_mb = false;
    4242             : 
    4243             :     /* We must have a connection, else fail immediately. */
    4244        3752 :     if (!conn)
    4245           0 :         return NULL;
    4246             : 
    4247        3752 :     if (conn->cmd_queue_head == NULL)
    4248        3752 :         pqClearConnErrorState(conn);
    4249             : 
    4250             :     /*
    4251             :      * Scan the string for characters that must be escaped and for invalidly
    4252             :      * encoded data.
    4253             :      */
    4254        3752 :     s = str;
    4255      935380 :     for (size_t remaining = input_len; remaining > 0; remaining--, s++)
    4256             :     {
    4257      931794 :         if (*s == quote_char)
    4258         186 :             ++num_quotes;
    4259      931608 :         else if (*s == '\\')
    4260         308 :             ++num_backslashes;
    4261      931300 :         else if (IS_HIGHBIT_SET(*s))
    4262             :         {
    4263             :             int         charlen;
    4264             : 
    4265             :             /* Slow path for possible multibyte characters */
    4266         222 :             charlen = pg_encoding_mblen_or_incomplete(conn->client_encoding,
    4267             :                                                       s, remaining);
    4268             : 
    4269         222 :             if (charlen > remaining)
    4270             :             {
    4271             :                 /* Multibyte character overruns allowable length. */
    4272         114 :                 libpq_append_conn_error(conn, "incomplete multibyte character");
    4273         114 :                 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         108 :             if (!validated_mb)
    4287             :             {
    4288         108 :                 if (pg_encoding_verifymbstr(conn->client_encoding, s, remaining)
    4289             :                     != remaining)
    4290             :                 {
    4291          52 :                     libpq_append_conn_error(conn, "invalid multibyte character");
    4292          52 :                     return NULL;
    4293             :                 }
    4294          56 :                 validated_mb = true;
    4295             :             }
    4296             : 
    4297             :             /* Adjust s, bearing in mind that for loop will increment it. */
    4298          56 :             s += charlen - 1;
    4299          56 :             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        7172 :     if (pg_add_size_overflow(input_len, num_quotes, &result_size) ||
    4308        3586 :         pg_add_size_overflow(result_size, 3, &result_size)) /* two quotes plus a NUL */
    4309           0 :         goto overflow;
    4310             : 
    4311        3586 :     if (!as_ident && num_backslashes > 0)
    4312             :     {
    4313         112 :         if (pg_add_size_overflow(result_size, num_backslashes, &result_size) ||
    4314          56 :             pg_add_size_overflow(result_size, 2, &result_size)) /* for " E" prefix */
    4315           0 :             goto overflow;
    4316             :     }
    4317             : 
    4318        3586 :     result = rp = (char *) malloc(result_size);
    4319        3586 :     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        3586 :     if (!as_ident && num_backslashes > 0)
    4333             :     {
    4334          56 :         *rp++ = ' ';
    4335          56 :         *rp++ = 'E';
    4336             :     }
    4337             : 
    4338             :     /* Opening quote. */
    4339        3586 :     *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        3586 :     if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
    4353             :     {
    4354        3482 :         memcpy(rp, str, input_len);
    4355        3482 :         rp += input_len;
    4356             :     }
    4357             :     else
    4358             :     {
    4359         104 :         s = str;
    4360        5934 :         for (size_t remaining = input_len; remaining > 0; remaining--, s++)
    4361             :         {
    4362        5830 :             if (*s == quote_char || (!as_ident && *s == '\\'))
    4363             :             {
    4364         450 :                 *rp++ = *s;
    4365         450 :                 *rp++ = *s;
    4366             :             }
    4367        5380 :             else if (!IS_HIGHBIT_SET(*s))
    4368        5358 :                 *rp++ = *s;
    4369             :             else
    4370             :             {
    4371          22 :                 int         i = pg_encoding_mblen(conn->client_encoding, s);
    4372             : 
    4373             :                 while (1)
    4374             :                 {
    4375          42 :                     *rp++ = *s;
    4376          42 :                     if (--i == 0)
    4377          22 :                         break;
    4378          20 :                     remaining--;
    4379          20 :                     ++s;        /* for loop will provide the final increment */
    4380             :                 }
    4381             :             }
    4382             :         }
    4383             :     }
    4384             : 
    4385             :     /* Closing quote and terminating NUL. */
    4386        3586 :     *rp++ = quote_char;
    4387        3586 :     *rp = '\0';
    4388             : 
    4389        3586 :     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        2094 : PQescapeLiteral(PGconn *conn, const char *str, size_t len)
    4400             : {
    4401        2094 :     return PQescapeInternal(conn, str, len, false);
    4402             : }
    4403             : 
    4404             : char *
    4405        1658 : PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
    4406             : {
    4407        1658 :     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 1.16