PostgreSQL Source Code  git master
fe-protocol2.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "port/pg_bswap.h"
#include <unistd.h>
Include dependency graph for fe-protocol2.c:

Go to the source code of this file.

Functions

static int getRowDescriptions (PGconn *conn)
 
static int getAnotherTuple (PGconn *conn, bool binary)
 
static int pqGetErrorNotice2 (PGconn *conn, bool isError)
 
static void checkXactStatus (PGconn *conn, const char *cmdTag)
 
static int getNotify (PGconn *conn)
 
PostgresPollingStatusType pqSetenvPoll (PGconn *conn)
 
void pqParseInput2 (PGconn *conn)
 
int pqGetCopyData2 (PGconn *conn, char **buffer, int async)
 
int pqGetline2 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync2 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy2 (PGconn *conn)
 
PGresultpqFunctionCall2 (PGconn *conn, Oid fnid, int *result_buf, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
char * pqBuildStartupPacket2 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 

Function Documentation

◆ checkXactStatus()

static void checkXactStatus ( PGconn conn,
const char *  cmdTag 
)
static

Definition at line 1093 of file fe-protocol2.c.

References PQTRANS_IDLE, PQTRANS_INERROR, PQTRANS_INTRANS, and pg_conn::xactStatus.

Referenced by pqParseInput2().

1094 {
1095  if (strcmp(cmdTag, "BEGIN") == 0)
1096  conn->xactStatus = PQTRANS_INTRANS;
1097  else if (strcmp(cmdTag, "COMMIT") == 0)
1098  conn->xactStatus = PQTRANS_IDLE;
1099  else if (strcmp(cmdTag, "ROLLBACK") == 0)
1100  conn->xactStatus = PQTRANS_IDLE;
1101  else if (strcmp(cmdTag, "START TRANSACTION") == 0) /* 7.3 only */
1102  conn->xactStatus = PQTRANS_INTRANS;
1103 
1104  /*
1105  * Normally we get into INERROR state by detecting an Error message.
1106  * However, if we see one of these tags then we know for sure the server
1107  * is in abort state ...
1108  */
1109  else if (strcmp(cmdTag, "*ABORT STATE*") == 0) /* pre-7.3 only */
1110  conn->xactStatus = PQTRANS_INERROR;
1111 }
PGTransactionStatusType xactStatus
Definition: libpq-int.h:382

◆ getAnotherTuple()

static int getAnotherTuple ( PGconn conn,
bool  binary 
)
static

Definition at line 789 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_result::attDescs, pg_result::binary, BITS_PER_BYTE, errmsg(), pg_conn::errorMessage, pgresAttDesc::format, free, i, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pgDataValue::len, libpq_gettext, malloc, NULL_LEN, pg_result::numAttributes, PGASYNC_READY, PGRES_FATAL_ERROR, pqClearAsyncResult(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), pqRowProcessor(), pqSkipnchar(), printfPQExpBuffer(), realloc, pg_conn::result, pg_conn::rowBuf, pg_conn::rowBufLen, and pgDataValue::value.

Referenced by pqParseInput2().

790 {
791  PGresult *result = conn->result;
792  int nfields = result->numAttributes;
793  const char *errmsg;
794  PGdataValue *rowbuf;
795 
796  /* the backend sends us a bitmap of which attributes are null */
797  char std_bitmap[64]; /* used unless it doesn't fit */
798  char *bitmap = std_bitmap;
799  int i;
800  size_t nbytes; /* the number of bytes in bitmap */
801  char bmap; /* One byte of the bitmap */
802  int bitmap_index; /* Its index */
803  int bitcnt; /* number of bits examined in current byte */
804  int vlen; /* length of the current field value */
805 
806  /* Resize row buffer if needed */
807  rowbuf = conn->rowBuf;
808  if (nfields > conn->rowBufLen)
809  {
810  rowbuf = (PGdataValue *) realloc(rowbuf,
811  nfields * sizeof(PGdataValue));
812  if (!rowbuf)
813  {
814  errmsg = NULL; /* means "out of memory", see below */
815  goto advance_and_error;
816  }
817  conn->rowBuf = rowbuf;
818  conn->rowBufLen = nfields;
819  }
820 
821  /* Save format specifier */
822  result->binary = binary;
823 
824  /*
825  * If it's binary, fix the column format indicators. We assume the
826  * backend will consistently send either B or D, not a mix.
827  */
828  if (binary)
829  {
830  for (i = 0; i < nfields; i++)
831  result->attDescs[i].format = 1;
832  }
833 
834  /* Get the null-value bitmap */
835  nbytes = (nfields + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
836  /* malloc() only for unusually large field counts... */
837  if (nbytes > sizeof(std_bitmap))
838  {
839  bitmap = (char *) malloc(nbytes);
840  if (!bitmap)
841  {
842  errmsg = NULL; /* means "out of memory", see below */
843  goto advance_and_error;
844  }
845  }
846 
847  if (pqGetnchar(bitmap, nbytes, conn))
848  goto EOFexit;
849 
850  /* Scan the fields */
851  bitmap_index = 0;
852  bmap = bitmap[bitmap_index];
853  bitcnt = 0;
854 
855  for (i = 0; i < nfields; i++)
856  {
857  /* get the value length */
858  if (!(bmap & 0200))
859  vlen = NULL_LEN;
860  else if (pqGetInt(&vlen, 4, conn))
861  goto EOFexit;
862  else
863  {
864  if (!binary)
865  vlen = vlen - 4;
866  if (vlen < 0)
867  vlen = 0;
868  }
869  rowbuf[i].len = vlen;
870 
871  /*
872  * rowbuf[i].value always points to the next address in the data
873  * buffer even if the value is NULL. This allows row processors to
874  * estimate data sizes more easily.
875  */
876  rowbuf[i].value = conn->inBuffer + conn->inCursor;
877 
878  /* Skip over the data value */
879  if (vlen > 0)
880  {
881  if (pqSkipnchar(vlen, conn))
882  goto EOFexit;
883  }
884 
885  /* advance the bitmap stuff */
886  bitcnt++;
887  if (bitcnt == BITS_PER_BYTE)
888  {
889  bitmap_index++;
890  bmap = bitmap[bitmap_index];
891  bitcnt = 0;
892  }
893  else
894  bmap <<= 1;
895  }
896 
897  /* Release bitmap now if we allocated it */
898  if (bitmap != std_bitmap)
899  free(bitmap);
900  bitmap = NULL;
901 
902  /* Advance inStart to show that the "D" message has been processed. */
903  conn->inStart = conn->inCursor;
904 
905  /* Process the collected row */
906  errmsg = NULL;
907  if (pqRowProcessor(conn, &errmsg))
908  return 0; /* normal, successful exit */
909 
910  goto set_error_result; /* pqRowProcessor failed, report it */
911 
912 advance_and_error:
913 
914  /*
915  * Discard the failed message. Unfortunately we don't know for sure where
916  * the end is, so just throw away everything in the input buffer. This is
917  * not very desirable but it's the best we can do in protocol v2.
918  */
919  conn->inStart = conn->inEnd;
920 
921 set_error_result:
922 
923  /*
924  * Replace partially constructed result with an error result. First
925  * discard the old result to try to win back some memory.
926  */
927  pqClearAsyncResult(conn);
928 
929  /*
930  * If preceding code didn't provide an error message, assume "out of
931  * memory" was meant. The advantage of having this special case is that
932  * freeing the old result first greatly improves the odds that gettext()
933  * will succeed in providing a translation.
934  */
935  if (!errmsg)
936  errmsg = libpq_gettext("out of memory for query result");
937 
938  printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
939 
940  /*
941  * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
942  * do to recover...
943  */
945  conn->asyncStatus = PGASYNC_READY;
946 
947 EOFexit:
948  if (bitmap != NULL && bitmap != std_bitmap)
949  free(bitmap);
950  return EOF;
951 }
int pqRowProcessor(PGconn *conn, const char **errmsgp)
Definition: fe-exec.c:1081
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
#define BITS_PER_BYTE
int rowBufLen
Definition: libpq-int.h:448
const char * value
Definition: libpq-int.h:290
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
#define NULL_LEN
Definition: libpq-int.h:133
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:195
PGresAttDesc * attDescs
Definition: libpq-int.h:171
PGresult * result
Definition: libpq-int.h:451
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
PGdataValue * rowBuf
Definition: libpq-int.h:447
int binary
Definition: libpq-int.h:179
int numAttributes
Definition: libpq-int.h:170
char * inBuffer
Definition: libpq-int.h:430
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define free(a)
Definition: header.h:65
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
int pqSkipnchar(size_t len, PGconn *conn)
Definition: fe-misc.c:224
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
int inCursor
Definition: libpq-int.h:433
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ getNotify()

static int getNotify ( PGconn conn)
static

Definition at line 1121 of file fe-protocol2.c.

References pgNotify::be_pid, PQExpBufferData::data, pgNotify::extra, malloc, pgNotify::next, pg_conn::notifyHead, pg_conn::notifyTail, pqGetInt(), pqGets(), pgNotify::relname, and pg_conn::workBuffer.

Referenced by pqFunctionCall2(), and pqParseInput2().

1122 {
1123  int be_pid;
1124  int nmlen;
1125  PGnotify *newNotify;
1126 
1127  if (pqGetInt(&be_pid, 4, conn))
1128  return EOF;
1129  if (pqGets(&conn->workBuffer, conn))
1130  return EOF;
1131 
1132  /*
1133  * Store the relation name right after the PQnotify structure so it can
1134  * all be freed at once. We don't use NAMEDATALEN because we don't want
1135  * to tie this interface to a specific server name length.
1136  */
1137  nmlen = strlen(conn->workBuffer.data);
1138  newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + 1);
1139  if (newNotify)
1140  {
1141  newNotify->relname = (char *) newNotify + sizeof(PGnotify);
1142  strcpy(newNotify->relname, conn->workBuffer.data);
1143  /* fake up an empty-string extra field */
1144  newNotify->extra = newNotify->relname + nmlen;
1145  newNotify->be_pid = be_pid;
1146  newNotify->next = NULL;
1147  if (conn->notifyTail)
1148  conn->notifyTail->next = newNotify;
1149  else
1150  conn->notifyHead = newNotify;
1151  conn->notifyTail = newNotify;
1152  }
1153 
1154  return 0;
1155 }
char * extra
Definition: libpq-fe.h:165
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:497
PGnotify * notifyHead
Definition: libpq-int.h:392
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
#define malloc(a)
Definition: header.h:50
int be_pid
Definition: libpq-fe.h:164
char * relname
Definition: libpq-fe.h:163
struct pgNotify * next
Definition: libpq-fe.h:167
PGnotify * notifyTail
Definition: libpq-int.h:393

◆ getRowDescriptions()

static int getRowDescriptions ( PGconn conn)
static

Definition at line 658 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_result::attDescs, pgresAttDesc::atttypmod, pgresAttDesc::columnid, PQExpBufferData::data, errmsg(), pg_conn::errorMessage, pgresAttDesc::format, i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, MemSet, pgresAttDesc::name, pg_result::numAttributes, PGASYNC_READY, PGRES_FATAL_ERROR, PGRES_TUPLES_OK, PQclear(), pqClearAsyncResult(), pqGetInt(), pqGets(), PQmakeEmptyPGresult(), pqResultAlloc(), pqResultStrdup(), printfPQExpBuffer(), pg_conn::result, pgresAttDesc::tableid, pgresAttDesc::typid, typlen, pgresAttDesc::typlen, and pg_conn::workBuffer.

Referenced by pqParseInput2().

659 {
660  PGresult *result;
661  int nfields;
662  const char *errmsg;
663  int i;
664 
665  result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
666  if (!result)
667  {
668  errmsg = NULL; /* means "out of memory", see below */
669  goto advance_and_error;
670  }
671 
672  /* parseInput already read the 'T' label. */
673  /* the next two bytes are the number of fields */
674  if (pqGetInt(&(result->numAttributes), 2, conn))
675  goto EOFexit;
676  nfields = result->numAttributes;
677 
678  /* allocate space for the attribute descriptors */
679  if (nfields > 0)
680  {
681  result->attDescs = (PGresAttDesc *)
682  pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
683  if (!result->attDescs)
684  {
685  errmsg = NULL; /* means "out of memory", see below */
686  goto advance_and_error;
687  }
688  MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
689  }
690 
691  /* get type info */
692  for (i = 0; i < nfields; i++)
693  {
694  int typid;
695  int typlen;
696  int atttypmod;
697 
698  if (pqGets(&conn->workBuffer, conn) ||
699  pqGetInt(&typid, 4, conn) ||
700  pqGetInt(&typlen, 2, conn) ||
701  pqGetInt(&atttypmod, 4, conn))
702  goto EOFexit;
703 
704  /*
705  * Since pqGetInt treats 2-byte integers as unsigned, we need to
706  * coerce the result to signed form.
707  */
708  typlen = (int) ((int16) typlen);
709 
710  result->attDescs[i].name = pqResultStrdup(result,
711  conn->workBuffer.data);
712  if (!result->attDescs[i].name)
713  {
714  errmsg = NULL; /* means "out of memory", see below */
715  goto advance_and_error;
716  }
717  result->attDescs[i].tableid = 0;
718  result->attDescs[i].columnid = 0;
719  result->attDescs[i].format = 0;
720  result->attDescs[i].typid = typid;
721  result->attDescs[i].typlen = typlen;
722  result->attDescs[i].atttypmod = atttypmod;
723  }
724 
725  /* Success! */
726  conn->result = result;
727 
728  /* Advance inStart to show that the "T" message has been processed. */
729  conn->inStart = conn->inCursor;
730 
731  /*
732  * We could perform additional setup for the new result set here, but for
733  * now there's nothing else to do.
734  */
735 
736  /* And we're done. */
737  return 0;
738 
739 advance_and_error:
740 
741  /*
742  * Discard the failed message. Unfortunately we don't know for sure where
743  * the end is, so just throw away everything in the input buffer. This is
744  * not very desirable but it's the best we can do in protocol v2.
745  */
746  conn->inStart = conn->inEnd;
747 
748  /*
749  * Replace partially constructed result with an error result. First
750  * discard the old result to try to win back some memory.
751  */
752  pqClearAsyncResult(conn);
753 
754  /*
755  * If preceding code didn't provide an error message, assume "out of
756  * memory" was meant. The advantage of having this special case is that
757  * freeing the old result first greatly improves the odds that gettext()
758  * will succeed in providing a translation.
759  */
760  if (!errmsg)
761  errmsg = libpq_gettext("out of memory for query result");
762 
763  printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
764 
765  /*
766  * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
767  * do to recover...
768  */
770  conn->asyncStatus = PGASYNC_READY;
771 
772 EOFexit:
773  if (result && result != conn->result)
774  PQclear(result);
775  return EOF;
776 }
signed short int16
Definition: c.h:312
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
int16 typlen
Definition: pg_type.h:55
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:497
#define MemSet(start, val, len)
Definition: c.h:908
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
int columnid
Definition: libpq-fe.h:239
PGresAttDesc * attDescs
Definition: libpq-int.h:171
PGresult * result
Definition: libpq-int.h:451
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int numAttributes
Definition: libpq-int.h:170
int atttypmod
Definition: libpq-fe.h:243
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void PQclear(PGresult *res)
Definition: fe-exec.c:671
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
char * name
Definition: libpq-fe.h:237
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
int inCursor
Definition: libpq-int.h:433
#define libpq_gettext(x)
Definition: libpq-int.h:760
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:623

◆ pqBuildStartupPacket2()

char* pqBuildStartupPacket2 ( PGconn conn,
int *  packetlen,
const PQEnvironmentOption options 
)

Definition at line 1607 of file fe-protocol2.c.

References StartupPacket::database, pg_conn::dbName, malloc, MemSet, StartupPacket::options, pg_hton32, pg_conn::pgoptions, pg_conn::pgtty, pg_conn::pguser, StartupPacket::protoVersion, pg_conn::pversion, SM_DATABASE, SM_OPTIONS, SM_TTY, SM_USER, StartupPacket::tty, and StartupPacket::user.

Referenced by PQconnectPoll().

1609 {
1610  StartupPacket *startpacket;
1611 
1612  *packetlen = sizeof(StartupPacket);
1613  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1614  if (!startpacket)
1615  return NULL;
1616 
1617  MemSet(startpacket, 0, sizeof(StartupPacket));
1618 
1619  startpacket->protoVersion = pg_hton32(conn->pversion);
1620 
1621  /* strncpy is safe here: postmaster will handle full fields correctly */
1622  strncpy(startpacket->user, conn->pguser, SM_USER);
1623  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1624  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1625 
1626  if (conn->pgoptions)
1627  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1628 
1629  return (char *) startpacket;
1630 }
char tty[SM_TTY]
Definition: pqcomm.h:149
struct StartupPacket StartupPacket
char * dbName
Definition: libpq-int.h:341
#define MemSet(start, val, len)
Definition: c.h:908
#define SM_USER
Definition: pqcomm.h:134
char options[SM_OPTIONS]
Definition: pqcomm.h:147
#define malloc(a)
Definition: header.h:50
#define SM_TTY
Definition: pqcomm.h:139
#define pg_hton32(x)
Definition: pg_bswap.h:121
char * pguser
Definition: libpq-int.h:343
char database[SM_DATABASE]
Definition: pqcomm.h:144
char * pgoptions
Definition: libpq-int.h:338
ProtocolVersion pversion
Definition: libpq-int.h:405
char user[SM_USER]
Definition: pqcomm.h:146
ProtocolVersion protoVersion
Definition: pqcomm.h:143
#define SM_OPTIONS
Definition: pqcomm.h:137
#define SM_DATABASE
Definition: pqcomm.h:133
char * pgtty
Definition: libpq-int.h:334

◆ pqEndcopy2()

int pqEndcopy2 ( PGconn conn)

Definition at line 1351 of file fe-protocol2.c.

References pg_conn::asyncStatus, PQExpBufferData::data, pg_conn::errorMessage, PQExpBufferData::len, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGRES_COMMAND_OK, PQclear(), pqFlush(), PQgetResult(), pqInternalNotice(), PQisBusy(), pqIsnonblocking, PQreset(), PQresetStart(), printfPQExpBuffer(), resetPQExpBuffer(), and pg_result::resultStatus.

Referenced by PQendcopy().

1352 {
1353  PGresult *result;
1354 
1355  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1356  conn->asyncStatus != PGASYNC_COPY_OUT)
1357  {
1359  libpq_gettext("no COPY in progress\n"));
1360  return 1;
1361  }
1362 
1363  /*
1364  * make sure no data is waiting to be sent, abort if we are non-blocking
1365  * and the flush fails
1366  */
1367  if (pqFlush(conn) && pqIsnonblocking(conn))
1368  return 1;
1369 
1370  /* non blocking connections may have to abort at this point. */
1371  if (pqIsnonblocking(conn) && PQisBusy(conn))
1372  return 1;
1373 
1374  /* Return to active duty */
1375  conn->asyncStatus = PGASYNC_BUSY;
1377 
1378  /* Wait for the completion response */
1379  result = PQgetResult(conn);
1380 
1381  /* Expecting a successful result */
1382  if (result && result->resultStatus == PGRES_COMMAND_OK)
1383  {
1384  PQclear(result);
1385  return 0;
1386  }
1387 
1388  /*
1389  * Trouble. For backwards-compatibility reasons, we issue the error
1390  * message as if it were a notice (would be nice to get rid of this
1391  * silliness, but too many apps probably don't handle errors from
1392  * PQendcopy reasonably). Note that the app can still obtain the error
1393  * status from the PGconn object.
1394  */
1395  if (conn->errorMessage.len > 0)
1396  {
1397  /* We have to strip the trailing newline ... pain in neck... */
1398  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1399 
1400  if (svLast == '\n')
1401  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1402  pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1403  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1404  }
1405 
1406  PQclear(result);
1407 
1408  /*
1409  * The worst case is that we've lost sync with the backend entirely due to
1410  * application screwup of the copy in/out protocol. To recover, reset the
1411  * connection (talk about using a sledgehammer...)
1412  */
1414  "lost synchronization with server, resetting connection");
1415 
1416  /*
1417  * Users doing non-blocking connections need to handle the reset
1418  * themselves, they'll need to check the connection status if we return an
1419  * error.
1420  */
1421  if (pqIsnonblocking(conn))
1422  PQresetStart(conn);
1423  else
1424  PQreset(conn);
1425 
1426  return 1;
1427 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int PQresetStart(PGconn *conn)
Definition: fe-connect.c:3693
#define pqIsnonblocking(conn)
Definition: libpq-int.h:754
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
#define libpq_gettext(x)
Definition: libpq-int.h:760
void PQreset(PGconn *conn)
Definition: fe-connect.c:3652

