PostgreSQL Source Code  git master
libpq-int.h File Reference
#include "libpq-events.h"
#include <time.h>
#include "getaddrinfo.h"
#include "libpq/pqcomm.h"
#include "pqexpbuffer.h"
Include dependency graph for libpq-int.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

union  pgresult_data
 
struct  pgresParamDesc
 
struct  pgresAttValue
 
struct  pgMessageField
 
struct  PGNoticeHooks
 
struct  PGEvent
 
struct  pg_result
 
struct  PQEnvironmentOption
 
struct  pgParameterStatus
 
struct  pgLobjfuncs
 
struct  pgDataValue
 
struct  pg_conn_host
 
struct  pg_conn
 
struct  pg_cancel
 

Macros

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */
 
#define NULL_LEN   (-1) /* pg_result len for NULL value */
 
#define pglock_thread()   ((void) 0)
 
#define pgunlock_thread()   ((void) 0)
 
#define pqIsnonblocking(conn)   ((conn)->nonblocking)
 
#define libpq_gettext(x)   (x)
 
#define libpq_ngettext(s, p, n)   ((n) == 1 ? (s) : (p))
 
#define SOCK_ERRNO   errno
 
#define SOCK_STRERROR   pqStrerror
 
#define SOCK_ERRNO_SET(e)   (errno = (e))
 

Typedefs

typedef union pgresult_data PGresult_data
 
typedef struct pgresParamDesc PGresParamDesc
 
typedef struct pgresAttValue PGresAttValue
 
typedef struct pgMessageField PGMessageField
 
typedef struct PGEvent PGEvent
 
typedef struct PQEnvironmentOption PQEnvironmentOption
 
typedef struct pgParameterStatus pgParameterStatus
 
typedef struct pgLobjfuncs PGlobjfuncs
 
typedef struct pgDataValue PGdataValue
 
typedef enum pg_conn_host_type pg_conn_host_type
 
typedef struct pg_conn_host pg_conn_host
 

Enumerations

enum  PGAsyncStatusType {
  PGASYNC_IDLE, PGASYNC_BUSY, PGASYNC_READY, PGASYNC_COPY_IN,
  PGASYNC_COPY_OUT, PGASYNC_COPY_BOTH
}
 
enum  PGQueryClass { PGQUERY_SIMPLE, PGQUERY_EXTENDED, PGQUERY_PREPARE, PGQUERY_DESCRIBE }
 
enum  PGSetenvStatusType {
  SETENV_STATE_CLIENT_ENCODING_SEND, SETENV_STATE_CLIENT_ENCODING_WAIT, SETENV_STATE_OPTION_SEND, SETENV_STATE_OPTION_WAIT,
  SETENV_STATE_QUERY1_SEND, SETENV_STATE_QUERY1_WAIT, SETENV_STATE_QUERY2_SEND, SETENV_STATE_QUERY2_WAIT,
  SETENV_STATE_IDLE
}
 
enum  pg_conn_host_type { CHT_HOST_NAME, CHT_HOST_ADDRESS, CHT_UNIX_SOCKET }
 

Functions

void pqDropConnection (PGconn *conn, bool flushInput)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
void pqSetResultError (PGresult *res, const char *msg)
 
void pqCatenateResultError (PGresult *res, const char *msg)
 
void * pqResultAlloc (PGresult *res, size_t nBytes, bool isBinary)
 
char * pqResultStrdup (PGresult *res, const char *str)
 
void pqClearAsyncResult (PGconn *conn)
 
void pqSaveErrorResult (PGconn *conn)
 
PGresultpqPrepareAsyncResult (PGconn *conn)
 
void pqInternalNotice (const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2
 
void void pqSaveMessageField (PGresult *res, char code, const char *value)
 
void pqSaveParameterStatus (PGconn *conn, const char *name, const char *value)
 
int pqRowProcessor (PGconn *conn, const char **errmsgp)
 
void pqHandleSendFailure (PGconn *conn)
 
PostgresPollingStatusType pqSetenvPoll (PGconn *conn)
 
char * pqBuildStartupPacket2 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
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 * pqBuildStartupPacket3 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
void pqParseInput3 (PGconn *conn)
 
int pqGetErrorNotice3 (PGconn *conn, bool isError)
 
void pqBuildErrorMessage3 (PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
 
int pqGetCopyData3 (PGconn *conn, char **buffer, int async)
 
int pqGetline3 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync3 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy3 (PGconn *conn)
 
PGresultpqFunctionCall3 (PGconn *conn, Oid fnid, int *result_buf, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
int pqCheckOutBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqCheckInBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqGetc (char *result, PGconn *conn)
 
int pqPutc (char c, PGconn *conn)
 
int pqGets (PQExpBuffer buf, PGconn *conn)
 
int pqGets_append (PQExpBuffer buf, PGconn *conn)
 
int pqPuts (const char *s, PGconn *conn)
 
int pqGetnchar (char *s, size_t len, PGconn *conn)
 
int pqSkipnchar (size_t len, PGconn *conn)
 
int pqPutnchar (const char *s, size_t len, PGconn *conn)
 
int pqGetInt (int *result, size_t bytes, PGconn *conn)
 
int pqPutInt (int value, size_t bytes, PGconn *conn)
 
int pqPutMsgStart (char msg_type, bool force_len, PGconn *conn)
 
int pqPutMsgEnd (PGconn *conn)
 
int pqReadData (PGconn *conn)
 
int pqFlush (PGconn *conn)
 
int pqWait (int forRead, int forWrite, PGconn *conn)
 
int pqWaitTimed (int forRead, int forWrite, PGconn *conn, time_t finish_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
int pqsecure_initialize (PGconn *)
 
void pqsecure_destroy (void)
 
PostgresPollingStatusType pqsecure_open_client (PGconn *)
 
void pqsecure_close (PGconn *)
 
ssize_t pqsecure_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_write (PGconn *, const void *ptr, size_t len)
 
ssize_t pqsecure_raw_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_raw_write (PGconn *, const void *ptr, size_t len)
 
void pgtls_init_library (bool do_ssl, int do_crypto)
 
int pgtls_init (PGconn *conn)
 
PostgresPollingStatusType pgtls_open_client (PGconn *conn)
 
void pgtls_close (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
bool pgtls_read_pending (PGconn *conn)
 
ssize_t pgtls_write (PGconn *conn, const void *ptr, size_t len)
 
char * pgtls_get_finished (PGconn *conn, size_t *len)
 
char * pgtls_get_peer_certificate_hash (PGconn *conn, size_t *len)
 
int pgtls_verify_peer_name_matches_certificate_guts (PGconn *conn, int *names_examined, char **first_name)
 

Variables

char *const pgresStatus []
 

Macro Definition Documentation

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

Definition at line 86 of file libpq-int.h.

Referenced by pqParseInput2(), and pqParseInput3().

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

Definition at line 760 of file libpq-int.h.

Referenced by build_client_final_message(), build_client_first_message(), connectDBStart(), connectFailureMessage(), connectNoDelay(), connectOptions2(), conninfo_add_defaults(), conninfo_array_parse(), conninfo_init(), conninfo_parse(), conninfo_storeval(), conninfo_uri_decode(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), do_field(), do_header(), fillPGconn(), getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), handleSyncLoss(), initialize_SSL(), lo_create(), lo_export(), lo_import_internal(), lo_initialize(), lo_lseek64(), lo_read(), lo_tell64(), lo_truncate(), lo_truncate64(), lo_write(), open_client_SSL(), openssl_verify_peer_name_matches_certificate_name(), parseServiceFile(), parseServiceInfo(), passwordFromFile(), pg_fe_getauthname(), pg_fe_scram_exchange(), pg_fe_sendauth(), pg_local_sendauth(), pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pgpassfileWarning(), pgtls_get_peer_certificate_hash(), pgtls_read(), pgtls_write(), pq_verify_peer_name_matches_certificate(), pq_verify_peer_name_matches_certificate_name(), pqAddTuple(), pqBuildErrorMessage3(), PQconnectPoll(), PQdisplayTuples(), PQencryptPasswordConn(), pqEndcopy2(), pqEndcopy3(), PQenv2encoding(), PQerrorMessage(), PQescapeByteaInternal(), PQescapeInternal(), PQescapeStringInternal(), PQexecStart(), PQfn(), pqFunctionCall2(), pqFunctionCall3(), PQgetCopyData(), pqGetCopyData2(), pqGetCopyData3(), pqGetErrorNotice2(), pqGetErrorNotice3(), pqGetline3(), PQgetResult(), pqInternalNotice(), pqPacketSend(), pqParseInput2(), pqParseInput3(), PQprint(), PQprintTuples(), PQputCopyData(), PQputCopyEnd(), pqReadData(), PQreset(), PQresetPoll(), PQresStatus(), PQresultVerboseErrorMessage(), pqsecure_raw_read(), pqsecure_raw_write(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), PQsendQueryParams(), PQsendQueryPrepared(), PQsendQueryStart(), pqSendSome(), PQsetdbLogin(), pqSetenvPoll(), PQsetvalue(), pqSocketCheck(), pqWaitTimed(), read_attr_value(), read_server_final_message(), read_server_first_message(), reportErrorPosition(), saveErrorMessage(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), and SSLerrmessage().

◆ libpq_ngettext

#define libpq_ngettext (   s,
  p,
 
)    ((n) == 1 ? (s) : (p))

Definition at line 761 of file libpq-int.h.

Referenced by pq_verify_peer_name_matches_certificate(), and PQenv2encoding().

◆ NULL_LEN

#define NULL_LEN   (-1) /* pg_result len for NULL value */

Definition at line 133 of file libpq-int.h.

Referenced by getAnotherTuple(), PQgetisnull(), PQgetlength(), pqRowProcessor(), and PQsetvalue().

◆ pglock_thread

#define pglock_thread ( )    ((void) 0)

Definition at line 564 of file libpq-int.h.

Referenced by pg_fe_getauthname(), pg_fe_sendauth(), and pg_frontend_random().

◆ pgunlock_thread

#define pgunlock_thread ( )    ((void) 0)

Definition at line 565 of file libpq-int.h.

Referenced by pg_fe_getauthname(), pg_fe_sendauth(), and pg_frontend_random().

◆ pqIsnonblocking

#define pqIsnonblocking (   conn)    ((conn)->nonblocking)

◆ SOCK_ERRNO

◆ SOCK_ERRNO_SET

#define SOCK_ERRNO_SET (   e)    (errno = (e))

◆ SOCK_STRERROR

Typedef Documentation

◆ pg_conn_host

◆ pg_conn_host_type

◆ PGdataValue

◆ PGEvent

◆ PGlobjfuncs

◆ PGMessageField

◆ pgParameterStatus

◆ PGresAttValue

◆ PGresParamDesc

◆ PGresult_data

Definition at line 101 of file libpq-int.h.

◆ PQEnvironmentOption

Enumeration Type Documentation

◆ pg_conn_host_type

Enumerator
CHT_HOST_NAME 
CHT_HOST_ADDRESS 
CHT_UNIX_SOCKET 

Definition at line 293 of file libpq-int.h.

◆ PGAsyncStatusType

Enumerator
PGASYNC_IDLE 
PGASYNC_BUSY 
PGASYNC_READY 
PGASYNC_COPY_IN 
PGASYNC_COPY_OUT 
PGASYNC_COPY_BOTH 

Definition at line 214 of file libpq-int.h.

215 {
216  PGASYNC_IDLE, /* nothing's happening, dude */
217  PGASYNC_BUSY, /* query in progress */
218  PGASYNC_READY, /* result ready for PQgetResult */
219  PGASYNC_COPY_IN, /* Copy In data transfer in progress */
220  PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
221  PGASYNC_COPY_BOTH /* Copy In/Out data transfer in progress */
PGAsyncStatusType
Definition: libpq-int.h:214

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 

Definition at line 225 of file libpq-int.h.

226 {
227  PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
228  PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
229  PGQUERY_PREPARE, /* Parse only (PQprepare) */
230  PGQUERY_DESCRIBE /* Describe Statement or Portal */
231 } PGQueryClass;
PGQueryClass
Definition: libpq-int.h:225

◆ PGSetenvStatusType

Enumerator
SETENV_STATE_CLIENT_ENCODING_SEND 
SETENV_STATE_CLIENT_ENCODING_WAIT 
SETENV_STATE_OPTION_SEND 
SETENV_STATE_OPTION_WAIT 
SETENV_STATE_QUERY1_SEND 
SETENV_STATE_QUERY1_WAIT 
SETENV_STATE_QUERY2_SEND 
SETENV_STATE_QUERY2_WAIT 
SETENV_STATE_IDLE 

Definition at line 235 of file libpq-int.h.

236 {
237  SETENV_STATE_CLIENT_ENCODING_SEND, /* About to send an Environment Option */
238  SETENV_STATE_CLIENT_ENCODING_WAIT, /* Waiting for above send to complete */
239  SETENV_STATE_OPTION_SEND, /* About to send an Environment Option */
240  SETENV_STATE_OPTION_WAIT, /* Waiting for above send to complete */
241  SETENV_STATE_QUERY1_SEND, /* About to send a status query */
242  SETENV_STATE_QUERY1_WAIT, /* Waiting for query to complete */
243  SETENV_STATE_QUERY2_SEND, /* About to send a status query */
244  SETENV_STATE_QUERY2_WAIT, /* Waiting for query to complete */
PGSetenvStatusType
Definition: libpq-int.h:235

Function Documentation

◆ pgtls_close()

void pgtls_close ( PGconn conn)

Definition at line 1304 of file fe-secure-openssl.c.

References destroy_ssl_system(), and pg_conn::ssl_in_use.

Referenced by open_client_SSL(), pgtls_open_client(), and pqsecure_close().

1305 {
1306  bool destroy_needed = false;
1307 
1308  if (conn->ssl)
1309  {
1310  /*
1311  * We can't destroy everything SSL-related here due to the possible
1312  * later calls to OpenSSL routines which may need our thread
1313  * callbacks, so set a flag here and check at the end.
1314  */
1315  destroy_needed = true;
1316 
1317  SSL_shutdown(conn->ssl);
1318  SSL_free(conn->ssl);
1319  conn->ssl = NULL;
1320  conn->ssl_in_use = false;
1321  }
1322 
1323  if (conn->peer)
1324  {
1325  X509_free(conn->peer);
1326  conn->peer = NULL;
1327  }
1328 
1329 #ifdef USE_SSL_ENGINE
1330  if (conn->engine)
1331  {
1332  ENGINE_finish(conn->engine);
1333  ENGINE_free(conn->engine);
1334  conn->engine = NULL;
1335  }
1336 #endif
1337 
1338  /*
1339  * This will remove our SSL locking hooks, if this is the last SSL
1340  * connection, which means we must wait to call it until after all SSL
1341  * calls have been made, otherwise we can end up with a race condition and
1342  * possible deadlocks.
1343  *
1344  * See comments above destroy_ssl_system().
1345  */
1346  if (destroy_needed)
1348 }
bool ssl_in_use
Definition: libpq-int.h:458
static void destroy_ssl_system(void)

◆ pgtls_get_finished()

char* pgtls_get_finished ( PGconn conn,
size_t *  len 
)

Definition at line 373 of file fe-secure-openssl.c.

References malloc.

Referenced by build_client_final_message().

374 {
375  char dummy[1];
376  char *result;
377 
378  /*
379  * OpenSSL does not offer an API to get directly the length of the TLS
380  * Finished message sent, so first do a dummy call to grab this
381  * information and then do an allocation with the correct size.
382  */
383  *len = SSL_get_finished(conn->ssl, dummy, sizeof(dummy));
384  result = malloc(*len);
385  if (result == NULL)
386  return NULL;
387  (void) SSL_get_finished(conn->ssl, result, *len);
388 
389  return result;
390 }
#define malloc(a)
Definition: header.h:50

◆ pgtls_get_peer_certificate_hash()

char* pgtls_get_peer_certificate_hash ( PGconn conn,
size_t *  len 
)

Definition at line 393 of file fe-secure-openssl.c.

References pg_conn::errorMessage, hash(), libpq_gettext, malloc, and printfPQExpBuffer().

Referenced by build_client_final_message().

394 {
395 #ifdef HAVE_X509_GET_SIGNATURE_NID
396  X509 *peer_cert;
397  const EVP_MD *algo_type;
398  unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
399  unsigned int hash_size;
400  int algo_nid;
401  char *cert_hash;
402 
403  *len = 0;
404 
405  if (!conn->peer)
406  return NULL;
407 
408  peer_cert = conn->peer;
409 
410  /*
411  * Get the signature algorithm of the certificate to determine the hash
412  * algorithm to use for the result.
413  */
414  if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
415  &algo_nid, NULL))
416  {
418  libpq_gettext("could not determine server certificate signature algorithm\n"));
419  return NULL;
420  }
421 
422  /*
423  * The TLS server's certificate bytes need to be hashed with SHA-256 if
424  * its signature algorithm is MD5 or SHA-1 as per RFC 5929
425  * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
426  * is used, the same hash as the signature algorithm is used.
427  */
428  switch (algo_nid)
429  {
430  case NID_md5:
431  case NID_sha1:
432  algo_type = EVP_sha256();
433  break;
434  default:
435  algo_type = EVP_get_digestbynid(algo_nid);
436  if (algo_type == NULL)
437  {
439  libpq_gettext("could not find digest for NID %s\n"),
440  OBJ_nid2sn(algo_nid));
441  return NULL;
442  }
443  break;
444  }
445 
446  if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
447  {
449  libpq_gettext("could not generate peer certificate hash\n"));
450  return NULL;
451  }
452 
453  /* save result */
454  cert_hash = malloc(hash_size);
455  if (cert_hash == NULL)
456  {
458  libpq_gettext("out of memory\n"));
459  return NULL;
460  }
461  memcpy(cert_hash, hash, hash_size);
462  *len = hash_size;
463 
464  return cert_hash;
465 #else
467  libpq_gettext("channel binding type \"tls-server-end-point\" is not supported by this build\n"));
468  return NULL;
469 #endif
470 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define malloc(a)
Definition: header.h:50
PQExpBufferData errorMessage
Definition: libpq-int.h:494
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pgtls_init()

