PostgreSQL Source Code git master
Loading...
Searching...
No Matches
fe-exec.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include "common/int.h"
#include "libpq-fe.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
Include dependency graph for fe-exec.c:

Go to the source code of this file.

Macros

#define PGRESULT_DATA_BLOCKSIZE   2048
 
#define PGRESULT_ALIGN_BOUNDARY   MAXIMUM_ALIGNOF /* from configure */
 
#define PGRESULT_BLOCK_OVERHEAD   Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
 
#define PGRESULT_SEP_ALLOC_THRESHOLD   (PGRESULT_DATA_BLOCKSIZE / 2)
 
#define ISFIRSTOCTDIGIT(CH)   ((CH) >= '0' && (CH) <= '3')
 
#define ISOCTDIGIT(CH)   ((CH) >= '0' && (CH) <= '7')
 
#define OCTVAL(CH)   ((CH) - '0')
 

Functions

static PGEventdupEvents (PGEvent *events, int count, size_t *memSize)
 
static bool pqAddTuple (PGresult *res, PGresAttValue *tup, const char **errmsgp)
 
static int PQsendQueryInternal (PGconn *conn, const char *query, bool newQuery)
 
static bool PQsendQueryStart (PGconn *conn, bool newQuery)
 
static int PQsendQueryGuts (PGconn *conn, const char *command, const char *stmtName, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
 
static void parseInput (PGconn *conn)
 
static PGresultgetCopyResult (PGconn *conn, ExecStatusType copytype)
 
static bool PQexecStart (PGconn *conn)
 
static PGresultPQexecFinish (PGconn *conn)
 
static int PQsendTypedCommand (PGconn *conn, char command, char type, const char *target)
 
static int check_field_number (const PGresult *res, int field_num)
 
static void pqPipelineProcessQueue (PGconn *conn)
 
static int pqPipelineSyncInternal (PGconn *conn, bool immediate_flush)
 
static int pqPipelineFlush (PGconn *conn)
 
PGresultPQmakeEmptyPGresult (PGconn *conn, ExecStatusType status)
 
int PQsetResultAttrs (PGresult *res, int numAttributes, PGresAttDesc *attDescs)
 
PGresultPQcopyResult (const PGresult *src, int flags)
 
int PQsetvalue (PGresult *res, int tup_num, int field_num, char *value, int len)
 
voidPQresultAlloc (PGresult *res, size_t nBytes)
 
voidpqResultAlloc (PGresult *res, size_t nBytes, bool isBinary)
 
size_t PQresultMemorySize (const PGresult *res)
 
charpqResultStrdup (PGresult *res, const char *str)
 
void pqSetResultError (PGresult *res, PQExpBuffer errorMessage, int offset)
 
void PQclear (PGresult *res)
 
void pqClearAsyncResult (PGconn *conn)
 
void pqSaveErrorResult (PGconn *conn)
 
static void pqSaveWriteError (PGconn *conn)
 
PGresultpqPrepareAsyncResult (PGconn *conn)
 
void pqInternalNotice (const PGNoticeHooks *hooks, const char *fmt,...)
 
void pqSaveMessageField (PGresult *res, char code, const char *value)
 
int pqSaveParameterStatus (PGconn *conn, const char *name, const char *value)
 
int pqRowProcessor (PGconn *conn, const char **errmsgp)
 
static PGcmdQueueEntrypqAllocCmdQueueEntry (PGconn *conn)
 
static void pqAppendCmdQueueEntry (PGconn *conn, PGcmdQueueEntry *entry)
 
static void pqRecycleCmdQueueEntry (PGconn *conn, PGcmdQueueEntry *entry)
 
int PQsendQuery (PGconn *conn, const char *query)
 
int PQsendQueryContinue (PGconn *conn, const char *query)
 
int PQsendQueryParams (PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
 
int PQsendPrepare (PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
 
int PQsendQueryPrepared (PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
 
static bool canChangeResultMode (PGconn *conn)
 
int PQsetSingleRowMode (PGconn *conn)
 
int PQsetChunkedRowsMode (PGconn *conn, int chunkSize)
 
int PQconsumeInput (PGconn *conn)
 
int PQisBusy (PGconn *conn)
 
PGresultPQgetResult (PGconn *conn)
 
PGresultPQexec (PGconn *conn, const char *query)
 
PGresultPQexecParams (PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
 
PGresultPQprepare (PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
 
PGresultPQexecPrepared (PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
 
PGresultPQdescribePrepared (PGconn *conn, const char *stmt)
 
PGresultPQdescribePortal (PGconn *conn, const char *portal)
 
int PQsendDescribePrepared (PGconn *conn, const char *stmt)
 
int PQsendDescribePortal (PGconn *conn, const char *portal)
 
PGresultPQclosePrepared (PGconn *conn, const char *stmt)
 
PGresultPQclosePortal (PGconn *conn, const char *portal)
 
int PQsendClosePrepared (PGconn *conn, const char *stmt)
 
int PQsendClosePortal (PGconn *conn, const char *portal)
 
PGnotifyPQnotifies (PGconn *conn)
 
int PQputCopyData (PGconn *conn, const char *buffer, int nbytes)
 
int PQputCopyEnd (PGconn *conn, const char *errormsg)
 
int PQgetCopyData (PGconn *conn, char **buffer, int async)
 
int PQgetline (PGconn *conn, char *buffer, int length)
 
int PQgetlineAsync (PGconn *conn, char *buffer, int bufsize)
 
int PQputline (PGconn *conn, const char *string)
 
int PQputnbytes (PGconn *conn, const char *buffer, int nbytes)
 
int PQendcopy (PGconn *conn)
 
PGresultPQfn (PGconn *conn, int fnid, int *result_buf, int *result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
PGresultPQnfn (PGconn *conn, int fnid, int *result_buf, int buf_size, int *result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
int PQenterPipelineMode (PGconn *conn)
 
int PQexitPipelineMode (PGconn *conn)
 
void pqCommandQueueAdvance (PGconn *conn, bool isReadyForQuery, bool gotSync)
 
int PQpipelineSync (PGconn *conn)
 
int PQsendPipelineSync (PGconn *conn)
 
int PQsendFlushRequest (PGconn *conn)
 
ExecStatusType PQresultStatus (const PGresult *res)
 
charPQresStatus (ExecStatusType status)
 
charPQresultErrorMessage (const PGresult *res)
 
charPQresultVerboseErrorMessage (const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
 
charPQresultErrorField (const PGresult *res, int fieldcode)
 
int PQntuples (const PGresult *res)
 
int PQnfields (const PGresult *res)
 
int PQbinaryTuples (const PGresult *res)
 
static int check_tuple_field_number (const PGresult *res, int tup_num, int field_num)
 
static int check_param_number (const PGresult *res, int param_num)
 
charPQfname (const PGresult *res, int field_num)
 
int PQfnumber (const PGresult *res, const char *field_name)
 
Oid PQftable (const PGresult *res, int field_num)
 
int PQftablecol (const PGresult *res, int field_num)
 
int PQfformat (const PGresult *res, int field_num)
 
Oid PQftype (const PGresult *res, int field_num)
 
int PQfsize (const PGresult *res, int field_num)
 
int PQfmod (const PGresult *res, int field_num)
 
charPQcmdStatus (PGresult *res)
 
charPQoidStatus (const PGresult *res)
 
Oid PQoidValue (const PGresult *res)
 
charPQcmdTuples (PGresult *res)
 
charPQgetvalue (const PGresult *res, int tup_num, int field_num)
 
int PQgetlength (const PGresult *res, int tup_num, int field_num)
 
int PQgetisnull (const PGresult *res, int tup_num, int field_num)
 
int PQnparams (const PGresult *res)
 
Oid PQparamtype (const PGresult *res, int param_num)
 
int PQsetnonblocking (PGconn *conn, int arg)
 
int PQisnonblocking (const PGconn *conn)
 
int PQisthreadsafe (void)
 
int PQflush (PGconn *conn)
 
void PQfreemem (void *ptr)
 
void PQfreeNotify (PGnotify *notify)
 
static size_t PQescapeStringInternal (PGconn *conn, char *to, const char *from, size_t length, int *error, int encoding, bool std_strings)
 
size_t PQescapeStringConn (PGconn *conn, char *to, const char *from, size_t length, int *error)
 
size_t PQescapeString (char *to, const char *from, size_t length)
 
static charPQescapeInternal (PGconn *conn, const char *str, size_t len, bool as_ident)
 
charPQescapeLiteral (PGconn *conn, const char *str, size_t len)
 
charPQescapeIdentifier (PGconn *conn, const char *str, size_t len)
 
static char get_hex (char c)
 
static unsigned charPQescapeByteaInternal (PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length, bool std_strings, bool use_hex)
 
unsigned charPQescapeByteaConn (PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length)
 
unsigned charPQescapeBytea (const unsigned char *from, size_t from_length, size_t *to_length)
 
unsigned charPQunescapeBytea (const unsigned char *strtext, size_t *retbuflen)
 

Variables

char *const pgresStatus []
 
static const PGresult OOM_result
 
static int static_client_encoding = PG_SQL_ASCII
 
static bool static_std_strings = false
 
static const char hextbl [] = "0123456789abcdef"
 
static const int8 hexlookup [128]
 

Macro Definition Documentation

◆ ISFIRSTOCTDIGIT

#define ISFIRSTOCTDIGIT (   CH)    ((CH) >= '0' && (CH) <= '3')

Definition at line 4619 of file fe-exec.c.

◆ ISOCTDIGIT

#define ISOCTDIGIT (   CH)    ((CH) >= '0' && (CH) <= '7')

Definition at line 4620 of file fe-exec.c.

◆ OCTVAL

#define OCTVAL (   CH)    ((CH) - '0')

Definition at line 4621 of file fe-exec.c.

◆ PGRESULT_ALIGN_BOUNDARY

#define PGRESULT_ALIGN_BOUNDARY   MAXIMUM_ALIGNOF /* from configure */

Definition at line 144 of file fe-exec.c.

◆ PGRESULT_BLOCK_OVERHEAD

#define PGRESULT_BLOCK_OVERHEAD   Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)

Definition at line 145 of file fe-exec.c.

◆ PGRESULT_DATA_BLOCKSIZE

#define PGRESULT_DATA_BLOCKSIZE   2048

Definition at line 143 of file fe-exec.c.

◆ PGRESULT_SEP_ALLOC_THRESHOLD

#define PGRESULT_SEP_ALLOC_THRESHOLD   (PGRESULT_DATA_BLOCKSIZE / 2)

Definition at line 146 of file fe-exec.c.

Function Documentation

◆ canChangeResultMode()

static bool canChangeResultMode ( PGconn conn)
static

Definition at line 1942 of file fe-exec.c.

1943{
1944 /*
1945 * Only allow changing the mode when we have launched a query and not yet
1946 * received any results.
1947 */
1948 if (!conn)
1949 return false;
1951 return false;
1952 if (!conn->cmd_queue_head ||
1955 return false;
1957 return false;
1958 return true;
1959}
@ PGASYNC_BUSY
Definition libpq-int.h:217
@ PGQUERY_SIMPLE
Definition libpq-int.h:322
@ PGQUERY_EXTENDED
Definition libpq-int.h:323
#define pgHavePendingResult(conn)
Definition libpq-int.h:940
PGconn * conn
Definition streamutil.c:52
PGQueryClass queryclass
Definition libpq-int.h:347
PGAsyncStatusType asyncStatus
Definition libpq-int.h:466
PGcmdQueueEntry * cmd_queue_head
Definition libpq-int.h:492

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, PGASYNC_BUSY, pgHavePendingResult, PGQUERY_EXTENDED, PGQUERY_SIMPLE, and PGcmdQueueEntry::queryclass.

Referenced by PQsetChunkedRowsMode(), and PQsetSingleRowMode().

◆ check_field_number()

static int check_field_number ( const PGresult res,
int  field_num 
)
static

Definition at line 3541 of file fe-exec.c.

3542{
3543 if (!res)
3544 return false; /* no way to display error message... */
3546 {
3548 "column number %d is out of range 0..%d",
3549 field_num, res->numAttributes - 1);
3550 return false;
3551 }
3552 return true;
3553}
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition fe-exec.c:944
static int fb(int x)
PGNoticeHooks noticeHooks
Definition libpq-int.h:184
int numAttributes
Definition libpq-int.h:168

References fb(), pg_result::noticeHooks, pg_result::numAttributes, and pqInternalNotice().

Referenced by PQfformat(), PQfmod(), PQfname(), PQfsize(), PQftable(), PQftablecol(), PQftype(), and PQsetvalue().

◆ check_param_number()

static int check_param_number ( const PGresult res,
int  param_num 
)
static

Definition at line 3579 of file fe-exec.c.

3580{
3581 if (!res)
3582 return false; /* no way to display error message... */
3584 {
3586 "parameter number %d is out of range 0..%d",
3587 param_num, res->numParameters - 1);
3588 return false;
3589 }
3590
3591 return true;
3592}
int numParameters
Definition libpq-int.h:173

References fb(), pg_result::noticeHooks, pg_result::numParameters, and pqInternalNotice().

Referenced by PQparamtype().

◆ check_tuple_field_number()

static int check_tuple_field_number ( const PGresult res,
int  tup_num,
int  field_num 
)
static

Definition at line 3556 of file fe-exec.c.

3558{
3559 if (!res)
3560 return false; /* no way to display error message... */
3562 {
3564 "row number %d is out of range 0..%d",
3565 tup_num, res->ntups - 1);
3566 return false;
3567 }
3569 {
3571 "column number %d is out of range 0..%d",
3572 field_num, res->numAttributes - 1);
3573 return false;
3574 }
3575 return true;
3576}

References fb(), pg_result::noticeHooks, pg_result::ntups, pg_result::numAttributes, and pqInternalNotice().

Referenced by PQgetisnull(), PQgetlength(), and PQgetvalue().

◆ dupEvents()

static PGEvent * dupEvents ( PGEvent events,
int  count,
size_t memSize 
)
static

Definition at line 409 of file fe-exec.c.

410{
412 size_t msize;
413 int i;
414
415 if (!events || count <= 0)
416 return NULL;
417
418 msize = count * sizeof(PGEvent);
420 if (!newEvents)
421 return NULL;
422
423 for (i = 0; i < count; i++)
424 {
425 newEvents[i].proc = events[i].proc;
426 newEvents[i].passThrough = events[i].passThrough;
427 newEvents[i].data = NULL;
428 newEvents[i].resultInitialized = false;
429 newEvents[i].name = strdup(events[i].name);
430 if (!newEvents[i].name)
431 {
432 while (--i >= 0)
435 return NULL;
436 }
437 msize += strlen(events[i].name) + 1;
438 }
439
440 *memSize += msize;
441 return newEvents;
442}
int i
Definition isn.c:77
#define free(a)
#define malloc(a)
void * passThrough
Definition libpq-int.h:160
PGEventProc proc
Definition libpq-int.h:158
const char * name

References fb(), free, i, malloc, name, PGEvent::passThrough, and PGEvent::proc.

Referenced by PQcopyResult(), and PQmakeEmptyPGresult().

◆ get_hex()

static char get_hex ( char  c)
inlinestatic

Definition at line 4444 of file fe-exec.c.

4445{
4446 int res = -1;
4447
4448 if (c > 0 && c < 127)
4449 res = hexlookup[(unsigned char) c];
4450
4451 return (char) res;
4452}
static const int8 hexlookup[128]
Definition fe-exec.c:4432
char * c

References fb(), and hexlookup.

Referenced by PQunescapeBytea().

◆ getCopyResult()

static PGresult * getCopyResult ( PGconn conn,
ExecStatusType  copytype 
)
static

Definition at line 2241 of file fe-exec.c.

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 if (conn->status != CONNECTION_OK)
2252 {
2255 return pqPrepareAsyncResult(conn);
2256 }
2257
2258 /* If we have an async result for the COPY, return that */
2260 return pqPrepareAsyncResult(conn);
2261
2262 /* Otherwise, invent a suitable PGresult */
2264}
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition fe-exec.c:857
void pqSaveErrorResult(PGconn *conn)
Definition fe-exec.c:809
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition fe-exec.c:160
@ CONNECTION_OK
Definition libpq-fe.h:90
@ PGASYNC_IDLE
Definition libpq-int.h:216
PGresult * result
Definition libpq-int.h:609
ConnStatusType status
Definition libpq-int.h:465
ExecStatusType resultStatus
Definition libpq-int.h:175

References pg_conn::asyncStatus, conn, CONNECTION_OK, fb(), PGASYNC_IDLE, PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqSaveErrorResult(), pg_conn::result, pg_result::resultStatus, and pg_conn::status.

Referenced by PQgetResult().

◆ parseInput()

static void parseInput ( PGconn conn)
static

Definition at line 2037 of file fe-exec.c.

2038{
2040}
void pqParseInput3(PGconn *conn)

References conn, and pqParseInput3().

Referenced by PQgetResult(), PQisBusy(), PQnotifies(), and PQputCopyData().

◆ pqAddTuple()

static bool pqAddTuple ( PGresult res,
PGresAttValue tup,
const char **  errmsgp 
)
static

Definition at line 999 of file fe-exec.c.

1000{
1001 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;
1016
1017 /*
1018 * Since we use integers for row numbers, we can't support more than
1019 * INT_MAX rows. Make sure we allow that many, though.
1020 */
1021 if (res->tupArrSize <= INT_MAX / 2)
1022 newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
1023 else if (res->tupArrSize < INT_MAX)
1024 newSize = INT_MAX;
1025 else
1026 {
1027 *errmsgp = libpq_gettext("PGresult cannot support more than INT_MAX tuples");
1028 return false;
1029 }
1030
1031 /*
1032 * Also, on 32-bit platforms we could, in theory, overflow size_t even
1033 * before newSize gets to INT_MAX. (In practice we'd doubtless hit
1034 * OOM long before that, but let's check.)
1035 */
1036#if INT_MAX >= (SIZE_MAX / 2)
1037 if (newSize > SIZE_MAX / sizeof(PGresAttValue *))
1038 {
1039 *errmsgp = libpq_gettext("size_t overflow");
1040 return false;
1041 }
1042#endif
1043
1044 if (res->tuples == NULL)
1046 malloc(newSize * sizeof(PGresAttValue *));
1047 else
1049 realloc(res->tuples, newSize * sizeof(PGresAttValue *));
1050 if (!newTuples)
1051 return false; /* malloc or realloc failed */
1052 res->memorySize +=
1053 (newSize - res->tupArrSize) * sizeof(PGresAttValue *);
1054 res->tupArrSize = newSize;
1055 res->tuples = newTuples;
1056 }
1057 res->tuples[res->ntups] = tup;
1058 res->ntups++;
1059 return true;
1060}
#define libpq_gettext(x)
Definition oauth-utils.h:44
#define realloc(a, b)
size_t memorySize
Definition libpq-int.h:210
PGresAttValue ** tuples
Definition libpq-int.h:170
int tupArrSize
Definition libpq-int.h:172

References fb(), libpq_gettext, malloc, pg_result::memorySize, pg_result::ntups, realloc, pg_result::tupArrSize, and pg_result::tuples.

Referenced by pqRowProcessor(), and PQsetvalue().

◆ pqAllocCmdQueueEntry()

static PGcmdQueueEntry * pqAllocCmdQueueEntry ( PGconn conn)
static

Definition at line 1323 of file fe-exec.c.

1324{
1325 PGcmdQueueEntry *entry;
1326
1327 if (conn->cmd_queue_recycle == NULL)
1328 {
1329 entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry));
1330 if (entry == NULL)
1331 {
1332 libpq_append_conn_error(conn, "out of memory");
1333 return NULL;
1334 }
1335 }
1336 else
1337 {
1338 entry = conn->cmd_queue_recycle;
1339 conn->cmd_queue_recycle = entry->next;
1340 }
1341 entry->next = NULL;
1342 entry->query = NULL;
1343
1344 return entry;
1345}
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition fe-misc.c:1404
struct PGcmdQueueEntry * next
Definition libpq-int.h:349
PGcmdQueueEntry * cmd_queue_recycle
Definition libpq-int.h:499

References pg_conn::cmd_queue_recycle, conn, fb(), libpq_append_conn_error(), malloc, PGcmdQueueEntry::next, and PGcmdQueueEntry::query.

Referenced by pqPipelineSyncInternal(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ pqAppendCmdQueueEntry()

static void pqAppendCmdQueueEntry ( PGconn conn,
PGcmdQueueEntry entry 
)
static

Definition at line 1356 of file fe-exec.c.

1357{
1358 Assert(entry->next == NULL);
1359
1360 if (conn->cmd_queue_head == NULL)
1361 conn->cmd_queue_head = entry;
1362 else
1363 conn->cmd_queue_tail->next = entry;
1364
1365 conn->cmd_queue_tail = entry;
1366
1367 switch (conn->pipelineStatus)
1368 {
1369 case PQ_PIPELINE_OFF:
1370 case PQ_PIPELINE_ON:
1371
1372 /*
1373 * When not in pipeline aborted state, if there's a result ready
1374 * to be consumed, let it be so (that is, don't change away from
1375 * READY or READY_MORE); otherwise set us busy to wait for
1376 * something to arrive from the server.
1377 */
1380 break;
1381
1383
1384 /*
1385 * In aborted pipeline state, we don't expect anything from the
1386 * server (since we don't send any queries that are queued).
1387 * Therefore, if IDLE then do what PQgetResult would do to let
1388 * itself consume commands from the queue; if we're in any other
1389 * state, we don't have to do anything.
1390 */
1391 if (conn->asyncStatus == PGASYNC_IDLE ||
1394 break;
1395 }
1396}
#define Assert(condition)
Definition c.h:943
static void pqPipelineProcessQueue(PGconn *conn)
Definition fe-exec.c:3211
@ PQ_PIPELINE_OFF
Definition libpq-fe.h:193
@ PQ_PIPELINE_ABORTED
Definition libpq-fe.h:195
@ PQ_PIPELINE_ON
Definition libpq-fe.h:194
@ PGASYNC_PIPELINE_IDLE
Definition libpq-int.h:226
PGcmdQueueEntry * cmd_queue_tail
Definition libpq-int.h:493
PGpipelineStatus pipelineStatus
Definition libpq-int.h:472

References Assert, pg_conn::asyncStatus, pg_conn::cmd_queue_head, pg_conn::cmd_queue_tail, conn, fb(), PGcmdQueueEntry::next, PGASYNC_BUSY, PGASYNC_IDLE, PGASYNC_PIPELINE_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_ABORTED, PQ_PIPELINE_OFF, PQ_PIPELINE_ON, and pqPipelineProcessQueue().

Referenced by pqPipelineSyncInternal(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ PQbinaryTuples()

int PQbinaryTuples ( const PGresult res)

Definition at line 3528 of file fe-exec.c.

3529{
3530 if (!res)
3531 return 0;
3532 return res->binary;
3533}

References pg_result::binary.

Referenced by HandleCopyResult().

◆ PQclear()

void PQclear ( PGresult res)

Definition at line 727 of file fe-exec.c.

728{
729 PGresult_data *block;
730 int i;
731
732 /* As a convenience, do nothing for a NULL pointer */
733 if (!res)
734 return;
735 /* Also, do nothing if the argument is OOM_result */
736 if ((const PGresult *) res == &OOM_result)
737 return;
738
739 /* Close down any events we may have */
740 for (i = 0; i < res->nEvents; i++)
741 {
742 /* only send DESTROY to successfully-initialized event procs */
743 if (res->events[i].resultInitialized)
744 {
746
747 evt.result = res;
749 res->events[i].passThrough);
750 }
751 free(res->events[i].name);
752 }
753
754 free(res->events);
755
756 /* Free all the subsidiary blocks */
757 while ((block = res->curBlock) != NULL)
758 {
759 res->curBlock = block->next;
760 free(block);
761 }
762
763 /* Free the top-level tuple pointer array */
764 free(res->tuples);
765
766 /* zero out the pointer fields to catch programming errors */
767 res->attDescs = NULL;
768 res->tuples = NULL;
769 res->paramDescs = NULL;
770 res->errFields = NULL;
771 res->events = NULL;
772 res->nEvents = 0;
773 /* res->curBlock was zeroed out earlier */
774
775 /* Free the PGresult structure itself */
776 free(res);
777}
static const PGresult OOM_result
Definition fe-exec.c:50
@ PGEVT_RESULTDESTROY
char * name
Definition libpq-int.h:159
bool resultInitialized
Definition libpq-int.h:162
int nEvents
Definition libpq-int.h:186
PGresAttDesc * attDescs
Definition libpq-int.h:169
PGMessageField * errFields
Definition libpq-int.h:195
PGresParamDesc * paramDescs
Definition libpq-int.h:174
PGEvent * events
Definition libpq-int.h:185
PGresult_data * curBlock
Definition libpq-int.h:206
PGresult_data * next
Definition libpq-int.h:103

References pg_result::attDescs, pg_result::curBlock, pg_result::errFields, pg_result::events, fb(), free, i, PGEvent::name, pg_result::nEvents, pgresult_data::next, OOM_result, pg_result::paramDescs, PGEvent::passThrough, PGEVT_RESULTDESTROY, PGEvent::proc, PGEventResultDestroy::result, PGEvent::resultInitialized, and pg_result::tuples.

◆ pqClearAsyncResult()

◆ PQclosePortal()

PGresult * PQclosePortal ( PGconn conn,
const char portal 
)

Definition at line 2556 of file fe-exec.c.

2557{
2558 if (!PQexecStart(conn))
2559 return NULL;
2560 if (!PQsendTypedCommand(conn, PqMsg_Close, 'P', portal))
2561 return NULL;
2562 return PQexecFinish(conn);
2563}
static PGresult * PQexecFinish(PGconn *conn)
Definition fe-exec.c:2427
static int PQsendTypedCommand(PGconn *conn, char command, char type, const char *target)
Definition fe-exec.c:2606
static bool PQexecStart(PGconn *conn)
Definition fe-exec.c:2361
#define PqMsg_Close
Definition protocol.h:20

References conn, fb(), PQexecFinish(), PQexecStart(), PqMsg_Close, and PQsendTypedCommand().

Referenced by test_prepared().

◆ PQclosePrepared()

PGresult * PQclosePrepared ( PGconn conn,
const char stmt 
)

Definition at line 2538 of file fe-exec.c.

2539{
2540 if (!PQexecStart(conn))
2541 return NULL;
2543 return NULL;
2544 return PQexecFinish(conn);
2545}
#define stmt

References conn, fb(), PQexecFinish(), PQexecStart(), PqMsg_Close, PQsendTypedCommand(), and stmt.

Referenced by test_prepared().

◆ PQcmdStatus()

char * PQcmdStatus ( PGresult res)

Definition at line 3783 of file fe-exec.c.

3784{
3785 if (!res)
3786 return NULL;
3787 return res->cmdStatus;
3788}
char cmdStatus[CMDSTATUS_LEN]
Definition libpq-int.h:176

References pg_result::cmdStatus, and fb().

◆ PQcmdTuples()

char * PQcmdTuples ( PGresult res)

Definition at line 3853 of file fe-exec.c.

3854{
3855 char *p,
3856 *c;
3857
3858 if (!res)
3859 return "";
3860
3861 if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
3862 {
3863 p = res->cmdStatus + 7;
3864 /* INSERT: skip oid and space */
3865 while (*p && *p != ' ')
3866 p++;
3867 if (*p == 0)
3868 goto interpret_error; /* no space? */
3869 p++;
3870 }
3871 else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
3872 strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
3873 strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
3874 p = res->cmdStatus + 7;
3875 else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0 ||
3876 strncmp(res->cmdStatus, "MERGE ", 6) == 0)
3877 p = res->cmdStatus + 6;
3878 else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
3879 strncmp(res->cmdStatus, "COPY ", 5) == 0)
3880 p = res->cmdStatus + 5;
3881 else
3882 return "";
3883
3884 /* check that we have an integer (at least one digit, nothing else) */
3885 for (c = p; *c; c++)
3886 {
3887 if (!isdigit((unsigned char) *c))
3888 goto interpret_error;
3889 }
3890 if (c == p)
3891 goto interpret_error;
3892
3893 return p;
3894
3897 "could not interpret result from server: %s",
3898 res->cmdStatus);
3899 return "";
3900}

References pg_result::cmdStatus, fb(), pg_result::noticeHooks, and pqInternalNotice().

◆ pqCommandQueueAdvance()

void pqCommandQueueAdvance ( PGconn conn,
bool  isReadyForQuery,
bool  gotSync 
)

Definition at line 3173 of file fe-exec.c.

3174{
3176
3177 if (conn->cmd_queue_head == NULL)
3178 return;
3179
3180 /*
3181 * If processing a query of simple query protocol, we only advance the
3182 * queue when we receive the ReadyForQuery message for it.
3183 */
3185 return;
3186
3187 /*
3188 * If we're waiting for a SYNC, don't advance the queue until we get one.
3189 */
3191 return;
3192
3193 /* delink element from queue */
3196
3197 /* If the queue is now empty, reset the tail too */
3198 if (conn->cmd_queue_head == NULL)
3200
3201 /* and make the queue element recyclable */
3202 prevquery->next = NULL;
3204}
static void pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition fe-exec.c:1403
@ PGQUERY_SYNC
Definition libpq-int.h:326

References pg_conn::cmd_queue_head, pg_conn::cmd_queue_tail, conn, fb(), PGcmdQueueEntry::next, PGQUERY_SIMPLE, PGQUERY_SYNC, pqRecycleCmdQueueEntry(), and PGcmdQueueEntry::queryclass.

Referenced by PQgetResult(), and pqParseInput3().

◆ PQconsumeInput()

int PQconsumeInput ( PGconn conn)

Definition at line 2001 of file fe-exec.c.

2002{
2003 if (!conn)
2004 return 0;
2005
2006 /*
2007 * for non-blocking connections try to flush the send-queue, otherwise we
2008 * may never get a response for something that may not have already been
2009 * sent because it's in our write buffer!
2010 */
2011 if (pqIsnonblocking(conn))
2012 {
2013 if (pqFlush(conn) < 0)
2014 return 0;
2015 }
2016
2017 /*
2018 * Load more data, if available. We do this no matter what state we are
2019 * in, since we are probably getting called because the application wants
2020 * to get rid of a read-select condition. Note that we will NOT block
2021 * waiting for more input.
2022 */
2023 if (pqReadData(conn) < 0)
2024 return 0;
2025
2026 /* Parsing of the data waits till later. */
2027 return 1;
2028}
int pqReadData(PGconn *conn)
Definition fe-misc.c:606
int pqFlush(PGconn *conn)
Definition fe-misc.c:994
#define pqIsnonblocking(conn)
Definition libpq-int.h:947

References conn, pqFlush(), pqIsnonblocking, and pqReadData().

Referenced by advanceConnectionState(), consume_query_cancel_impl(), CopyStreamReceive(), dblink_get_notify(), dblink_is_busy(), do_sql_command_end(), ecpg_process_output(), libpqrcv_receive(), libpqsrv_get_result(), main(), pgfdw_cancel_query_end(), pgfdw_exec_cleanup_query_end(), pgfdw_get_cleanup_result(), postgresForeignAsyncNotify(), PQconnectPoll(), PrintNotifications(), process_slot(), StreamLogicalLog(), test_nosync(), test_pipelined_insert(), test_uniqviol(), try_complete_step(), and wait_on_slots().

◆ PQcopyResult()

PGresult * PQcopyResult ( const PGresult src,
int  flags 
)

Definition at line 319 of file fe-exec.c.

320{
321 PGresult *dest;
322 int i;
323
324 if (!src)
325 return NULL;
326
328 if (!dest)
329 return NULL;
330
331 /* Always copy these over. Is cmdStatus really useful here? */
332 dest->client_encoding = src->client_encoding;
333 strcpy(dest->cmdStatus, src->cmdStatus);
334
335 /* Wants attrs? */
336 if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
337 {
338 if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs))
339 {
340 PQclear(dest);
341 return NULL;
342 }
343 }
344
345 /* Wants to copy tuples? */
346 if (flags & PG_COPYRES_TUPLES)
347 {
348 int tup,
349 field;
350
351 for (tup = 0; tup < src->ntups; tup++)
352 {
353 for (field = 0; field < src->numAttributes; field++)
354 {
355 if (!PQsetvalue(dest, tup, field,
356 src->tuples[tup][field].value,
357 src->tuples[tup][field].len))
358 {
359 PQclear(dest);
360 return NULL;
361 }
362 }
363 }
364 }
365
366 /* Wants to copy notice hooks? */
367 if (flags & PG_COPYRES_NOTICEHOOKS)
368 dest->noticeHooks = src->noticeHooks;
369
370 /* Wants to copy PGEvents? */
371 if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
372 {
373 dest->events = dupEvents(src->events, src->nEvents,
374 &dest->memorySize);
375 if (!dest->events)
376 {
377 PQclear(dest);
378 return NULL;
379 }
380 dest->nEvents = src->nEvents;
381 }
382
383 /* Okay, trigger PGEVT_RESULTCOPY event */
384 for (i = 0; i < dest->nEvents; i++)
385 {
386 /* We don't fire events that had some previous failure */
387 if (src->events[i].resultInitialized)
388 {
390
391 evt.src = src;
392 evt.dest = dest;
393 if (dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
394 dest->events[i].passThrough))
395 dest->events[i].resultInitialized = true;
396 }
397 }
398
399 return dest;
400}
int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
Definition fe-exec.c:250
static PGEvent * dupEvents(PGEvent *events, int count, size_t *memSize)
Definition fe-exec.c:409
int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
Definition fe-exec.c:453
@ PGEVT_RESULTCOPY
@ PGRES_TUPLES_OK
Definition libpq-fe.h:134
#define PG_COPYRES_TUPLES
Definition libpq-fe.h:76
#define PG_COPYRES_ATTRS
Definition libpq-fe.h:75
#define PG_COPYRES_EVENTS
Definition libpq-fe.h:77
#define PG_COPYRES_NOTICEHOOKS
Definition libpq-fe.h:78
const PGresult * src
int client_encoding
Definition libpq-int.h:187