◆ pqFunctionCall2()

PGresult* pqFunctionCall2 ( PGconn conn,
Oid  fnid,
int *  result_buf,
int *  actual_result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)

Definition at line 1436 of file fe-protocol2.c.

References pg_conn::errorMessage, getNotify(), i, pg_conn::inCursor, pg_conn::inStart, PQArgBlock::integer, PQArgBlock::len, libpq_gettext, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pqFlush(), pqGetc(), pqGetErrorNotice2(), pqGetInt(), pqGetnchar(), pqHandleSendFailure(), PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqPuts(), pqReadData(), pqSaveErrorResult(), pqWait(), printfPQExpBuffer(), PQArgBlock::ptr, pg_conn::result, and status().

Referenced by PQfn().

1440 {
1441  bool needInput = false;
1443  char id;
1444  int i;
1445 
1446  /* PQfn already validated connection state */
1447 
1448  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1449  pqPuts(" ", conn) < 0 || /* dummy string */
1450  pqPutInt(fnid, 4, conn) != 0 || /* function id */
1451  pqPutInt(nargs, 4, conn) != 0) /* # of args */
1452  {
1453  pqHandleSendFailure(conn);
1454  return NULL;
1455  }
1456 
1457  for (i = 0; i < nargs; ++i)
1458  { /* len.int4 + contents */
1459  if (pqPutInt(args[i].len, 4, conn))
1460  {
1461  pqHandleSendFailure(conn);
1462  return NULL;
1463  }
1464 
1465  if (args[i].isint)
1466  {
1467  if (pqPutInt(args[i].u.integer, 4, conn))
1468  {
1469  pqHandleSendFailure(conn);
1470  return NULL;
1471  }
1472  }
1473  else
1474  {
1475  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1476  {
1477  pqHandleSendFailure(conn);
1478  return NULL;
1479  }
1480  }
1481  }
1482 
1483  if (pqPutMsgEnd(conn) < 0 ||
1484  pqFlush(conn))
1485  {
1486  pqHandleSendFailure(conn);
1487  return NULL;
1488  }
1489 
1490  for (;;)
1491  {
1492  if (needInput)
1493  {
1494  /* Wait for some data to arrive (or for the channel to close) */
1495  if (pqWait(true, false, conn) ||
1496  pqReadData(conn) < 0)
1497  break;
1498  }
1499 
1500  /*
1501  * Scan the message. If we run out of data, loop around to try again.
1502  */
1503  conn->inCursor = conn->inStart;
1504  needInput = true;
1505 
1506  if (pqGetc(&id, conn))
1507  continue;
1508 
1509  /*
1510  * We should see V or E response to the command, but might get N
1511  * and/or A notices first. We also need to swallow the final Z before
1512  * returning.
1513  */
1514  switch (id)
1515  {
1516  case 'V': /* function result */
1517  if (pqGetc(&id, conn))
1518  continue;
1519  if (id == 'G')
1520  {
1521  /* function returned nonempty value */
1522  if (pqGetInt(actual_result_len, 4, conn))
1523  continue;
1524  if (result_is_int)
1525  {
1526  if (pqGetInt(result_buf, 4, conn))
1527  continue;
1528  }
1529  else
1530  {
1531  if (pqGetnchar((char *) result_buf,
1532  *actual_result_len,
1533  conn))
1534  continue;
1535  }
1536  if (pqGetc(&id, conn)) /* get the last '0' */
1537  continue;
1538  }
1539  if (id == '0')
1540  {
1541  /* correctly finished function result message */
1542  status = PGRES_COMMAND_OK;
1543  }
1544  else
1545  {
1546  /* The backend violates the protocol. */
1548  libpq_gettext("protocol error: id=0x%x\n"),
1549  id);
1550  pqSaveErrorResult(conn);
1551  conn->inStart = conn->inCursor;
1552  return pqPrepareAsyncResult(conn);
1553  }
1554  break;
1555  case 'E': /* error return */
1556  if (pqGetErrorNotice2(conn, true))
1557  continue;
1558  status = PGRES_FATAL_ERROR;
1559  break;
1560  case 'A': /* notify message */
1561  /* handle notify and go back to processing return values */
1562  if (getNotify(conn))
1563  continue;
1564  break;
1565  case 'N': /* notice */
1566  /* handle notice and go back to processing return values */
1567  if (pqGetErrorNotice2(conn, false))
1568  continue;
1569  break;
1570  case 'Z': /* backend is ready for new query */
1571  /* consume the message and exit */
1572  conn->inStart = conn->inCursor;
1573  /* if we saved a result object (probably an error), use it */
1574  if (conn->result)
1575  return pqPrepareAsyncResult(conn);
1576  return PQmakeEmptyPGresult(conn, status);
1577  default:
1578  /* The backend violates the protocol. */
1580  libpq_gettext("protocol error: id=0x%x\n"),
1581  id);
1582  pqSaveErrorResult(conn);
1583  conn->inStart = conn->inCursor;
1584  return pqPrepareAsyncResult(conn);
1585  }
1586  /* Completed this message, keep going */
1587  conn->inStart = conn->inCursor;
1588  needInput = false;
1589  }
1590 
1591  /*
1592  * We fall out of the loop only upon failing to read data.
1593  * conn->errorMessage has been set by pqWait or pqReadData. We want to
1594  * append it to any already-received error message.
1595  */
1596  pqSaveErrorResult(conn);
1597  return pqPrepareAsyncResult(conn);
1598 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
void pqHandleSendFailure(PGconn *conn)
Definition: fe-exec.c:1633
int inStart
Definition: libpq-int.h:432
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
ExecStatusType
Definition: libpq-fe.h:82
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:195
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:777
PGresult * result
Definition: libpq-int.h:451
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:307
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqPuts(const char *s, PGconn *conn)
Definition: fe-misc.c:179
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
static int getNotify(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:246
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587
int i
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:433
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
int * ptr
Definition: libpq-fe.h:226
#define libpq_gettext(x)
Definition: libpq-int.h:760
int integer
Definition: libpq-fe.h:227
static int pqGetErrorNotice2(PGconn *conn, bool isError)
Definition: fe-protocol2.c:962

◆ pqGetCopyData2()

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

Definition at line 1168 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, malloc, PGASYNC_BUSY, pqReadData(), pqWait(), and printfPQExpBuffer().

Referenced by PQgetCopyData().

1169 {
1170  bool found;
1171  int msgLength;
1172 
1173  for (;;)
1174  {
1175  /*
1176  * Do we have a complete line of data?
1177  */
1178  conn->inCursor = conn->inStart;
1179  found = false;
1180  while (conn->inCursor < conn->inEnd)
1181  {
1182  char c = conn->inBuffer[conn->inCursor++];
1183 
1184  if (c == '\n')
1185  {
1186  found = true;
1187  break;
1188  }
1189  }
1190  if (!found)
1191  goto nodata;
1192  msgLength = conn->inCursor - conn->inStart;
1193 
1194  /*
1195  * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and
1196  * let caller read status with PQgetResult().
1197  */
1198  if (msgLength == 3 &&
1199  strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)
1200  {
1201  conn->inStart = conn->inCursor;
1202  conn->asyncStatus = PGASYNC_BUSY;
1203  return -1;
1204  }
1205 
1206  /*
1207  * Pass the line back to the caller.
1208  */
1209  *buffer = (char *) malloc(msgLength + 1);
1210  if (*buffer == NULL)
1211  {
1213  libpq_gettext("out of memory\n"));
1214  return -2;
1215  }
1216  memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
1217  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1218 
1219  /* Mark message consumed */
1220  conn->inStart = conn->inCursor;
1221 
1222  return msgLength;
1223 
1224 nodata:
1225  /* Don't block if async read requested */
1226  if (async)
1227  return 0;
1228  /* Need to load more data */
1229  if (pqWait(true, false, conn) ||
1230  pqReadData(conn) < 0)
1231  return -2;
1232  }
1233 }
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
char * c
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
char * inBuffer
Definition: libpq-int.h:430
PQExpBufferData errorMessage
Definition: libpq-int.h:494
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
int inCursor
Definition: libpq-int.h:433
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqGetErrorNotice2()