int pgtls_init ( PGconn conn)

Definition at line 662 of file fe-secure-openssl.c.

References free, i, malloc, pq_init_crypto_lib, pq_init_ssl_lib, pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(), and ssl_lib_initialized.

Referenced by pqsecure_initialize().

663 {
664 #ifdef ENABLE_THREAD_SAFETY
665 #ifdef WIN32
666  /* Also see similar code in fe-connect.c, default_threadlock() */
667  if (ssl_config_mutex == NULL)
668  {
669  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
670  /* loop, another thread own the lock */ ;
671  if (ssl_config_mutex == NULL)
672  {
673  if (pthread_mutex_init(&ssl_config_mutex, NULL))
674  return -1;
675  }
676  InterlockedExchange(&win32_ssl_create_mutex, 0);
677  }
678 #endif
679  if (pthread_mutex_lock(&ssl_config_mutex))
680  return -1;
681 
682 #ifdef HAVE_CRYPTO_LOCK
683  if (pq_init_crypto_lib)
684  {
685  /*
686  * If necessary, set up an array to hold locks for libcrypto.
687  * libcrypto will tell us how big to make this array.
688  */
689  if (pq_lockarray == NULL)
690  {
691  int i;
692 
693  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
694  if (!pq_lockarray)
695  {
696  pthread_mutex_unlock(&ssl_config_mutex);
697  return -1;
698  }
699  for (i = 0; i < CRYPTO_num_locks(); i++)
700  {
701  if (pthread_mutex_init(&pq_lockarray[i], NULL))
702  {
703  free(pq_lockarray);
704  pq_lockarray = NULL;
705  pthread_mutex_unlock(&ssl_config_mutex);
706  return -1;
707  }
708  }
709  }
710 
711  if (ssl_open_connections++ == 0)
712  {
713  /*
714  * These are only required for threaded libcrypto applications,
715  * but make sure we don't stomp on them if they're already set.
716  */
717  if (CRYPTO_get_id_callback() == NULL)
718  CRYPTO_set_id_callback(pq_threadidcallback);
719  if (CRYPTO_get_locking_callback() == NULL)
720  CRYPTO_set_locking_callback(pq_lockingcallback);
721  }
722  }
723 #endif /* HAVE_CRYPTO_LOCK */
724 #endif /* ENABLE_THREAD_SAFETY */
725 
726  if (!ssl_lib_initialized)
727  {
728  if (pq_init_ssl_lib)
729  {
730 #ifdef HAVE_OPENSSL_INIT_SSL
731  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
732 #else
733  OPENSSL_config(NULL);
734  SSL_library_init();
735  SSL_load_error_strings();
736 #endif
737  }
738  ssl_lib_initialized = true;
739  }
740 
741 #ifdef ENABLE_THREAD_SAFETY
742  pthread_mutex_unlock(&ssl_config_mutex);
743 #endif
744  return 0;
745 }
static bool pq_init_ssl_lib
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
#define malloc(a)
Definition: header.h:50
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
static bool pq_init_crypto_lib
#define free(a)
Definition: header.h:65
int i
static bool ssl_lib_initialized

◆ pgtls_init_library()

void pgtls_init_library ( bool  do_ssl,
int  do_crypto 
)

Definition at line 102 of file fe-secure-openssl.c.

References pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

103 {
104 #ifdef ENABLE_THREAD_SAFETY
105 
106  /*
107  * Disallow changing the flags while we have open connections, else we'd
108  * get completely confused.
109  */
110  if (ssl_open_connections != 0)
111  return;
112 #endif
113 
114  pq_init_ssl_lib = do_ssl;
115  pq_init_crypto_lib = do_crypto;
116 }
static bool pq_init_ssl_lib
static bool pq_init_crypto_lib

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

Definition at line 119 of file fe-secure-openssl.c.

References initialize_SSL(), open_client_SSL(), PGRES_POLLING_FAILED, and pgtls_close().

Referenced by pqsecure_open_client().

120 {
121  /* First time through? */
122  if (conn->ssl == NULL)
123  {
124  /*
125  * Create a connection-specific SSL object, and load client
126  * certificate, private key, and trusted CA certs.
127  */
128  if (initialize_SSL(conn) != 0)
129  {
130  /* initialize_SSL already put a message in conn->errorMessage */
131  pgtls_close(conn);
132  return PGRES_POLLING_FAILED;
133  }
134  }
135 
136  /* Begin or continue the actual handshake */
137  return open_client_SSL(conn);
138 }
static PostgresPollingStatusType open_client_SSL(PGconn *)
static int initialize_SSL(PGconn *conn)
void pgtls_close(PGconn *conn)

◆ pgtls_read()

ssize_t pgtls_read ( PGconn conn,
void *  ptr,
size_t  len 
)

Definition at line 141 of file fe-secure-openssl.c.

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

142 {
143  ssize_t n;
144  int result_errno = 0;
145  char sebuf[256];
146  int err;
147  unsigned long ecode;
148 
149 rloop:
150 
151  /*
152  * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
153  * queue. In general, the current thread's error queue must be empty
154  * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
155  * not work reliably. Since the possibility exists that other OpenSSL
156  * clients running in the same thread but not under our control will fail
157  * to call ERR_get_error() themselves (after their own I/O operations),
158  * pro-actively clear the per-thread error queue now.
159  */
160  SOCK_ERRNO_SET(0);
161  ERR_clear_error();
162  n = SSL_read(conn->ssl, ptr, len);
163  err = SSL_get_error(conn->ssl, n);
164 
165  /*
166  * Other clients of OpenSSL may fail to call ERR_get_error(), but we
167  * always do, so as to not cause problems for OpenSSL clients that don't
168  * call ERR_clear_error() defensively. Be sure that this happens by
169  * calling now. SSL_get_error() relies on the OpenSSL per-thread error
170  * queue being intact, so this is the earliest possible point
171  * ERR_get_error() may be called.
172  */
173  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
174  switch (err)
175  {
176  case SSL_ERROR_NONE:
177  if (n < 0)
178  {
179  /* Not supposed to happen, so we don't translate the msg */
181  "SSL_read failed but did not provide error information\n");
182  /* assume the connection is broken */
183  result_errno = ECONNRESET;
184  }
185  break;
186  case SSL_ERROR_WANT_READ:
187  n = 0;
188  break;
189  case SSL_ERROR_WANT_WRITE:
190 
191  /*
192  * Returning 0 here would cause caller to wait for read-ready,
193  * which is not correct since what SSL wants is wait for
194  * write-ready. The former could get us stuck in an infinite
195  * wait, so don't risk it; busy-loop instead.
196  */
197  goto rloop;
198  case SSL_ERROR_SYSCALL:
199  if (n < 0)
200  {
201  result_errno = SOCK_ERRNO;
202  if (result_errno == EPIPE ||
203  result_errno == ECONNRESET)
206  "server closed the connection unexpectedly\n"
207  "\tThis probably means the server terminated abnormally\n"
208  "\tbefore or while processing the request.\n"));
209  else
211  libpq_gettext("SSL SYSCALL error: %s\n"),
212  SOCK_STRERROR(result_errno,
213  sebuf, sizeof(sebuf)));
214  }
215  else
216  {
218  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
219  /* assume the connection is broken */
220  result_errno = ECONNRESET;
221  n = -1;
222  }
223  break;
224  case SSL_ERROR_SSL:
225  {
226  char *errm = SSLerrmessage(ecode);
227 
229  libpq_gettext("SSL error: %s\n"), errm);
230  SSLerrfree(errm);
231  /* assume the connection is broken */
232  result_errno = ECONNRESET;
233  n = -1;
234  break;
235  }
236  case SSL_ERROR_ZERO_RETURN:
237 
238  /*
239  * Per OpenSSL documentation, this error code is only returned for
240  * a clean connection closure, so we should not report it as a
241  * server crash.
242  */
244  libpq_gettext("SSL connection has been closed unexpectedly\n"));
245  result_errno = ECONNRESET;
246  n = -1;
247  break;
248  default:
250  libpq_gettext("unrecognized SSL error code: %d\n"),
251  err);
252  /* assume the connection is broken */
253  result_errno = ECONNRESET;
254  n = -1;
255  break;
256  }
257 
258  /* ensure we return the intended errno to caller */
259  SOCK_ERRNO_SET(result_errno);
260 
261  return n;
262 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define SOCK_ERRNO
Definition: libpq-int.h:773
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:775
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define ECONNRESET
Definition: win32_port.h:344
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

Definition at line 265 of file fe-secure-openssl.c.

Referenced by pqSocketCheck().

266 {
267  return SSL_pending(conn->ssl);
268 }

◆ pgtls_verify_peer_name_matches_certificate_guts()

int pgtls_verify_peer_name_matches_certificate_guts ( PGconn conn,
int *  names_examined,
char **  first_name 
)

Definition at line 534 of file fe-secure-openssl.c.

References free, i, name, openssl_verify_peer_name_matches_certificate_name(), pthread_mutex_lock(), pthread_mutex_unlock(), and pthread_self().

Referenced by pq_verify_peer_name_matches_certificate().

537 {
538  STACK_OF(GENERAL_NAME) *peer_san;
539  int i;
540  int rc = 0;
541 
542  /*
543  * First, get the Subject Alternative Names (SANs) from the certificate,
544  * and compare them against the originally given hostname.
545  */
546  peer_san = (STACK_OF(GENERAL_NAME) *)
547  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
548 
549  if (peer_san)
550  {
551  int san_len = sk_GENERAL_NAME_num(peer_san);
552 
553  for (i = 0; i < san_len; i++)
554  {
555  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
556 
557  if (name->type == GEN_DNS)
558  {
559  char *alt_name;
560 
561  (*names_examined)++;
563  name->d.dNSName,
564  &alt_name);
565 
566  if (alt_name)
567  {
568  if (!*first_name)
569  *first_name = alt_name;
570  else
571  free(alt_name);
572  }
573  }
574  if (rc != 0)
575  break;
576  }
577  sk_GENERAL_NAME_free(peer_san);
578  }
579 
580  /*
581  * If there is no subjectAltName extension of type dNSName, check the
582  * Common Name.
583  *
584  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
585  * dNSName is present, the CN must be ignored.)
586  */
587  if (*names_examined == 0)
588  {
589  X509_NAME *subject_name;
590 
591  subject_name = X509_get_subject_name(conn->peer);
592  if (subject_name != NULL)
593  {
594  int cn_index;
595 
596  cn_index = X509_NAME_get_index_by_NID(subject_name,
597  NID_commonName, -1);
598  if (cn_index >= 0)
599  {
600  (*names_examined)++;
602  conn,
603  X509_NAME_ENTRY_get_data(
604  X509_NAME_get_entry(subject_name, cn_index)),
605  first_name);
606  }
607  }
608  }
609 
610  return rc;
611 }
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name, char **store_name)
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:521
int i

◆ pgtls_write()

ssize_t pgtls_write ( PGconn conn,
const void *  ptr,
size_t  len 
)

Definition at line 271 of file fe-secure-openssl.c.

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

