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 1085 of file fe-protocol2.c.

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

Referenced by pqParseInput2().

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

◆ 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:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
#define BITS_PER_BYTE
int rowBufLen
Definition: libpq-int.h:447
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:450
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
PGdataValue * rowBuf
Definition: libpq-int.h:446
int binary
Definition: libpq-int.h:179
int numAttributes
Definition: libpq-int.h:170
char * inBuffer
Definition: libpq-int.h:429
PQExpBufferData errorMessage
Definition: libpq-int.h:493
#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:432
#define libpq_gettext(x)
Definition: libpq-int.h:685

◆ getNotify()

static int getNotify ( PGconn conn)
static

Definition at line 1113 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().

1114 {
1115  int be_pid;
1116  int nmlen;
1117  PGnotify *newNotify;
1118 
1119  if (pqGetInt(&be_pid, 4, conn))
1120  return EOF;
1121  if (pqGets(&conn->workBuffer, conn))
1122  return EOF;
1123 
1124  /*
1125  * Store the relation name right after the PQnotify structure so it can
1126  * all be freed at once. We don't use NAMEDATALEN because we don't want
1127  * to tie this interface to a specific server name length.
1128  */
1129  nmlen = strlen(conn->workBuffer.data);
1130  newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + 1);
1131  if (newNotify)
1132  {
1133  newNotify->relname = (char *) newNotify + sizeof(PGnotify);
1134  strcpy(newNotify->relname, conn->workBuffer.data);
1135  /* fake up an empty-string extra field */
1136  newNotify->extra = newNotify->relname + nmlen;
1137  newNotify->be_pid = be_pid;
1138  newNotify->next = NULL;
1139  if (conn->notifyTail)
1140  conn->notifyTail->next = newNotify;
1141  else
1142  conn->notifyHead = newNotify;
1143  conn->notifyTail = newNotify;
1144  }
1145 
1146  return 0;
1147 }
char * extra
Definition: libpq-fe.h:165
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:496
PGnotify * notifyHead
Definition: libpq-int.h:391
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:392

◆ 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, 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:283
int inEnd
Definition: libpq-int.h:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:496
#define MemSet(start, val, len)
Definition: c.h:853
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:450
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
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:493
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:432
#define libpq_gettext(x)
Definition: libpq-int.h:685
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 1599 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().

1601 {
1602  StartupPacket *startpacket;
1603 
1604  *packetlen = sizeof(StartupPacket);
1605  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1606  if (!startpacket)
1607  return NULL;
1608 
1609  MemSet(startpacket, 0, sizeof(StartupPacket));
1610 
1611  startpacket->protoVersion = pg_hton32(conn->pversion);
1612 
1613  /* strncpy is safe here: postmaster will handle full fields correctly */
1614  strncpy(startpacket->user, conn->pguser, SM_USER);
1615  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1616  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1617 
1618  if (conn->pgoptions)
1619  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1620 
1621  return (char *) startpacket;
1622 }
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:853
#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:404
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 1343 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().

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

◆ 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 1428 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().