References pg_result::attDescs, pg_result::client_encoding, pg_result::cmdStatus, dupEvents(), pg_result::events, fb(), i, pgresAttValue::len, pg_result::nEvents, pg_result::noticeHooks, pg_result::ntups, pg_result::numAttributes, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PG_COPYRES_TUPLES, PGEVT_RESULTCOPY, PGRES_TUPLES_OK, PQclear, PQmakeEmptyPGresult(), PQsetResultAttrs(), PQsetvalue(), PGEvent::resultInitialized, PGEventResultCopy::src, pg_result::tuples, and pgresAttValue::value.

Referenced by pqRowProcessor().

◆ PQdescribePortal()

PGresult * PQdescribePortal ( PGconn conn,
const char portal 
)

Definition at line 2491 of file fe-exec.c.

2492{
2493 if (!PQexecStart(conn))
2494 return NULL;
2495 if (!PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal))
2496 return NULL;
2497 return PQexecFinish(conn);
2498}
#define PqMsg_Describe
Definition protocol.h:21

References conn, fb(), PQexecFinish(), PQexecStart(), PqMsg_Describe, and PQsendTypedCommand().

Referenced by test_prepared().

◆ PQdescribePrepared()

PGresult * PQdescribePrepared ( PGconn conn,
const char stmt 
)

Definition at line 2472 of file fe-exec.c.

2473{
2474 if (!PQexecStart(conn))
2475 return NULL;
2477 return NULL;
2478 return PQexecFinish(conn);
2479}

References conn, fb(), PQexecFinish(), PQexecStart(), PqMsg_Describe, PQsendTypedCommand(), and stmt.

Referenced by DescribeQuery(), ECPGdescribe(), and test_prepared().

◆ PQendcopy()

int PQendcopy ( PGconn conn)

Definition at line 2966 of file fe-exec.c.

2967{
2968 if (!conn)
2969 return 0;
2970
2971 return pqEndcopy3(conn);
2972}
int pqEndcopy3(PGconn *conn)

References conn, and pqEndcopy3().

Referenced by ecpg_check_PQresult(), initPopulateTable(), libpqrcv_endstreaming(), and readCommandResponse().

◆ PQenterPipelineMode()

int PQenterPipelineMode ( PGconn conn)

Definition at line 3073 of file fe-exec.c.

3074{
3075 if (!conn)
3076 return 0;
3077
3078 /* succeed with no action if already in pipeline mode */
3080 return 1;
3081
3083 {
3084 libpq_append_conn_error(conn, "cannot enter pipeline mode, connection not idle");
3085 return 0;
3086 }
3087
3089
3090 return 1;
3091}

References pg_conn::asyncStatus, conn, libpq_append_conn_error(), PGASYNC_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, and PQ_PIPELINE_ON.

Referenced by ExecQueryAndProcessResults(), executeMetaCommand(), test_disallowed_in_pipeline(), test_multi_pipelines(), test_nosync(), test_pipeline_abort(), test_pipeline_idle(), test_pipelined_insert(), test_prepared(), test_simple_pipeline(), test_singlerowmode(), test_transaction(), and test_uniqviol().

◆ PQescapeBytea()

unsigned char * PQescapeBytea ( const unsigned char from,
size_t  from_length,
size_t to_length 
)

Definition at line 4611 of file fe-exec.c.

4612{
4615 false /* can't use hex */ );
4616}
static unsigned char * PQescapeByteaInternal(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length, bool std_strings, bool use_hex)
Definition fe-exec.c:4471
static bool static_std_strings
Definition fe-exec.c:61

References fb(), PQescapeByteaInternal(), and static_std_strings.

◆ PQescapeByteaConn()

unsigned char * PQescapeByteaConn ( PGconn conn,
const unsigned char from,
size_t  from_length,
size_t to_length 
)

Definition at line 4595 of file fe-exec.c.

4598{
4599 if (!conn)
4600 return NULL;
4601
4602 if (conn->cmd_queue_head == NULL)
4604
4607 (conn->sversion >= 90000));
4608}
#define pqClearConnErrorState(conn)
Definition libpq-int.h:931
bool std_strings
Definition libpq-int.h:560
int sversion
Definition libpq-int.h:507

References pg_conn::cmd_queue_head, conn, fb(), pqClearConnErrorState, PQescapeByteaInternal(), pg_conn::std_strings, and pg_conn::sversion.

◆ PQescapeByteaInternal()

static unsigned char * PQescapeByteaInternal ( PGconn conn,
const unsigned char from,
size_t  from_length,
size_t to_length,
bool  std_strings,
bool  use_hex 
)
static

Definition at line 4471 of file fe-exec.c.