272 {
273  ssize_t n;
274  int result_errno = 0;
275  char sebuf[256];
276  int err;
277  unsigned long ecode;
278 
279  SOCK_ERRNO_SET(0);
280  ERR_clear_error();
281  n = SSL_write(conn->ssl, ptr, len);
282  err = SSL_get_error(conn->ssl, n);
283  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
284  switch (err)
285  {
286  case SSL_ERROR_NONE:
287  if (n < 0)
288  {
289  /* Not supposed to happen, so we don't translate the msg */
291  "SSL_write failed but did not provide error information\n");
292  /* assume the connection is broken */
293  result_errno = ECONNRESET;
294  }
295  break;
296  case SSL_ERROR_WANT_READ:
297 
298  /*
299  * Returning 0 here causes caller to wait for write-ready, which
300  * is not really the right thing, but it's the best we can do.
301  */
302  n = 0;
303  break;
304  case SSL_ERROR_WANT_WRITE:
305  n = 0;
306  break;
307  case SSL_ERROR_SYSCALL:
308  if (n < 0)
309  {
310  result_errno = SOCK_ERRNO;
311  if (result_errno == EPIPE || result_errno == ECONNRESET)
314  "server closed the connection unexpectedly\n"
315  "\tThis probably means the server terminated abnormally\n"
316  "\tbefore or while processing the request.\n"));
317  else
319  libpq_gettext("SSL SYSCALL error: %s\n"),
320  SOCK_STRERROR(result_errno,
321  sebuf, sizeof(sebuf)));
322  }
323  else
324  {
326  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
327  /* assume the connection is broken */
328  result_errno = ECONNRESET;
329  n = -1;
330  }
331  break;
332  case SSL_ERROR_SSL:
333  {
334  char *errm = SSLerrmessage(ecode);
335 
337  libpq_gettext("SSL error: %s\n"), errm);
338  SSLerrfree(errm);
339  /* assume the connection is broken */
340  result_errno = ECONNRESET;
341  n = -1;
342  break;
343  }
344  case SSL_ERROR_ZERO_RETURN:
345 
346  /*
347  * Per OpenSSL documentation, this error code is only returned for
348  * a clean connection closure, so we should not report it as a
349  * server crash.
350  */
352  libpq_gettext("SSL connection has been closed unexpectedly\n"));
353  result_errno = ECONNRESET;
354  n = -1;
355  break;
356  default:
358  libpq_gettext("unrecognized SSL error code: %d\n"),
359  err);
360  /* assume the connection is broken */
361  result_errno = ECONNRESET;
362  n = -1;
363  break;
364  }
365 
366  /* ensure we return the intended errno to caller */
367  SOCK_ERRNO_SET(result_errno);
368 
369  return n;
370 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define SOCK_STRERROR
Definition: libpq-int.h:774
#define SOCK_ERRNO
Definition: libpq-int.h:773
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:775
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define ECONNRESET
Definition: win32_port.h:344
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqBuildErrorMessage3()

void pqBuildErrorMessage3 ( PQExpBuffer  msg,
const PGresult res,
PGVerbosity  verbosity,
PGContextVisibility  show_context 
)

Definition at line 989 of file fe-protocol3.c.

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_result::client_encoding, pg_result::errFields, pg_result::errMsg, pg_result::errQuery, libpq_gettext, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_CONTEXT, PG_DIAG_DATATYPE_NAME, PG_DIAG_INTERNAL_POSITION, PG_DIAG_INTERNAL_QUERY, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_HINT, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SCHEMA_NAME, PG_DIAG_SEVERITY, PG_DIAG_SOURCE_FILE, PG_DIAG_SOURCE_FUNCTION, PG_DIAG_SOURCE_LINE, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PG_DIAG_TABLE_NAME, PGRES_FATAL_ERROR, PQERRORS_TERSE, PQERRORS_VERBOSE, PQresultErrorField(), PQSHOW_CONTEXT_ALWAYS, PQSHOW_CONTEXT_ERRORS, reportErrorPosition(), pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

991 {
992  const char *val;
993  const char *querytext = NULL;
994  int querypos = 0;
995 
996  /* If we couldn't allocate a PGresult, just say "out of memory" */
997  if (res == NULL)
998  {
999  appendPQExpBuffer(msg, libpq_gettext("out of memory\n"));
1000  return;
1001  }
1002 
1003  /*
1004  * If we don't have any broken-down fields, just return the base message.
1005  * This mainly applies if we're given a libpq-generated error result.
1006  */
1007  if (res->errFields == NULL)
1008  {
1009  if (res->errMsg && res->errMsg[0])
1010  appendPQExpBufferStr(msg, res->errMsg);
1011  else
1012  appendPQExpBuffer(msg, libpq_gettext("no error message available\n"));
1013  return;
1014  }
1015 
1016  /* Else build error message from relevant fields */
1018  if (val)
1019  appendPQExpBuffer(msg, "%s: ", val);
1020  if (verbosity == PQERRORS_VERBOSE)
1021  {
1023  if (val)
1024  appendPQExpBuffer(msg, "%s: ", val);
1025  }
1027  if (val)
1028  appendPQExpBufferStr(msg, val);
1030  if (val)
1031  {
1032  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1033  {
1034  /* emit position as a syntax cursor display */
1035  querytext = res->errQuery;
1036  querypos = atoi(val);
1037  }
1038  else
1039  {
1040  /* emit position as text addition to primary message */
1041  /* translator: %s represents a digit string */
1042  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1043  val);
1044  }
1045  }
1046  else
1047  {
1049  if (val)
1050  {
1051  querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1052  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1053  {
1054  /* emit position as a syntax cursor display */
1055  querypos = atoi(val);
1056  }
1057  else
1058  {
1059  /* emit position as text addition to primary message */
1060  /* translator: %s represents a digit string */
1061  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1062  val);
1063  }
1064  }
1065  }
1066  appendPQExpBufferChar(msg, '\n');
1067  if (verbosity != PQERRORS_TERSE)
1068  {
1069  if (querytext && querypos > 0)
1070  reportErrorPosition(msg, querytext, querypos,
1071  res->client_encoding);
1073  if (val)
1074  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1076  if (val)
1077  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1079  if (val)
1080  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1081  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1082  (show_context == PQSHOW_CONTEXT_ERRORS &&
1084  {
1085  val = PQresultErrorField(res, PG_DIAG_CONTEXT);
1086  if (val)
1087  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1088  val);
1089  }
1090  }
1091  if (verbosity == PQERRORS_VERBOSE)
1092  {
1094  if (val)
1095  appendPQExpBuffer(msg,
1096  libpq_gettext("SCHEMA NAME: %s\n"), val);
1098  if (val)
1099  appendPQExpBuffer(msg,
1100  libpq_gettext("TABLE NAME: %s\n"), val);
1102  if (val)
1103  appendPQExpBuffer(msg,
1104  libpq_gettext("COLUMN NAME: %s\n"), val);
1106  if (val)
1107  appendPQExpBuffer(msg,
1108  libpq_gettext("DATATYPE NAME: %s\n"), val);
1110  if (val)
1111  appendPQExpBuffer(msg,
1112  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1113  }
1114  if (verbosity == PQERRORS_VERBOSE)
1115  {
1116  const char *valf;
1117  const char *vall;
1118 
1122  if (val || valf || vall)
1123  {
1124  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1125  if (val)
1126  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1127  if (valf && vall) /* unlikely we'd have just one */
1128  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1129  valf, vall);
1130  appendPQExpBufferChar(msg, '\n');
1131  }
1132  }
1133 }
PGMessageField * errFields
Definition: libpq-int.h:197
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:71
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:62
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
char * errMsg
Definition: libpq-int.h:196
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:70
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:55
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
char * errQuery
Definition: libpq-int.h:198
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
#define PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:63
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2709
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:72
ExecStatusType resultStatus
Definition: libpq-int.h:177
long val
Definition: informix.c:689
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64
#define libpq_gettext(x)
Definition: libpq-int.h:760
int client_encoding
Definition: libpq-int.h:189

◆ pqBuildStartupPacket2()

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

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

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

Referenced by PQconnectPoll().

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

◆ pqBuildStartupPacket3()

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

Definition at line 2125 of file fe-protocol3.c.

References build_startup_packet(), and malloc.

Referenced by PQconnectPoll().

2127 {
2128  char *startpacket;
2129 
2130  *packetlen = build_startup_packet(conn, NULL, options);
2131  startpacket = (char *) malloc(*packetlen);
2132  if (!startpacket)
2133  return NULL;
2134  *packetlen = build_startup_packet(conn, startpacket, options);
2135  return startpacket;
2136 }
static int build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)
#define malloc(a)
Definition: header.h:50

◆ pqCatenateResultError()

void pqCatenateResultError ( PGresult res,
const char *  msg 
)

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

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, initPQExpBuffer(), pqSetResultError(), and termPQExpBuffer().

Referenced by PQexecFinish(), and pqSaveErrorResult().

653 {
654  PQExpBufferData errorBuf;
655 
656  if (!res || !msg)
657  return;
658  initPQExpBuffer(&errorBuf);
659  if (res->errMsg)
660  appendPQExpBufferStr(&errorBuf, res->errMsg);
661  appendPQExpBufferStr(&errorBuf, msg);
662  pqSetResultError(res, errorBuf.data);
663  termPQExpBuffer(&errorBuf);
664 }
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
void pqSetResultError(PGresult *res, const char *msg)
Definition: fe-exec.c:637
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

Definition at line 408 of file fe-misc.c.

References pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, memmove, printfPQExpBuffer(), and realloc.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqParseInput3(), and pqReadData().

409 {
410  int newsize = conn->inBufSize;
411  char *newbuf;
412 
413  /* Quick exit if we have enough space */
414  if (bytes_needed <= (size_t) newsize)
415  return 0;
416 
417  /*
418  * Before concluding that we need to enlarge the buffer, left-justify
419  * whatever is in it and recheck. The caller's value of bytes_needed
420  * includes any data to the left of inStart, but we can delete that in
421  * preference to enlarging the buffer. It's slightly ugly to have this
422  * function do this, but it's better than making callers worry about it.
423  */
424  bytes_needed -= conn->inStart;
425 
426  if (conn->inStart < conn->inEnd)
427  {
428  if (conn->inStart > 0)
429  {
430  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
431  conn->inEnd - conn->inStart);
432  conn->inEnd -= conn->inStart;
433  conn->inCursor -= conn->inStart;
434  conn->inStart = 0;
435  }
436  }
437  else
438  {
439  /* buffer is logically empty, reset it */
440  conn->inStart = conn->inCursor = conn->inEnd = 0;
441  }
442 
443  /* Recheck whether we have enough space */
444  if (bytes_needed <= (size_t) newsize)
445  return 0;
446 
447  /*
448  * If we need to enlarge the buffer, we first try to double it in size; if
449  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
450  * the malloc pool by repeated small enlargements.
451  *
452  * Note: tests for newsize > 0 are to catch integer overflow.
453  */
454  do
455  {
456  newsize *= 2;
457  } while (newsize > 0 && bytes_needed > (size_t) newsize);
458 
459  if (newsize > 0 && bytes_needed <= (size_t) newsize)
460  {
461  newbuf = realloc(conn->inBuffer, newsize);
462  if (newbuf)
463  {
464  /* realloc succeeded */
465  conn->inBuffer = newbuf;
466  conn->inBufSize = newsize;
467  return 0;
468  }
469  }
470 
471  newsize = conn->inBufSize;
472  do
473  {
474  newsize += 8192;
475  } while (newsize > 0 && bytes_needed > (size_t) newsize);
476 
477  if (newsize > 0 && bytes_needed <= (size_t) newsize)
478  {
479  newbuf = realloc(conn->inBuffer, newsize);
480  if (newbuf)
481  {
482  /* realloc succeeded */
483  conn->inBuffer = newbuf;
484  conn->inBufSize = newsize;
485  return 0;
486  }
487  }
488 
489  /* realloc failed. Probably out of memory */
491  "cannot allocate memory for input buffer\n");
492  return EOF;
493 }
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
int inBufSize
Definition: libpq-int.h:431
#define memmove(d, s, c)
Definition: c.h:1135
char * inBuffer
Definition: libpq-int.h:430
PQExpBufferData errorMessage
Definition: libpq-int.h:494
#define realloc(a, b)
Definition: header.h:60
int inCursor
Definition: libpq-int.h:433

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

Definition at line 344 of file fe-misc.c.

References pg_conn::errorMessage, pg_conn::outBuffer, pg_conn::outBufSize, printfPQExpBuffer(), and realloc.

Referenced by PQputCopyData(), pqPutMsgBytes(), and pqPutMsgStart().

345 {
346  int newsize = conn->outBufSize;
347  char *newbuf;
348 
349  /* Quick exit if we have enough space */
350  if (bytes_needed <= (size_t) newsize)
351  return 0;
352 
353  /*
354  * If we need to enlarge the buffer, we first try to double it in size; if
355  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
356  * the malloc pool by repeated small enlargements.
357  *
358  * Note: tests for newsize > 0 are to catch integer overflow.
359  */
360  do
361  {
362  newsize *= 2;
363  } while (newsize > 0 && bytes_needed > (size_t) newsize);
364 
365  if (newsize > 0 && bytes_needed <= (size_t) newsize)
366  {
367  newbuf = realloc(conn->outBuffer, newsize);
368  if (newbuf)
369  {
370  /* realloc succeeded */
371  conn->outBuffer = newbuf;
372  conn->outBufSize = newsize;
373  return 0;
374  }
375  }
376 
377  newsize = conn->outBufSize;
378  do
379  {
380  newsize += 8192;
381  } while (newsize > 0 && bytes_needed > (size_t) newsize);
382 
383  if (newsize > 0 && bytes_needed <= (size_t) newsize)
384  {
385  newbuf = realloc(conn->outBuffer, newsize);
386  if (newbuf)
387  {
388  /* realloc succeeded */
389  conn->outBuffer = newbuf;
390  conn->outBufSize = newsize;
391  return 0;
392  }
393  }
394 
395  /* realloc failed. Probably out of memory */
397  "cannot allocate memory for output buffer\n");
398  return EOF;
399 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
PQExpBufferData errorMessage
Definition: libpq-int.h:494
int outBufSize
Definition: libpq-int.h:438
#define realloc(a, b)
Definition: header.h:60
char * outBuffer
Definition: libpq-int.h:437

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)

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

References pg_conn::next_result, PQclear(), and pg_conn::result.

Referenced by closePGconn(), getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), pqGetErrorNotice2(), pqGetErrorNotice3(), pqSaveErrorResult(), and PQsendQueryStart().