1432 {
1433  bool needInput = false;
1435  char id;
1436  int i;
1437 
1438  /* PQfn already validated connection state */
1439 
1440  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1441  pqPuts(" ", conn) < 0 || /* dummy string */
1442  pqPutInt(fnid, 4, conn) != 0 || /* function id */
1443  pqPutInt(nargs, 4, conn) != 0) /* # of args */
1444  {
1445  pqHandleSendFailure(conn);
1446  return NULL;
1447  }
1448 
1449  for (i = 0; i < nargs; ++i)
1450  { /* len.int4 + contents */
1451  if (pqPutInt(args[i].len, 4, conn))
1452  {
1453  pqHandleSendFailure(conn);
1454  return NULL;
1455  }
1456 
1457  if (args[i].isint)
1458  {
1459  if (pqPutInt(args[i].u.integer, 4, conn))
1460  {
1461  pqHandleSendFailure(conn);
1462  return NULL;
1463  }
1464  }
1465  else
1466  {
1467  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1468  {
1469  pqHandleSendFailure(conn);
1470  return NULL;
1471  }
1472  }
1473  }
1474 
1475  if (pqPutMsgEnd(conn) < 0 ||
1476  pqFlush(conn))
1477  {
1478  pqHandleSendFailure(conn);
1479  return NULL;
1480  }
1481 
1482  for (;;)
1483  {
1484  if (needInput)
1485  {
1486  /* Wait for some data to arrive (or for the channel to close) */
1487  if (pqWait(true, false, conn) ||
1488  pqReadData(conn) < 0)
1489  break;
1490  }
1491 
1492  /*
1493  * Scan the message. If we run out of data, loop around to try again.
1494  */
1495  conn->inCursor = conn->inStart;
1496  needInput = true;
1497 
1498  if (pqGetc(&id, conn))
1499  continue;
1500 
1501  /*
1502  * We should see V or E response to the command, but might get N
1503  * and/or A notices first. We also need to swallow the final Z before
1504  * returning.
1505  */
1506  switch (id)
1507  {
1508  case 'V': /* function result */
1509  if (pqGetc(&id, conn))
1510  continue;
1511  if (id == 'G')
1512  {
1513  /* function returned nonempty value */
1514  if (pqGetInt(actual_result_len, 4, conn))
1515  continue;
1516  if (result_is_int)
1517  {
1518  if (pqGetInt(result_buf, 4, conn))
1519  continue;
1520  }
1521  else
1522  {
1523  if (pqGetnchar((char *) result_buf,
1524  *actual_result_len,
1525  conn))
1526  continue;
1527  }
1528  if (pqGetc(&id, conn)) /* get the last '0' */
1529  continue;
1530  }
1531  if (id == '0')
1532  {
1533  /* correctly finished function result message */
1534  status = PGRES_COMMAND_OK;
1535  }
1536  else
1537  {
1538  /* The backend violates the protocol. */
1540  libpq_gettext("protocol error: id=0x%x\n"),
1541  id);
1542  pqSaveErrorResult(conn);
1543  conn->inStart = conn->inCursor;
1544  return pqPrepareAsyncResult(conn);
1545  }
1546  break;
1547  case 'E': /* error return */
1548  if (pqGetErrorNotice2(conn, true))
1549  continue;
1550  status = PGRES_FATAL_ERROR;
1551  break;
1552  case 'A': /* notify message */
1553  /* handle notify and go back to processing return values */
1554  if (getNotify(conn))
1555  continue;
1556  break;
1557  case 'N': /* notice */
1558  /* handle notice and go back to processing return values */
1559  if (pqGetErrorNotice2(conn, false))
1560  continue;
1561  break;
1562  case 'Z': /* backend is ready for new query */
1563  /* consume the message and exit */
1564  conn->inStart = conn->inCursor;
1565  /* if we saved a result object (probably an error), use it */
1566  if (conn->result)
1567  return pqPrepareAsyncResult(conn);
1568  return PQmakeEmptyPGresult(conn, status);
1569  default:
1570  /* The backend violates the protocol. */
1572  libpq_gettext("protocol error: id=0x%x\n"),
1573  id);
1574  pqSaveErrorResult(conn);
1575  conn->inStart = conn->inCursor;
1576  return pqPrepareAsyncResult(conn);
1577  }
1578  /* Completed this message, keep going */
1579  conn->inStart = conn->inCursor;
1580  needInput = false;
1581  }
1582 
1583  /*
1584  * We fall out of the loop only upon failing to read data.
1585  * conn->errorMessage has been set by pqWait or pqReadData. We want to
1586  * append it to any already-received error message.
1587  */
1588  pqSaveErrorResult(conn);
1589  return pqPrepareAsyncResult(conn);
1590 }
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:431
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:450
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:493
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:432
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:685
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 1160 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().

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