4474{
4475 const unsigned char *vp;
4476 unsigned char *rp;
4477 unsigned char *result;
4478 size_t i;
4479 size_t len;
4480 const size_t bslash_len = (std_strings ? 1 : 2);
4481
4482 /*
4483 * Calculate the escaped length, watching for overflow as we do with
4484 * PQescapeInternal(). The following code relies on a small constant
4485 * bslash_len so that small additions and multiplications don't need their
4486 * own overflow checks.
4487 *
4488 * Start with the empty string, which has 1 char ('\0').
4489 */
4490 len = 1;
4491
4492 if (use_hex)
4493 {
4494 /* We prepend "\x" and double each input character. */
4495 if (pg_add_size_overflow(len, bslash_len + 1, &len) ||
4498 goto overflow;
4499 }
4500 else
4501 {
4502 vp = from;
4503 for (i = from_length; i > 0; i--, vp++)
4504 {
4505 if (*vp < 0x20 || *vp > 0x7e)
4506 {
4507 if (pg_add_size_overflow(len, bslash_len + 3, &len)) /* octal "\ooo" */
4508 goto overflow;
4509 }
4510 else if (*vp == '\'')
4511 {
4512 if (pg_add_size_overflow(len, 2, &len)) /* double each quote */
4513 goto overflow;
4514 }
4515 else if (*vp == '\\')
4516 {
4517 if (pg_add_size_overflow(len, bslash_len * 2, &len)) /* double each backslash */
4518 goto overflow;
4519 }
4520 else
4521 {
4522 if (pg_add_size_overflow(len, 1, &len))
4523 goto overflow;
4524 }
4525 }
4526 }
4527
4528 *to_length = len;
4529 rp = result = (unsigned char *) malloc(len);
4530 if (rp == NULL)
4531 {
4532 if (conn)
4533 libpq_append_conn_error(conn, "out of memory");
4534 return NULL;
4535 }
4536
4537 if (use_hex)
4538 {
4539 if (!std_strings)
4540 *rp++ = '\\';
4541 *rp++ = '\\';
4542 *rp++ = 'x';
4543 }
4544
4545 vp = from;
4546 for (i = from_length; i > 0; i--, vp++)
4547 {
4548 unsigned char c = *vp;
4549
4550 if (use_hex)
4551 {
4552 *rp++ = hextbl[(c >> 4) & 0xF];
4553 *rp++ = hextbl[c & 0xF];
4554 }
4555 else if (c < 0x20 || c > 0x7e)
4556 {
4557 if (!std_strings)
4558 *rp++ = '\\';
4559 *rp++ = '\\';
4560 *rp++ = (c >> 6) + '0';
4561 *rp++ = ((c >> 3) & 07) + '0';
4562 *rp++ = (c & 07) + '0';
4563 }
4564 else if (c == '\'')
4565 {
4566 *rp++ = '\'';
4567 *rp++ = '\'';
4568 }
4569 else if (c == '\\')
4570 {
4571 if (!std_strings)
4572 {
4573 *rp++ = '\\';
4574 *rp++ = '\\';
4575 }
4576 *rp++ = '\\';
4577 *rp++ = '\\';
4578 }
4579 else
4580 *rp++ = c;
4581 }
4582 *rp = '\0';
4583
4584 return result;
4585
4586overflow:
4587 if (conn)
4589 "escaped bytea size exceeds the maximum allowed (%zu)",
4590 SIZE_MAX);
4591 return NULL;
4592}
uint32 result
static const char hextbl[]
Definition fe-exec.c:4430
static bool pg_add_size_overflow(size_t a, size_t b, size_t *result)
Definition int.h:608
const void size_t len

References conn, fb(), hextbl, i, len, libpq_append_conn_error(), malloc, pg_add_size_overflow(), and result.

Referenced by PQescapeBytea(), and PQescapeByteaConn().

◆ PQescapeIdentifier()

char * PQescapeIdentifier ( PGconn conn,
const char str,
size_t  len 
)

Definition at line 4424 of file fe-exec.c.

4425{
4426 return PQescapeInternal(conn, str, len, true);
4427}
static char * PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
Definition fe-exec.c:4250
const char * str

References conn, len, PQescapeInternal(), and str.

Referenced by create_publication(), create_subscription(), drop_existing_subscription(), drop_publication(), enable_subscription(), escape_identifier(), initCreatePKeys(), initCreateTables(), main(), PQchangePassword(), psql_get_variable(), stringlist_to_identifierstr(), and vacuumlo().

◆ PQescapeInternal()

static char * PQescapeInternal ( PGconn conn,
const char str,
size_t  len,
bool  as_ident 
)
static

Definition at line 4250 of file fe-exec.c.

4251{
4252 const char *s;
4253 char *result;
4254 char *rp;
4255 size_t num_quotes = 0; /* single or double, depending on as_ident */
4256 size_t num_backslashes = 0;
4257 size_t input_len = strnlen(str, len);
4258 size_t result_size;
4259 char quote_char = as_ident ? '"' : '\'';
4260 bool validated_mb = false;
4261
4262 /* We must have a connection, else fail immediately. */
4263 if (!conn)
4264 return NULL;
4265
4266 if (conn->cmd_queue_head == NULL)
4268
4269 /*
4270 * Scan the string for characters that must be escaped and for invalidly
4271 * encoded data.
4272 */
4273 s = str;
4274 for (size_t remaining = input_len; remaining > 0; remaining--, s++)
4275 {
4276 if (*s == quote_char)
4277 ++num_quotes;
4278 else if (*s == '\\')
4280 else if (IS_HIGHBIT_SET(*s))
4281 {
4282 int charlen;
4283
4284 /* Slow path for possible multibyte characters */
4286 s, remaining);
4287
4288 if (charlen > remaining)
4289 {
4290 /* Multibyte character overruns allowable length. */
4291 libpq_append_conn_error(conn, "incomplete multibyte character");
4292 return NULL;
4293 }
4294
4295 /*
4296 * If we haven't already, check that multibyte characters are
4297 * valid. It's important to verify that as invalid multi-byte
4298 * characters could e.g. be used to "skip" over quote characters,
4299 * e.g. when parsing character-by-character.
4300 *
4301 * We check validity once, for the whole remainder of the string,
4302 * when we first encounter any multi-byte character. Some
4303 * encodings have optimized implementations for longer strings.
4304 */
4305 if (!validated_mb)
4306 {
4308 != remaining)
4309 {
4310 libpq_append_conn_error(conn, "invalid multibyte character");
4311 return NULL;
4312 }
4313 validated_mb = true;
4314 }
4315
4316 /* Adjust s, bearing in mind that for loop will increment it. */
4317 s += charlen - 1;
4318 remaining -= charlen - 1;
4319 }
4320 }
4321
4322 /*
4323 * Allocate output buffer. Protect against overflow, in case the caller
4324 * has allocated a large fraction of the available size_t.
4325 */
4326 if (pg_add_size_overflow(input_len, num_quotes, &result_size) ||
4327 pg_add_size_overflow(result_size, 3, &result_size)) /* two quotes plus a NUL */
4328 goto overflow;
4329
4330 if (!as_ident && num_backslashes > 0)
4331 {
4332 if (pg_add_size_overflow(result_size, num_backslashes, &result_size) ||
4333 pg_add_size_overflow(result_size, 2, &result_size)) /* for " E" prefix */
4334 goto overflow;
4335 }
4336
4337 result = rp = (char *) malloc(result_size);
4338 if (rp == NULL)
4339 {
4340 libpq_append_conn_error(conn, "out of memory");
4341 return NULL;
4342 }
4343
4344 /*
4345 * If we are escaping a literal that contains backslashes, we use the
4346 * escape string syntax so that the result is correct under either value
4347 * of standard_conforming_strings. We also emit a leading space in this
4348 * case, to guard against the possibility that the result might be
4349 * interpolated immediately following an identifier.
4350 */
4351 if (!as_ident && num_backslashes > 0)
4352 {
4353 *rp++ = ' ';
4354 *rp++ = 'E';
4355 }
4356
4357 /* Opening quote. */
4358 *rp++ = quote_char;
4359
4360 /*
4361 * Use fast path if possible.
4362 *
4363 * We've already verified that the input string is well-formed in the
4364 * current encoding. If it contains no quotes and, in the case of
4365 * literal-escaping, no backslashes, then we can just copy it directly to
4366 * the output buffer, adding the necessary quotes.
4367 *
4368 * If not, we must rescan the input and process each character
4369 * individually.
4370 */
4371 if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
4372 {
4373 memcpy(rp, str, input_len);
4374 rp += input_len;
4375 }
4376 else
4377 {
4378 s = str;
4379 for (size_t remaining = input_len; remaining > 0; remaining--, s++)
4380 {
4381 if (*s == quote_char || (!as_ident && *s == '\\'))
4382 {
4383 *rp++ = *s;
4384 *rp++ = *s;
4385 }
4386 else if (!IS_HIGHBIT_SET(*s))
4387 *rp++ = *s;
4388 else
4389 {
4391
4392 while (1)
4393 {
4394 *rp++ = *s;
4395 if (--i == 0)
4396 break;
4397 remaining--;
4398 ++s; /* for loop will provide the final increment */
4399 }
4400 }
4401 }
4402 }
4403
4404 /* Closing quote and terminating NUL. */
4405 *rp++ = quote_char;
4406 *rp = '\0';
4407
4408 return result;
4409
4410overflow:
4412 "escaped string size exceeds the maximum allowed (%zu)",
4413 SIZE_MAX);
4414 return NULL;
4415}
#define IS_HIGHBIT_SET(ch)
Definition c.h:1244
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int remaining
Definition informix.c:692
int client_encoding
Definition libpq-int.h:559
int pg_encoding_mblen_or_incomplete(int encoding, const char *mbstr, size_t remaining)
Definition wchar.c:1947
int pg_encoding_verifymbstr(int encoding, const char *mbstr, int len)
Definition wchar.c:2002
int pg_encoding_mblen(int encoding, const char *mbstr)
Definition wchar.c:1935

References pg_conn::client_encoding, pg_conn::cmd_queue_head, conn, fb(), i, IS_HIGHBIT_SET, len, libpq_append_conn_error(), malloc, memcpy(), pg_add_size_overflow(), pg_encoding_mblen(), pg_encoding_mblen_or_incomplete(), pg_encoding_verifymbstr(), pqClearConnErrorState, remaining, result, and str.

Referenced by PQescapeIdentifier(), and PQescapeLiteral().

◆ PQescapeLiteral()

◆ PQescapeString()

size_t PQescapeString ( char to,
const char from,
size_t  length 
)

Definition at line 4235 of file fe-exec.c.

4236{
4237 return PQescapeStringInternal(NULL, to, from, length, NULL,
4240}
static size_t PQescapeStringInternal(PGconn *conn, char *to, const char *from, size_t length, int *error, int encoding, bool std_strings)
Definition fe-exec.c:4107
static int static_client_encoding
Definition fe-exec.c:60

References fb(), PQescapeStringInternal(), static_client_encoding, and static_std_strings.

Referenced by escape_string(), get_comma_elts(), and quote_postgres().

◆ PQescapeStringConn()

size_t PQescapeStringConn ( PGconn conn,
char to,
const char from,
size_t  length,
int error 
)

Definition at line 4213 of file fe-exec.c.

4216{
4217 if (!conn)
4218 {
4219 /* force empty-string result */
4220 *to = '\0';
4221 if (error)
4222 *error = 1;
4223 return 0;
4224 }
4225
4226 if (conn->cmd_queue_head == NULL)
4228
4229 return PQescapeStringInternal(conn, to, from, length, error,
4231 conn->std_strings);
4232}
static void error(void)

References pg_conn::client_encoding, pg_conn::cmd_queue_head, conn, error(), fb(), pqClearConnErrorState, PQescapeStringInternal(), and pg_conn::std_strings.

Referenced by AppendStringCommandOption(), appendStringLiteralConn(), check_loadable_libraries(), do_lo_import(), and escape_string_conn().

◆ PQescapeStringInternal()

static size_t PQescapeStringInternal ( PGconn conn,
char to,
const char from,
size_t  length,
int error,
int  encoding,
bool  std_strings 
)
static

Definition at line 4107 of file fe-exec.c.

4111{
4112 const char *source = from;
4113 char *target = to;
4114 size_t remaining = strnlen(from, length);
4115 bool already_complained = false;
4116
4117 if (error)
4118 *error = 0;
4119
4120 while (remaining > 0)
4121 {
4122 char c = *source;
4123 int charlen;
4124 int i;
4125
4126 /* Fast path for plain ASCII */
4127 if (!IS_HIGHBIT_SET(c))
4128 {
4129 /* Apply quoting if needed */
4130 if (SQL_STR_DOUBLE(c, !std_strings))
4131 *target++ = c;
4132 /* Copy the character */
4133 *target++ = c;
4134 source++;
4135 remaining--;
4136 continue;
4137 }
4138
4139 /* Slow path for possible multibyte characters */
4141 source, remaining);
4142
4143 if (remaining < charlen ||
4144 pg_encoding_verifymbchar(encoding, source, charlen) == -1)
4145 {
4146 /*
4147 * Multibyte character is invalid. It's important to verify that
4148 * as invalid multibyte characters could e.g. be used to "skip"
4149 * over quote characters, e.g. when parsing
4150 * character-by-character.
4151 *
4152 * Report an error if possible, and replace the character's first
4153 * byte with an invalid sequence. The invalid sequence ensures
4154 * that the escaped string will trigger an error on the
4155 * server-side, even if we can't directly report an error here.
4156 *
4157 * This isn't *that* crucial when we can report an error to the
4158 * caller; but if we can't or the caller ignores it, the caller
4159 * will use this string unmodified and it needs to be safe for
4160 * parsing.
4161 *
4162 * We know there's enough space for the invalid sequence because
4163 * the "to" buffer needs to be at least 2 * length + 1 long, and
4164 * at worst we're replacing a single input byte with two invalid
4165 * bytes.
4166 *
4167 * It would be a bit faster to verify the whole string the first
4168 * time we encounter a set highbit, but this way we can replace
4169 * just the invalid data, which probably makes it easier for users
4170 * to find the invalidly encoded portion of a larger string.
4171 */
4172 if (error)
4173 *error = 1;
4174 if (conn && !already_complained)
4175 {
4176 if (remaining < charlen)
4177 libpq_append_conn_error(conn, "incomplete multibyte character");
4178 else
4179 libpq_append_conn_error(conn, "invalid multibyte character");
4180 /* Issue a complaint only once per string */
4181 already_complained = true;
4182 }
4183
4185 target += 2;
4186
4187 /*
4188 * Handle the following bytes as if this byte didn't exist. That's
4189 * safer in case the subsequent bytes contain important characters
4190 * for the caller (e.g. '>' in html).
4191 */
4192 source++;
4193 remaining--;
4194 }
4195 else
4196 {
4197 /* Copy the character */
4198 for (i = 0; i < charlen; i++)
4199 {
4200 *target++ = *source++;
4201 remaining--;
4202 }
4203 }
4204 }
4205
4206 /* Write the terminating NUL character. */
4207 *target = '\0';
4208
4209 return target - to;
4210}
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition c.h:1252
static char * encoding
Definition initdb.c:139
static rewind_source * source
Definition pg_rewind.c:89
void pg_encoding_set_invalid(int encoding, char *dst)
Definition wchar.c:1852
int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len)
Definition wchar.c:1989

References conn, encoding, error(), fb(), i, IS_HIGHBIT_SET, libpq_append_conn_error(), pg_encoding_mblen_or_incomplete(), pg_encoding_set_invalid(), pg_encoding_verifymbchar(), remaining, source, and SQL_STR_DOUBLE.

Referenced by PQescapeString(), and PQescapeStringConn().

◆ PQexec()

PGresult * PQexec ( PGconn conn,
const char query 
)

Definition at line 2279 of file fe-exec.c.

2280{
2281 if (!PQexecStart(conn))
2282 return NULL;
2283 if (!PQsendQuery(conn, query))
2284 return NULL;
2285 return PQexecFinish(conn);
2286}
int PQsendQuery(PGconn *conn, const char *query)
Definition fe-exec.c:1433

References conn, fb(), PQexecFinish(), PQexecStart(), and PQsendQuery().

Referenced by _doSetSessionAuth(), _printTableAccessMethodNoStorage(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), check_and_drop_existing_subscriptions(), check_and_drop_publications(), check_loadable_libraries(), check_prepare_conn(), check_publisher(), check_subscriber(), connect_database(), create_logical_replication_slot(), create_publication(), create_subscription(), CreateReplicationSlot(), deallocate_one(), DescribeQuery(), drop_existing_subscription(), drop_failover_replication_slots(), drop_publication(), drop_replication_slot(), DropReplicationSlot(), ecpg_autostart_transaction(), ecpg_execute(), ecpg_is_type_an_array(), ECPGsetcommit(), ECPGtrans(), enable_subscription(), executeCommand(), executeCommand(), executeMaintenanceCommand(), executeQuery(), executeQuery(), executeQueryOrDie(), ExecuteSqlCommand(), ExecuteSqlQuery(), ExecuteSqlStatement(), executeStatement(), find_publication(), generate_object_name(), get_create_object_cmd(), get_primary_sysid(), get_publisher_databases(), GetConnection(), GetSlotInformation(), GetTableInfo(), init_libpq_conn(), initPopulateTable(), libpq_traverse_files(), lo_initialize(), lockTableForWorker(), lookup_object_oid(), main(), main(), PQchangePassword(), PQencryptPasswordConn(), PQsetClientEncoding(), PSQLexec(), ReceiveXlogStream(), RetrieveDataDirCreatePerm(), RetrieveWalSegSize(), run_permutation(), run_simple_command(), run_simple_query(), RunIdentifySystem(), SendQuery(), server_is_in_recovery(), set_replication_progress(), setup_publisher(), sql_conn(), sql_exec(), StreamLogicalLog(), test_disallowed_in_pipeline(), test_pipeline_abort(), test_prepared(), test_transaction(), test_uniqviol(), tryExecuteStatement(), and vacuumlo().

◆ PQexecFinish()

static PGresult * PQexecFinish ( PGconn conn)
static

Definition at line 2427 of file fe-exec.c.