727 {
728  if (conn->result)
729  PQclear(conn->result);
730  conn->result = NULL;
731  if (conn->next_result)
732  PQclear(conn->next_result);
733  conn->next_result = NULL;
734 }
PGresult * result
Definition: libpq-int.h:451
PGresult * next_result
Definition: libpq-int.h:452
void PQclear(PGresult *res)
Definition: fe-exec.c:671

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

Definition at line 431 of file fe-connect.c.

References closesocket, free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, pg_fe_scram_free(), PGINVALID_SOCKET, pqsecure_close(), pg_conn::sasl_state, and pg_conn::sock.

Referenced by closePGconn(), connectDBComplete(), connectDBStart(), handleSyncLoss(), PQconnectPoll(), and pqReadData().

432 {
433  /* Drop any SSL state */
434  pqsecure_close(conn);
435 
436  /* Close the socket itself */
437  if (conn->sock != PGINVALID_SOCKET)
438  closesocket(conn->sock);
439  conn->sock = PGINVALID_SOCKET;
440 
441  /* Optionally discard any unread data */
442  if (flushInput)
443  conn->inStart = conn->inCursor = conn->inEnd = 0;
444 
445  /* Always discard any unsent data */
446  conn->outCount = 0;
447 
448  /* Free authentication state */
449 #ifdef ENABLE_GSS
450  {
451  OM_uint32 min_s;
452 
453  if (conn->gctx)
454  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
455  if (conn->gtarg_nam)
456  gss_release_name(&min_s, &conn->gtarg_nam);
457  }
458 #endif
459 #ifdef ENABLE_SSPI
460  if (conn->sspitarget)
461  {
462  free(conn->sspitarget);
463  conn->sspitarget = NULL;
464  }
465  if (conn->sspicred)
466  {
467  FreeCredentialsHandle(conn->sspicred);
468  free(conn->sspicred);
469  conn->sspicred = NULL;
470  }
471  if (conn->sspictx)
472  {
473  DeleteSecurityContext(conn->sspictx);
474  free(conn->sspictx);
475  conn->sspictx = NULL;
476  }
477  conn->usesspi = 0;
478 #endif
479  if (conn->sasl_state)
480  {
481  /*
482  * XXX: if support for more authentication mechanisms is added, this
483  * needs to call the right 'free' function.
484  */
486  conn->sasl_state = NULL;
487  }
488 }
int inEnd
Definition: libpq-int.h:434
int inStart
Definition: libpq-int.h:432
void pg_fe_scram_free(void *opaq)
#define closesocket
Definition: port.h:292
int outCount
Definition: libpq-int.h:439
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:197
void * sasl_state
Definition: libpq-int.h:455
pgsocket sock
Definition: libpq-int.h:401
#define PGINVALID_SOCKET
Definition: port.h:33
#define free(a)
Definition: header.h:65
int inCursor
Definition: libpq-int.h:433

◆ pqEndcopy2()

int pqEndcopy2 ( PGconn conn)

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

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

Referenced by PQendcopy().

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

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)

Definition at line 1815 of file fe-protocol3.c.

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

Referenced by PQendcopy().

1816 {
1817  PGresult *result;
1818 
1819  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1820  conn->asyncStatus != PGASYNC_COPY_OUT &&
1821  conn->asyncStatus != PGASYNC_COPY_BOTH)
1822  {
1824  libpq_gettext("no COPY in progress\n"));
1825  return 1;
1826  }
1827 
1828  /* Send the CopyDone message if needed */
1829  if (conn->asyncStatus == PGASYNC_COPY_IN ||
1830  conn->asyncStatus == PGASYNC_COPY_BOTH)
1831  {
1832  if (pqPutMsgStart('c', false, conn) < 0 ||
1833  pqPutMsgEnd(conn) < 0)
1834  return 1;
1835 
1836  /*
1837  * If we sent the COPY command in extended-query mode, we must issue a
1838  * Sync as well.
1839  */
1840  if (conn->queryclass != PGQUERY_SIMPLE)
1841  {
1842  if (pqPutMsgStart('S', false, conn) < 0 ||
1843  pqPutMsgEnd(conn) < 0)
1844  return 1;
1845  }
1846  }
1847 
1848  /*
1849  * make sure no data is waiting to be sent, abort if we are non-blocking
1850  * and the flush fails
1851  */
1852  if (pqFlush(conn) && pqIsnonblocking(conn))
1853  return 1;
1854 
1855  /* Return to active duty */
1856  conn->asyncStatus = PGASYNC_BUSY;
1858 
1859  /*
1860  * Non blocking connections may have to abort at this point. If everyone
1861  * played the game there should be no problem, but in error scenarios the
1862  * expected messages may not have arrived yet. (We are assuming that the
1863  * backend's packetizing will ensure that CommandComplete arrives along
1864  * with the CopyDone; are there corner cases where that doesn't happen?)
1865  */
1866  if (pqIsnonblocking(conn) && PQisBusy(conn))
1867  return 1;
1868 
1869  /* Wait for the completion response */
1870  result = PQgetResult(conn);
1871 
1872  /* Expecting a successful result */
1873  if (result && result->resultStatus == PGRES_COMMAND_OK)
1874  {
1875  PQclear(result);
1876  return 0;
1877  }
1878 
1879  /*
1880  * Trouble. For backwards-compatibility reasons, we issue the error
1881  * message as if it were a notice (would be nice to get rid of this
1882  * silliness, but too many apps probably don't handle errors from
1883  * PQendcopy reasonably). Note that the app can still obtain the error
1884  * status from the PGconn object.
1885  */
1886  if (conn->errorMessage.len > 0)
1887  {
1888  /* We have to strip the trailing newline ... pain in neck... */
1889  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1890 
1891  if (svLast == '\n')
1892  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1893  pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1894  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1895  }
1896 
1897  PQclear(result);
1898 
1899  return 1;
1900 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define pqIsnonblocking(conn)
Definition: libpq-int.h:754
PGQueryClass queryclass
Definition: libpq-int.h:383
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqFlush()

int pqFlush ( PGconn conn)

Definition at line 961 of file fe-misc.c.

References pg_conn::outCount, pg_conn::Pfdebug, and pqSendSome().

Referenced by pg_SASL_init(), PQconnectPoll(), PQconsumeInput(), pqEndcopy2(), pqEndcopy3(), PQflush(), pqFunctionCall2(), pqFunctionCall3(), PQgetResult(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), PQsetnonblocking(), and sendTerminateConn().

962 {
963  if (conn->Pfdebug)
964  fflush(conn->Pfdebug);
965 
966  if (conn->outCount > 0)
967  return pqSendSome(conn, conn->outCount);
968 
969  return 0;
970 }
int outCount
Definition: libpq-int.h:439
FILE * Pfdebug
Definition: libpq-int.h:369
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:829

◆ pqFunctionCall2()

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

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

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

Referenced by PQfn().

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

◆ pqFunctionCall3()

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

Definition at line 1909 of file fe-protocol3.c.

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

Referenced by PQfn().

1913 {
1914  bool needInput = false;
1916  char id;
1917  int msgLength;
1918  int avail;
1919  int i;
1920 
1921  /* PQfn already validated connection state */
1922 
1923  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1924  pqPutInt(fnid, 4, conn) < 0 || /* function id */
1925  pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1926  pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1927  pqPutInt(nargs, 2, conn) < 0) /* # of args */
1928  {
1929  pqHandleSendFailure(conn);
1930  return NULL;
1931  }
1932 
1933  for (i = 0; i < nargs; ++i)
1934  { /* len.int4 + contents */
1935  if (pqPutInt(args[i].len, 4, conn))
1936  {
1937  pqHandleSendFailure(conn);
1938  return NULL;
1939  }
1940  if (args[i].len == -1)
1941  continue; /* it's NULL */
1942 
1943  if (args[i].isint)
1944  {
1945  if (pqPutInt(args[i].u.integer, args[i].len, conn))
1946  {
1947  pqHandleSendFailure(conn);
1948  return NULL;
1949  }
1950  }
1951  else
1952  {
1953  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1954  {
1955  pqHandleSendFailure(conn);
1956  return NULL;
1957  }
1958  }
1959  }
1960 
1961  if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
1962  {
1963  pqHandleSendFailure(conn);
1964  return NULL;
1965  }
1966 
1967  if (pqPutMsgEnd(conn) < 0 ||
1968  pqFlush(conn))
1969  {
1970  pqHandleSendFailure(conn);
1971  return NULL;
1972  }
1973 
1974  for (;;)
1975  {
1976  if (needInput)
1977  {
1978  /* Wait for some data to arrive (or for the channel to close) */
1979  if (pqWait(true, false, conn) ||
1980  pqReadData(conn) < 0)
1981  break;
1982  }
1983 
1984  /*
1985  * Scan the message. If we run out of data, loop around to try again.
1986  */
1987  needInput = true;
1988 
1989  conn->inCursor = conn->inStart;
1990  if (pqGetc(&id, conn))
1991  continue;
1992  if (pqGetInt(&msgLength, 4, conn))
1993  continue;
1994 
1995  /*
1996  * Try to validate message type/length here. A length less than 4 is
1997  * definitely broken. Large lengths should only be believed for a few
1998  * message types.
1999  */
2000  if (msgLength < 4)
2001  {
2002  handleSyncLoss(conn, id, msgLength);
2003  break;
2004  }
2005  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2006  {
2007  handleSyncLoss(conn, id, msgLength);
2008  break;
2009  }
2010 
2011  /*
2012  * Can't process if message body isn't all here yet.
2013  */
2014  msgLength -= 4;
2015  avail = conn->inEnd - conn->inCursor;
2016  if (avail < msgLength)
2017  {
2018  /*
2019  * Before looping, enlarge the input buffer if needed to hold the
2020  * whole message. See notes in parseInput.
2021  */
2022  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2023  conn))
2024  {
2025  /*
2026  * XXX add some better recovery code... plan is to skip over
2027  * the message using its length, then report an error. For the
2028  * moment, just treat this like loss of sync (which indeed it
2029  * might be!)
2030  */
2031  handleSyncLoss(conn, id, msgLength);
2032  break;
2033  }
2034  continue;
2035  }
2036 
2037  /*
2038  * We should see V or E response to the command, but might get N
2039  * and/or A notices first. We also need to swallow the final Z before
2040  * returning.
2041  */
2042  switch (id)
2043  {
2044  case 'V': /* function result */
2045  if (pqGetInt(actual_result_len, 4, conn))
2046  continue;
2047  if (*actual_result_len != -1)
2048  {
2049  if (result_is_int)
2050  {
2051  if (pqGetInt(result_buf, *actual_result_len, conn))
2052  continue;
2053  }
2054  else
2055  {
2056  if (pqGetnchar((char *) result_buf,
2057  *actual_result_len,
2058  conn))
2059  continue;
2060  }
2061  }
2062  /* correctly finished function result message */
2063  status = PGRES_COMMAND_OK;
2064  break;
2065  case 'E': /* error return */
2066  if (pqGetErrorNotice3(conn, true))
2067  continue;
2068  status = PGRES_FATAL_ERROR;
2069  break;
2070  case 'A': /* notify message */
2071  /* handle notify and go back to processing return values */
2072  if (getNotify(conn))
2073  continue;
2074  break;
2075  case 'N': /* notice */
2076  /* handle notice and go back to processing return values */
2077  if (pqGetErrorNotice3(conn, false))
2078  continue;
2079  break;
2080  case 'Z': /* backend is ready for new query */
2081  if (getReadyForQuery(conn))
2082  continue;
2083  /* consume the message and exit */
2084  conn->inStart += 5 + msgLength;
2085  /* if we saved a result object (probably an error), use it */
2086  if (conn->result)
2087  return pqPrepareAsyncResult(conn);
2088  return PQmakeEmptyPGresult(conn, status);
2089  case 'S': /* parameter status */
2090  if (getParameterStatus(conn))
2091  continue;
2092  break;
2093  default:
2094  /* The backend violates the protocol. */
2096  libpq_gettext("protocol error: id=0x%x\n"),
2097  id);
2098  pqSaveErrorResult(conn);
2099  /* trust the specified message length as what to skip */
2100  conn->inStart += 5 + msgLength;
2101  return pqPrepareAsyncResult(conn);
2102  }
2103  /* Completed this message, keep going */
2104  /* trust the specified message length as what to skip */
2105  conn->inStart += 5 + msgLength;
2106  needInput = false;
2107  }
2108 
2109  /*
2110  * We fall out of the loop only upon failing to read data.
2111  * conn->errorMessage has been set by pqWait or pqReadData. We want to
2112  * append it to any already-received error message.
2113  */
2114  pqSaveErrorResult(conn);
2115  return pqPrepareAsyncResult(conn);
2116 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
void pqHandleSendFailure(PGconn *conn)
Definition: fe-exec.c:1633
int inStart
Definition: libpq-int.h:432
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
ExecStatusType
Definition: libpq-fe.h:82
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:195
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:777
PGresult * result
Definition: libpq-int.h:451
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:307
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:875
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:40
PQExpBufferData errorMessage
Definition: libpq-int.h:494
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:246
static int getReadyForQuery(PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
int i
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:449
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:433
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
int * ptr
Definition: libpq-fe.h:226
#define libpq_gettext(x)
Definition: libpq-int.h:760
int integer
Definition: libpq-fe.h:227

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

Definition at line 94 of file fe-misc.c.

References pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and pg_conn::Pfdebug.

Referenced by getCopyDataMessage(), getCopyStart(), getReadyForQuery(), PQconnectPoll(), pqFunctionCall2(), pqFunctionCall3(), pqGetErrorNotice3(), pqParseInput2(), and pqParseInput3().

95 {
96  if (conn->inCursor >= conn->inEnd)
97  return EOF;
98 
99  *result = conn->inBuffer[conn->inCursor++];
100 
101  if (conn->Pfdebug)
102  fprintf(conn->Pfdebug, "From backend> %c\n", *result);
103 
104  return 0;
105 }
int inEnd
Definition: libpq-int.h:434
FILE * Pfdebug
Definition: libpq-int.h:369
char * inBuffer
Definition: libpq-int.h:430
int inCursor
Definition: libpq-int.h:433

◆ pqGetCopyData2()

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

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

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

Referenced by PQgetCopyData().

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

◆ pqGetCopyData3()

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

Definition at line 1648 of file fe-protocol3.c.

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

Referenced by PQgetCopyData().

1649 {
1650  int msgLength;
1651 
1652  for (;;)
1653  {
1654  /*
1655  * Collect the next input message. To make life simpler for async
1656  * callers, we keep returning 0 until the next message is fully
1657  * available, even if it is not Copy Data.
1658  */
1659  msgLength = getCopyDataMessage(conn);
1660  if (msgLength < 0)
1661  return msgLength; /* end-of-copy or error */
1662  if (msgLength == 0)
1663  {
1664  /* Don't block if async read requested */
1665  if (async)
1666  return 0;
1667  /* Need to load more data */
1668  if (pqWait(true, false, conn) ||
1669  pqReadData(conn) < 0)
1670  return -2;
1671  continue;
1672  }
1673 
1674  /*
1675  * Drop zero-length messages (shouldn't happen anyway). Otherwise
1676  * pass the data back to the caller.
1677  */
1678  msgLength -= 4;
1679  if (msgLength > 0)
1680  {
1681  *buffer = (char *) malloc(msgLength + 1);
1682  if (*buffer == NULL)
1683  {
1685  libpq_gettext("out of memory\n"));
1686  return -2;
1687  }
1688  memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1689  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1690 
1691  /* Mark message consumed */
1692  conn->inStart = conn->inCursor + msgLength;
1693 
1694  return msgLength;
1695  }
1696 
1697  /* Empty, so drop it and loop around for another */
1698  conn->inStart = conn->inCursor;
1699  }
1700 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
#define malloc(a)
Definition: header.h:50
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
char * inBuffer
Definition: libpq-int.h:430
static int getCopyDataMessage(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:494
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
int inCursor
Definition: libpq-int.h:433
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

Definition at line 875 of file fe-protocol3.c.

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, pg_result::errQuery, initPQExpBuffer(), pg_conn::last_query, pg_conn::last_sqlstate, libpq_gettext, pg_result::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, pqBuildErrorMessage3(), PQclear(), pqClearAsyncResult(), PQExpBufferDataBroken, pqGetc(), pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), printfPQExpBuffer(), resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, pg_conn::show_context, strlcpy(), termPQExpBuffer(), and pg_conn::verbosity.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), and pqParseInput3().