static int pqGetErrorNotice2 ( PGconn conn,
bool  isError 
)
static

Definition at line 962 of file fe-protocol2.c.

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, initPQExpBuffer(), PQExpBufferData::len, libpq_gettext, pg_result::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SEVERITY, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, PQclear(), pqClearAsyncResult(), PQExpBufferDataBroken, pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), PQTRANS_INERROR, PQTRANS_INTRANS, printfPQExpBuffer(), resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, termPQExpBuffer(), and pg_conn::xactStatus.

Referenced by pqFunctionCall2(), and pqParseInput2().

963 {
964  PGresult *res = NULL;
965  PQExpBufferData workBuf;
966  char *startp;
967  char *splitp;
968 
969  /*
970  * If this is an error message, pre-emptively clear any incomplete query
971  * result we may have. We'd just throw it away below anyway, and
972  * releasing it before collecting the error might avoid out-of-memory.
973  */
974  if (isError)
975  pqClearAsyncResult(conn);
976 
977  /*
978  * Since the message might be pretty long, we create a temporary
979  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
980  * for stuff that is expected to be short.
981  */
982  initPQExpBuffer(&workBuf);
983  if (pqGets(&workBuf, conn))
984  goto failure;
985 
986  /*
987  * Make a PGresult to hold the message. We temporarily lie about the
988  * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
989  * conn->errorMessage.
990  *
991  * NB: This allocation can fail, if you run out of memory. The rest of the
992  * function handles that gracefully, and we still try to set the error
993  * message as the connection's error message.
994  */
996  if (res)
997  {
999  res->errMsg = pqResultStrdup(res, workBuf.data);
1000  }
1001 
1002  /*
1003  * Break the message into fields. We can't do very much here, but we can
1004  * split the severity code off, and remove trailing newlines. Also, we use
1005  * the heuristic that the primary message extends only to the first
1006  * newline --- anything after that is detail message. (In some cases it'd
1007  * be better classed as hint, but we can hardly be expected to guess that
1008  * here.)
1009  */
1010  while (workBuf.len > 0 && workBuf.data[workBuf.len - 1] == '\n')
1011  workBuf.data[--workBuf.len] = '\0';
1012  splitp = strstr(workBuf.data, ": ");
1013  if (splitp)
1014  {
1015  /* what comes before the colon is severity */
1016  *splitp = '\0';
1017  pqSaveMessageField(res, PG_DIAG_SEVERITY, workBuf.data);
1018  startp = splitp + 3;
1019  }
1020  else
1021  {
1022  /* can't find a colon? oh well... */
1023  startp = workBuf.data;
1024  }
1025  splitp = strchr(startp, '\n');
1026  if (splitp)
1027  {
1028  /* what comes before the newline is primary message */
1029  *splitp++ = '\0';
1031  /* the rest is detail; strip any leading whitespace */
1032  while (*splitp && isspace((unsigned char) *splitp))
1033  splitp++;
1035  }
1036  else
1037  {
1038  /* single-line message, so all primary */
1040  }
1041 
1042  /*
1043  * Either save error as current async result, or just emit the notice.
1044  * Also, if it's an error and we were in a transaction block, assume the
1045  * server has now gone to error-in-transaction state.
1046  */
1047  if (isError)
1048  {
1049  pqClearAsyncResult(conn); /* redundant, but be safe */
1050  conn->result = res;
1052  if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
1054  else
1056  libpq_gettext("out of memory"));
1057  if (conn->xactStatus == PQTRANS_INTRANS)
1058  conn->xactStatus = PQTRANS_INERROR;
1059  }
1060  else
1061  {
1062  if (res)
1063  {
1064  if (res->noticeHooks.noticeRec != NULL)
1066  PQclear(res);
1067  }
1068  }
1069 
1070  termPQExpBuffer(&workBuf);
1071  return 0;
1072 
1073 failure:
1074  if (res)
1075  PQclear(res);
1076  termPQExpBuffer(&workBuf);
1077  return EOF;
1078 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:451
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:55
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition: fe-exec.c:942
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
#define libpq_gettext(x)
Definition: libpq-int.h:760
PGTransactionStatusType xactStatus
Definition: libpq-int.h:382
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:623
void * noticeRecArg
Definition: libpq-int.h:153

