LCOV - differential code coverage report
Current view: top level - src/interfaces/libpq - fe-exec.c (source / functions) Coverage Total Hit UNC LBC UBC GBC GNC CBC DUB DCB
Current: 7a15cff1f11193467898da1c1fabf06fd2caee04 vs 84a3778c79c2d28b4dc281d03ef2ab019b16483b Lines: 62.1 % 1627 1011 7 2 607 2 4 1005 8 9
Current Date: 2025-12-15 18:36:29 -0500 Functions: 83.1 % 118 98 1 19 1 97 1
Baseline: lcov-20251216-010103-baseline Branches: 53.2 % 1182 629 18 2 533 2 4 623
Baseline Date: 2025-12-15 13:30:48 -0800 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 36.4 % 11 4 7 4
(30,360] days: 68.4 % 57 39 18 39
(360..) days: 62.1 % 1559 968 2 589 2 966
Function coverage date bins:
(360..) days: 83.1 % 118 98 1 19 1 97
Branch coverage date bins:
(7,30] days: 18.2 % 22 4 18 4
(30,360] days: 76.7 % 30 23 7 23
(360..) days: 53.3 % 1130 602 2 526 2 600

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

Generated by: LCOV version 2.4-beta