876 {
877  PGresult *res = NULL;
878  bool have_position = false;
879  PQExpBufferData workBuf;
880  char id;
881 
882  /*
883  * If this is an error message, pre-emptively clear any incomplete query
884  * result we may have. We'd just throw it away below anyway, and
885  * releasing it before collecting the error might avoid out-of-memory.
886  */
887  if (isError)
888  pqClearAsyncResult(conn);
889 
890  /*
891  * Since the fields might be pretty long, we create a temporary
892  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
893  * for stuff that is expected to be short. We shouldn't use
894  * conn->errorMessage either, since this might be only a notice.
895  */
896  initPQExpBuffer(&workBuf);
897 
898  /*
899  * Make a PGresult to hold the accumulated fields. We temporarily lie
900  * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
901  * copy conn->errorMessage.
902  *
903  * NB: This allocation can fail, if you run out of memory. The rest of the
904  * function handles that gracefully, and we still try to set the error
905  * message as the connection's error message.
906  */
908  if (res)
910 
911  /*
912  * Read the fields and save into res.
913  *
914  * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
915  * we saw a PG_DIAG_STATEMENT_POSITION field.
916  */
917  for (;;)
918  {
919  if (pqGetc(&id, conn))
920  goto fail;
921  if (id == '\0')
922  break; /* terminator found */
923  if (pqGets(&workBuf, conn))
924  goto fail;
925  pqSaveMessageField(res, id, workBuf.data);
926  if (id == PG_DIAG_SQLSTATE)
927  strlcpy(conn->last_sqlstate, workBuf.data,
928  sizeof(conn->last_sqlstate));
929  else if (id == PG_DIAG_STATEMENT_POSITION)
930  have_position = true;
931  }
932 
933  /*
934  * Save the active query text, if any, into res as well; but only if we
935  * might need it for an error cursor display, which is only true if there
936  * is a PG_DIAG_STATEMENT_POSITION field.
937  */
938  if (have_position && conn->last_query && res)
939  res->errQuery = pqResultStrdup(res, conn->last_query);
940 
941  /*
942  * Now build the "overall" error message for PQresultErrorMessage.
943  */
944  resetPQExpBuffer(&workBuf);
945  pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
946 
947  /*
948  * Either save error as current async result, or just emit the notice.
949  */
950  if (isError)
951  {
952  if (res)
953  res->errMsg = pqResultStrdup(res, workBuf.data);
954  pqClearAsyncResult(conn); /* redundant, but be safe */
955  conn->result = res;
956  if (PQExpBufferDataBroken(workBuf))
958  libpq_gettext("out of memory"));
959  else
960  appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
961  }
962  else
963  {
964  /* if we couldn't allocate the result set, just discard the NOTICE */
965  if (res)
966  {
967  /* We can cheat a little here and not copy the message. */
968  res->errMsg = workBuf.data;
969  if (res->noticeHooks.noticeRec != NULL)
971  PQclear(res);
972  }
973  }
974 
975  termPQExpBuffer(&workBuf);
976  return 0;
977 
978 fail:
979  PQclear(res);
980  termPQExpBuffer(&workBuf);
981  return EOF;
982 }
PGContextVisibility show_context
Definition: libpq-int.h:426
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:451
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
PGVerbosity verbosity
Definition: libpq-int.h:425
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
char * last_query
Definition: libpq-int.h:384
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
char * errQuery
Definition: libpq-int.h:198
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition: fe-exec.c:942
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void PQclear(PGresult *res)
Definition: fe-exec.c:671
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
Definition: fe-protocol3.c:989
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
ExecStatusType resultStatus
Definition: libpq-int.h:177
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
#define libpq_gettext(x)
Definition: libpq-int.h:760
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:623
void * noticeRecArg
Definition: libpq-int.h:153
char last_sqlstate[6]
Definition: libpq-int.h:385

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

Definition at line 6543 of file fe-connect.c.

References pqGetpwuid(), snprintf(), and strlcpy().

Referenced by connectOptions2(), initialize_SSL(), and parseServiceInfo().