◆ pqGetline2()

int pqGetline2 ( PGconn conn,
char *  s,
int  maxlen 
)

Definition at line 1242 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::inBuffer, pg_conn::inEnd, pg_conn::inStart, PGASYNC_COPY_OUT, PGINVALID_SOCKET, pqReadData(), pqWait(), and pg_conn::sock.

Referenced by PQgetline().

1243 {
1244  int result = 1; /* return value if buffer overflows */
1245 
1246  if (conn->sock == PGINVALID_SOCKET ||
1247  conn->asyncStatus != PGASYNC_COPY_OUT)
1248  {
1249  *s = '\0';
1250  return EOF;
1251  }
1252 
1253  /*
1254  * Since this is a purely synchronous routine, we don't bother to maintain
1255  * conn->inCursor; there is no need to back up.
1256  */
1257  while (maxlen > 1)
1258  {
1259  if (conn->inStart < conn->inEnd)
1260  {
1261  char c = conn->inBuffer[conn->inStart++];
1262 
1263  if (c == '\n')
1264  {
1265  result = 0; /* success exit */
1266  break;
1267  }
1268  *s++ = c;
1269  maxlen--;
1270  }
1271  else
1272  {
1273  /* need to load more data */
1274  if (pqWait(true, false, conn) ||
1275  pqReadData(conn) < 0)
1276  {
1277  result = EOF;
1278  break;
1279  }
1280  }
1281  }
1282  *s = '\0';
1283 
1284  return result;
1285 }
int inEnd
Definition: libpq-int.h:434
int inStart
Definition: libpq-int.h:432
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
char * c
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
pgsocket sock
Definition: libpq-int.h:401
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:430