2428{
2431
2432 /*
2433 * For backwards compatibility, return the last result if there are more
2434 * than one. (We used to have logic here to concatenate successive error
2435 * messages, but now that happens automatically, since conn->errorMessage
2436 * will continue to accumulate errors throughout this loop.)
2437 *
2438 * We have to stop if we see copy in/out/both, however. We will resume
2439 * parsing after application performs the data transfer.
2440 *
2441 * Also stop if the connection is lost (else we'll loop infinitely).
2442 */
2443 lastResult = NULL;
2444 while ((result = PQgetResult(conn)) != NULL)
2445 {
2448 if (result->resultStatus == PGRES_COPY_IN ||
2449 result->resultStatus == PGRES_COPY_OUT ||
2450 result->resultStatus == PGRES_COPY_BOTH ||
2452 break;
2453 }
2454
2455 return lastResult;
2456}
#define PQgetResult
@ CONNECTION_BAD
Definition libpq-fe.h:91
@ PGRES_COPY_IN
Definition libpq-fe.h:138
@ PGRES_COPY_BOTH
Definition libpq-fe.h:143
@ PGRES_COPY_OUT
Definition libpq-fe.h:137

References conn, CONNECTION_BAD, fb(), PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PQclear, PQgetResult, result, and pg_conn::status.

Referenced by PQclosePortal(), PQclosePrepared(), PQdescribePortal(), PQdescribePrepared(), PQexec(), PQexecParams(), PQexecPrepared(), and PQprepare().

◆ PQexecParams()

PGresult * PQexecParams ( PGconn conn,
const char command,
int  nParams,
const Oid paramTypes,
const char *const paramValues,
const int paramLengths,
const int paramFormats,
int  resultFormat 
)

Definition at line 2293 of file fe-exec.c.

2301{
2302 if (!PQexecStart(conn))
2303 return NULL;
2304 if (!PQsendQueryParams(conn, command,
2305 nParams, paramTypes, paramValues, paramLengths,
2307 return NULL;
2308 return PQexecFinish(conn);
2309}
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition fe-exec.c:1509

References conn, fb(), PQexecFinish(), PQexecStart(), and PQsendQueryParams().

Referenced by ecpg_execute(), get_table_relkind(), libpq_fetch_file(), main(), and wait_for_connection_state().

◆ PQexecPrepared()

PGresult * PQexecPrepared ( PGconn conn,
const char stmtName,
int  nParams,
const char *const paramValues,
const int paramLengths,
const int paramFormats,
int  resultFormat 
)

Definition at line 2340 of file fe-exec.c.

2347{
2348 if (!PQexecStart(conn))
2349 return NULL;
2350 if (!PQsendQueryPrepared(conn, stmtName,
2353 return NULL;
2354 return PQexecFinish(conn);
2355}
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition fe-exec.c:1650

References conn, fb(), PQexecFinish(), PQexecStart(), and PQsendQueryPrepared().

Referenced by ecpg_execute(), and try_complete_step().

◆ PQexecStart()

static bool PQexecStart ( PGconn conn)
static

Definition at line 2361 of file fe-exec.c.

2362{
2364
2365 if (!conn)
2366 return false;
2367
2368 /*
2369 * Since this is the beginning of a query cycle, reset the error state.
2370 * However, in pipeline mode with something already queued, the error
2371 * buffer belongs to that command and we shouldn't clear it.
2372 */
2373 if (conn->cmd_queue_head == NULL)
2375
2377 {
2378 libpq_append_conn_error(conn, "synchronous command execution functions are not allowed in pipeline mode");
2379 return false;
2380 }
2381
2382 /*
2383 * Silently discard any prior query result that application didn't eat.
2384 * This is probably poor design, but it's here for backward compatibility.
2385 */
2386 while ((result = PQgetResult(conn)) != NULL)
2387 {
2388 ExecStatusType resultStatus = result->resultStatus;
2389
2390 PQclear(result); /* only need its status */
2391 if (resultStatus == PGRES_COPY_IN)
2392 {
2393 /* get out of a COPY IN state */
2394 if (PQputCopyEnd(conn,
2395 libpq_gettext("COPY terminated by new PQexec")) < 0)
2396 return false;
2397 /* keep waiting to swallow the copy's failure message */
2398 }
2399 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 */
2406 /* keep waiting to swallow the copy's completion message */
2407 }
2408 else if (resultStatus == PGRES_COPY_BOTH)
2409 {
2410 /* We don't allow PQexec during COPY BOTH */
2411 libpq_append_conn_error(conn, "PQexec not allowed during COPY BOTH");
2412 return false;
2413 }
2414 /* check for loss of connection, too */
2415 if (conn->status == CONNECTION_BAD)
2416 return false;
2417 }
2418
2419 /* OK to send a command */
2420 return true;
2421}
int PQputCopyEnd(PGconn *conn, const char *errormsg)
Definition fe-exec.c:2766
ExecStatusType
Definition libpq-fe.h:129

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, CONNECTION_BAD, fb(), libpq_append_conn_error(), libpq_gettext, PGASYNC_BUSY, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQclear, pqClearConnErrorState, PQgetResult, PQputCopyEnd(), result, and pg_conn::status.

Referenced by PQclosePortal(), PQclosePrepared(), PQdescribePortal(), PQdescribePrepared(), PQexec(), PQexecParams(), PQexecPrepared(), and PQprepare().

◆ PQexitPipelineMode()

int PQexitPipelineMode ( PGconn conn)

Definition at line 3104 of file fe-exec.c.

3105{
3106 if (!conn)
3107 return 0;
3108
3113 return 1;
3114
3115 switch (conn->asyncStatus)
3116 {
3117 case PGASYNC_READY:
3118 case PGASYNC_READY_MORE:
3119 /* there are some uncollected results */
3120 libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results");
3121 return 0;
3122
3123 case PGASYNC_BUSY:
3124 libpq_append_conn_error(conn, "cannot exit pipeline mode while busy");
3125 return 0;
3126
3127 case PGASYNC_IDLE:
3129 /* OK */
3130 break;
3131
3132 case PGASYNC_COPY_IN:
3133 case PGASYNC_COPY_OUT:
3134 case PGASYNC_COPY_BOTH:
3135 libpq_append_conn_error(conn, "cannot exit pipeline mode while in COPY");
3136 }
3137
3138 /* still work to process */
3139 if (conn->cmd_queue_head != NULL)
3140 {
3141 libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results");
3142 return 0;
3143 }
3144
3147
3148 /* Flush any pending data in out buffer */
3149 if (pqFlush(conn) < 0)
3150 return 0; /* error message is setup already */
3151 return 1;
3152}
@ PGASYNC_COPY_OUT
Definition libpq-int.h:224
@ PGASYNC_READY_MORE
Definition libpq-int.h:220
@ PGASYNC_READY
Definition libpq-int.h:218
@ PGASYNC_COPY_BOTH
Definition libpq-int.h:225
@ PGASYNC_COPY_IN
Definition libpq-int.h:223

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, fb(), libpq_append_conn_error(), PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_PIPELINE_IDLE, PGASYNC_READY, PGASYNC_READY_MORE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, and pqFlush().

Referenced by discardUntilSync(), ExecQueryAndProcessResults(), readCommandResponse(), test_disallowed_in_pipeline(), test_multi_pipelines(), test_pipeline_abort(), test_pipeline_idle(), test_pipelined_insert(), test_prepared(), test_simple_pipeline(), test_singlerowmode(), and test_transaction().

◆ PQfformat()

int PQfformat ( const PGresult res,
int  field_num 
)

Definition at line 3739 of file fe-exec.c.

3740{
3741 if (!check_field_number(res, field_num))
3742 return 0;
3743 if (res->attDescs)
3744 return res->attDescs[field_num].format;
3745 else
3746 return 0;
3747}
static int check_field_number(const PGresult *res, int field_num)
Definition fe-exec.c:3541

References pg_result::attDescs, check_field_number(), fb(), and pgresAttDesc::format.

Referenced by ecpg_get_data(), ecpg_store_result(), and process_queued_fetch_requests().

◆ PQflush()

◆ PQfmod()

int PQfmod ( const PGresult res,
int  field_num 
)

Definition at line 3772 of file fe-exec.c.

3773{
3774 if (!check_field_number(res, field_num))
3775 return 0;
3776 if (res->attDescs)
3777 return res->attDescs[field_num].atttypmod;
3778 else
3779 return 0;
3780}

References pg_result::attDescs, pgresAttDesc::atttypmod, check_field_number(), and fb().

Referenced by DescribeQuery(), and ECPGget_desc().

◆ PQfn()

PGresult * PQfn ( PGconn conn,
int  fnid,
int result_buf,
int result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)

Definition at line 2997 of file fe-exec.c.

3004{
3005 return PQnfn(conn, fnid, result_buf, -1, result_len,
3006 result_is_int, args, nargs);
3007}
PGresult * PQnfn(PGconn *conn, int fnid, int *result_buf, int buf_size, int *result_len, int result_is_int, const PQArgBlock *args, int nargs)
Definition fe-exec.c:3016

References conn, fb(), and PQnfn().

Referenced by lo_close(), lo_creat(), lo_create(), lo_lseek(), lo_open(), lo_tell(), lo_truncate(), lo_truncate64(), lo_unlink(), and lo_write().

◆ PQfname()

char * PQfname ( const PGresult res,
int  field_num 
)

Definition at line 3598 of file fe-exec.c.

3599{
3600 if (!check_field_number(res, field_num))
3601 return NULL;
3602 if (res->attDescs)
3603 return res->attDescs[field_num].name;
3604 else
3605 return NULL;
3606}
char * name
Definition libpq-fe.h:320

References pg_result::attDescs, check_field_number(), fb(), and pgresAttDesc::name.

◆ PQfnumber()

int PQfnumber ( const PGresult res,
const char field_name 
)

Definition at line 3620 of file fe-exec.c.

3621{
3622 char *field_case;
3623 bool in_quotes;
3624 bool all_lower = true;
3625 const char *iptr;
3626 char *optr;
3627 int i;
3628
3629 if (!res)
3630 return -1;
3631
3632 /*
3633 * Note: it is correct to reject a zero-length input string; the proper
3634 * input to match a zero-length field name would be "".
3635 */
3636 if (field_name == NULL ||
3637 field_name[0] == '\0' ||
3638 res->attDescs == NULL)
3639 return -1;
3640
3641 /*
3642 * Check if we can avoid the strdup() and related work because the
3643 * passed-in string wouldn't be changed before we do the check anyway.
3644 */
3645 for (iptr = field_name; *iptr; iptr++)
3646 {
3647 char c = *iptr;
3648
3649 if (c == '"' || c != pg_tolower((unsigned char) c))
3650 {
3651 all_lower = false;
3652 break;
3653 }
3654 }
3655
3656 if (all_lower)
3657 for (i = 0; i < res->numAttributes; i++)
3658 if (strcmp(field_name, res->attDescs[i].name) == 0)
3659 return i;
3660
3661 /* Fall through to the normal check if that didn't work out. */
3662
3663 /*
3664 * Note: this code will not reject partially quoted strings, eg
3665 * foo"BAR"foo will become fooBARfoo when it probably ought to be an error
3666 * condition.
3667 */
3669 if (field_case == NULL)
3670 return -1; /* grotty */
3671
3672 in_quotes = false;
3673 optr = field_case;
3674 for (iptr = field_case; *iptr; iptr++)
3675 {
3676 char c = *iptr;
3677
3678 if (in_quotes)
3679 {
3680 if (c == '"')
3681 {
3682 if (iptr[1] == '"')
3683 {
3684 /* doubled quotes become a single quote */
3685 *optr++ = '"';
3686 iptr++;
3687 }
3688 else
3689 in_quotes = false;
3690 }
3691 else
3692 *optr++ = c;
3693 }
3694 else if (c == '"')
3695 in_quotes = true;
3696 else
3697 {
3698 c = pg_tolower((unsigned char) c);
3699 *optr++ = c;
3700 }
3701 }
3702 *optr = '\0';
3703
3704 for (i = 0; i < res->numAttributes; i++)
3705 {
3706 if (strcmp(field_case, res->attDescs[i].name) == 0)
3707 {
3709 return i;
3710 }
3711 }
3713 return -1;
3714}
unsigned char pg_tolower(unsigned char ch)

References pg_result::attDescs, fb(), free, i, pgresAttDesc::name, pg_result::numAttributes, and pg_tolower().

Referenced by append_depends_on_extension(), binary_upgrade_set_type_oids_by_type_oid(), buildMatViewRefreshDependencies(), check_for_connection_status(), check_for_pg_role_prefix(), check_for_unsupported_encodings(), check_new_cluster_replication_slots(), collectComments(), collectSecLabels(), describeOneTableDetails(), dropRoles(), dumpAgg(), dumpBaseType(), dumpCollation(), dumpCompositeType(), dumpCompositeTypeColComments(), dumpConversion(), dumpDatabase(), dumpDomain(), dumpEnumType(), dumpFunc(), dumpOpclass(), dumpOpfamily(), dumpOpr(), dumpRangeType(), dumpRelationStats_dumper(), dumpRoleMembership(), dumpRoles(), dumpStatisticsExtStats(), dumpTableSchema(), dumpTSConfig(), dumpUserMappings(), get_db_infos(), get_subscription_info(), get_tablespace_paths(), get_template0_info(), getAccessMethods(), getAggregates(), getCasts(), getCollations(), getConstraints(), getConversions(), getDefaultACLs(), getDependencies(), getDomainConstraints(), getEventTriggers(), getExtendedStatistics(), getExtensionMembership(), getExtensions(), getForeignDataWrappers(), getForeignServers(), getFuncs(), getIndexes(), getInherits(), getLOs(), getNamespaces(), getOpclasses(), getOperators(), getOpfamilies(), getPolicies(), getProcLangs(), getPublicationNamespaces(), getPublications(), getPublicationTables(), getRules(), getSubscriptionRelations(), getSubscriptions(), getTableAttrs(), getTables(), getTransforms(), getTriggers(), getTSConfigurations(), getTSDictionaries(), getTSParsers(), getTSTemplates(), getTypes(), old_9_6_invalidate_hash_indexes(), process_data_type_check(), process_extension_updates(), process_gist_inet_ops_check(), process_incompat_polymorphics(), process_inconsistent_notnull(), process_isn_and_int8_passing_mismatch(), process_old_cluster_logical_slot_infos(), process_old_sub_state_check(), process_rel_infos(), process_unicode_update(), process_user_defined_encoding_conversions(), process_user_defined_postfix_ops(), process_with_oids_check(), processExtensionTables(), set_frozenxids(), and show_binary_results().

◆ PQfreemem()

◆ PQfreeNotify()

void PQfreeNotify ( PGnotify notify)

Definition at line 4085 of file fe-exec.c.

4086{
4088}
void PQfreemem(void *ptr)
Definition fe-exec.c:4068

References fb(), and PQfreemem().

◆ PQfsize()

int PQfsize ( const PGresult res,
int  field_num 
)

Definition at line 3761 of file fe-exec.c.

3762{
3763 if (!check_field_number(res, field_num))
3764 return 0;
3765 if (res->attDescs)
3766 return res->attDescs[field_num].typlen;
3767 else
3768 return 0;
3769}

References pg_result::attDescs, check_field_number(), fb(), and pgresAttDesc::typlen.

Referenced by ecpg_build_compat_sqlda(), and ECPGget_desc().

◆ PQftable()

Oid PQftable ( const PGresult res,
int  field_num 
)

Definition at line 3717 of file fe-exec.c.

3718{
3719 if (!check_field_number(res, field_num))
3720 return InvalidOid;
3721 if (res->attDescs)
3722 return res->attDescs[field_num].tableid;
3723 else
3724 return InvalidOid;
3725}
#define InvalidOid

References pg_result::attDescs, check_field_number(), fb(), InvalidOid, and pgresAttDesc::tableid.

◆ PQftablecol()

int PQftablecol ( const PGresult res,
int  field_num 
)

Definition at line 3728 of file fe-exec.c.

3729{
3730 if (!check_field_number(res, field_num))
3731 return 0;
3732 if (res->attDescs)
3733 return res->attDescs[field_num].columnid;
3734 else
3735 return 0;
3736}

References pg_result::attDescs, check_field_number(), pgresAttDesc::columnid, and fb().

◆ PQftype()

◆ PQgetCopyData()

int PQgetCopyData ( PGconn conn,
char **  buffer,
int  async 
)

Definition at line 2833 of file fe-exec.c.

2834{
2835 *buffer = NULL; /* for all failure cases */
2836 if (!conn)
2837 return -2;
2840 {
2841 libpq_append_conn_error(conn, "no COPY in progress");
2842 return -2;
2843 }
2844 return pqGetCopyData3(conn, buffer, async);
2845}
int pqGetCopyData3(PGconn *conn, char **buffer, int async)

References pg_conn::asyncStatus, conn, fb(), libpq_append_conn_error(), PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, and pqGetCopyData3().

Referenced by CopyStreamReceive(), dumpTableData_copy(), ecpg_process_output(), handleCopyOut(), libpqrcv_receive(), ReceiveCopyData(), and StreamLogicalLog().

◆ PQgetisnull()

int PQgetisnull ( const PGresult res,
int  tup_num,
int  field_num 
)

Definition at line 3934 of file fe-exec.c.

3935{
3937 return 1; /* pretend it is null */
3938 if (res->tuples[tup_num][field_num].len == NULL_LEN)
3939 return 1;
3940 else
3941 return 0;
3942}
static int check_tuple_field_number(const PGresult *res, int tup_num, int field_num)
Definition fe-exec.c:3556
#define NULL_LEN
Definition libpq-int.h:131

References check_tuple_field_number(), fb(), pgresAttValue::len, NULL_LEN, and pg_result::tuples.

◆ PQgetlength()

int PQgetlength ( const PGresult res,
int  tup_num,
int  field_num 
)

Definition at line 3919 of file fe-exec.c.

3920{
3922 return 0;
3923 if (res->tuples[tup_num][field_num].len != NULL_LEN)
3924 return res->tuples[tup_num][field_num].len;
3925 else
3926 return 0;
3927}

References check_tuple_field_number(), fb(), pgresAttValue::len, NULL_LEN, and pg_result::tuples.

◆ PQgetline()

int PQgetline ( PGconn conn,
char buffer,
int  length 
)

Definition at line 2871 of file fe-exec.c.

2872{
2873 if (!buffer || length <= 0)
2874 return EOF;
2875 *buffer = '\0';
2876 /* length must be at least 3 to hold the \. terminator! */
2877 if (length < 3)
2878 return EOF;
2879
2880 if (!conn)
2881 return EOF;
2882
2883 return pqGetline3(conn, buffer, length);
2884}
int pqGetline3(PGconn *conn, char *s, int maxlen)

References conn, fb(), and pqGetline3().

◆ PQgetlineAsync()

int PQgetlineAsync ( PGconn conn,
char buffer,
int  bufsize 
)

Definition at line 2918 of file fe-exec.c.

2919{
2920 if (!conn)
2921 return -1;
2922
2923 return pqGetlineAsync3(conn, buffer, bufsize);
2924}
int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
#define bufsize

References bufsize, conn, and pqGetlineAsync3().

Referenced by pqGetline3().

◆ PQgetResult()

PGresult * PQgetResult ( PGconn conn)

Definition at line 2079 of file fe-exec.c.

2080{
2081 PGresult *res;
2082
2083 if (!conn)
2084 return NULL;
2085
2086 /* Parse any available data, if our state permits. */
2088
2089 /* If not ready to return something, block until we are. */
2090 while (conn->asyncStatus == PGASYNC_BUSY)
2091 {
2092 int flushResult;
2093
2094 /*
2095 * If data remains unsent, send it. Else we might be waiting for the
2096 * result of a command the backend hasn't even got yet.
2097 */
2098 while ((flushResult = pqFlush(conn)) > 0)
2099 {
2100 if (pqWait(false, true, conn))
2101 {
2102 flushResult = -1;
2103 break;
2104 }
2105 }
2106
2107 /*
2108 * Wait for some more data, and load it. (Note: if the connection has
2109 * been lost, pqWait should return immediately because the socket
2110 * should be read-ready, either with the last server data or with an
2111 * EOF indication. We expect therefore that this won't result in any
2112 * undue delay in reporting a previous write failure.)
2113 */
2114 if (flushResult ||
2115 pqWait(true, false, conn) ||
2116 pqReadData(conn) < 0)
2117 {
2118 /* Report the error saved by pqWait or pqReadData */
2121 return pqPrepareAsyncResult(conn);
2122 }
2123
2124 /* Parse it. */
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 */
2132 {
2135 return pqPrepareAsyncResult(conn);
2136 }
2137 }
2138
2139 /* Return the appropriate thing. */
2140 switch (conn->asyncStatus)
2141 {
2142 case PGASYNC_IDLE:
2143 res = NULL; /* query is complete */
2144 break;
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 */
2155 res = NULL; /* query is complete */
2156 break;
2157
2158 case PGASYNC_READY:
2160
2161 /*
2162 * Normally pqPrepareAsyncResult will have left conn->result
2163 * empty. Otherwise, "res" must be a not-full PGRES_TUPLES_CHUNK
2164 * result, which we want to return to the caller while staying in
2165 * PGASYNC_READY state. Then the next call here will return the
2166 * empty PGRES_TUPLES_OK result that was restored from
2167 * saved_result, after which we can proceed.
2168 */
2169 if (conn->result)
2170 {
2172 break;
2173 }
2174
2175 /* Advance the queue as appropriate */
2178
2180 {
2181 /*
2182 * We're about to send the results of the current query. Set
2183 * us idle now, and ...
2184 */
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 */
2200 }
2201 else
2202 {
2203 /* Set the state back to BUSY, allowing parsing to proceed. */
2205 }
2206 break;
2207 case PGASYNC_READY_MORE:
2209 /* Set the state back to BUSY, allowing parsing to proceed. */
2211 break;
2212 case PGASYNC_COPY_IN:
2214 break;
2215 case PGASYNC_COPY_OUT:
2217 break;
2218 case PGASYNC_COPY_BOTH:
2220 break;
2221 default:
2222 libpq_append_conn_error(conn, "unexpected asyncStatus: %d", (int) conn->asyncStatus);
2224 conn->asyncStatus = PGASYNC_IDLE; /* try to restore valid state */
2226 break;
2227 }
2228
2229 /* Time to fire PGEVT_RESULTCREATE events, if there are any */
2230 if (res && res->nEvents > 0)
2232
2233 return res;
2234}
static void pqSaveWriteError(PGconn *conn)
Definition fe-exec.c:826
void pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
Definition fe-exec.c:3173
static PGresult * getCopyResult(PGconn *conn, ExecStatusType copytype)
Definition fe-exec.c:2241
static void parseInput(PGconn *conn)
Definition fe-exec.c:2037
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition fe-misc.c:1019
int PQfireResultCreateEvents(PGconn *conn, PGresult *res)
@ PGRES_TUPLES_CHUNK
Definition libpq-fe.h:148
@ PGRES_PIPELINE_SYNC
Definition libpq-fe.h:145
bool write_failed
Definition libpq-int.h:515

References Assert, pg_conn::asyncStatus, conn, fb(), getCopyResult(), libpq_append_conn_error(), pg_result::nEvents, parseInput(), PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_PIPELINE_IDLE, PGASYNC_READY, PGASYNC_READY_MORE, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_PIPELINE_SYNC, PGRES_TUPLES_CHUNK, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqCommandQueueAdvance(), PQfireResultCreateEvents(), pqFlush(), pqPipelineProcessQueue(), pqPrepareAsyncResult(), pqReadData(), pqSaveErrorResult(), pqSaveWriteError(), pqWait(), pg_conn::result, pg_result::resultStatus, and pg_conn::write_failed.

◆ PQgetvalue()

char * PQgetvalue ( const PGresult res,
int  tup_num,
int  field_num 
)

Definition at line 3907 of file fe-exec.c.

3908{
3910 return NULL;
3911 return res->tuples[tup_num][field_num].value;
3912}

References check_tuple_field_number(), fb(), pg_result::tuples, and pgresAttValue::value.

◆ pqInternalNotice()

void pqInternalNotice ( const PGNoticeHooks hooks,
const char fmt,
  ... 
)

Definition at line 944 of file fe-exec.c.

945{
946 char msgBuf[1024];
948 PGresult *res;
949
950 if (hooks->noticeRec == NULL)
951 return; /* nobody home to receive notice? */
952
953 /* Format the message */
954 va_start(args, fmt);
955 vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args);
956 va_end(args);
957 msgBuf[sizeof(msgBuf) - 1] = '\0'; /* make real sure it's terminated */
958
959 /* Make a PGresult to pass to the notice receiver */
961 if (!res)
962 return;
963 res->noticeHooks = *hooks;
964
965 /*
966 * Set up fields of notice.
967 */
971 /* XXX should provide a SQLSTATE too? */
972
973 /*
974 * Result text is always just the primary message + newline. If we can't
975 * allocate it, substitute "out of memory", as in pqSetResultError.
976 */
977 res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, false);
978 if (res->errMsg)
979 sprintf(res->errMsg, "%s\n", msgBuf);
980 else
981 res->errMsg = libpq_gettext("out of memory\n");
982
983 /*
984 * Pass to receiver, then free it.
985 */
986 res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res);
987 PQclear(res);
988}
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition fe-exec.c:564
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition fe-exec.c:1066
@ PGRES_NONFATAL_ERROR
Definition libpq-fe.h:141
#define vsnprintf
Definition port.h:260
#define sprintf
Definition port.h:263
#define PG_DIAG_SEVERITY_NONLOCALIZED
#define PG_DIAG_MESSAGE_PRIMARY
#define PG_DIAG_SEVERITY

References pg_result::errMsg, fb(), libpq_gettext, pg_result::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SEVERITY, PG_DIAG_SEVERITY_NONLOCALIZED, PGRES_NONFATAL_ERROR, PQclear, PQmakeEmptyPGresult(), pqResultAlloc(), pqSaveMessageField(), sprintf, and vsnprintf.

Referenced by check_field_number(), check_param_number(), check_tuple_field_number(), PQcmdTuples(), pqEndcopy3(), pqGetInt(), pqParseInput3(), pqPutInt(), and PQsetvalue().

◆ PQisBusy()

int PQisBusy ( PGconn conn)

Definition at line 2048 of file fe-exec.c.

2049{
2050 if (!conn)
2051 return false;
2052
2053 /* Parse any available data, if our state permits. */
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 */
2065}

References pg_conn::asyncStatus, conn, CONNECTION_BAD, parseInput(), PGASYNC_BUSY, and pg_conn::status.

Referenced by advanceConnectionState(), consume_query_cancel_impl(), dblink_is_busy(), libpqsrv_get_result(), pgfdw_get_cleanup_result(), PQconnectPoll(), pqEndcopy3(), process_slot(), test_disallowed_in_pipeline(), test_pipelined_insert(), test_uniqviol(), try_complete_step(), and wait_on_slots().

◆ PQisnonblocking()

int PQisnonblocking ( const PGconn conn)

Definition at line 4019 of file fe-exec.c.

4020{
4021 if (!conn || conn->status == CONNECTION_BAD)
4022 return false;
4023 return pqIsnonblocking(conn);
4024}

References conn, CONNECTION_BAD, pqIsnonblocking, and pg_conn::status.

Referenced by test_disallowed_in_pipeline(), and test_simple_pipeline().

◆ PQisthreadsafe()

int PQisthreadsafe ( void  )

Definition at line 4028 of file fe-exec.c.

4029{
4030 return true;
4031}

◆ PQmakeEmptyPGresult()

PGresult * PQmakeEmptyPGresult ( PGconn conn,
ExecStatusType  status 
)

Definition at line 160 of file fe-exec.c.

161{
163
164 result = (PGresult *) malloc(sizeof(PGresult));
165 if (!result)
166 return NULL;
167
168 result->ntups = 0;
169 result->numAttributes = 0;
170 result->attDescs = NULL;
171 result->tuples = NULL;
172 result->tupArrSize = 0;
173 result->numParameters = 0;
174 result->paramDescs = NULL;
175 result->resultStatus = status;
176 result->cmdStatus[0] = '\0';
177 result->binary = 0;
178 result->events = NULL;
179 result->nEvents = 0;
180 result->errMsg = NULL;
181 result->errFields = NULL;
182 result->errQuery = NULL;
183 result->null_field[0] = '\0';
184 result->curBlock = NULL;
185 result->curOffset = 0;
186 result->spaceLeft = 0;
187 result->memorySize = sizeof(PGresult);
188
189 if (conn)
190 {
191 /* copy connection data we might need for operations on PGresult */
192 result->noticeHooks = conn->noticeHooks;
193 result->client_encoding = conn->client_encoding;
194
195 /* consider copying conn's errorMessage */
196 switch (status)
197 {
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:
206 /* non-error cases */
207 break;
208 default:
209 /* we intentionally do not use or modify errorReported here */
211 break;
212 }
213
214 /* copy events last; result must be valid if we need to PQclear */
215 if (conn->nEvents > 0)
216 {
217 result->events = dupEvents(conn->events, conn->nEvents,
218 &result->memorySize);
219 if (!result->events)
220 {
222 return NULL;
223 }
224 result->nEvents = conn->nEvents;
225 }
226 }
227 else
228 {
229 /* defaults... */
230 result->noticeHooks.noticeRec = NULL;
231 result->noticeHooks.noticeRecArg = NULL;
232 result->noticeHooks.noticeProc = NULL;
233 result->noticeHooks.noticeProcArg = NULL;
234 result->client_encoding = PG_SQL_ASCII;
235 }
236
237 return result;
238}
void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
Definition fe-exec.c:698
#define PGresult
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
@ PGRES_SINGLE_TUPLE
Definition libpq-fe.h:144
@ PGRES_EMPTY_QUERY
Definition libpq-fe.h:130
@ PG_SQL_ASCII
Definition pg_wchar.h:76
PQExpBufferData errorMessage
Definition libpq-int.h:686
int nEvents
Definition libpq-int.h:461
PGNoticeHooks noticeHooks
Definition libpq-int.h:457
PGEvent * events
Definition libpq-int.h:460

References pg_conn::client_encoding, conn, dupEvents(), pg_conn::errorMessage, pg_conn::events, fb(), malloc, pg_conn::nEvents, pg_conn::noticeHooks, pg_result::ntups, PG_SQL_ASCII, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_SINGLE_TUPLE, PGRES_TUPLES_CHUNK, PGRES_TUPLES_OK, PGresult, PQclear, pqSetResultError(), and result.

Referenced by ECPGallocate_desc(), getCopyResult(), getCopyStart(), getParamDescriptions(), getRowDescriptions(), PQcopyResult(), pqFunctionCall3(), pqGetErrorNotice3(), pqInternalNotice(), pqParseInput3(), pqPipelineProcessQueue(), and pqPrepareAsyncResult().

◆ PQnfields()

int PQnfields ( const PGresult res)

Definition at line 3520 of file fe-exec.c.

3521{
3522 if (!res)
3523 return 0;
3524 return res->numAttributes;
3525}

References pg_result::numAttributes.

◆ PQnfn()

PGresult * PQnfn ( PGconn conn,
int  fnid,
int result_buf,
int  buf_size,
int result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)

Definition at line 3016 of file fe-exec.c.

3018{
3019 *result_len = 0;
3020
3021 if (!conn)
3022 return NULL;
3023
3024 /*
3025 * Since this is the beginning of a query cycle, reset the error state.
3026 * However, in pipeline mode with something already queued, the error
3027 * buffer belongs to that command and we shouldn't clear it.
3028 */
3029 if (conn->cmd_queue_head == NULL)
3031
3033 {
3034 libpq_append_conn_error(conn, "%s not allowed in pipeline mode", "PQfn");
3035 return NULL;
3036 }
3037
3040 {
3041 libpq_append_conn_error(conn, "connection in wrong state");
3042 return NULL;
3043 }
3044
3045 return pqFunctionCall3(conn, fnid,
3048 args, nargs);
3049}
PGresult * pqFunctionCall3(PGconn *conn, Oid fnid, int *result_buf, int buf_size, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
#define PGINVALID_SOCKET
Definition port.h:31
pgsocket sock
Definition libpq-int.h:502

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, fb(), libpq_append_conn_error(), PGASYNC_IDLE, pgHavePendingResult, PGINVALID_SOCKET, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearConnErrorState, pqFunctionCall3(), and pg_conn::sock.

Referenced by lo_lseek64(), lo_read(), lo_tell64(), and PQfn().

◆ PQnotifies()

PGnotify * PQnotifies ( PGconn conn)

Definition at line 2684 of file fe-exec.c.

2685{
2686 PGnotify *event;
2687
2688 if (!conn)
2689 return NULL;
2690
2691 /* Parse any available data to see if we can extract NOTIFY messages. */
2693
2694 event = conn->notifyHead;
2695 if (event)
2696 {
2697 conn->notifyHead = event->next;
2698 if (!conn->notifyHead)
2699 conn->notifyTail = NULL;
2700 event->next = NULL; /* don't let app see the internal state */
2701 }
2702 return event;
2703}
struct pgNotify * next
Definition libpq-fe.h:247
PGnotify * notifyHead
Definition libpq-int.h:479
PGnotify * notifyTail
Definition libpq-int.h:480

References conn, fb(), pgNotify::next, pg_conn::notifyHead, pg_conn::notifyTail, and parseInput().

Referenced by dblink_get_notify(), ecpg_process_output(), main(), PrintNotifications(), and try_complete_step().

◆ PQnparams()

int PQnparams ( const PGresult res)

Definition at line 3949 of file fe-exec.c.

3950{
3951 if (!res)
3952 return 0;
3953 return res->numParameters;
3954}

References pg_result::numParameters.

◆ PQntuples()

int PQntuples ( const PGresult res)

Definition at line 3512 of file fe-exec.c.

3513{
3514 if (!res)
3515 return 0;
3516 return res->ntups;
3517}

References pg_result::ntups.

◆ PQoidStatus()

char * PQoidStatus ( const PGresult res)

Definition at line 3796 of file fe-exec.c.

3797{
3798 /*
3799 * This must be enough to hold the result. Don't laugh, this is better
3800 * than what this function used to do.
3801 */
3802 static char buf[24];
3803
3804 size_t len;
3805
3806 if (!res || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
3807 return "";
3808
3809 len = strspn(res->cmdStatus + 7, "0123456789");
3810 if (len > sizeof(buf) - 1)
3811 len = sizeof(buf) - 1;
3812 memcpy(buf, res->cmdStatus + 7, len);
3813 buf[len] = '\0';
3814
3815 return buf;
3816}
static char buf[DEFAULT_XLOG_SEG_SIZE]

References buf, pg_result::cmdStatus, fb(), len, and memcpy().

◆ PQoidValue()

Oid PQoidValue ( const PGresult res)

Definition at line 3824 of file fe-exec.c.

3825{
3826 char *endptr = NULL;
3827 unsigned long result;
3828
3829 if (!res ||
3830 strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
3831 res->cmdStatus[7] < '0' ||
3832 res->cmdStatus[7] > '9')
3833 return InvalidOid;
3834
3835 result = strtoul(res->cmdStatus + 7, &endptr, 10);
3836
3837 if (!endptr || (*endptr != ' ' && *endptr != '\0'))
3838 return InvalidOid;
3839 else
3840 return (Oid) result;
3841}
unsigned int Oid

References pg_result::cmdStatus, fb(), InvalidOid, and result.

Referenced by ecpg_process_output(), and PrintQueryStatus().

◆ PQparamtype()

Oid PQparamtype ( const PGresult res,
int  param_num 
)

Definition at line 3961 of file fe-exec.c.

3962{
3963 if (!check_param_number(res, param_num))
3964 return InvalidOid;
3965 if (res->paramDescs)
3966 return res->paramDescs[param_num].typid;
3967 else
3968 return InvalidOid;
3969}
static int check_param_number(const PGresult *res, int param_num)
Definition fe-exec.c:3579

References check_param_number(), fb(), InvalidOid, pg_result::paramDescs, and pgresParamDesc::typid.

◆ pqPipelineFlush()

static int pqPipelineFlush ( PGconn conn)
static

Definition at line 4052 of file fe-exec.c.

4053{
4056 return pqFlush(conn);
4057 return 0;
4058}
#define OUTBUFFER_THRESHOLD
Definition libpq-int.h:952
int outCount
Definition libpq-int.h:588

References conn, OUTBUFFER_THRESHOLD, pg_conn::outCount, pg_conn::pipelineStatus, PQ_PIPELINE_ON, and pqFlush().

Referenced by pqPipelineSyncInternal(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), and PQsendTypedCommand().

◆ pqPipelineProcessQueue()

static void pqPipelineProcessQueue ( PGconn conn)
static

Definition at line 3211 of file fe-exec.c.

3212{
3213 switch (conn->asyncStatus)
3214 {
3215 case PGASYNC_COPY_IN:
3216 case PGASYNC_COPY_OUT:
3217 case PGASYNC_COPY_BOTH:
3218 case PGASYNC_READY:
3219 case PGASYNC_READY_MORE:
3220 case PGASYNC_BUSY:
3221 /* client still has to process current query or results */
3222 return;
3223
3224 case PGASYNC_IDLE:
3225
3226 /*
3227 * If we're in IDLE mode and there's some command in the queue,
3228 * get us into PIPELINE_IDLE mode and process normally. Otherwise
3229 * there's nothing for us to do.
3230 */
3231 if (conn->cmd_queue_head != NULL)
3232 {
3234 break;
3235 }
3236 return;
3237
3240 /* next query please */
3241 break;
3242 }
3243
3244 /*
3245 * Reset partial-result mode. (Client has to set it up for each query, if
3246 * desired.)
3247 */
3248 conn->partialResMode = false;
3249 conn->singleRowMode = false;
3250 conn->maxChunkSize = 0;
3251
3252 /*
3253 * If there are no further commands to process in the queue, get us in
3254 * "real idle" mode now.
3255 */
3256 if (conn->cmd_queue_head == NULL)
3257 {
3259 return;
3260 }
3261
3262 /*
3263 * Reset the error state. This and the next couple of steps correspond to
3264 * what PQsendQueryStart didn't do for this query.
3265 */
3267
3268 /* Initialize async result-accumulation state */
3270
3273 {
3274 /*
3275 * In an aborted pipeline we don't get anything from the server for
3276 * each result; we're just discarding commands from the queue until we
3277 * get to the next sync from the server.
3278 *
3279 * The PGRES_PIPELINE_ABORTED results tell the client that its queries
3280 * got aborted.
3281 */
3283 if (!conn->result)
3284 {
3285 libpq_append_conn_error(conn, "out of memory");
3287 return;
3288 }
3290 }
3291 else
3292 {
3293 /* allow parsing to continue */
3295 }
3296}
void pqClearAsyncResult(PGconn *conn)
Definition fe-exec.c:785
@ PGRES_PIPELINE_ABORTED
Definition libpq-fe.h:146
int maxChunkSize
Definition libpq-int.h:475
bool singleRowMode
Definition libpq-int.h:474
bool partialResMode
Definition libpq-int.h:473

References Assert, pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, fb(), libpq_append_conn_error(), pg_conn::maxChunkSize, pg_conn::partialResMode, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_PIPELINE_IDLE, PGASYNC_READY, PGASYNC_READY_MORE, PGQUERY_SYNC, PGRES_PIPELINE_ABORTED, pg_conn::pipelineStatus, PQ_PIPELINE_ABORTED, PQ_PIPELINE_OFF, pqClearAsyncResult(), pqClearConnErrorState, PQmakeEmptyPGresult(), pqSaveErrorResult(), PGcmdQueueEntry::queryclass, pg_conn::result, and pg_conn::singleRowMode.

Referenced by pqAppendCmdQueueEntry(), and PQgetResult().

◆ PQpipelineSync()

int PQpipelineSync ( PGconn conn)

◆ pqPipelineSyncInternal()

static int pqPipelineSyncInternal ( PGconn conn,
bool  immediate_flush 
)
static

Definition at line 3325 of file fe-exec.c.

3326{
3327 PGcmdQueueEntry *entry;
3328
3329 if (!conn)
3330 return 0;
3331
3333 {
3334 libpq_append_conn_error(conn, "cannot send pipeline when not in pipeline mode");
3335 return 0;
3336 }
3337
3338 switch (conn->asyncStatus)
3339 {
3340 case PGASYNC_COPY_IN:
3341 case PGASYNC_COPY_OUT:
3342 case PGASYNC_COPY_BOTH:
3343 /* should be unreachable */
3345 "internal error: cannot send pipeline while in COPY\n");
3346 return 0;
3347 case PGASYNC_READY:
3348 case PGASYNC_READY_MORE:
3349 case PGASYNC_BUSY:
3350 case PGASYNC_IDLE:
3352 /* OK to send sync */
3353 break;
3354 }
3355
3356 entry = pqAllocCmdQueueEntry(conn);
3357 if (entry == NULL)
3358 return 0; /* error msg already set */
3359
3360 entry->queryclass = PGQUERY_SYNC;
3361 entry->query = NULL;
3362
3363 /* construct the Sync message */
3364 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
3365 pqPutMsgEnd(conn) < 0)
3366 goto sendFailed;
3367
3368 /*
3369 * Give the data a push. In nonblock mode, don't complain if we're unable
3370 * to send it all; PQgetResult() will do any additional flushing needed.
3371 * If immediate_flush is disabled, the data is pushed if we are past the
3372 * size threshold.
3373 */
3374 if (immediate_flush)
3375 {
3376 if (pqFlush(conn) < 0)
3377 goto sendFailed;
3378 }
3379 else
3380 {
3381 if (pqPipelineFlush(conn) < 0)
3382 goto sendFailed;
3383 }
3384
3385 /* OK, it's launched! */
3387
3388 return 1;
3389
3392 /* error message should be set up already */
3393 return 0;
3394}
static PGcmdQueueEntry * pqAllocCmdQueueEntry(PGconn *conn)
Definition fe-exec.c:1323
static void pqAppendCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition fe-exec.c:1356
static int pqPipelineFlush(PGconn *conn)
Definition fe-exec.c:4052
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition fe-misc.c:473
int pqPutMsgEnd(PGconn *conn)
Definition fe-misc.c:532
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
#define PqMsg_Sync
Definition protocol.h:27

References appendPQExpBufferStr(), pg_conn::asyncStatus, conn, pg_conn::errorMessage, fb(), libpq_append_conn_error(), PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_PIPELINE_IDLE, PGASYNC_READY, PGASYNC_READY_MORE, PGQUERY_SYNC, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqAllocCmdQueueEntry(), pqAppendCmdQueueEntry(), pqFlush(), PqMsg_Sync, pqPipelineFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqRecycleCmdQueueEntry(), PGcmdQueueEntry::query, and PGcmdQueueEntry::queryclass.

Referenced by PQpipelineSync(), and PQsendPipelineSync().

◆ PQprepare()

PGresult * PQprepare ( PGconn conn,
const char stmtName,
const char query,
int  nParams,
const Oid paramTypes 
)

Definition at line 2323 of file fe-exec.c.

2326{
2327 if (!PQexecStart(conn))
2328 return NULL;
2329 if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
2330 return NULL;
2331 return PQexecFinish(conn);
2332}
int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
Definition fe-exec.c:1553

References conn, fb(), PQexecFinish(), PQexecStart(), and PQsendPrepare().

Referenced by DescribeQuery(), init_libpq_conn(), main(), prepare_common(), prepareCommand(), and test_uniqviol().

◆ pqPrepareAsyncResult()

PGresult * pqPrepareAsyncResult ( PGconn conn)

Definition at line 857 of file fe-exec.c.

858{
859 PGresult *res;
860
861 res = conn->result;
862 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 */
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 if (!conn->error_result)
880 libpq_append_conn_error(conn, "no error text available");
881
882 /* Paranoia: be sure errorReported offset is sane */
883 if (conn->errorReported < 0 ||
885 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 */
893 if (res)
894 {
895 /*
896 * Report whatever new error text we have, and advance
897 * errorReported.
898 */
902 }
903 else
904 {
905 /*
906 * Ouch, not enough memory for a PGresult. Fortunately, we have a
907 * card up our sleeve: we can use the static OOM_result. Casting
908 * away const here is a bit ugly, but it seems best to declare
909 * OOM_result as const, in hopes it will be allocated in read-only
910 * storage.
911 */
912 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 */
928 conn->error_result = false; /* saved_result is never an error */
930
931 return res;
932}
#define unconstify(underlying_type, expr)
Definition c.h:1325
@ PGRES_FATAL_ERROR
Definition libpq-fe.h:142
int errorReported
Definition libpq-int.h:687

References conn, pg_conn::error_result, pg_conn::errorMessage, pg_conn::errorReported, fb(), PQExpBufferData::len, libpq_append_conn_error(), OOM_result, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), pqSetResultError(), pg_conn::result, pg_result::resultStatus, pg_conn::saved_result, and unconstify.

Referenced by getCopyResult(), pqFunctionCall3(), and PQgetResult().

◆ PQputCopyData()

int PQputCopyData ( PGconn conn,
const char buffer,
int  nbytes 
)

Definition at line 2712 of file fe-exec.c.

2713{
2714 if (!conn)
2715 return -1;
2718 {
2719 libpq_append_conn_error(conn, "no COPY in progress");
2720 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 */
2732
2733 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 if ((conn->outBufSize - conn->outCount - 5) < nbytes)
2742 {
2743 if (pqFlush(conn) < 0)
2744 return -1;
2745 if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes,
2746 conn))
2747 return pqIsnonblocking(conn) ? 0 : -1;
2748 }
2749 /* Send the data (too simple to delegate to fe-protocol files) */
2750 if (pqPutMsgStart(PqMsg_CopyData, conn) < 0 ||
2751 pqPutnchar(buffer, nbytes, conn) < 0 ||
2752 pqPutMsgEnd(conn) < 0)
2753 return -1;
2754 }
2755 return 1;
2756}
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition fe-misc.c:287
int pqPutnchar(const void *s, size_t len, PGconn *conn)
Definition fe-misc.c:202
#define PqMsg_CopyData
Definition protocol.h:65
int outBufSize
Definition libpq-int.h:587