6544 {
6545 #ifndef WIN32
6546  char pwdbuf[BUFSIZ];
6547  struct passwd pwdstr;
6548  struct passwd *pwd = NULL;
6549 
6550  (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
6551  if (pwd == NULL)
6552  return false;
6553  strlcpy(buf, pwd->pw_dir, bufsize);
6554  return true;
6555 #else
6556  char tmppath[MAX_PATH];
6557 
6558  ZeroMemory(tmppath, sizeof(tmppath));
6559  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
6560  return false;
6561  snprintf(buf, bufsize, "%s/postgresql", tmppath);
6562  return true;
6563 #endif
6564 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static char * buf
Definition: pg_test_fsync.c:67
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
Definition: thread.c:95

◆ pqGetInt()

int pqGetInt ( int *  result,
size_t  bytes,
PGconn conn 
)

Definition at line 267 of file fe-misc.c.

References pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::noticeHooks, pg_conn::Pfdebug, pg_ntoh16, pg_ntoh32, and pqInternalNotice().

Referenced by getAnotherTuple(), getCopyDataMessage(), getCopyStart(), getNotify(), getParamDescriptions(), getRowDescriptions(), PQconnectPoll(), pqFunctionCall2(), pqFunctionCall3(), pqParseInput2(), and pqParseInput3().

268 {
269  uint16 tmp2;
270  uint32 tmp4;
271 
272  switch (bytes)
273  {
274  case 2:
275  if (conn->inCursor + 2 > conn->inEnd)
276  return EOF;
277  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
278  conn->inCursor += 2;
279  *result = (int) pg_ntoh16(tmp2);
280  break;
281  case 4:
282  if (conn->inCursor + 4 > conn->inEnd)
283  return EOF;
284  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
285  conn->inCursor += 4;
286  *result = (int) pg_ntoh32(tmp4);
287  break;
288  default:
290  "integer of size %lu not supported by pqGetInt",
291  (unsigned long) bytes);
292  return EOF;
293  }
294 
295  if (conn->Pfdebug)
296  fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
297 
298  return 0;
299 }
int inEnd
Definition: libpq-int.h:434
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
FILE * Pfdebug
Definition: libpq-int.h:369
unsigned short uint16
Definition: c.h:324
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
unsigned int uint32
Definition: c.h:325
char * inBuffer
Definition: libpq-int.h:430
int inCursor
Definition: libpq-int.h:433

◆ pqGetline2()

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

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

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

Referenced by PQgetline().

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

◆ pqGetline3()

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

Definition at line 1708 of file fe-protocol3.c.

References pg_conn::asyncStatus, pg_conn::copy_is_binary, pg_conn::errorMessage, libpq_gettext, PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, PGINVALID_SOCKET, PQgetlineAsync(), pqReadData(), pqWait(), printfPQExpBuffer(), pg_conn::sock, and status().

Referenced by PQgetline().

1709 {
1710  int status;
1711 
1712  if (conn->sock == PGINVALID_SOCKET ||
1713  (conn->asyncStatus != PGASYNC_COPY_OUT &&
1714  conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1715  conn->copy_is_binary)
1716  {
1718  libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1719  *s = '\0';
1720  return EOF;
1721  }
1722 
1723  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1724  {
1725  /* need to load more data */
1726  if (pqWait(true, false, conn) ||
1727  pqReadData(conn) < 0)
1728  {
1729  *s = '\0';
1730  return EOF;
1731  }
1732  }
1733 
1734  if (status < 0)
1735  {
1736  /* End of copy detected; gin up old-style terminator */
1737  strcpy(s, "\\.");
1738  return 0;
1739  }
1740 
1741  /* Add null terminator, and strip trailing \n if present */
1742  if (s[status - 1] == '\n')
1743  {
1744  s[status - 1] = '\0';
1745  return 0;
1746  }
1747  else
1748  {
1749  s[status] = '\0';
1750  return 1;
1751  }
1752 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition: fe-exec.c:2520
char copy_is_binary
Definition: libpq-int.h:390
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:984
pgsocket sock
Definition: libpq-int.h:401
#define PGINVALID_SOCKET
Definition: port.h:33
PQExpBufferData errorMessage
Definition: libpq-int.h:494
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqGetlineAsync2()

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

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

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

Referenced by PQgetlineAsync().

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

◆ pqGetlineAsync3()

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

Definition at line 1760 of file fe-protocol3.c.

References pg_conn::asyncStatus, pg_conn::copy_already_done, getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inStart, PGASYNC_COPY_BOTH, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

1761 {
1762  int msgLength;
1763  int avail;
1764 
1765  if (conn->asyncStatus != PGASYNC_COPY_OUT
1766  && conn->asyncStatus != PGASYNC_COPY_BOTH)
1767  return -1; /* we are not doing a copy... */
1768 
1769  /*
1770  * Recognize the next input message. To make life simpler for async
1771  * callers, we keep returning 0 until the next message is fully available
1772  * even if it is not Copy Data. This should keep PQendcopy from blocking.
1773  * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1774  */
1775  msgLength = getCopyDataMessage(conn);
1776  if (msgLength < 0)
1777  return -1; /* end-of-copy or error */
1778  if (msgLength == 0)
1779  return 0; /* no data yet */
1780 
1781  /*
1782  * Move data from libpq's buffer to the caller's. In the case where a
1783  * prior call found the caller's buffer too small, we use
1784  * conn->copy_already_done to remember how much of the row was already
1785  * returned to the caller.
1786  */
1787  conn->inCursor += conn->copy_already_done;
1788  avail = msgLength - 4 - conn->copy_already_done;
1789  if (avail <= bufsize)
1790  {
1791  /* Able to consume the whole message */
1792  memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1793  /* Mark message consumed */
1794  conn->inStart = conn->inCursor + avail;
1795  /* Reset state for next time */
1796  conn->copy_already_done = 0;
1797  return avail;
1798  }
1799  else
1800  {
1801  /* We must return a partial message */
1802  memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1803  /* The message is NOT consumed from libpq's buffer */
1804  conn->copy_already_done += bufsize;
1805  return bufsize;
1806  }
1807 }
int inStart
Definition: libpq-int.h:432
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
char * inBuffer
Definition: libpq-int.h:430
static int getCopyDataMessage(PGconn *conn)
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
int copy_already_done
Definition: libpq-int.h:391
int inCursor
Definition: libpq-int.h:433

◆ pqGetnchar()

int pqGetnchar ( char *  s,
size_t  len,
PGconn conn 
)

Definition at line 195 of file fe-misc.c.

References fputnbytes(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and pg_conn::Pfdebug.

Referenced by getAnotherTuple(), pg_password_sendauth(), pg_SASL_continue(), pqFunctionCall2(), and pqFunctionCall3().

196 {
197  if (len > (size_t) (conn->inEnd - conn->inCursor))
198  return EOF;
199 
200  memcpy(s, conn->inBuffer + conn->inCursor, len);
201  /* no terminating null */
202 
203  conn->inCursor += len;
204 
205  if (conn->Pfdebug)
206  {
207  fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
208  fputnbytes(conn->Pfdebug, s, len);
209  fprintf(conn->Pfdebug, "\n");
210  }
211 
212  return 0;
213 }
int inEnd
Definition: libpq-int.h:434
FILE * Pfdebug
Definition: libpq-int.h:369
char * inBuffer
Definition: libpq-int.h:430
static void fputnbytes(FILE *f, const char *str, size_t n)
Definition: fe-misc.c:79
int inCursor
Definition: libpq-int.h:433

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

Definition at line 163 of file fe-misc.c.

References pqGets_internal().

Referenced by getNotify(), getParameterStatus(), getRowDescriptions(), pg_SASL_init(), pqGetErrorNotice2(), pqGetErrorNotice3(), pqParseInput2(), and pqParseInput3().

164 {
165  return pqGets_internal(buf, conn, true);
166 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:132

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

Definition at line 169 of file fe-misc.c.

References pqGets_internal().

Referenced by PQconnectPoll().

170 {
171  return pqGets_internal(buf, conn, false);
172 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:132

◆ pqHandleSendFailure()

void pqHandleSendFailure ( PGconn conn)

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

References parseInput(), and pqReadData().

Referenced by pqFunctionCall2(), pqFunctionCall3(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), and PQsendQueryGuts().

1634 {
1635  /*
1636  * Accept and parse any available input data, ignoring I/O errors. Note
1637  * that if pqReadData decides the backend has closed the channel, it will
1638  * close our side of the socket --- that's just what we want here.
1639  */
1640  while (pqReadData(conn) > 0)
1641  parseInput(conn);
1642 
1643  /*
1644  * Be sure to parse available input messages even if we read no data.
1645  * (Note: calling parseInput within the above loop isn't really necessary,
1646  * but it prevents buffer bloat if there's a lot of data available.)
1647  */
1648  parseInput(conn);
1649 }
int pqReadData(PGconn *conn)
Definition: fe-misc.c:629
static void parseInput(PGconn *conn)
Definition: fe-exec.c:1718

◆ pqInternalNotice()

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

◆ pqPacketSend()

int pqPacketSend ( PGconn conn,
char  pack_type,
const void *  buf,
size_t  buf_len 
)

Definition at line 3983 of file fe-connect.c.

References DefaultHost, free, hostname, i, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, malloc, pg_strcasecmp(), pg_strncasecmp(), port, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), printfPQExpBuffer(), STATUS_ERROR, STATUS_OK, _internalPQconninfoOption::val, _PQconninfoOption::val, and values.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and PQconnectPoll().

3985 {
3986  /* Start the message. */
3987  if (pqPutMsgStart(pack_type, true, conn))
3988  return STATUS_ERROR;
3989 
3990  /* Send the message body. */
3991  if (pqPutnchar(buf, buf_len, conn))
3992  return STATUS_ERROR;
3993 
3994  /* Finish the message. */
3995  if (pqPutMsgEnd(conn))
3996  return STATUS_ERROR;
3997 
3998  /* Flush to ensure backend gets it. */
3999  if (pqFlush(conn))
4000  return STATUS_ERROR;
4001 
4002  return STATUS_OK;
4003 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:961
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:519
#define STATUS_ERROR
Definition: c.h:1009
static char * buf
Definition: pg_test_fsync.c:67
#define STATUS_OK
Definition: c.h:1008
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:246
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:587

◆ pqParseInput2()

void pqParseInput2 ( PGconn conn)

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

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

Referenced by parseInput().

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

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)

Definition at line 65 of file fe-protocol3.c.

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, pg_result::cmdStatus, CMDSTATUS_LEN, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::errorMessage, getAnotherTuple(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleSyncLoss(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_TUPLES_OK, pqCheckInBufferSpace(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), pqSaveErrorResult(), printfPQExpBuffer(), pg_conn::queryclass, pg_conn::result, pg_result::resultStatus, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

66 {
67  char id;
68  int msgLength;
69  int avail;
70 
71  /*
72  * Loop to parse successive complete messages available in the buffer.
73  */
74  for (;;)
75  {
76  /*
77  * Try to read a message. First get the type code and length. Return
78  * if not enough data.
79  */
80  conn->inCursor = conn->inStart;
81  if (pqGetc(&id, conn))
82  return;
83  if (pqGetInt(&msgLength, 4, conn))
84  return;
85 
86  /*
87  * Try to validate message type/length here. A length less than 4 is
88  * definitely broken. Large lengths should only be believed for a few
89  * message types.
90  */
91  if (msgLength < 4)
92  {
93  handleSyncLoss(conn, id, msgLength);
94  return;
95  }
96  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
97  {
98  handleSyncLoss(conn, id, msgLength);
99  return;
100  }
101 
102  /*
103  * Can't process if message body isn't all here yet.
104  */
105  msgLength -= 4;
106  avail = conn->inEnd - conn->inCursor;
107  if (avail < msgLength)
108  {
109  /*
110  * Before returning, enlarge the input buffer if needed to hold
111  * the whole message. This is better than leaving it to
112  * pqReadData because we can avoid multiple cycles of realloc()
113  * when the message is large; also, we can implement a reasonable
114  * recovery strategy if we are unable to make the buffer big
115  * enough.
116  */
117  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
118  conn))
119  {
120  /*
121  * XXX add some better recovery code... plan is to skip over
122  * the message using its length, then report an error. For the
123  * moment, just treat this like loss of sync (which indeed it
124  * might be!)
125  */
126  handleSyncLoss(conn, id, msgLength);
127  }
128  return;
129  }
130 
131  /*
132  * NOTIFY and NOTICE messages can happen in any state; always process
133  * them right away.
134  *
135  * Most other messages should only be processed while in BUSY state.
136  * (In particular, in READY state we hold off further parsing until
137  * the application collects the current PGresult.)
138  *
139  * However, if the state is IDLE then we got trouble; we need to deal
140  * with the unexpected message somehow.
141  *
142  * ParameterStatus ('S') messages are a special case: in IDLE state we
143  * must process 'em (this case could happen if a new value was adopted
144  * from config file due to SIGHUP), but otherwise we hold off until
145  * BUSY state.
146  */
147  if (id == 'A')
148  {
149  if (getNotify(conn))
150  return;
151  }
152  else if (id == 'N')
153  {
154  if (pqGetErrorNotice3(conn, false))
155  return;
156  }
157  else if (conn->asyncStatus != PGASYNC_BUSY)
158  {
159  /* If not IDLE state, just wait ... */
160  if (conn->asyncStatus != PGASYNC_IDLE)
161  return;
162 
163  /*
164  * Unexpected message in IDLE state; need to recover somehow.
165  * ERROR messages are handled using the notice processor;
166  * ParameterStatus is handled normally; anything else is just
167  * dropped on the floor after displaying a suitable warning
168  * notice. (An ERROR is very possibly the backend telling us why
169  * it is about to close the connection, so we don't want to just
170  * discard it...)
171  */
172  if (id == 'E')
173  {
174  if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
175  return;
176  }
177  else if (id == 'S')
178  {
179  if (getParameterStatus(conn))
180  return;
181  }
182  else
183  {
185  "message type 0x%02x arrived from server while idle",
186  id);
187  /* Discard the unexpected message */
188  conn->inCursor += msgLength;
189  }
190  }
191  else
192  {
193  /*
194  * In BUSY state, we can process everything.
195  */
196  switch (id)
197  {
198  case 'C': /* command complete */
199  if (pqGets(&conn->workBuffer, conn))
200  return;
201  if (conn->result == NULL)
202  {
203  conn->result = PQmakeEmptyPGresult(conn,
205  if (!conn->result)
206  {
208  libpq_gettext("out of memory"));
209  pqSaveErrorResult(conn);
210  }
211  }
212  if (conn->result)
213  strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
214  CMDSTATUS_LEN);
215  conn->asyncStatus = PGASYNC_READY;
216  break;
217  case 'E': /* error return */
218  if (pqGetErrorNotice3(conn, true))
219  return;
220  conn->asyncStatus = PGASYNC_READY;
221  break;
222  case 'Z': /* backend is ready for new query */
223  if (getReadyForQuery(conn))
224  return;
225  conn->asyncStatus = PGASYNC_IDLE;
226  break;
227  case 'I': /* empty query */
228  if (conn->result == NULL)
229  {
230  conn->result = PQmakeEmptyPGresult(conn,
232  if (!conn->result)
233  {
235  libpq_gettext("out of memory"));
236  pqSaveErrorResult(conn);
237  }
238  }
239  conn->asyncStatus = PGASYNC_READY;
240  break;
241  case '1': /* Parse Complete */
242  /* If we're doing PQprepare, we're done; else ignore */
243  if (conn->queryclass == PGQUERY_PREPARE)
244  {
245  if (conn->result == NULL)
246  {
247  conn->result = PQmakeEmptyPGresult(conn,
249  if (!conn->result)
250  {
252  libpq_gettext("out of memory"));
253  pqSaveErrorResult(conn);
254  }
255  }
256  conn->asyncStatus = PGASYNC_READY;
257  }
258  break;
259  case '2': /* Bind Complete */
260  case '3': /* Close Complete */
261  /* Nothing to do for these message types */
262  break;
263  case 'S': /* parameter status */
264  if (getParameterStatus(conn))
265  return;
266  break;
267  case 'K': /* secret key data from the backend */
268 
269  /*
270  * This is expected only during backend startup, but it's
271  * just as easy to handle it as part of the main loop.
272  * Save the data and continue processing.
273  */
274  if (pqGetInt(&(conn->be_pid), 4, conn))
275  return;
276  if (pqGetInt(&(conn->be_key), 4, conn))
277  return;
278  break;
279  case 'T': /* Row Description */
280  if (conn->result != NULL &&
282  {
283  /*
284  * We've already choked for some reason. Just discard
285  * the data till we get to the end of the query.
286  */
287  conn->inCursor += msgLength;
288  }
289  else if (conn->result == NULL ||
290  conn->queryclass == PGQUERY_DESCRIBE)
291  {
292  /* First 'T' in a query sequence */
293  if (getRowDescriptions(conn, msgLength))
294  return;
295  /* getRowDescriptions() moves inStart itself */
296  continue;
297  }
298  else
299  {
300  /*
301  * A new 'T' message is treated as the start of
302  * another PGresult. (It is not clear that this is
303  * really possible with the current backend.) We stop
304  * parsing until the application accepts the current
305  * result.
306  */
307  conn->asyncStatus = PGASYNC_READY;
308  return;
309  }
310  break;
311  case 'n': /* No Data */
312 
313  /*
314  * NoData indicates that we will not be seeing a
315  * RowDescription message because the statement or portal
316  * inquired about doesn't return rows.
317  *
318  * If we're doing a Describe, we have to pass something
319  * back to the client, so set up a COMMAND_OK result,
320  * instead of TUPLES_OK. Otherwise we can just ignore
321  * this message.
322  */
323  if (conn->queryclass == PGQUERY_DESCRIBE)
324  {
325  if (conn->result == NULL)
326  {
327  conn->result = PQmakeEmptyPGresult(conn,
329  if (!conn->result)
330  {
332  libpq_gettext("out of memory"));
333  pqSaveErrorResult(conn);
334  }
335  }
336  conn->asyncStatus = PGASYNC_READY;
337  }
338  break;
339  case 't': /* Parameter Description */
340  if (getParamDescriptions(conn, msgLength))
341  return;
342  /* getParamDescriptions() moves inStart itself */
343  continue;
344  case 'D': /* Data Row */
345  if (conn->result != NULL &&
347  {
348  /* Read another tuple of a normal query response */
349  if (getAnotherTuple(conn, msgLength))
350  return;
351  /* getAnotherTuple() moves inStart itself */
352  continue;
353  }
354  else if (conn->result != NULL &&
356  {
357  /*
358  * We've already choked for some reason. Just discard
359  * tuples till we get to the end of the query.
360  */
361  conn->inCursor += msgLength;
362  }
363  else
364  {
365  /* Set up to report error at end of query */
367  libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
368  pqSaveErrorResult(conn);
369  /* Discard the unexpected message */
370  conn->inCursor += msgLength;
371  }
372  break;
373  case 'G': /* Start Copy In */
374  if (getCopyStart(conn, PGRES_COPY_IN))
375  return;
377  break;
378  case 'H': /* Start Copy Out */
379  if (getCopyStart(conn, PGRES_COPY_OUT))
380  return;
382  conn->copy_already_done = 0;
383  break;
384  case 'W': /* Start Copy Both */
385  if (getCopyStart(conn, PGRES_COPY_BOTH))
386  return;
388  conn->copy_already_done = 0;
389  break;
390  case 'd': /* Copy Data */
391 
392  /*
393  * If we see Copy Data, just silently drop it. This would
394  * only occur if application exits COPY OUT mode too
395  * early.
396  */
397  conn->inCursor += msgLength;
398  break;
399  case 'c': /* Copy Done */
400 
401  /*
402  * If we see Copy Done, just silently drop it. This is
403  * the normal case during PQendcopy. We will keep
404  * swallowing data, expecting to see command-complete for
405  * the COPY command.
406  */
407  break;
408  default:
411  "unexpected response from server; first received character was \"%c\"\n"),
412  id);
413  /* build an error result holding the error message */
414  pqSaveErrorResult(conn);
415  /* not sure if we will see more, so go to ready state */
416  conn->asyncStatus = PGASYNC_READY;
417  /* Discard the unexpected message */
418  conn->inCursor += msgLength;
419  break;
420  } /* switch on protocol character */
421  }
422  /* Successfully consumed this message */
423  if (conn->inCursor == conn->inStart + 5 + msgLength)
424  {
425  /* Normal case: parsing agrees with specified length */
426  conn->inStart = conn->inCursor;
427  }
428  else
429  {
430  /* Trouble --- report it */
432  libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
433  id);
434  /* build an error result holding the error message */
435  pqSaveErrorResult(conn);
436  conn->asyncStatus = PGASYNC_READY;
437  /* trust the specified message length as what to skip */
438  conn->inStart += 5 + msgLength;
439  }
440  }
441 }
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:163
PQExpBufferData workBuffer
Definition: libpq-int.h:497
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
PGQueryClass queryclass
Definition: libpq-int.h:383
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:267
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:650
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:451
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:472
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:875
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:747
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:94
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:40
PQExpBufferData errorMessage
Definition: libpq-int.h:494
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int getReadyForQuery(PGconn *conn)
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:178
int be_key
Definition: libpq-int.h:421
int copy_already_done
Definition: libpq-int.h:391
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:449
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:749
int inCursor
Definition: libpq-int.h:433
int be_pid
Definition: libpq-int.h:420
ExecStatusType resultStatus
Definition: libpq-int.h:177
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqPrepareAsyncResult()

PGresult* pqPrepareAsyncResult ( PGconn conn)

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

References appendPQExpBufferStr(), pg_conn::errorMessage, pg_conn::next_result, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), PQresultErrorMessage(), resetPQExpBuffer(), and pg_conn::result.

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

778 {
779  PGresult *res;
780 
781  /*
782  * conn->result is the PGresult to return. If it is NULL (which probably
783  * shouldn't happen) we assume there is an appropriate error message in
784  * conn->errorMessage.
785  */
786  res = conn->result;
787  if (!res)
789  else
790  {
791  /*
792  * Make sure PQerrorMessage agrees with result; it could be different
793  * if we have concatenated messages.
794  */
797  PQresultErrorMessage(res));
798  }
799 
800  /*
801  * Replace conn->result with next_result, if any. In the normal case
802  * there isn't a next result and we're just dropping ownership of the
803  * current result. In single-row mode this restores the situation to what
804  * it was before we created the current single-row result.
805  */
806  conn->result = conn->next_result;
807  conn->next_result = NULL;
808 
809  return res;
810 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
PGresult * result
Definition: libpq-int.h:451
PGresult * next_result
Definition: libpq-int.h:452
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
PQExpBufferData errorMessage
Definition: libpq-int.h:494
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2663
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)

Definition at line 112 of file fe-misc.c.

References pg_conn::Pfdebug, and pqPutMsgBytes().

Referenced by PQsendDescribe(), and PQsendQueryGuts().

113 {
114  if (pqPutMsgBytes(&c, 1, conn))
115  return EOF;
116 
117  if (conn->Pfdebug)
118  fprintf(conn->Pfdebug, "To backend> %c\n", c);
119 
120  return 0;
121 }
FILE * Pfdebug
Definition: libpq-int.h:369
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564
char * c

◆ pqPutInt()

int pqPutInt ( int  value,
size_t  bytes,
PGconn conn 
)

Definition at line 307 of file fe-misc.c.

References pg_conn::noticeHooks, pg_conn::Pfdebug, pg_hton16, pg_hton32, pqInternalNotice(), and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall2(), pqFunctionCall3(), PQsendPrepare(), and PQsendQueryGuts().

308 {
309  uint16 tmp2;
310  uint32 tmp4;
311 
312  switch (bytes)
313  {
314  case 2:
315  tmp2 = pg_hton16((uint16) value);
316  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
317  return EOF;
318  break;
319  case 4:
320  tmp4 = pg_hton32((uint32) value);
321  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
322  return EOF;
323  break;
324  default:
326  "integer of size %lu not supported by pqPutInt",
327  (unsigned long) bytes);
328  return EOF;
329  }
330 
331  if (conn->Pfdebug)
332  fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
333 
334  return 0;
335 }
#define pg_hton16(x)
Definition: pg_bswap.h:120
FILE * Pfdebug
Definition: libpq-int.h:369
unsigned short uint16
Definition: c.h:324
#define pg_hton32(x)
Definition: pg_bswap.h:121
PGNoticeHooks noticeHooks
Definition: libpq-int.h:372
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:822
unsigned int uint32
Definition: c.h:325
static struct @131 value

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