◆ 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  * Since the message might be pretty long, we create a temporary
971  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
972  * for stuff that is expected to be short.
973  */
974  initPQExpBuffer(&workBuf);
975  if (pqGets(&workBuf, conn))
976  goto failure;
977 
978  /*
979  * Make a PGresult to hold the message. We temporarily lie about the
980  * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
981  * conn->errorMessage.
982  *
983  * NB: This allocation can fail, if you run out of memory. The rest of the
984  * function handles that gracefully, and we still try to set the error
985  * message as the connection's error message.
986  */
988  if (res)
989  {
991  res->errMsg = pqResultStrdup(res, workBuf.data);
992  }
993 
994  /*
995  * Break the message into fields. We can't do very much here, but we can
996  * split the severity code off, and remove trailing newlines. Also, we use
997  * the heuristic that the primary message extends only to the first
998  * newline --- anything after that is detail message. (In some cases it'd
999  * be better classed as hint, but we can hardly be expected to guess that
1000  * here.)
1001  */
1002  while (workBuf.len > 0 && workBuf.data[workBuf.len - 1] == '\n')
1003  workBuf.data[--workBuf.len] = '\0';
1004  splitp = strstr(workBuf.data, ": ");
1005  if (splitp)
1006  {
1007  /* what comes before the colon is severity */
1008  *splitp = '\0';
1009  pqSaveMessageField(res, PG_DIAG_SEVERITY, workBuf.data);
1010  startp = splitp + 3;
1011  }
1012  else
1013  {
1014  /* can't find a colon? oh well... */
1015  startp = workBuf.data;
1016  }
1017  splitp = strchr(startp, '\n');
1018  if (splitp)
1019  {
1020  /* what comes before the newline is primary message */
1021  *splitp++ = '\0';
1023  /* the rest is detail; strip any leading whitespace */
1024  while (*splitp && isspace((unsigned char) *splitp))
1025  splitp++;
1027  }
1028  else
1029  {
1030  /* single-line message, so all primary */
1032  }
1033 
1034  /*
1035  * Either save error as current async result, or just emit the notice.
1036  * Also, if it's an error and we were in a transaction block, assume the
1037  * server has now gone to error-in-transaction state.
1038  */
1039  if (isError)
1040  {
1041  pqClearAsyncResult(conn);
1042  conn->result = res;
1044  if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
1046  else
1048  libpq_gettext("out of memory"));
1049  if (conn->xactStatus == PQTRANS_INTRANS)
1050  conn->xactStatus = PQTRANS_INERROR;
1051  }
1052  else
1053  {
1054  if (res)
1055  {
1056  if (res->noticeHooks.noticeRec != NULL)
1058  PQclear(res);
1059  }
1060  }
1061 
1062  termPQExpBuffer(&workBuf);
1063  return 0;
1064 
1065 failure:
1066  if (res)
1067  PQclear(res);
1068  termPQExpBuffer(&workBuf);
1069  return EOF;
1070 }
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:450
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:493
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:685
PGTransactionStatusType xactStatus
Definition: libpq-int.h:381
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 1234 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().

1235 {
1236  int result = 1; /* return value if buffer overflows */
1237 
1238  if (conn->sock == PGINVALID_SOCKET ||
1239  conn->asyncStatus != PGASYNC_COPY_OUT)
1240  {
1241  *s = '\0';
1242  return EOF;
1243  }
1244 
1245  /*
1246  * Since this is a purely synchronous routine, we don't bother to maintain
1247  * conn->inCursor; there is no need to back up.
1248  */
1249  while (maxlen > 1)
1250  {
1251  if (conn->inStart < conn->inEnd)
1252  {
1253  char c = conn->inBuffer[conn->inStart++];
1254 
1255  if (c == '\n')
1256  {
1257  result = 0; /* success exit */
1258  break;
1259  }
1260  *s++ = c;
1261  maxlen--;
1262  }
1263  else
1264  {
1265  /* need to load more data */
1266  if (pqWait(true, false, conn) ||
1267  pqReadData(conn) < 0)
1268  {
1269  result = EOF;
1270  break;
1271  }
1272  }
1273  }
1274  *s = '\0';
1275 
1276  return result;
1277 }
int inEnd
Definition: libpq-int.h:433
int inStart
Definition: libpq-int.h:431
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
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:400
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:429

◆ pqGetlineAsync2()

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

Definition at line 1285 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().

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

◆ 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:433
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:431
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:496
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:450
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:380
PGNoticeHooks noticeHooks
Definition: libpq-int.h:371
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:493
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:420
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:432
int be_pid
Definition: libpq-int.h:419
#define libpq_gettext(x)
Definition: libpq-int.h:685
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:405
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1183
PGSetenvStatusType setenv_state
Definition: libpq-int.h:414
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
const PQEnvironmentOption * next_eo
Definition: libpq-int.h:415
const char * pgName
Definition: libpq-int.h:251
PQExpBufferData errorMessage
Definition: libpq-int.h:493
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
ConnStatusType status
Definition: libpq-int.h:379
long val
Definition: informix.c:689
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
#define libpq_gettext(x)
Definition: libpq-int.h:685