References pg_conn::asyncStatus, conn, libpq_append_conn_error(), pg_conn::outBufSize, pg_conn::outCount, parseInput(), PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, pqCheckOutBufferSpace(), pqFlush(), pqIsnonblocking, PqMsg_CopyData, pqPutMsgEnd(), pqPutMsgStart(), and pqPutnchar().

Referenced by BaseBackup(), ExecuteSqlCommandBuf(), handleCopyIn(), libpqrcv_send(), PQputnbytes(), sendFeedback(), and sendFeedback().

◆ PQputCopyEnd()

int PQputCopyEnd ( PGconn conn,
const char errormsg 
)

Definition at line 2766 of file fe-exec.c.

2767{
2768 if (!conn)
2769 return -1;
2772 {
2773 libpq_append_conn_error(conn, "no COPY in progress");
2774 return -1;
2775 }
2776
2777 /*
2778 * Send the COPY END indicator. This is simple enough that we don't
2779 * bother delegating it to the fe-protocol files.
2780 */
2781 if (errormsg)
2782 {
2783 /* Send COPY FAIL */
2784 if (pqPutMsgStart(PqMsg_CopyFail, conn) < 0 ||
2785 pqPuts(errormsg, conn) < 0 ||
2786 pqPutMsgEnd(conn) < 0)
2787 return -1;
2788 }
2789 else
2790 {
2791 /* Send COPY DONE */
2792 if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
2793 pqPutMsgEnd(conn) < 0)
2794 return -1;
2795 }
2796
2797 /*
2798 * If we sent the COPY command in extended-query mode, we must issue a
2799 * Sync as well.
2800 */
2801 if (conn->cmd_queue_head &&
2803 {
2804 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
2805 pqPutMsgEnd(conn) < 0)
2806 return -1;
2807 }
2808
2809 /* Return to active duty */
2812 else
2814
2815 /* Try to flush data */
2816 if (pqFlush(conn) < 0)
2817 return -1;
2818
2819 return 1;
2820}
int pqPuts(const char *s, PGconn *conn)
Definition fe-misc.c:152
#define PqMsg_CopyDone
Definition protocol.h:64
#define PqMsg_CopyFail
Definition protocol.h:29

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, libpq_append_conn_error(), PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGQUERY_SIMPLE, pqFlush(), PqMsg_CopyDone, PqMsg_CopyFail, PqMsg_Sync, pqPutMsgEnd(), pqPutMsgStart(), pqPuts(), and PGcmdQueueEntry::queryclass.