Definition at line 587 of file fe-misc.c.

References pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, and pqSendSome().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), and sendTerminateConn().

588 {
589  if (conn->Pfdebug)
590  fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
591  conn->outMsgEnd - conn->outCount);
592 
593  /* Fill in length word if needed */
594  if (conn->outMsgStart >= 0)
595  {
596  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
597 
598  msgLen = pg_hton32(msgLen);
599  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
600  }
601 
602  /* Make message eligible to send */
603  conn->outCount = conn->outMsgEnd;
604 
605  if (conn->outCount >= 8192)
606  {
607  int toSend = conn->outCount - (conn->outCount % 8192);
608 
609  if (pqSendSome(conn, toSend) < 0)
610  return EOF;
611  /* in nonblock mode, don't complain if unable to send it all */
612  }
613 
614  return 0;
615 }
int outCount
Definition: libpq-int.h:439
int outMsgEnd
Definition: libpq-int.h:444
FILE * Pfdebug
Definition: libpq-int.h:369
#define pg_hton32(x)
Definition: pg_bswap.h:121
unsigned int uint32
Definition: c.h:325
int outMsgStart
Definition: libpq-int.h:442
char * outBuffer
Definition: libpq-int.h:437
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:829

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
bool  force_len,
PGconn conn 
)

Definition at line 519 of file fe-misc.c.

References pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, PG_PROTOCOL_MAJOR, pqCheckOutBufferSpace(), and pg_conn::pversion.

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), and sendTerminateConn().

520 {
521  int lenPos;
522  int endPos;
523 
524  /* allow room for message type byte */
525  if (msg_type)
526  endPos = conn->outCount + 1;
527  else
528  endPos = conn->outCount;
529 
530  /* do we want a length word? */
531  if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
532  {
533  lenPos = endPos;
534  /* allow room for message length */
535  endPos += 4;
536  }
537  else
538  lenPos = -1;
539 
540  /* make sure there is room for message header */
541  if (pqCheckOutBufferSpace(endPos, conn))
542  return EOF;
543  /* okay, save the message type byte if any */
544  if (msg_type)
545  conn->outBuffer[conn->outCount] = msg_type;
546  /* set up the message pointers */
547  conn->outMsgStart = lenPos;
548  conn->outMsgEnd = endPos;
549  /* length word, if needed, will be filled in by pqPutMsgEnd */
550 
551  if (conn->Pfdebug)
552  fprintf(conn->Pfdebug, "To backend> Msg %c\n",
553  msg_type ? msg_type : ' ');
554 
555  return 0;
556 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:344
int outCount
Definition: libpq-int.h:439
int outMsgEnd
Definition: libpq-int.h:444
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
FILE * Pfdebug
Definition: libpq-int.h:369
int outMsgStart
Definition: libpq-int.h:442
ProtocolVersion pversion
Definition: libpq-int.h:405
char * outBuffer
Definition: libpq-int.h:437

◆ pqPutnchar()

int pqPutnchar ( const char *  s,
size_t  len,
PGconn conn 
)

Definition at line 246 of file fe-misc.c.

References fputnbytes(), pg_conn::Pfdebug, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), and PQsendQueryGuts().

247 {
248  if (pqPutMsgBytes(s, len, conn))
249  return EOF;
250 
251  if (conn->Pfdebug)
252  {
253  fprintf(conn->Pfdebug, "To backend> ");
254  fputnbytes(conn->Pfdebug, s, len);
255  fprintf(conn->Pfdebug, "\n");
256  }
257 
258  return 0;
259 }
FILE * Pfdebug
Definition: libpq-int.h:369
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564
static void fputnbytes(FILE *f, const char *str, size_t n)
Definition: fe-misc.c:79

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

Definition at line 179 of file fe-misc.c.

References pg_conn::Pfdebug, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall2(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), and PQsendQueryGuts().

180 {
181  if (pqPutMsgBytes(s, strlen(s) + 1, conn))
182  return EOF;
183 
184  if (conn->Pfdebug)
185  fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
186 
187  return 0;
188 }
FILE * Pfdebug
Definition: libpq-int.h:369
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:564

◆ pqReadData()

int pqReadData ( PGconn conn)

Definition at line 629 of file fe-misc.c.

References CONNECTION_BAD, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, memmove, PGINVALID_SOCKET, pqCheckInBufferSpace(), pqDropConnection(), pqReadReady(), pqsecure_read(), printfPQExpBuffer(), pg_conn::sock, SOCK_ERRNO, pg_conn::ssl_in_use, and pg_conn::status.

Referenced by PQconnectPoll(), PQconsumeInput(), pqFunctionCall2(), pqFunctionCall3(), pqGetCopyData2(), pqGetCopyData3(), pqGetline2(), pqGetline3(), PQgetResult(), pqHandleSendFailure(), pqSendSome(), and pqSetenvPoll().

630 {
631  int someread = 0;
632  int nread;
633 
634  if (conn->sock == PGINVALID_SOCKET)
635  {
637  libpq_gettext("connection not open\n"));
638  return -1;
639  }
640 
641  /* Left-justify any data in the buffer to make room */
642  if (conn->inStart < conn->inEnd)
643  {
644  if (conn->inStart > 0)
645  {
646  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
647  conn->inEnd - conn->inStart);
648  conn->inEnd -= conn->inStart;
649  conn->inCursor -= conn->inStart;
650  conn->inStart = 0;
651  }
652  }
653  else
654  {
655  /* buffer is logically empty, reset it */
656  conn->inStart = conn->inCursor = conn->inEnd = 0;
657  }
658 
659  /*
660  * If the buffer is fairly full, enlarge it. We need to be able to enlarge
661  * the buffer in case a single message exceeds the initial buffer size. We
662  * enlarge before filling the buffer entirely so as to avoid asking the
663  * kernel for a partial packet. The magic constant here should be large
664  * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
665  * buffer size, so...
666  */
667  if (conn->inBufSize - conn->inEnd < 8192)
668  {
669  if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
670  {
671  /*
672  * We don't insist that the enlarge worked, but we need some room
673  */
674  if (conn->inBufSize - conn->inEnd < 100)
675  return -1; /* errorMessage already set */
676  }
677  }
678 
679  /* OK, try to read some data */
680 retry3:
681  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
682  conn->inBufSize - conn->inEnd);
683  if (nread < 0)
684  {
685  if (SOCK_ERRNO == EINTR)
686  goto retry3;
687  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
688 #ifdef EAGAIN
689  if (SOCK_ERRNO == EAGAIN)
690  return someread;
691 #endif
692 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
693  if (SOCK_ERRNO == EWOULDBLOCK)
694  return someread;
695 #endif
696  /* We might get ECONNRESET here if using TCP and backend died */
697 #ifdef ECONNRESET
698  if (SOCK_ERRNO == ECONNRESET)
699  goto definitelyFailed;
700 #endif
701  /* pqsecure_read set the error message for us */
702  return -1;
703  }
704  if (nread > 0)
705  {
706  conn->inEnd += nread;
707 
708  /*
709  * Hack to deal with the fact that some kernels will only give us back
710  * 1 packet per recv() call, even if we asked for more and there is
711  * more available. If it looks like we are reading a long message,
712  * loop back to recv() again immediately, until we run out of data or
713  * buffer space. Without this, the block-and-restart behavior of
714  * libpq's higher levels leads to O(N^2) performance on long messages.
715  *
716  * Since we left-justified the data above, conn->inEnd gives the
717  * amount of data already read in the current message. We consider
718  * the message "long" once we have acquired 32k ...
719  */
720  if (conn->inEnd > 32768 &&
721  (conn->inBufSize - conn->inEnd) >= 8192)
722  {
723  someread = 1;
724  goto retry3;
725  }
726  return 1;
727  }
728 
729  if (someread)
730  return 1; /* got a zero read after successful tries */
731 
732  /*
733  * A return value of 0 could mean just that no data is now available, or
734  * it could mean EOF --- that is, the server has closed the connection.
735  * Since we have the socket in nonblock mode, the only way to tell the
736  * difference is to see if select() is saying that the file is ready.
737  * Grumble. Fortunately, we don't expect this path to be taken much,
738  * since in normal practice we should not be trying to read data unless
739  * the file selected for reading already.
740  *
741  * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
742  * data could arrive before we make the pqReadReady() test, but the second
743  * SSL_read() could still say WANT_READ because the data received was not
744  * a complete SSL record. So we must play dumb and assume there is more
745  * data, relying on the SSL layer to detect true EOF.
746  */
747 
748 #ifdef USE_SSL
749  if (conn->ssl_in_use)
750  return 0;
751 #endif
752 
753  switch (pqReadReady(conn))
754  {
755  case 0:
756  /* definitely no data available */
757  return 0;
758  case 1:
759  /* ready for read */
760  break;
761  default:
762  /* we override pqReadReady's message with something more useful */
763  goto definitelyEOF;
764  }
765 
766  /*
767  * Still not sure that it's EOF, because some data could have just
768  * arrived.
769  */
770 retry4:
771  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
772  conn->inBufSize - conn->inEnd);
773  if (nread < 0)
774  {
775  if (SOCK_ERRNO == EINTR)
776  goto retry4;
777  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
778 #ifdef EAGAIN
779  if (SOCK_ERRNO == EAGAIN)
780  return 0;
781 #endif
782 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
783  if (SOCK_ERRNO == EWOULDBLOCK)
784  return 0;
785 #endif
786  /* We might get ECONNRESET here if using TCP and backend died */
787 #ifdef ECONNRESET
788  if (SOCK_ERRNO == ECONNRESET)
789  goto definitelyFailed;
790 #endif
791  /* pqsecure_read set the error message for us */
792  return -1;
793  }
794  if (nread > 0)
795  {
796  conn->inEnd += nread;
797  return 1;
798  }
799 
800  /*
801  * OK, we are getting a zero read even though select() says ready. This
802  * means the connection has been closed. Cope.
803  */
804 definitelyEOF:
807  "server closed the connection unexpectedly\n"
808  "\tThis probably means the server terminated abnormally\n"
809  "\tbefore or while processing the request.\n"));
810 
811  /* Come here if lower-level code already set a suitable errorMessage */
812 definitelyFailed:
813  /* Do *not* drop any already-read data; caller still wants it */
814  pqDropConnection(conn, false);
815  conn->status = CONNECTION_BAD; /* No more connection to backend */
816  return -1;
817 }
int inEnd
Definition: libpq-int.h:434
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
int inStart
Definition: libpq-int.h:432
int pqReadReady(PGconn *conn)
Definition: fe-misc.c:1021
#define EAGAIN
Definition: win32_port.h:332
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:408
ssize_t pqsecure_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:213
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:431
#define SOCK_ERRNO
Definition: libpq-int.h:773
int inBufSize
Definition: libpq-int.h:431
bool ssl_in_use
Definition: libpq-int.h:458
#define memmove(d, s, c)
Definition: c.h:1135
pgsocket sock
Definition: libpq-int.h:401
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:430
PQExpBufferData errorMessage
Definition: libpq-int.h:494
ConnStatusType status
Definition: libpq-int.h:380
#define ECONNRESET
Definition: win32_port.h:344
#define EWOULDBLOCK
Definition: win32_port.h:340
int inCursor
Definition: libpq-int.h:433
#define EINTR
Definition: win32_port.h:334
#define libpq_gettext(x)
Definition: libpq-int.h:760

◆ pqReadReady()

int pqReadReady ( PGconn conn)

Definition at line 1021 of file fe-misc.c.

References pqSocketCheck().

Referenced by pqReadData().