◆ pqGetlineAsync2()

int pqGetlineAsync2 ( PGconn conn,
char *  buffer,
int  bufsize 
)

Definition at line 1293 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

1294 {
1295  int avail;
1296 
1297  if (conn->asyncStatus != PGASYNC_COPY_OUT)
1298  return -1; /* we are not doing a copy... */
1299 
1300  /*
1301  * Move data from libpq's buffer to the caller's. We want to accept data
1302  * only in units of whole lines, not partial lines. This ensures that we
1303  * can recognize the terminator line "\\.\n". (Otherwise, if it happened
1304  * to cross a packet/buffer boundary, we might hand the first one or two
1305  * characters off to the caller, which we shouldn't.)
1306  */
1307 
1308  conn->inCursor = conn->inStart;
1309 
1310  avail = bufsize;
1311  while (avail > 0 && conn->inCursor < conn->inEnd)
1312  {
1313  char c = conn->inBuffer[conn->inCursor++];
1314 
1315  *buffer++ = c;
1316  --avail;
1317  if (c == '\n')
1318  {
1319  /* Got a complete line; mark the data removed from libpq */
1320  conn->inStart = conn->inCursor;
1321  /* Is it the endmarker line? */
1322  if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
1323  return -1;
1324  /* No, return the data line to the caller */
1325  return bufsize - avail;
1326  }
1327  }
1328 
1329  /*
1330  * We don't have a complete line. We'd prefer to leave it in libpq's
1331  * buffer until the rest arrives, but there is a special case: what if the
1332  * line is longer than the buffer the caller is offering us? In that case
1333  * we'd better hand over a partial line, else we'd get into an infinite
1334  * loop. Do this in a way that ensures we can't misrecognize a terminator
1335  * line later: leave last 3 characters in libpq buffer.
1336  */
1337  if (avail == 0 && bufsize > 3)
1338  {
1339  conn->inStart = conn->inCursor - 3;
1340  return bufsize - 3;
1341  }
1342  return 0;
1343 }
int inEnd
Definition: libpq-int.h:434
int inStart
Definition: libpq-int.h:432
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
char * c
char * inBuffer
Definition: libpq-int.h:430
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
int inCursor
Definition: libpq-int.h:433