Referenced by BaseBackup(), CheckCopyStreamStop(), EndDBCopyMode(), handleCopyIn(), HandleEndOfCopyStream(), libpqrcv_endstreaming(), PQexecStart(), prepareToTerminate(), and ProcessWALDataMsg().

◆ PQputline()

int PQputline ( PGconn conn,
const char string 
)

Definition at line 2935 of file fe-exec.c.

2936{
2937 return PQputnbytes(conn, string, strlen(string));
2938}
int PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
Definition fe-exec.c:2945

References conn, fb(), and PQputnbytes().

Referenced by initPopulateTable().

◆ PQputnbytes()

int PQputnbytes ( PGconn conn,
const char buffer,
int  nbytes 
)

Definition at line 2945 of file fe-exec.c.

2946{
2947 if (PQputCopyData(conn, buffer, nbytes) > 0)
2948 return 0;
2949 else
2950 return EOF;
2951}
int PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
Definition fe-exec.c:2712

References conn, fb(), and PQputCopyData().

Referenced by PQputline().

◆ pqRecycleCmdQueueEntry()

static void pqRecycleCmdQueueEntry ( PGconn conn,
PGcmdQueueEntry entry 
)
static

Definition at line 1403 of file fe-exec.c.

1404{
1405 if (entry == NULL)
1406 return;
1407
1408 /* recyclable entries should not have a follow-on command */
1409 Assert(entry->next == NULL);
1410
1411 if (entry->query)
1412 {
1413 free(entry->query);
1414 entry->query = NULL;
1415 }
1416
1417 entry->next = conn->cmd_queue_recycle;
1418 conn->cmd_queue_recycle = entry;
1419}

References Assert, pg_conn::cmd_queue_recycle, conn, fb(), free, PGcmdQueueEntry::next, and PGcmdQueueEntry::query.

Referenced by pqCommandQueueAdvance(), pqPipelineSyncInternal(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ PQresStatus()

char * PQresStatus ( ExecStatusType  status)

Definition at line 3450 of file fe-exec.c.

3451{
3452 if ((unsigned int) status >= lengthof(pgresStatus))
3453 return libpq_gettext("invalid ExecStatusType code");
3454 return pgresStatus[status];
3455}
#define lengthof(array)
Definition c.h:873
char *const pgresStatus[]
Definition fe-exec.c:33

References lengthof, libpq_gettext, and pgresStatus.

Referenced by BaseBackup(), confirm_result_status_impl(), consume_null_result_impl(), process_result(), test_pipeline_abort(), test_pipelined_insert(), test_prepared(), test_singlerowmode(), test_transaction(), and try_complete_step().

◆ PQresultAlloc()

void * PQresultAlloc ( PGresult res,
size_t  nBytes 
)

Definition at line 544 of file fe-exec.c.

545{
546 /* Fail if argument is NULL or OOM_result */
547 if (!res || (const PGresult *) res == &OOM_result)
548 return NULL;
549
550 return pqResultAlloc(res, nBytes, true);
551}

References fb(), OOM_result, and pqResultAlloc().

Referenced by PQsetResultAttrs().

◆ pqResultAlloc()

void * pqResultAlloc ( PGresult res,
size_t  nBytes,
bool  isBinary 
)

Definition at line 564 of file fe-exec.c.

565{
566 char *space;
567 PGresult_data *block;
568
569 if (!res)
570 return NULL;
571
572 if (nBytes <= 0)
573 return res->null_field;
574
575 /*
576 * If alignment is needed, round up the current position to an alignment
577 * boundary.
578 */
579 if (isBinary)
580 {
581 int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
582
583 if (offset)
584 {
585 res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
586 res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
587 }
588 }
589
590 /* If there's enough space in the current block, no problem. */
591 if (nBytes <= (size_t) res->spaceLeft)
592 {
593 space = res->curBlock->space + res->curOffset;
594 res->curOffset += nBytes;
595 res->spaceLeft -= nBytes;
596 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 */
606 {
607 size_t alloc_size;
608
609 /* Don't wrap around with overly large requests. */
611 return NULL;
612
614 block = (PGresult_data *) malloc(alloc_size);
615 if (!block)
616 return NULL;
617 res->memorySize += alloc_size;
618 space = block->space + PGRESULT_BLOCK_OVERHEAD;
619 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 block->next = res->curBlock->next;
626 res->curBlock->next = block;
627 }
628 else
629 {
630 /* Must set up the new block as the first active block. */
631 block->next = NULL;
632 res->curBlock = block;
633 res->spaceLeft = 0; /* be sure it's marked full */
634 }
635 return space;
636 }
637
638 /* Otherwise, start a new block. */
640 if (!block)
641 return NULL;
643 block->next = res->curBlock;
644 res->curBlock = block;
645 if (isBinary)
646 {
647 /* object needs full alignment */
650 }
651 else
652 {
653 /* we can cram it right after the overhead pointer */
654 res->curOffset = sizeof(PGresult_data);
656 }
657
658 space = block->space + res->curOffset;
659 res->curOffset += nBytes;
660 res->spaceLeft -= nBytes;
661 return space;
662}
#define PGRESULT_DATA_BLOCKSIZE
Definition fe-exec.c:143
#define PGRESULT_BLOCK_OVERHEAD
Definition fe-exec.c:145
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition fe-exec.c:146
#define PGRESULT_ALIGN_BOUNDARY
Definition fe-exec.c:144
union pgresult_data PGresult_data
Definition libpq-int.h:99
int curOffset
Definition libpq-int.h:207
char null_field[1]
Definition libpq-int.h:199
int spaceLeft
Definition libpq-int.h:208
char space[1]
Definition libpq-int.h:104

References pg_result::curBlock, pg_result::curOffset, fb(), malloc, pg_result::memorySize, pgresult_data::next, pg_result::null_field, PGRESULT_ALIGN_BOUNDARY, PGRESULT_BLOCK_OVERHEAD, PGRESULT_DATA_BLOCKSIZE, PGRESULT_SEP_ALLOC_THRESHOLD, pgresult_data::space, and pg_result::spaceLeft.

Referenced by getCopyStart(), getParamDescriptions(), getRowDescriptions(), pqInternalNotice(), PQresultAlloc(), pqResultStrdup(), pqRowProcessor(), pqSaveMessageField(), and PQsetvalue().

◆ PQresultErrorField()

char * PQresultErrorField ( const PGresult res,
int  fieldcode 
)

Definition at line 3497 of file fe-exec.c.

3498{
3500
3501 if (!res)
3502 return NULL;
3503 for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
3504 {
3505 if (pfield->code == fieldcode)
3506 return pfield->contents;
3507 }
3508 return NULL;
3509}
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition libpq-int.h:144

References pgMessageField::contents, pg_result::errFields, and fb().

◆ PQresultErrorMessage()

char * PQresultErrorMessage ( const PGresult res)

Definition at line 3458 of file fe-exec.c.

3459{
3460 if (!res || !res->errMsg)
3461 return "";
3462 return res->errMsg;
3463}
char * errMsg
Definition libpq-int.h:194

References pg_result::errMsg.

◆ PQresultMemorySize()

size_t PQresultMemorySize ( const PGresult res)

Definition at line 669 of file fe-exec.c.

670{
671 if (!res)
672 return 0;
673 return res->memorySize;
674}

References pg_result::memorySize.

◆ PQresultStatus()

ExecStatusType PQresultStatus ( const PGresult res)

Definition at line 3442 of file fe-exec.c.

3443{
3444 if (!res)
3445 return PGRES_FATAL_ERROR;
3446 return res->resultStatus;
3447}

References PGRES_FATAL_ERROR, and pg_result::resultStatus.

◆ pqResultStrdup()

char * pqResultStrdup ( PGresult res,
const char str 
)

Definition at line 681 of file fe-exec.c.

682{
683 char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
684
685 if (space)
686 strcpy(space, str);
687 return space;
688}

References fb(), pqResultAlloc(), and str.

Referenced by getRowDescriptions(), pqGetErrorNotice3(), PQsetResultAttrs(), and pqSetResultError().

◆ PQresultVerboseErrorMessage()

char * PQresultVerboseErrorMessage ( const PGresult res,
PGVerbosity  verbosity,
PGContextVisibility  show_context 
)

Definition at line 3466 of file fe-exec.c.

3469{
3471
3472 /*
3473 * Because the caller is expected to free the result string, we must
3474 * strdup any constant result. We use plain strdup and document that
3475 * callers should expect NULL if out-of-memory.
3476 */
3477 if (!res ||
3480 return strdup(libpq_gettext("PGresult is not an error result\n"));
3481
3483
3484 pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
3485
3486 /* If insufficient memory to format the message, fail cleanly */
3488 {
3490 return strdup(libpq_gettext("out of memory\n"));
3491 }
3492
3493 return workBuf.data;
3494}
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
Definition pqexpbuffer.h:67

References fb(), initPQExpBuffer(), libpq_gettext, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, pqBuildErrorMessage3(), PQExpBufferDataBroken, pg_result::resultStatus, and termPQExpBuffer().

Referenced by exec_command_errverbose().

◆ pqRowProcessor()

int pqRowProcessor ( PGconn conn,
const char **  errmsgp 
)

Definition at line 1223 of file fe-exec.c.

1224{
1225 PGresult *res = conn->result;
1226 int nfields = res->numAttributes;
1227 const PGdataValue *columns = conn->rowBuf;
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 */
1240 {
1241 /* Copy everything that should be in the result at this point */
1242 res = PQcopyResult(res,
1245 if (!res)
1246 return 0;
1247 /* Change result status to appropriate special value */
1249 /* And stash it as the active result */
1251 conn->result = res;
1252 }
1253
1254 /*
1255 * Basically we just allocate space in the PGresult for each field and
1256 * copy the data over.
1257 *
1258 * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1259 * caller will take to mean "out of memory". This is preferable to trying
1260 * to set up such a message here, because evidently there's not enough
1261 * memory for gettext() to do anything.
1262 */
1263 tup = (PGresAttValue *)
1264 pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1265 if (tup == NULL)
1266 return 0;
1267
1268 for (i = 0; i < nfields; i++)
1269 {
1270 int clen = columns[i].len;
1271
1272 if (clen < 0)
1273 {
1274 /* null field */
1275 tup[i].len = NULL_LEN;
1276 tup[i].value = res->null_field;
1277 }
1278 else
1279 {
1280 bool isbinary = (res->attDescs[i].format != 0);
1281 char *val;
1282
1283 val = (char *) pqResultAlloc(res, (size_t) clen + 1, isbinary);
1284 if (val == NULL)
1285 return 0;
1286
1287 /* copy and zero-terminate the data (even if it's binary) */
1288 memcpy(val, columns[i].value, clen);
1289 val[clen] = '\0';
1290
1291 tup[i].len = clen;
1292 tup[i].value = val;
1293 }
1294 }
1295
1296 /* And add the tuple to the PGresult's tuple array */
1297 if (!pqAddTuple(res, tup, errmsgp))
1298 return 0;
1299
1300 /*
1301 * Success. In partial-result mode, if we have enough rows then make the
1302 * result available to the client immediately.
1303 */
1304 if (conn->partialResMode && res->ntups >= conn->maxChunkSize)
1306
1307 return 1;
1308}
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition fe-exec.c:319
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition fe-exec.c:999
long val
Definition informix.c:689
static struct @177 value
PGdataValue * rowBuf
Definition libpq-int.h:596

References pg_conn::asyncStatus, pg_result::attDescs, conn, fb(), pgresAttDesc::format, i, pgDataValue::len, pg_conn::maxChunkSize, memcpy(), pg_result::ntups, pg_result::null_field, NULL_LEN, pg_result::numAttributes, pg_conn::partialResMode, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY_MORE, PGRES_SINGLE_TUPLE, PGRES_TUPLES_CHUNK, pqAddTuple(), PQcopyResult(), pqResultAlloc(), pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::saved_result, pg_conn::singleRowMode, val, and value.

Referenced by getAnotherTuple().

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)

Definition at line 809 of file fe-exec.c.

810{
811 /* Drop any pending result ... */
813 /* ... and set flag to remember to make an error result later */
814 conn->error_result = true;
815}

References conn, pg_conn::error_result, and pqClearAsyncResult().

Referenced by getAnotherTuple(), getCopyResult(), getParamDescriptions(), getRowDescriptions(), handleFatalError(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), PQgetResult(), pqParseInput3(), pqPipelineProcessQueue(), and pqSaveWriteError().

◆ pqSaveMessageField()

void pqSaveMessageField ( PGresult res,
char  code,
const char value 
)

Definition at line 1066 of file fe-exec.c.

1067{
1069
1071 pqResultAlloc(res,
1072 offsetof(PGMessageField, contents) +
1073 strlen(value) + 1,
1074 true);
1075 if (!pfield)
1076 return; /* out of memory? */
1077 pfield->code = code;
1078 strcpy(pfield->contents, value);
1079 pfield->next = res->errFields;
1080 res->errFields = pfield;
1081}

References pgMessageField::code, pg_result::errFields, fb(), pqResultAlloc(), and value.

Referenced by pqGetErrorNotice3(), and pqInternalNotice().

◆ pqSaveParameterStatus()

int pqSaveParameterStatus ( PGconn conn,
const char name,
const char value 
)

Definition at line 1091 of file fe-exec.c.

1092{
1093 pgParameterStatus *pstatus;
1094 pgParameterStatus *prev;
1095
1096 /*
1097 * Forget any old information about the parameter
1098 */
1099 for (pstatus = conn->pstatus, prev = NULL;
1100 pstatus != NULL;
1101 prev = pstatus, pstatus = pstatus->next)
1102 {
1103 if (strcmp(pstatus->name, name) == 0)
1104 {
1105 if (prev)
1106 prev->next = pstatus->next;
1107 else
1108 conn->pstatus = pstatus->next;
1109 free(pstatus); /* frees name and value strings too */
1110 break;
1111 }
1112 }
1113
1114 /*
1115 * Store new info as a single malloc block
1116 */
1117 pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
1118 strlen(name) + strlen(value) + 2);
1119 if (pstatus)
1120 {
1121 char *ptr;
1122
1123 ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1124 pstatus->name = ptr;
1125 strcpy(ptr, name);
1126 ptr += strlen(name) + 1;
1127 pstatus->value = ptr;
1128 strcpy(ptr, value);
1129 pstatus->next = conn->pstatus;
1130 conn->pstatus = pstatus;
1131 }
1132 else
1133 {
1134 /* out of memory */
1135 return 0;
1136 }
1137
1138 /*
1139 * Save values of settings that are of interest to libpq in fields of the
1140 * PGconn object. We keep client_encoding and standard_conforming_strings
1141 * in static variables as well, so that PQescapeString and PQescapeBytea
1142 * can behave somewhat sanely (at least in single-connection-using
1143 * programs).
1144 */
1145 if (strcmp(name, "client_encoding") == 0)
1146 {
1148 /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1149 if (conn->client_encoding < 0)
1152 }
1153 else if (strcmp(name, "standard_conforming_strings") == 0)
1154 {
1155 conn->std_strings = (strcmp(value, "on") == 0);
1157 }
1158 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 cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1167
1168 if (cnt == 3)
1169 {
1170 /* old style, e.g. 9.6.1 */
1171 conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1172 }
1173 else if (cnt == 2)
1174 {
1175 if (vmaj >= 10)
1176 {
1177 /* new style, e.g. 10.1 */
1178 conn->sversion = 100 * 100 * vmaj + vmin;
1179 }
1180 else
1181 {
1182 /* old style without minor version, e.g. 9.6devel */
1183 conn->sversion = (100 * vmaj + vmin) * 100;
1184 }
1185 }
1186 else if (cnt == 1)
1187 {
1188 /* new style without minor version, e.g. 10devel */
1189 conn->sversion = 100 * 100 * vmaj;
1190 }
1191 else
1192 conn->sversion = 0; /* unknown */
1193 }
1194 else if (strcmp(name, "default_transaction_read_only") == 0)
1195 {
1197 (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1198 }
1199 else if (strcmp(name, "in_hot_standby") == 0)
1200 {
1202 (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1203 }
1204 else if (strcmp(name, "scram_iterations") == 0)
1205 {
1207 }
1208
1209 return 1;
1210}
@ PG_BOOL_YES
Definition oauth-utils.h:34
@ PG_BOOL_NO
Definition oauth-utils.h:35
#define pg_char_to_encoding
Definition pg_wchar.h:482
struct pgParameterStatus * next
Definition libpq-int.h:272
PGTernaryBool in_hot_standby
Definition libpq-int.h:562
PGTernaryBool default_transaction_read_only
Definition libpq-int.h:561
pgParameterStatus * pstatus
Definition libpq-int.h:558
int scram_sha_256_iterations
Definition libpq-int.h:616

References pg_conn::client_encoding, conn, pg_conn::default_transaction_read_only, fb(), free, pg_conn::in_hot_standby, malloc, name, pgParameterStatus::name, pgParameterStatus::next, PG_BOOL_NO, PG_BOOL_YES, pg_char_to_encoding, PG_SQL_ASCII, pg_conn::pstatus, pg_conn::scram_sha_256_iterations, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, value, and pgParameterStatus::value.

Referenced by getParameterStatus().

◆ pqSaveWriteError()

static void pqSaveWriteError ( PGconn conn)
static

Definition at line 826 of file fe-exec.c.

827{
828 /*
829 * If write_err_msg is null because of previous strdup failure, do what we
830 * can. (It's likely our machinations here will get OOM failures as well,
831 * but might as well try.)
832 */
833 if (conn->write_err_msg)
834 {
836 /* Avoid possibly appending the same message twice */
837 conn->write_err_msg[0] = '\0';
838 }
839 else
840 libpq_append_conn_error(conn, "write to server failed");
841
843}
char * write_err_msg
Definition libpq-int.h:516

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, libpq_append_conn_error(), pqSaveErrorResult(), and pg_conn::write_err_msg.

Referenced by PQgetResult().

◆ PQsendClosePortal()

int PQsendClosePortal ( PGconn conn,
const char portal 
)

Definition at line 2586 of file fe-exec.c.

2587{
2588 return PQsendTypedCommand(conn, PqMsg_Close, 'P', portal);
2589}

References conn, PqMsg_Close, and PQsendTypedCommand().

Referenced by test_prepared().

◆ PQsendClosePrepared()

int PQsendClosePrepared ( PGconn conn,
const char stmt 
)

Definition at line 2573 of file fe-exec.c.

2574{
2575 return PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt);
2576}

References conn, PqMsg_Close, PQsendTypedCommand(), and stmt.

Referenced by ExecQueryAndProcessResults(), and test_prepared().

◆ PQsendDescribePortal()

int PQsendDescribePortal ( PGconn conn,
const char portal 
)

Definition at line 2521 of file fe-exec.c.

2522{
2523 return PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal);
2524}

