PostgreSQL Source Code  git master
fe-protocol2.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "port/pg_bswap.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 1087 of file fe-protocol2.c.

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

Referenced by pqParseInput2().

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

◆ getAnotherTuple()

static int getAnotherTuple ( PGconn conn,
bool  binary 
)
static

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

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

◆ getNotify()

static int getNotify ( PGconn conn)
static

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

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

◆ getRowDescriptions()

static int getRowDescriptions ( PGconn conn)
static

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

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

◆ pqBuildStartupPacket2()

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

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

1591 {
1592  StartupPacket *startpacket;
1593 
1594  *packetlen = sizeof(StartupPacket);
1595  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1596  if (!startpacket)
1597  return NULL;
1598 
1599  MemSet(startpacket, 0, sizeof(StartupPacket));
1600 
1601  startpacket->protoVersion = pg_hton32(conn->pversion);
1602 
1603  /* strncpy is safe here: postmaster will handle full fields correctly */
1604  strncpy(startpacket->user, conn->pguser, SM_USER);
1605  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1606  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1607 
1608  if (conn->pgoptions)
1609  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1610 
1611  return (char *) startpacket;
1612 }
char tty[SM_TTY]
Definition: pqcomm.h:149
struct StartupPacket StartupPacket
char * dbName
Definition: libpq-int.h:345
#define MemSet(start, val, len)
Definition: c.h:971
#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:347
char database[SM_DATABASE]
Definition: pqcomm.h:144
char * pgoptions
Definition: libpq-int.h:342
ProtocolVersion pversion
Definition: libpq-int.h:414
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:337

◆ pqEndcopy2()

int pqEndcopy2 ( PGconn conn)

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

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

◆ 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 1430 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(), PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqPuts(), pqReadData(), pqSaveErrorResult(), pqWait(), printfPQExpBuffer(), PQArgBlock::ptr, pg_conn::result, and status().

Referenced by PQfn().

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

◆ pqGetCopyData2()

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

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

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

◆ pqGetErrorNotice2()

static int pqGetErrorNotice2 ( PGconn conn,
bool  isError 
)
static

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

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

◆ pqGetline2()

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

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

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

◆ pqGetlineAsync2()

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

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

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

◆ pqParseInput2()

void pqParseInput2 ( PGconn conn)

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

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

◆ pqSetenvPoll()

PostgresPollingStatusType pqSetenvPoll ( PGconn conn)

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

References pg_conn::client_encoding_initial, CONNECTION_BAD, PQEnvironmentOption::envName, pg_conn::errorMessage, fprintf, 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, sprintf, pg_conn::status, pg_conn::sversion, and val.

Referenced by PQconnectPoll().

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