1022 {
1023  return pqSocketCheck(conn, 1, 0, (time_t) 0);
1024 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1045

◆ pqResultAlloc()

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

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

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

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

528 {
529  char *space;
530  PGresult_data *block;
531 
532  if (!res)
533  return NULL;
534 
535  if (nBytes <= 0)
536  return res->null_field;
537 
538  /*
539  * If alignment is needed, round up the current position to an alignment
540  * boundary.
541  */
542  if (isBinary)
543  {
544  int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
545 
546  if (offset)
547  {
548  res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
549  res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
550  }
551  }
552 
553  /* If there's enough space in the current block, no problem. */
554  if (nBytes <= (size_t) res->spaceLeft)
555  {
556  space = res->curBlock->space + res->curOffset;
557  res->curOffset += nBytes;
558  res->spaceLeft -= nBytes;
559  return space;
560  }
561 
562  /*
563  * If the requested object is very large, give it its own block; this
564  * avoids wasting what might be most of the current block to start a new
565  * block. (We'd have to special-case requests bigger than the block size
566  * anyway.) The object is always given binary alignment in this case.
567  */
568  if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
569  {
570  block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
571  if (!block)
572  return NULL;
573  space = block->space + PGRESULT_BLOCK_OVERHEAD;
574  if (res->curBlock)
575  {
576  /*
577  * Tuck special block below the active block, so that we don't
578  * have to waste the free space in the active block.
579  */
580  block->next = res->curBlock->next;
581  res->curBlock->next = block;
582  }
583  else
584  {
585  /* Must set up the new block as the first active block. */
586  block->next = NULL;
587  res->curBlock = block;
588  res->spaceLeft = 0; /* be sure it's marked full */
589  }
590  return space;
591  }
592 
593  /* Otherwise, start a new block. */
595  if (!block)
596  return NULL;
597  block->next = res->curBlock;
598  res->curBlock = block;
599  if (isBinary)
600  {
601  /* object needs full alignment */
604  }
605  else
606  {
607  /* we can cram it right after the overhead pointer */
608  res->curOffset = sizeof(PGresult_data);
610  }
611 
612  space = block->space + res->curOffset;
613  res->curOffset += nBytes;
614  res->spaceLeft -= nBytes;
615  return space;
616 }
char space[1]
Definition: libpq-int.h:106
PGresult_data * next
Definition: libpq-int.h:105
union pgresult_data PGresult_data
Definition: libpq-int.h:101
int spaceLeft
Definition: libpq-int.h:210
char null_field[1]
Definition: libpq-int.h:201
#define malloc(a)
Definition: header.h:50
#define PGRESULT_ALIGN_BOUNDARY
Definition: fe-exec.c:130
int curOffset
Definition: libpq-int.h:209
#define PGRESULT_BLOCK_OVERHEAD
Definition: fe-exec.c:131
PGresult_data * curBlock
Definition: libpq-int.h:208
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition: fe-exec.c:132
#define PGRESULT_DATA_BLOCKSIZE
Definition: fe-exec.c:129

◆ pqResultStrdup()

char* pqResultStrdup ( PGresult res,
const char *  str 
)

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

References pqResultAlloc().

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

624 {
625  char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
626 
627  if (space)
628  strcpy(space, str);
629  return space;
630 }
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527

◆ pqRowProcessor()

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

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

References pg_conn::asyncStatus, pg_result::attDescs, pgresAttDesc::format, i, pgresAttValue::len, pgDataValue::len, pg_conn::next_result, pg_result::null_field, NULL_LEN, pg_result::numAttributes, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY, PGRES_SINGLE_TUPLE, pqAddTuple(), PQclear(), PQcopyResult(), pqResultAlloc(), pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::singleRowMode, val, pgresAttValue::value, and value.

Referenced by getAnotherTuple().

1082 {
1083  PGresult *res = conn->result;
1084  int nfields = res->numAttributes;
1085  const PGdataValue *columns = conn->rowBuf;
1086  PGresAttValue *tup;
1087  int i;
1088 
1089  /*
1090  * In single-row mode, make a new PGresult that will hold just this one
1091  * row; the original conn->result is left unchanged so that it can be used
1092  * again as the template for future rows.
1093  */
1094  if (conn->singleRowMode)
1095  {
1096  /* Copy everything that should be in the result at this point */
1097  res = PQcopyResult(res,
1100  if (!res)
1101  return 0;
1102  }
1103 
1104  /*
1105  * Basically we just allocate space in the PGresult for each field and
1106  * copy the data over.
1107  *
1108  * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1109  * caller will take to mean "out of memory". This is preferable to trying
1110  * to set up such a message here, because evidently there's not enough
1111  * memory for gettext() to do anything.
1112  */
1113  tup = (PGresAttValue *)
1114  pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1115  if (tup == NULL)
1116  goto fail;
1117 
1118  for (i = 0; i < nfields; i++)
1119  {
1120  int clen = columns[i].len;
1121 
1122  if (clen < 0)
1123  {
1124  /* null field */
1125  tup[i].len = NULL_LEN;
1126  tup[i].value = res->null_field;
1127  }
1128  else
1129  {
1130  bool isbinary = (res->attDescs[i].format != 0);
1131  char *val;
1132 
1133  val = (char *) pqResultAlloc(res, clen + 1, isbinary);
1134  if (val == NULL)
1135  goto fail;
1136 
1137  /* copy and zero-terminate the data (even if it's binary) */
1138  memcpy(val, columns[i].value, clen);
1139  val[clen] = '\0';
1140 
1141  tup[i].len = clen;
1142  tup[i].value = val;
1143  }
1144  }
1145 
1146  /* And add the tuple to the PGresult's tuple array */
1147  if (!pqAddTuple(res, tup, errmsgp))
1148  goto fail;
1149 
1150  /*
1151  * Success. In single-row mode, make the result available to the client
1152  * immediately.
1153  */
1154  if (conn->singleRowMode)
1155  {
1156  /* Change result status to special single-row value */
1158  /* Stash old result for re-use later */
1159  conn->next_result = conn->result;
1160  conn->result = res;
1161  /* And mark the result ready to return */
1162  conn->asyncStatus = PGASYNC_READY;
1163  }
1164 
1165  return 1;
1166 
1167 fail:
1168  /* release locally allocated PGresult, if we made one */
1169  if (res != conn->result)
1170  PQclear(res);
1171  return 0;
1172 }
bool singleRowMode
Definition: libpq-int.h:389
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition: fe-exec.c:293
#define NULL_LEN
Definition: libpq-int.h:133
char null_field[1]
Definition: libpq-int.h:201
PGresAttDesc * attDescs
Definition: libpq-int.h:171
PGresult * result
Definition: libpq-int.h:451
PGresult * next_result
Definition: libpq-int.h:452
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:381
#define PG_COPYRES_EVENTS
Definition: libpq-fe.h:36
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition: fe-exec.c:877
#define PG_COPYRES_NOTICEHOOKS
Definition: libpq-fe.h:37
PGdataValue * rowBuf
Definition: libpq-int.h:447
int numAttributes
Definition: libpq-int.h:170
static struct @131 value
#define PG_COPYRES_ATTRS
Definition: libpq-fe.h:34
void PQclear(PGresult *res)
Definition: fe-exec.c:671
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527
int i
char * value
Definition: libpq-int.h:138
ExecStatusType resultStatus
Definition: libpq-int.h:177
long val
Definition: informix.c:689

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)

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

References PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, PGRES_FATAL_ERROR, pqCatenateResultError(), pqClearAsyncResult(), PQmakeEmptyPGresult(), pg_conn::result, and pg_result::resultStatus.

Referenced by getAnotherTuple(), getCopyResult(), getParamDescriptions(), getRowDescriptions(), handleSyncLoss(), pqFunctionCall2(), pqFunctionCall3(), PQgetResult(), pqParseInput2(), and pqParseInput3().

750 {
751  /*
752  * If no old async result, just let PQmakeEmptyPGresult make one. Likewise
753  * if old result is not an error message.
754  */
755  if (conn->result == NULL ||
757  conn->result->errMsg == NULL)
758  {
759  pqClearAsyncResult(conn);
761  }
762  else
763  {
764  /* Else, concatenate error message to existing async result. */
766  }
767 }
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:451
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:142
PQExpBufferData errorMessage
Definition: libpq-int.h:494
void pqCatenateResultError(PGresult *res, const char *msg)
Definition: fe-exec.c:652
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:726
ExecStatusType resultStatus
Definition: libpq-int.h:177

◆ pqSaveMessageField()

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

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

References pgMessageField::code, pgMessageField::contents, pg_result::errFields, pgMessageField::next, offsetof, and pqResultAlloc().

Referenced by pqGetErrorNotice2(), pqGetErrorNotice3(), and pqInternalNotice().

943 {
944  PGMessageField *pfield;
945 
946  pfield = (PGMessageField *)
947  pqResultAlloc(res,
948  offsetof(PGMessageField, contents) +
949  strlen(value) + 1,
950  true);
951  if (!pfield)
952  return; /* out of memory? */
953  pfield->code = code;
954  strcpy(pfield->contents, value);
955  pfield->next = res->errFields;
956  res->errFields = pfield;
957 }
PGMessageField * errFields
Definition: libpq-int.h:197
struct pgMessageField * next
Definition: libpq-int.h:144
static struct @131 value
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:527
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition: libpq-int.h:146
#define offsetof(type, field)
Definition: c.h:622

◆ pqSaveParameterStatus()

void pqSaveParameterStatus ( PGconn conn,
const char *  name,
const char *  value 
)

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

References pg_conn::client_encoding, free, malloc, pgParameterStatus::name, pgParameterStatus::next, pg_conn::Pfdebug, pg_char_to_encoding(), PG_SQL_ASCII, pg_conn::pstatus, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, and pgParameterStatus::value.

Referenced by getParameterStatus(), PQsetClientEncoding(), and pqSetenvPoll().

964 {
965  pgParameterStatus *pstatus;
966  pgParameterStatus *prev;
967 
968  if (conn->Pfdebug)
969  fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
970  name, value);
971 
972  /*
973  * Forget any old information about the parameter
974  */
975  for (pstatus = conn->pstatus, prev = NULL;
976  pstatus != NULL;
977  prev = pstatus, pstatus = pstatus->next)
978  {
979  if (strcmp(pstatus->name, name) == 0)
980  {
981  if (prev)
982  prev->next = pstatus->next;
983  else
984  conn->pstatus = pstatus->next;
985  free(pstatus); /* frees name and value strings too */
986  break;
987  }
988  }
989 
990  /*
991  * Store new info as a single malloc block
992  */
993  pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
994  strlen(name) + strlen(value) + 2);
995  if (pstatus)
996  {
997  char *ptr;
998 
999  ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1000  pstatus->name = ptr;
1001  strcpy(ptr, name);
1002  ptr += strlen(name) + 1;
1003  pstatus->value = ptr;
1004  strcpy(ptr, value);
1005  pstatus->next = conn->pstatus;
1006  conn->pstatus = pstatus;
1007  }
1008 
1009  /*
1010  * Special hacks: remember client_encoding and
1011  * standard_conforming_strings, and convert server version to a numeric
1012  * form. We keep the first two of these in static variables as well, so
1013  * that PQescapeString and PQescapeBytea can behave somewhat sanely (at
1014  * least in single-connection-using programs).
1015  */
1016  if (strcmp(name, "client_encoding") == 0)
1017  {
1019  /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1020  if (conn->client_encoding < 0)
1021  conn->client_encoding = PG_SQL_ASCII;
1023  }
1024  else if (strcmp(name, "standard_conforming_strings") == 0)
1025  {
1026  conn->std_strings = (strcmp(value, "on") == 0);
1028  }
1029  else if (strcmp(name, "server_version") == 0)
1030  {
1031  int cnt;
1032  int vmaj,
1033  vmin,
1034  vrev;
1035 
1036  cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1037 
1038  if (cnt == 3)
1039  {
1040  /* old style, e.g. 9.6.1 */
1041  conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1042  }
1043  else if (cnt == 2)
1044  {
1045  if (vmaj >= 10)
1046  {
1047  /* new style, e.g. 10.1 */
1048  conn->sversion = 100 * 100 * vmaj + vmin;
1049  }
1050  else
1051  {
1052  /* old style without minor version, e.g. 9.6devel */
1053  conn->sversion = (100 * vmaj + vmin) * 100;
1054  }
1055  }
1056  else if (cnt == 1)
1057  {
1058  /* new style without minor version, e.g. 10devel */
1059  conn->sversion = 100 * 100 * vmaj;
1060  }
1061  else
1062  conn->sversion = 0; /* unknown */
1063  }
1064 }
static bool static_std_strings
Definition: fe-exec.c:51
int pg_char_to_encoding(const char *name)
Definition: encnames.c:551
FILE * Pfdebug
Definition: libpq-int.h:369
#define malloc(a)
Definition: header.h:50
int sversion
Definition: libpq-int.h:406
struct pgParameterStatus pgParameterStatus
static int static_client_encoding
Definition: fe-exec.c:50
pgParameterStatus * pstatus
Definition: libpq-int.h:422
static struct @131 value
bool std_strings
Definition: libpq-int.h:424
#define free(a)
Definition: header.h:65
struct pgParameterStatus * next
Definition: libpq-int.h:258
const char * name
Definition: encode.c:521
int client_encoding
Definition: libpq-int.h:423

◆ pqsecure_close()

void pqsecure_close ( PGconn )

Definition at line 197 of file fe-secure.c.

References pgtls_close(), and pg_conn::ssl_in_use.

Referenced by pqDropConnection().

198 {
199 #ifdef USE_SSL
200  if (conn->ssl_in_use)
201  pgtls_close(conn);
202 #endif
203 }
PGconn * conn
Definition: streamutil.c:55
bool ssl_in_use
Definition: libpq-int.h:458
void pgtls_close(PGconn *conn)

◆ pqsecure_destroy()

void pqsecure_destroy ( void  )

◆ pqsecure_initialize()

int pqsecure_initialize ( PGconn )

Definition at line 168 of file fe-secure.c.

References pgtls_init().

Referenced by PQconnectPoll().

169 {
170  int r = 0;
171 
172 #ifdef USE_SSL
173  r = pgtls_init(conn);
174 #endif
175 
176  return r;
177 }
PGconn * conn
Definition: streamutil.c:55
int pgtls_init(PGconn *conn)

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn )

Definition at line 183 of file fe-secure.c.

References PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

184 {
185 #ifdef USE_SSL
186  return pgtls_open_client(conn);
187 #else
188  /* shouldn't get here */
189  return PGRES_POLLING_FAILED;
190 #endif
191 }
PostgresPollingStatusType pgtls_open_client(PGconn *conn)
PGconn * conn
Definition: streamutil.c:55

◆ pqsecure_raw_read()

ssize_t pqsecure_raw_read ( PGconn ,
void *  ptr,
size_t  len 
)

Definition at line 232 of file fe-secure.c.

References EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, printfPQExpBuffer(), recv, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by my_sock_read(), and pqsecure_read().

233 {
234  ssize_t n;
235  int result_errno = 0;
236  char sebuf[256];
237 
238  n = recv(conn->sock, ptr, len, 0);
239 
240  if (n < 0)
241  {
242  result_errno = SOCK_ERRNO;
243 
244  /* Set error message if appropriate */
245  switch (result_errno)
246  {
247 #ifdef EAGAIN
248  case EAGAIN:
249 #endif
250 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
251  case EWOULDBLOCK:
252 #endif
253  case EINTR:
254  /* no error message, caller is expected to retry */
255  break;
256 
257 #ifdef ECONNRESET
258  case ECONNRESET:
261  "server closed the connection unexpectedly\n"
262  "\tThis probably means the server terminated abnormally\n"
263  "\tbefore or while processing the request.\n"));
264  break;
265 #endif
266 
267  default:
269  libpq_gettext("could not receive data from server: %s\n"),
270  SOCK_STRERROR(result_errno,
271  sebuf, sizeof(sebuf)));
272  break;
273  }
274  }
275 
276  /* ensure we return the intended errno to caller */
277  SOCK_ERRNO_SET(result_errno);
278 
279  return n;
280 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define EAGAIN
<