References conn, PqMsg_Describe, and PQsendTypedCommand().

Referenced by test_prepared().

◆ PQsendDescribePrepared()

int PQsendDescribePrepared ( PGconn conn,
const char stmt 
)

Definition at line 2508 of file fe-exec.c.

2509{
2511}

References conn, PqMsg_Describe, PQsendTypedCommand(), and stmt.

Referenced by test_prepared().

◆ PQsendFlushRequest()

int PQsendFlushRequest ( PGconn conn)

Definition at line 3402 of file fe-exec.c.

3403{
3404 if (!conn)
3405 return 0;
3406
3407 /* Don't try to send if we know there's no live connection. */
3408 if (conn->status != CONNECTION_OK)
3409 {
3410 libpq_append_conn_error(conn, "no connection to the server");
3411 return 0;
3412 }
3413
3414 /* Can't send while already busy, either, unless enqueuing for later */
3415 if (conn->asyncStatus != PGASYNC_IDLE &&
3417 {
3418 libpq_append_conn_error(conn, "another command is already in progress");
3419 return 0;
3420 }
3421
3422 if (pqPutMsgStart(PqMsg_Flush, conn) < 0 ||
3423 pqPutMsgEnd(conn) < 0)
3424 {
3425 return 0;
3426 }
3427
3428 /*
3429 * Give the data a push (in pipeline mode, only if we're past the size
3430 * threshold). In nonblock mode, don't complain if we're unable to send
3431 * it all; PQgetResult() will do any additional flushing needed.
3432 */
3433 if (pqPipelineFlush(conn) < 0)
3434 return 0;
3435
3436 return 1;
3437}
#define PqMsg_Flush
Definition protocol.h:24

References pg_conn::asyncStatus, conn, CONNECTION_OK, libpq_append_conn_error(), PGASYNC_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PqMsg_Flush, pqPipelineFlush(), pqPutMsgEnd(), pqPutMsgStart(), and pg_conn::status.

Referenced by ExecQueryAndProcessResults(), test_nosync(), test_pipeline_idle(), test_singlerowmode(), and test_uniqviol().

◆ PQsendPipelineSync()

int PQsendPipelineSync ( PGconn conn)

Definition at line 3313 of file fe-exec.c.

3314{
3315 return pqPipelineSyncInternal(conn, false);
3316}

References conn, and pqPipelineSyncInternal().

Referenced by ExecQueryAndProcessResults(), executeMetaCommand(), and test_multi_pipelines().

◆ PQsendPrepare()

int PQsendPrepare ( PGconn conn,
const char stmtName,
const char query,
int  nParams,
const Oid paramTypes 
)

Definition at line 1553 of file fe-exec.c.

1556{
1557 PGcmdQueueEntry *entry = NULL;
1558
1559 if (!PQsendQueryStart(conn, true))
1560 return 0;
1561
1562 /* check the arguments */
1563 if (!stmtName)
1564 {
1565 libpq_append_conn_error(conn, "statement name is a null pointer");
1566 return 0;
1567 }
1568 if (!query)
1569 {
1570 libpq_append_conn_error(conn, "command string is a null pointer");
1571 return 0;
1572 }
1574 {
1575 libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
1577 return 0;
1578 }
1579
1580 entry = pqAllocCmdQueueEntry(conn);
1581 if (entry == NULL)
1582 return 0; /* error msg already set */
1583
1584 /* construct the Parse message */
1585 if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
1586 pqPuts(stmtName, conn) < 0 ||
1587 pqPuts(query, conn) < 0)
1588 goto sendFailed;
1589
1590 if (nParams > 0 && paramTypes)
1591 {
1592 int i;
1593
1594 if (pqPutInt(nParams, 2, conn) < 0)
1595 goto sendFailed;
1596 for (i = 0; i < nParams; i++)
1597 {
1598 if (pqPutInt(paramTypes[i], 4, conn) < 0)
1599 goto sendFailed;
1600 }
1601 }
1602 else
1603 {
1604 if (pqPutInt(0, 2, conn) < 0)
1605 goto sendFailed;
1606 }
1607 if (pqPutMsgEnd(conn) < 0)
1608 goto sendFailed;
1609
1610 /* Add a Sync, unless in pipeline mode. */
1612 {
1613 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
1614 pqPutMsgEnd(conn) < 0)
1615 goto sendFailed;
1616 }
1617
1618 /* remember we are doing just a Parse */
1619 entry->queryclass = PGQUERY_PREPARE;
1620
1621 /* and remember the query text too, if possible */
1622 /* if insufficient memory, query just winds up NULL */
1623 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 if (pqPipelineFlush(conn) < 0)
1631 goto sendFailed;
1632
1633 /* OK, it's launched! */
1635
1636 return 1;
1637
1640 /* error message should be set up already */
1641 return 0;
1642}
static bool PQsendQueryStart(PGconn *conn, bool newQuery)
Definition fe-exec.c:1690
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition fe-misc.c:253
#define PQ_QUERY_PARAM_MAX_LIMIT
Definition libpq-fe.h:524
@ PGQUERY_PREPARE
Definition libpq-int.h:324
#define PqMsg_Parse
Definition protocol.h:25

References conn, fb(), i, libpq_append_conn_error(), PGQUERY_PREPARE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQ_QUERY_PARAM_MAX_LIMIT, pqAllocCmdQueueEntry(), pqAppendCmdQueueEntry(), PqMsg_Parse, PqMsg_Sync, pqPipelineFlush(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPuts(), pqRecycleCmdQueueEntry(), PQsendQueryStart(), PGcmdQueueEntry::query, and PGcmdQueueEntry::queryclass.

Referenced by ExecQueryAndProcessResults(), PQprepare(), prepare_foreign_modify(), test_pipelined_insert(), test_prepared(), and test_transaction().

◆ PQsendQuery()

◆ PQsendQueryContinue()

int PQsendQueryContinue ( PGconn conn,
const char query 
)

Definition at line 1439 of file fe-exec.c.

1440{
1441 return PQsendQueryInternal(conn, query, false);
1442}

References conn, and PQsendQueryInternal().

Referenced by PQconnectPoll().

◆ PQsendQueryGuts()

static int PQsendQueryGuts ( PGconn conn,
const char command,
const char stmtName,
int  nParams,
const Oid paramTypes,
const char *const paramValues,
const int paramLengths,
const int paramFormats,
int  resultFormat 
)
static

Definition at line 1774 of file fe-exec.c.

1783{
1784 int i;
1785 PGcmdQueueEntry *entry;
1786
1787 entry = pqAllocCmdQueueEntry(conn);
1788 if (entry == NULL)
1789 return 0; /* error msg already set */
1790
1791 /*
1792 * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync
1793 * (if not in pipeline mode), using specified statement name and the
1794 * unnamed portal.
1795 */
1796
1797 if (command)
1798 {
1799 /* construct the Parse message */
1800 if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
1801 pqPuts(stmtName, conn) < 0 ||
1802 pqPuts(command, conn) < 0)
1803 goto sendFailed;
1804 if (nParams > 0 && paramTypes)
1805 {
1806 if (pqPutInt(nParams, 2, conn) < 0)
1807 goto sendFailed;
1808 for (i = 0; i < nParams; i++)
1809 {
1810 if (pqPutInt(paramTypes[i], 4, conn) < 0)
1811 goto sendFailed;
1812 }
1813 }
1814 else
1815 {
1816 if (pqPutInt(0, 2, conn) < 0)
1817 goto sendFailed;
1818 }
1819 if (pqPutMsgEnd(conn) < 0)
1820 goto sendFailed;
1821 }
1822
1823 /* Construct the Bind message */
1824 if (pqPutMsgStart(PqMsg_Bind, conn) < 0 ||
1825 pqPuts("", conn) < 0 ||
1826 pqPuts(stmtName, conn) < 0)
1827 goto sendFailed;
1828
1829 /* Send parameter formats */
1830 if (nParams > 0 && paramFormats)
1831 {
1832 if (pqPutInt(nParams, 2, conn) < 0)
1833 goto sendFailed;
1834 for (i = 0; i < nParams; i++)
1835 {
1836 if (pqPutInt(paramFormats[i], 2, conn) < 0)
1837 goto sendFailed;
1838 }
1839 }
1840 else
1841 {
1842 if (pqPutInt(0, 2, conn) < 0)
1843 goto sendFailed;
1844 }
1845
1846 if (pqPutInt(nParams, 2, conn) < 0)
1847 goto sendFailed;
1848
1849 /* Send parameters */
1850 for (i = 0; i < nParams; i++)
1851 {
1852 if (paramValues && paramValues[i])
1853 {
1854 int nbytes;
1855
1856 if (paramFormats && paramFormats[i] != 0)
1857 {
1858 /* binary parameter */
1859 if (paramLengths)
1860 nbytes = paramLengths[i];
1861 else
1862 {
1863 libpq_append_conn_error(conn, "length must be given for binary parameter");
1864 goto sendFailed;
1865 }
1866 }
1867 else
1868 {
1869 /* text parameter, do not use paramLengths */
1870 nbytes = strlen(paramValues[i]);
1871 }
1872 if (pqPutInt(nbytes, 4, conn) < 0 ||
1873 pqPutnchar(paramValues[i], nbytes, conn) < 0)
1874 goto sendFailed;
1875 }
1876 else
1877 {
1878 /* take the param as NULL */
1879 if (pqPutInt(-1, 4, conn) < 0)
1880 goto sendFailed;
1881 }
1882 }
1883 if (pqPutInt(1, 2, conn) < 0 ||
1885 goto sendFailed;
1886 if (pqPutMsgEnd(conn) < 0)
1887 goto sendFailed;
1888
1889 /* construct the Describe Portal message */
1890 if (pqPutMsgStart(PqMsg_Describe, conn) < 0 ||
1891 pqPutc('P', conn) < 0 ||
1892 pqPuts("", conn) < 0 ||
1893 pqPutMsgEnd(conn) < 0)
1894 goto sendFailed;
1895
1896 /* construct the Execute message */
1897 if (pqPutMsgStart(PqMsg_Execute, conn) < 0 ||
1898 pqPuts("", conn) < 0 ||
1899 pqPutInt(0, 4, conn) < 0 ||
1900 pqPutMsgEnd(conn) < 0)
1901 goto sendFailed;
1902
1903 /* construct the Sync message if not in pipeline mode */
1905 {
1906 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
1907 pqPutMsgEnd(conn) < 0)
1908 goto sendFailed;
1909 }
1910
1911 /* remember we are using extended query protocol */
1913
1914 /* and remember the query text too, if possible */
1915 /* if insufficient memory, query just winds up NULL */
1916 if (command)
1917 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 if (pqPipelineFlush(conn) < 0)
1925 goto sendFailed;
1926
1927 /* OK, it's launched! */
1929
1930 return 1;
1931
1934 /* error message should be set up already */
1935 return 0;
1936}
int pqPutc(char c, PGconn *conn)
Definition fe-misc.c:92
#define PqMsg_Bind
Definition protocol.h:19
#define PqMsg_Execute
Definition protocol.h:22

