PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
fe-protocol2.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.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

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

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

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

Referenced by pqParseInput2().

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

Definition at line 790 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, NULL_LEN, pg_result::numAttributes, PGASYNC_READY, PGRES_FATAL_ERROR, pqClearAsyncResult(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), pqRowProcessor(), pqSkipnchar(), printfPQExpBuffer(), realloc, pg_conn::result, result, pg_conn::rowBuf, pg_conn::rowBufLen, and pgDataValue::value.

Referenced by pqParseInput2().

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

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

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

Referenced by pqFunctionCall2(), and pqParseInput2().

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

Definition at line 659 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, NULL, pg_result::numAttributes, PGASYNC_READY, PGRES_FATAL_ERROR, PGRES_TUPLES_OK, PQclear(), pqClearAsyncResult(), pqGetInt(), pqGets(), PQmakeEmptyPGresult(), pqResultAlloc(), pqResultStrdup(), printfPQExpBuffer(), pg_conn::result, result, pgresAttDesc::tableid, TRUE, pgresAttDesc::typid, pgresAttDesc::typlen, and pg_conn::workBuffer.

Referenced by pqParseInput2().

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

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

References StartupPacket::database, pg_conn::dbName, malloc, MemSet, NULL, StartupPacket::options, 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().

1602 {
1603  StartupPacket *startpacket;
1604 
1605  *packetlen = sizeof(StartupPacket);
1606  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1607  if (!startpacket)
1608  return NULL;
1609 
1610  MemSet(startpacket, 0, sizeof(StartupPacket));
1611 
1612  startpacket->protoVersion = htonl(conn->pversion);
1613 
1614  /* strncpy is safe here: postmaster will handle full fields correctly */
1615  strncpy(startpacket->user, conn->pguser, SM_USER);
1616  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1617  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1618 
1619  if (conn->pgoptions)
1620  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1621 
1622  return (char *) startpacket;
1623 }
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:857
#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
char * pguser
Definition: libpq-int.h:343
char database[SM_DATABASE]
Definition: pqcomm.h:144
#define NULL
Definition: c.h:229
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
int pqEndcopy2 ( PGconn conn)

Definition at line 1344 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(), result, and pg_result::resultStatus.

Referenced by PQendcopy().

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

References pg_conn::errorMessage, FALSE, getNotify(), i, pg_conn::inCursor, pg_conn::inStart, PQArgBlock::integer, PQArgBlock::len, libpq_gettext, NULL, 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, status(), and TRUE.

Referenced by PQfn().

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

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

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

Referenced by PQgetCopyData().

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

Definition at line 963 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, NULL, 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().

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

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

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

Referenced by PQgetline().

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

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

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

Definition at line 411 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, FALSE, getAnotherTuple(), getNotify(), getRowDescriptions(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, NULL, 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(), TRUE, and pg_conn::workBuffer.

Referenced by parseInput().

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

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

References pg_conn::client_encoding_initial, CONNECTION_BAD, PQEnvironmentOption::envName, pg_conn::errorMessage, libpq_gettext, pg_conn::next_eo, NULL, 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().

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