◆ pqParseInput2()

void pqParseInput2 ( PGconn conn)

Definition at line 410 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, checkXactStatus(), pg_result::cmdStatus, CMDSTATUS_LEN, PQExpBufferData::data, pg_conn::errorMessage, getAnotherTuple(), getNotify(), getRowDescriptions(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, PGRES_COMMAND_OK, PGRES_EMPTY_QUERY, pqGetc(), pqGetErrorNotice2(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), pqSaveErrorResult(), printfPQExpBuffer(), pg_conn::result, strlcpy(), and pg_conn::workBuffer.

Referenced by parseInput().

411 {
412  char id;
413 
414  /*
415  * Loop to parse successive complete messages available in the buffer.
416  */
417  for (;;)
418  {
419  /*
420  * Quit if in COPY_OUT state: we expect raw data from the server until
421  * PQendcopy is called. Don't try to parse it according to the normal
422  * protocol. (This is bogus. The data lines ought to be part of the
423  * protocol and have identifying leading characters.)
424  */
425  if (conn->asyncStatus == PGASYNC_COPY_OUT)
426  return;
427 
428  /*
429  * OK to try to read a message type code.
430  */
431  conn->inCursor = conn->inStart;
432  if (pqGetc(&id, conn))
433  return;
434 
435  /*
436  * NOTIFY and NOTICE messages can happen in any state besides COPY
437  * OUT; always process them right away.
438  *
439  * Most other messages should only be processed while in BUSY state.
440  * (In particular, in READY state we hold off further parsing until
441  * the application collects the current PGresult.)
442  *
443  * However, if the state is IDLE then we got trouble; we need to deal
444  * with the unexpected message somehow.
445  */
446  if (id == 'A')
447  {
448  if (getNotify(conn))
449  return;
450  }
451  else if (id == 'N')
452  {
453  if (pqGetErrorNotice2(conn, false))
454  return;
455  }
456  else if (conn->asyncStatus != PGASYNC_BUSY)
457  {
458  /* If not IDLE state, just wait ... */
459  if (conn->asyncStatus != PGASYNC_IDLE)
460  return;
461 
462  /*
463  * Unexpected message in IDLE state; need to recover somehow.
464  * ERROR messages are displayed using the notice processor;
465  * anything else is just dropped on the floor after displaying a
466  * suitable warning notice. (An ERROR is very possibly the
467  * backend telling us why it is about to close the connection, so
468  * we don't want to just discard it...)
469  */
470  if (id == 'E')
471  {
472  if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
473  return;
474  }
475  else
476  {
478  "message type 0x%02x arrived from server while idle",
479  id);
480  /* Discard the unexpected message; good idea?? */
481  conn->inStart = conn->inEnd;
482  break;
483  }
484  }
485  else
486  {
487  /*
488  * In BUSY state, we can process everything.
489  */
490  switch (id)
491  {
492  case 'C': /* command complete */
493  if (pqGets(&conn->workBuffer, conn))
494  return;
495  if (conn->result == NULL)
496  {
497  conn->result = PQmakeEmptyPGresult(conn,
499  if (!conn->result)
500  {
502  libpq_gettext("out of memory"));
503  pqSaveErrorResult(conn);
504  }
505  }
506  if (conn->result)
507  {
508  strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
509  CMDSTATUS_LEN);
510  }
511  checkXactStatus(conn, conn->workBuffer.data);
512  conn->asyncStatus = PGASYNC_READY;
513  break;
514  case 'E': /* error return */
515  if (pqGetErrorNotice2(conn, true))
516  return;
517  conn->asyncStatus = PGASYNC_READY;
518  break;
519  case 'Z': /* backend is ready for new query */
520  conn->asyncStatus = PGASYNC_IDLE;
521  break;
522  case 'I': /* empty query */
523  /* read and throw away the closing '\0' */
524  if (pqGetc(&id, conn))
525  return;
526  if (id != '\0')
528  "unexpected character %c following empty query response (\"I\" message)",
529  id);
530  if (conn->result == NULL)
531  {
532  conn->result = PQmakeEmptyPGresult(conn,
534  if (!conn->result)
535  {
537  libpq_gettext("out of memory"));
538  pqSaveErrorResult(conn);
539  }
540  }
541  conn->asyncStatus = PGASYNC_READY;
542  break;
543  case 'K': /* secret key data from the backend */
544 
545  /*
546  * This is expected only during backend startup, but it's
547  * just as easy to handle it as part of the main loop.
548  * Save the data and continue processing.
549  */
550  if (pqGetInt(&(conn->be_pid), 4, conn))
551  return;
552  if (pqGetInt(&(conn->be_key), 4, conn))
553  return;
554  break;
555  case 'P': /* synchronous (normal) portal */
556  if (pqGets(&conn->workBuffer, conn))
557  return;
558  /* We pretty much ignore this message type... */
559  break;
560  case 'T': /* row descriptions (start of query results) */
561  if (conn->result == NULL)
562  {
563  /* First 'T' in a query sequence */
564  if (getRowDescriptions(conn))
565  return;
566  /* getRowDescriptions() moves inStart itself */
567  continue;
568  }
569  else
570  {
571  /*
572  * A new 'T' message is treated as the start of
573  * another PGresult. (It is not clear that this is
574  * really possible with the current backend.) We stop
575  * parsing until the application accepts the current
576  * result.
577  */
578  conn->asyncStatus = PGASYNC_READY;
579  return;
580  }
581  break;
582  case 'D': /* ASCII data tuple */
583  if (conn->result != NULL)
584  {
585  /* Read another tuple of a normal query response */
586  if (getAnotherTuple(conn, false))
587  return;
588  /* getAnotherTuple() moves inStart itself */
589  continue;
590  }
591  else
592  {
594  "server sent data (\"D\" message) without prior row description (\"T\" message)");
595  /* Discard the unexpected message; good idea?? */
596  conn->inStart = conn->inEnd;
597  return;
598  }
599  break;
600  case 'B': /* Binary data tuple */
601  if (conn->result != NULL)
602  {
603  /* Read another tuple of a normal query response */
604  if (getAnotherTuple(conn, true))
605  return;
606  /* getAnotherTuple() moves inStart itself */
607  continue;
608  }
609  else
610  {
612  "server sent binary data (\"B\" message) without prior row description (\"T\" message)");
613  /* Discard the unexpected message; good idea?? */
614  conn->inStart = conn->inEnd;
615  return;
616  }
617  break;
618  case 'G': /* Start Copy In */
620  break;
621  case 'H': /* Start Copy Out */
623  break;
624 
625  /*
626  * Don't need to process CopyBothResponse here because it
627  * never arrives from the server during protocol 2.0.
628  */
629  default:
632  "unexpected response from server; first received character was \"%c\"\n"),
633  id);
634  /* build an error result holding the error message */
635  pqSaveErrorResult(conn);
636  /* Discard the unexpected message; good idea?? */
637  conn->inStart = conn->inEnd;
638  conn->asyncStatus = PGASYNC_READY;
639  return;
640  } /* switch on protocol character */
641  }
642  /* Successfully consumed this message */
643  conn->inStart = conn->inCursor;
644  }
645 }
static void checkXactStatus(PGconn *conn, const char *cmdTag)
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
static int getRowDescriptions(PGconn *conn)
Definition: fe-protocol2.c:658
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:497
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:451
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
static int getAnotherTuple(PGconn *conn, bool binary)
Definition: fe-protocol2.c:789
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
static int getNotify(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:178
int be_key
Definition: libpq-int.h:421
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:433
int be_pid
Definition: libpq-int.h:420
#define libpq_gettext(x)
Definition: libpq-int.h:760
static int pqGetErrorNotice2(PGconn *conn, bool isError)
Definition: fe-protocol2.c:962

◆ pqSetenvPoll()

PostgresPollingStatusType pqSetenvPoll ( PGconn conn)

Definition at line 49 of file fe-protocol2.c.

References pg_conn::client_encoding_initial, CONNECTION_BAD, PQEnvironmentOption::envName, pg_conn::errorMessage, libpq_gettext, pg_conn::next_eo, pg_strcasecmp(), PQEnvironmentOption::pgName, PGRES_COMMAND_OK, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_TUPLES_OK, PQclear(), PQgetResult(), PQgetvalue(), PQisBusy(), PQntuples(), pqReadData(), PQresultStatus(), pqSaveParameterStatus(), PQsendQuery(), printfPQExpBuffer(), pg_conn::setenv_state, SETENV_STATE_CLIENT_ENCODING_SEND, SETENV_STATE_CLIENT_ENCODING_WAIT, SETENV_STATE_IDLE, SETENV_STATE_OPTION_SEND, SETENV_STATE_OPTION_WAIT, SETENV_STATE_QUERY1_SEND, SETENV_STATE_QUERY1_WAIT, SETENV_STATE_QUERY2_SEND, SETENV_STATE_QUERY2_WAIT, pg_conn::status, pg_conn::sversion, and val.

Referenced by PQconnectPoll().

50 {
51  PGresult *res;
52 
53  if (conn == NULL || conn->status == CONNECTION_BAD)
54  return PGRES_POLLING_FAILED;
55 
56  /* Check whether there are any data for us */
57  switch (conn->setenv_state)
58  {
59  /* These are reading states */
64  {
65  /* Load waiting data */
66  int n = pqReadData(conn);
67 
68  if (n < 0)
69  goto error_return;
70  if (n == 0)
71  return PGRES_POLLING_READING;
72 
73  break;
74  }
75 
76  /* These are writing states, so we just proceed. */
81  break;
82 
83  /* Should we raise an error if called when not active? */
84  case SETENV_STATE_IDLE:
85  return PGRES_POLLING_OK;
86 
87  default:
90  "invalid setenv state %c, "
91  "probably indicative of memory corruption\n"
92  ),
93  conn->setenv_state);
94  goto error_return;
95  }
96 
97  /* We will loop here until there is nothing left to do in this call. */
98  for (;;)
99  {
100  switch (conn->setenv_state)
101  {
102  /*
103  * The _CLIENT_ENCODING_SEND code is slightly different from
104  * _OPTION_SEND below (e.g., no getenv() call), which is why a
105  * different state is used.
106  */
108  {
109  char setQuery[100]; /* note length limit in
110  * sprintf below */
111  const char *val = conn->client_encoding_initial;
112 
113  if (val)
114  {
115  if (pg_strcasecmp(val, "default") == 0)
116  sprintf(setQuery, "SET client_encoding = DEFAULT");
117  else
118  sprintf(setQuery, "SET client_encoding = '%.60s'",
119  val);
120 #ifdef CONNECTDEBUG
121  fprintf(stderr,
122  "Sending client_encoding with %s\n",
123  setQuery);
124 #endif
125  if (!PQsendQuery(conn, setQuery))
126  goto error_return;
127 
129  }
130  else
132  break;
133  }
134 
136  {
137  /*
138  * Send SET commands for stuff directed by Environment
139  * Options. Note: we assume that SET commands won't start
140  * transaction blocks, even in a 7.3 server with
141  * autocommit off.
142  */
143  char setQuery[100]; /* note length limit in
144  * sprintf below */
145 
146  if (conn->next_eo->envName)
147  {
148  const char *val;
149 
150  if ((val = getenv(conn->next_eo->envName)))
151  {
152  if (pg_strcasecmp(val, "default") == 0)
153  sprintf(setQuery, "SET %s = DEFAULT",
154  conn->next_eo->pgName);
155  else
156  sprintf(setQuery, "SET %s = '%.60s'",
157  conn->next_eo->pgName, val);
158 #ifdef CONNECTDEBUG
159  fprintf(stderr,
160  "Use environment variable %s to send %s\n",
161  conn->next_eo->envName, setQuery);
162 #endif
163  if (!PQsendQuery(conn, setQuery))
164  goto error_return;
165 
167  }
168  else
169  conn->next_eo++;
170  }
171  else
172  {
173  /* No more options to send, so move on to querying */
175  }
176  break;
177  }
178 
180  {
181  if (PQisBusy(conn))
182  return PGRES_POLLING_READING;
183 
184  res = PQgetResult(conn);
185 
186  if (res)
187  {
188  if (PQresultStatus(res) != PGRES_COMMAND_OK)
189  {
190  PQclear(res);
191  goto error_return;
192  }
193  PQclear(res);
194  /* Keep reading until PQgetResult returns NULL */
195  }
196  else
197  {
198  /* Query finished, so send the next option */
200  }
201  break;
202  }
203 
205  {
206  if (PQisBusy(conn))
207  return PGRES_POLLING_READING;
208 
209  res = PQgetResult(conn);
210 
211  if (res)
212  {
213  if (PQresultStatus(res) != PGRES_COMMAND_OK)
214  {
215  PQclear(res);
216  goto error_return;
217  }
218  PQclear(res);
219  /* Keep reading until PQgetResult returns NULL */
220  }
221  else
222  {
223  /* Query finished, so send the next option */
224  conn->next_eo++;
226  }
227  break;
228  }
229 
231  {
232  /*
233  * Issue query to get information we need. Here we must
234  * use begin/commit in case autocommit is off by default
235  * in a 7.3 server.
236  *
237  * Note: version() exists in all protocol-2.0-supporting
238  * backends. In 7.3 it would be safer to write
239  * pg_catalog.version(), but we can't do that without
240  * causing problems on older versions.
241  */
242  if (!PQsendQuery(conn, "begin; select version(); end"))
243  goto error_return;
244 
246  return PGRES_POLLING_READING;
247  }
248 
250  {
251  if (PQisBusy(conn))
252  return PGRES_POLLING_READING;
253 
254  res = PQgetResult(conn);
255 
256  if (res)
257  {
258  char *val;
259 
260  if (PQresultStatus(res) == PGRES_COMMAND_OK)
261  {
262  /* ignore begin/commit command results */
263  PQclear(res);
264  continue;
265  }
266 
267  if (PQresultStatus(res) != PGRES_TUPLES_OK ||
268  PQntuples(res) != 1)
269  {
270  PQclear(res);
271  goto error_return;
272  }
273 
274  /*
275  * Extract server version and save as if
276  * ParameterStatus
277  */
278  val = PQgetvalue(res, 0, 0);
279  if (val && strncmp(val, "PostgreSQL ", 11) == 0)
280  {
281  char *ptr;
282 
283  /* strip off PostgreSQL part */
284  val += 11;
285 
286  /*
287  * strip off platform part (scribbles on result,
288  * naughty naughty)
289  */
290  ptr = strchr(val, ' ');
291  if (ptr)
292  *ptr = '\0';
293 
294  pqSaveParameterStatus(conn, "server_version",
295  val);
296  }
297 
298  PQclear(res);
299  /* Keep reading until PQgetResult returns NULL */
300  }
301  else
302  {
303  /* Query finished, move to next */
305  }
306  break;
307  }
308 
310  {
311  const char *query;
312 
313  /*
314  * pg_client_encoding does not exist in pre-7.2 servers.
315  * So we need to be prepared for an error here. Do *not*
316  * start a transaction block, except in 7.3 servers where
317  * we need to prevent autocommit-off from starting a
318  * transaction anyway.
319  */
320  if (conn->sversion >= 70300 &&
321  conn->sversion < 70400)
322  query = "begin; select pg_catalog.pg_client_encoding(); end";
323  else
324  query = "select pg_client_encoding()";
325  if (!PQsendQuery(conn, query))
326  goto error_return;
327 
329  return PGRES_POLLING_READING;
330  }
331 
333  {
334  if (PQisBusy(conn))
335  return PGRES_POLLING_READING;
336 
337  res = PQgetResult(conn);
338 
339  if (res)
340  {
341  const char *val;
342 
343  if (PQresultStatus(res) == PGRES_COMMAND_OK)
344  {
345  /* ignore begin/commit command results */
346  PQclear(res);
347  continue;
348  }
349 
350  if (PQresultStatus(res) == PGRES_TUPLES_OK &&
351  PQntuples(res) == 1)
352  {
353  /* Extract client encoding and save it */
354  val = PQgetvalue(res, 0, 0);
355  if (val && *val) /* null should not happen, but */
356  pqSaveParameterStatus(conn, "client_encoding",
357  val);
358  }
359  else
360  {
361  /*
362  * Error: presumably function not available, so
363  * use PGCLIENTENCODING or SQL_ASCII as the
364  * fallback.
365  */
366  val = getenv("PGCLIENTENCODING");
367  if (val && *val)
368  pqSaveParameterStatus(conn, "client_encoding",
369  val);
370  else
371  pqSaveParameterStatus(conn, "client_encoding",
372  "SQL_ASCII");
373  }
374 
375  PQclear(res);
376  /* Keep reading until PQgetResult returns NULL */
377  }
378  else
379  {
380  /* Query finished, so we're done */
382  return PGRES_POLLING_OK;
383  }
384  break;
385  }
386 
387  default:
389  libpq_gettext("invalid state %c, "
390  "probably indicative of memory corruption\n"),
391  conn->setenv_state);
392  goto error_return;
393  }
394  }
395 
396  /* Unreachable */
397 
398 error_return:
400  return PGRES_POLLING_FAILED;
401 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
const char * envName
Definition: libpq-int.h:251
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
void pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
Definition: fe-exec.c:963
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
char * client_encoding_initial
Definition: libpq-int.h:337
int sversion
Definition: libpq-int.h:406
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1183
PGSetenvStatusType setenv_state
Definition: libpq-int.h:415
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
const PQEnvironmentOption * next_eo
Definition: libpq-int.h:416
const char * pgName
Definition: libpq-int.h:251
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
ConnStatusType status
Definition: libpq-int.h:380
long val
Definition: informix.c:689
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
#define libpq_gettext(x)
Definition: libpq-int.h:760