References conn, fb(), i, libpq_append_conn_error(), PGQUERY_EXTENDED, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqAllocCmdQueueEntry(), pqAppendCmdQueueEntry(), PqMsg_Bind, PqMsg_Describe, PqMsg_Execute, PqMsg_Parse, PqMsg_Sync, pqPipelineFlush(), pqPutc(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqPuts(), pqRecycleCmdQueueEntry(), PGcmdQueueEntry::query, and PGcmdQueueEntry::queryclass.

Referenced by PQsendQueryParams(), and PQsendQueryPrepared().

◆ PQsendQueryInternal()

static int PQsendQueryInternal ( PGconn conn,
const char query,
bool  newQuery 
)
static

Definition at line 1445 of file fe-exec.c.

1446{
1447 PGcmdQueueEntry *entry = NULL;
1448
1450 return 0;
1451
1452 /* check the argument */
1453 if (!query)
1454 {
1455 libpq_append_conn_error(conn, "command string is a null pointer");
1456 return 0;
1457 }
1458
1460 {
1461 libpq_append_conn_error(conn, "%s not allowed in pipeline mode",
1462 "PQsendQuery");
1463 return 0;
1464 }
1465
1466 entry = pqAllocCmdQueueEntry(conn);
1467 if (entry == NULL)
1468 return 0; /* error msg already set */
1469
1470 /* Send the query message(s) */
1471 /* construct the outgoing Query message */
1472 if (pqPutMsgStart(PqMsg_Query, conn) < 0 ||
1473 pqPuts(query, conn) < 0 ||
1474 pqPutMsgEnd(conn) < 0)
1475 {
1476 /* error message should be set up already */
1478 return 0;
1479 }
1480
1481 /* remember we are using simple query protocol */
1482 entry->queryclass = PGQUERY_SIMPLE;
1483 /* and remember the query text too, if possible */
1484 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 if (pqFlush(conn) < 0)
1491 goto sendFailed;
1492
1493 /* OK, it's launched! */
1495
1496 return 1;
1497
1500 /* error message should be set up already */
1501 return 0;
1502}
#define PqMsg_Query
Definition protocol.h:26

References conn, fb(), libpq_append_conn_error(), PGQUERY_SIMPLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqAllocCmdQueueEntry(), pqAppendCmdQueueEntry(), pqFlush(), PqMsg_Query, pqPutMsgEnd(), pqPutMsgStart(), pqPuts(), pqRecycleCmdQueueEntry(), PQsendQueryStart(), PGcmdQueueEntry::query, and PGcmdQueueEntry::queryclass.

Referenced by PQsendQuery(), and PQsendQueryContinue().

◆ PQsendQueryParams()

int PQsendQueryParams ( PGconn conn,
const char command,
int  nParams,
const Oid paramTypes,
const char *const paramValues,
const int paramLengths,
const int paramFormats,
int  resultFormat 
)

Definition at line 1509 of file fe-exec.c.

1517{
1518 if (!PQsendQueryStart(conn, true))
1519 return 0;
1520
1521 /* check the arguments */
1522 if (!command)
1523 {
1524 libpq_append_conn_error(conn, "command string is a null pointer");
1525 return 0;
1526 }
1528 {
1529 libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
1531 return 0;
1532 }
1533
1534 return PQsendQueryGuts(conn,
1535 command,
1536 "", /* use unnamed statement */
1537 nParams,
1538 paramTypes,
1542 resultFormat);
1543}
static int PQsendQueryGuts(PGconn *conn, const char *command, const char *stmtName, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition fe-exec.c:1774

References conn, fb(), libpq_append_conn_error(), PQ_QUERY_PARAM_MAX_LIMIT, PQsendQueryGuts(), and PQsendQueryStart().

Referenced by create_cursor(), ExecQueryAndProcessResults(), execute_dml_stmt(), libpqsrv_exec_params(), PQexecParams(), send_cancellable_query_impl(), sendCommand(), test_multi_pipelines(), test_nosync(), test_pipeline_abort(), test_pipeline_idle(), test_pipelined_insert(), test_simple_pipeline(), test_singlerowmode(), and test_transaction().

◆ PQsendQueryPrepared()

int PQsendQueryPrepared ( PGconn conn,
const char stmtName,
int  nParams,
const char *const paramValues,
const int paramLengths,
const int paramFormats,
int  resultFormat 
)

Definition at line 1650 of file fe-exec.c.

1657{
1658 if (!PQsendQueryStart(conn, true))
1659 return 0;
1660
1661 /* check the arguments */
1662 if (!stmtName)
1663 {
1664 libpq_append_conn_error(conn, "statement name is a null pointer");
1665 return 0;
1666 }
1668 {
1669 libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
1671 return 0;
1672 }
1673
1674 return PQsendQueryGuts(conn,
1675 NULL, /* no command to parse */
1676 stmtName,
1677 nParams,
1678 NULL, /* no param types */
1682 resultFormat);
1683}

References conn, fb(), libpq_append_conn_error(), PQ_QUERY_PARAM_MAX_LIMIT, PQsendQueryGuts(), and PQsendQueryStart().

Referenced by ExecQueryAndProcessResults(), execute_foreign_modify(), PQexecPrepared(), process_queued_fetch_requests(), sendCommand(), test_pipelined_insert(), test_transaction(), and test_uniqviol().

◆ PQsendQueryStart()

static bool PQsendQueryStart ( PGconn conn,
bool  newQuery 
)
static

Definition at line 1690 of file fe-exec.c.

1691{
1692 if (!conn)
1693 return false;
1694
1695 /*
1696 * If this is the beginning of a query cycle, reset the error state.
1697 * However, in pipeline mode with something already queued, the error
1698 * buffer belongs to that command and we shouldn't clear it.
1699 */
1700 if (newQuery && conn->cmd_queue_head == NULL)
1702
1703 /* Don't try to send if we know there's no live connection. */
1704 if (conn->status != CONNECTION_OK)
1705 {
1706 libpq_append_conn_error(conn, "no connection to the server");
1707 return false;
1708 }
1709
1710 /* Can't send while already busy, either, unless enqueuing for later */
1711 if (conn->asyncStatus != PGASYNC_IDLE &&
1713 {
1714 libpq_append_conn_error(conn, "another command is already in progress");
1715 return false;
1716 }
1717
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 switch (conn->asyncStatus)
1732 {
1733 case PGASYNC_IDLE:
1735 case PGASYNC_READY:
1736 case PGASYNC_READY_MORE:
1737 case PGASYNC_BUSY:
1738 /* ok to queue */
1739 break;
1740
1741 case PGASYNC_COPY_IN:
1742 case PGASYNC_COPY_OUT:
1743 case PGASYNC_COPY_BOTH:
1744 libpq_append_conn_error(conn, "cannot queue commands during COPY");
1745 return false;
1746 }
1747 }
1748 else
1749 {
1750 /*
1751 * This command's results will come in immediately. Initialize async
1752 * result-accumulation state
1753 */
1755
1756 /* reset partial-result mode */
1757 conn->partialResMode = false;
1758 conn->singleRowMode = false;
1759 conn->maxChunkSize = 0;
1760 }
1761
1762 /* ready to send command message */
1763 return true;
1764}

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, CONNECTION_OK, fb(), libpq_append_conn_error(), pg_conn::maxChunkSize, pg_conn::partialResMode, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_PIPELINE_IDLE, PGASYNC_READY, PGASYNC_READY_MORE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearAsyncResult(), pqClearConnErrorState, pg_conn::singleRowMode, and pg_conn::status.

Referenced by PQsendPrepare(), PQsendQueryInternal(), PQsendQueryParams(), PQsendQueryPrepared(), and PQsendTypedCommand().

◆ PQsendTypedCommand()

static int PQsendTypedCommand ( PGconn conn,
char  command,
char  type,
const char target 
)
static

Definition at line 2606 of file fe-exec.c.

2607{
2608 PGcmdQueueEntry *entry = NULL;
2609
2610 /* Treat null target as empty string */
2611 if (!target)
2612 target = "";
2613
2614 if (!PQsendQueryStart(conn, true))
2615 return 0;
2616
2617 entry = pqAllocCmdQueueEntry(conn);
2618 if (entry == NULL)
2619 return 0; /* error msg already set */
2620
2621 /* construct the Close message */
2622 if (pqPutMsgStart(command, conn) < 0 ||
2623 pqPutc(type, conn) < 0 ||
2624 pqPuts(target, conn) < 0 ||
2625 pqPutMsgEnd(conn) < 0)
2626 goto sendFailed;
2627
2628 /* construct the Sync message */
2630 {
2631 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
2632 pqPutMsgEnd(conn) < 0)
2633 goto sendFailed;
2634 }
2635
2636 /* remember if we are doing a Close or a Describe */
2637 if (command == PqMsg_Close)
2638 {
2639 entry->queryclass = PGQUERY_CLOSE;
2640 }
2641 else if (command == PqMsg_Describe)
2642 {
2644 }
2645 else
2646 {
2647 libpq_append_conn_error(conn, "unrecognized message type \"%c\"", command);
2648 goto sendFailed;
2649 }
2650
2651 /*
2652 * Give the data a push (in pipeline mode, only if we're past the size
2653 * threshold). In nonblock mode, don't complain if we're unable to send
2654 * it all; PQgetResult() will do any additional flushing needed.
2655 */
2656 if (pqPipelineFlush(conn) < 0)
2657 goto sendFailed;
2658
2659 /* OK, it's launched! */
2661
2662 return 1;
2663
2666 /* error message should be set up already */
2667 return 0;
2668}
@ PGQUERY_DESCRIBE
Definition libpq-int.h:325
@ PGQUERY_CLOSE
Definition libpq-int.h:327
const char * type

References conn, fb(), libpq_append_conn_error(), PGQUERY_CLOSE, PGQUERY_DESCRIBE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqAllocCmdQueueEntry(), pqAppendCmdQueueEntry(), PqMsg_Close, PqMsg_Describe, PqMsg_Sync, pqPipelineFlush(), pqPutc(), pqPutMsgEnd(), pqPutMsgStart(), pqPuts(), pqRecycleCmdQueueEntry(), PQsendQueryStart(), PGcmdQueueEntry::queryclass, and type.

Referenced by PQclosePortal(), PQclosePrepared(), PQdescribePortal(), PQdescribePrepared(), PQsendClosePortal(), PQsendClosePrepared(), PQsendDescribePortal(), and PQsendDescribePrepared().

◆ PQsetChunkedRowsMode()

int PQsetChunkedRowsMode ( PGconn conn,
int  chunkSize 
)

Definition at line 1982 of file fe-exec.c.

1983{
1984 if (chunkSize > 0 && canChangeResultMode(conn))
1985 {
1986 conn->partialResMode = true;
1987 conn->singleRowMode = false;
1988 conn->maxChunkSize = chunkSize;
1989 return 1;
1990 }
1991 else
1992 return 0;
1993}
static bool canChangeResultMode(PGconn *conn)
Definition fe-exec.c:1942

References canChangeResultMode(), conn, pg_conn::maxChunkSize, pg_conn::partialResMode, and pg_conn::singleRowMode.

Referenced by ExecQueryAndProcessResults(), and test_singlerowmode().

◆ PQsetnonblocking()

int PQsetnonblocking ( PGconn conn,
int  arg 
)

Definition at line 3980 of file fe-exec.c.

3981{
3982 bool barg;
3983
3984 if (!conn || conn->status == CONNECTION_BAD)
3985 return -1;
3986
3987 barg = (arg ? true : false);
3988
3989 /* early out if the socket is already in the state requested */
3990 if (barg == conn->nonblocking)
3991 return 0;
3992
3993 /*
3994 * to guarantee constancy for flushing/query/result-polling behavior we
3995 * need to flush the send queue at this point in order to guarantee proper
3996 * behavior. this is ok because either they are making a transition _from_
3997 * or _to_ blocking mode, either way we can block them.
3998 *
3999 * Clear error state in case pqFlush adds to it, unless we're actively
4000 * pipelining, in which case it seems best not to.
4001 */
4002 if (conn->cmd_queue_head == NULL)
4004
4005 /* if we are going from blocking to non-blocking flush here */
4006 if (pqFlush(conn))
4007 return -1;
4008
4010
4011 return 0;
4012}
Datum arg
Definition elog.c:1323
return true
Definition isn.c:130
bool nonblocking
Definition libpq-int.h:470

References arg, pg_conn::cmd_queue_head, conn, CONNECTION_BAD, fb(), pg_conn::nonblocking, pqClearConnErrorState, pqFlush(), pg_conn::status, and true.

Referenced by test_cancel(), test_pipelined_insert(), and test_uniqviol().

◆ PQsetResultAttrs()

int PQsetResultAttrs ( PGresult res,
int  numAttributes,
PGresAttDesc attDescs 
)

Definition at line 250 of file fe-exec.c.

251{
252 int i;
253
254 /* Fail if argument is NULL or OOM_result */
255 if (!res || (const PGresult *) res == &OOM_result)
256 return false;
257
258 /* If attrs already exist, they cannot be overwritten. */
259 if (res->numAttributes > 0)
260 return false;
261
262 /* ignore no-op request */
263 if (numAttributes <= 0 || !attDescs)
264 return true;
265
266 res->attDescs = (PGresAttDesc *)
267 PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
268
269 if (!res->attDescs)
270 return false;
271
272 res->numAttributes = numAttributes;
273 memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
274
275 /* deep-copy the attribute names, and determine format */
276 res->binary = 1;
277 for (i = 0; i < res->numAttributes; i++)
278 {
279 if (res->attDescs[i].name)
280 res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
281 else
282 res->attDescs[i].name = res->null_field;
283
284 if (!res->attDescs[i].name)
285 return false;
286
287 if (res->attDescs[i].format == 0)
288 res->binary = 0;
289 }
290
291 return true;
292}
void * PQresultAlloc(PGresult *res, size_t nBytes)
Definition fe-exec.c:544
char * pqResultStrdup(PGresult *res, const char *str)
Definition fe-exec.c:681

References pg_result::attDescs, pg_result::binary, pgresAttDesc::format, i, memcpy(), pgresAttDesc::name, pg_result::null_field, pg_result::numAttributes, OOM_result, PQresultAlloc(), and pqResultStrdup().

Referenced by PQcopyResult().

◆ pqSetResultError()

void pqSetResultError ( PGresult res,
PQExpBuffer  errorMessage,
int  offset 
)

Definition at line 698 of file fe-exec.c.

699{
700 char *msg;
701
702 if (!res)
703 return;
704
705 /*
706 * We handle two OOM scenarios here. The errorMessage buffer might be
707 * marked "broken" due to having previously failed to allocate enough
708 * memory for the message, or it might be fine but pqResultStrdup fails
709 * and returns NULL. In either case, just make res->errMsg point directly
710 * at a constant "out of memory" string.
711 */
712 if (!PQExpBufferBroken(errorMessage))
713 msg = pqResultStrdup(res, errorMessage->data + offset);
714 else
715 msg = NULL;
716 if (msg)
717 res->errMsg = msg;
718 else
719 res->errMsg = libpq_gettext("out of memory\n");
720}
#define PQExpBufferBroken(str)
Definition pqexpbuffer.h:59

References PQExpBufferData::data, pg_result::errMsg, fb(), libpq_gettext, PQExpBufferBroken, and pqResultStrdup().

Referenced by pqGetErrorNotice3(), PQmakeEmptyPGresult(), and pqPrepareAsyncResult().

◆ PQsetSingleRowMode()

int PQsetSingleRowMode ( PGconn conn)

Definition at line 1965 of file fe-exec.c.

1966{
1968 {
1969 conn->partialResMode = true;
1970 conn->singleRowMode = true;
1971 conn->maxChunkSize = 1;
1972 return 1;
1973 }
1974 else
1975 return 0;
1976}

References canChangeResultMode(), conn, pg_conn::maxChunkSize, pg_conn::partialResMode, and pg_conn::singleRowMode.

Referenced by process_queued_fetch_requests(), storeQueryResult(), test_pipeline_abort(), and test_singlerowmode().

◆ PQsetvalue()

int PQsetvalue ( PGresult res,
int  tup_num,
int  field_num,
char value,
int  len 
)

Definition at line 453 of file fe-exec.c.

454{
456 const char *errmsg = NULL;
457
458 /* Fail if argument is NULL or OOM_result */
459 if (!res || (const PGresult *) res == &OOM_result)
460 return false;
461
462 /* Invalid field_num? */
463 if (!check_field_number(res, field_num))
464 return false;
465
466 /* Invalid tup_num, must be <= ntups */
468 {
470 "row number %d is out of range 0..%d",
471 tup_num, res->ntups);
472 return false;
473 }
474
475 /* need to allocate a new tuple? */
476 if (tup_num == res->ntups)
477 {
479 int i;
480
481 tup = (PGresAttValue *)
482 pqResultAlloc(res, res->numAttributes * sizeof(PGresAttValue),
483 true);
484
485 if (!tup)
486 goto fail;
487
488 /* initialize each column to NULL */
489 for (i = 0; i < res->numAttributes; i++)
490 {
491 tup[i].len = NULL_LEN;
492 tup[i].value = res->null_field;
493 }
494
495 /* add it to the array */
496 if (!pqAddTuple(res, tup, &errmsg))
497 goto fail;
498 }
499
500 attval = &res->tuples[tup_num][field_num];
501
502 /* treat either NULL_LEN or NULL value pointer as a NULL field */
503 if (len == NULL_LEN || value == NULL)
504 {
506 attval->value = res->null_field;
507 }
508 else if (len <= 0)
509 {
510 attval->len = 0;
511 attval->value = res->null_field;
512 }
513 else
514 {
515 attval->value = (char *) pqResultAlloc(res, (size_t) len + 1, true);
516 if (!attval->value)
517 goto fail;
518 attval->len = len;
519 memcpy(attval->value, value, len);
520 attval->value[len] = '\0';
521 }
522
523 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 */
529fail:
530 if (!errmsg)
531 errmsg = libpq_gettext("out of memory");
532 pqInternalNotice(&res->noticeHooks, "%s", errmsg);
533
534 return false;
535}
static char * errmsg

References check_field_number(), errmsg, fb(), i, pgresAttValue::len, len, libpq_gettext, memcpy(), pg_result::noticeHooks, pg_result::ntups, pg_result::null_field, NULL_LEN, pg_result::numAttributes, OOM_result, pqAddTuple(), pqInternalNotice(), pqResultAlloc(), pg_result::tuples, and value.

Referenced by PQcopyResult().

◆ PQunescapeBytea()

unsigned char * PQunescapeBytea ( const unsigned char strtext,
size_t retbuflen 
)

Definition at line 4636 of file fe-exec.c.

4637{
4638 size_t strtextlen,
4639 buflen;
4640 unsigned char *buffer,
4641 *tmpbuf;
4642 size_t i,
4643 j;
4644
4645 if (strtext == NULL)
4646 return NULL;
4647
4648 strtextlen = strlen((const char *) strtext);
4649
4650 if (strtext[0] == '\\' && strtext[1] == 'x')
4651 {
4652 const unsigned char *s;
4653 unsigned char *p;
4654
4655 buflen = (strtextlen - 2) / 2;
4656 /* Avoid unportable malloc(0) */
4657 buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1);
4658 if (buffer == NULL)
4659 return NULL;
4660
4661 s = strtext + 2;
4662 p = buffer;
4663 while (*s)
4664 {
4665 char v1,
4666 v2;
4667
4668 /*
4669 * Bad input is silently ignored. Note that this includes
4670 * whitespace between hex pairs, which is allowed by byteain.
4671 */
4672 v1 = get_hex(*s++);
4673 if (!*s || v1 == (char) -1)
4674 continue;
4675 v2 = get_hex(*s++);
4676 if (v2 != (char) -1)
4677 *p++ = (v1 << 4) | v2;
4678 }
4679
4680 buflen = p - buffer;
4681 }
4682 else
4683 {
4684 /*
4685 * Length of input is max length of output, but add one to avoid
4686 * unportable malloc(0) if input is zero-length.
4687 */
4688 buffer = (unsigned char *) malloc(strtextlen + 1);
4689 if (buffer == NULL)
4690 return NULL;
4691
4692 for (i = j = 0; i < strtextlen;)
4693 {
4694 switch (strtext[i])
4695 {
4696 case '\\':
4697 i++;
4698 if (strtext[i] == '\\')
4699 buffer[j++] = strtext[i++];
4700 else
4701 {
4702 if ((ISFIRSTOCTDIGIT(strtext[i])) &&
4703 (ISOCTDIGIT(strtext[i + 1])) &&
4704 (ISOCTDIGIT(strtext[i + 2])))
4705 {
4706 int byte;
4707
4708 byte = OCTVAL(strtext[i++]);
4709 byte = (byte << 3) + OCTVAL(strtext[i++]);
4710 byte = (byte << 3) + OCTVAL(strtext[i++]);
4711 buffer[j++] = byte;
4712 }
4713 }
4714
4715 /*
4716 * Note: if we see '\' followed by something that isn't a
4717 * recognized escape sequence, we loop around having done
4718 * nothing except advance i. Therefore the something will
4719 * be emitted as ordinary data on the next cycle. Corner
4720 * case: '\' at end of string will just be discarded.
4721 */
4722 break;
4723
4724 default:
4725 buffer[j++] = strtext[i++];
4726 break;
4727 }
4728 }
4729 buflen = j; /* buflen is the length of the dequoted data */
4730 }
4731
4732 /* Shrink the buffer to be no larger than necessary */
4733 /* +1 avoids unportable behavior when buflen==0 */
4734 tmpbuf = realloc(buffer, buflen + 1);
4735
4736 /* It would only be a very brain-dead realloc that could fail, but... */
4737 if (!tmpbuf)
4738 {
4739 free(buffer);
4740 return NULL;
4741 }
4742
4743 *retbuflen = buflen;
4744 return tmpbuf;
4745}
static char get_hex(char c)
Definition fe-exec.c:4444
#define ISOCTDIGIT(CH)
Definition fe-exec.c:4620
#define OCTVAL(CH)
Definition fe-exec.c:4621
#define ISFIRSTOCTDIGIT(CH)
Definition fe-exec.c:4619
int j
Definition isn.c:78
static StringInfoData tmpbuf
Definition walsender.c:195

References fb(), free, get_hex(), i, ISFIRSTOCTDIGIT, ISOCTDIGIT, j, malloc, OCTVAL, realloc, and tmpbuf.

Variable Documentation

◆ hexlookup

const int8 hexlookup[128]
static
Initial value:
= {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
}

Definition at line 4432 of file fe-exec.c.

4432 {
4433 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4434 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4435 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4436 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
4437 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4438 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4439 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4440 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4441};

Referenced by get_hex().

◆ hextbl

const char hextbl[] = "0123456789abcdef"
static

Definition at line 4430 of file fe-exec.c.

Referenced by PQescapeByteaInternal().

◆ OOM_result

const PGresult OOM_result
static
Initial value:
= {
.resultStatus = PGRES_FATAL_ERROR,
.client_encoding = PG_SQL_ASCII,
.errMsg = "out of memory\n",
}

Definition at line 50 of file fe-exec.c.

50 {
51 .resultStatus = PGRES_FATAL_ERROR,
52 .client_encoding = PG_SQL_ASCII,
53 .errMsg = "out of memory\n",
54};

Referenced by PQclear(), pqPrepareAsyncResult(), PQresultAlloc(), PQsetResultAttrs(), and PQsetvalue().

◆ pgresStatus

char* const pgresStatus[]
Initial value:
= {
"PGRES_EMPTY_QUERY",
"PGRES_COMMAND_OK",
"PGRES_TUPLES_OK",
"PGRES_COPY_OUT",
"PGRES_COPY_IN",
"PGRES_BAD_RESPONSE",
"PGRES_NONFATAL_ERROR",
"PGRES_FATAL_ERROR",
"PGRES_COPY_BOTH",
"PGRES_SINGLE_TUPLE",
"PGRES_PIPELINE_SYNC",
"PGRES_PIPELINE_ABORTED",
"PGRES_TUPLES_CHUNK"
}

Definition at line 33 of file fe-exec.c.

33 {
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};

Referenced by PQresStatus().

◆ static_client_encoding

int static_client_encoding = PG_SQL_ASCII
static

Definition at line 60 of file fe-exec.c.

Referenced by PQescapeString(), and pqSaveParameterStatus().

◆ static_std_strings

bool static_std_strings = false
static

Definition at line 61 of file fe-exec.c.

Referenced by PQescapeBytea(), PQescapeString(), and pqSaveParameterStatus().