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

Generated by: LCOV version 1.14