libpq-int.h 18 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * libpq-int.h
4 5 6
 *	  This file contains internal definitions meant to be used only by
 *	  the frontend libpq library, not by applications that call it.
 *
7 8 9 10 11
 *	  An application can include this file if it wants to bypass the
 *	  official API defined by libpq-fe.h, but code that does so is much
 *	  more likely to break across PostgreSQL releases than code that uses
 *	  only the official API.
 *
Bruce Momjian's avatar
Bruce Momjian committed
12
 * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
13
 * Portions Copyright (c) 1994, Regents of the University of California
14
 *
15
 * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.98 2004/12/02 23:20:21 tgl Exp $
16 17 18 19 20 21 22
 *
 *-------------------------------------------------------------------------
 */

#ifndef LIBPQ_INT_H
#define LIBPQ_INT_H

23 24 25
/* We assume libpq-fe.h has already been included. */
#include "postgres_fe.h"

26
#include <time.h>
Tom Lane's avatar
Tom Lane committed
27
#include <sys/types.h>
28 29 30
#ifndef WIN32
#include <sys/time.h>
#endif
31

32 33
#ifdef ENABLE_THREAD_SAFETY
#include <pthread.h>
34
#include <signal.h>
35
#endif
36

37
#ifdef WIN32_CLIENT_ONLY
38
typedef int ssize_t;			/* ssize_t doesn't exist in VC (at least
Bruce Momjian's avatar
Bruce Momjian committed
39 40
								 * not VC6) */
#endif
41

42
/* include stuff common to fe and be */
43
#include "getaddrinfo.h"
44
#include "libpq/pqcomm.h"
45 46 47
/* include stuff found in fe only */
#include "pqexpbuffer.h"

48
#ifdef USE_SSL
49 50
#include <openssl/ssl.h>
#include <openssl/err.h>
51 52
#endif

53 54 55
/*
 * POSTGRES backend dependent Constants.
 */
Bruce Momjian's avatar
Bruce Momjian committed
56
#define PQERRORMSG_LENGTH 1024
57 58
#define CMDSTATUS_LEN 40

59 60
/*
 * PGresult and the subsidiary types PGresAttDesc, PGresAttValue
61 62 63 64 65
 * represent the result of a query (or more precisely, of a single SQL
 * command --- a query string given to PQexec can contain multiple commands).
 * Note we assume that a single command can return at most one tuple group,
 * hence there is no need for multiple descriptor sets.
 */
66 67 68 69

/* Subsidiary-storage management structure for PGresult.
 * See space management routines in fe-exec.c for details.
 * Note that space[k] refers to the k'th byte starting from the physical
70
 * head of the block --- it's a union, not a struct!
71
 */
Bruce Momjian's avatar
Bruce Momjian committed
72
typedef union pgresult_data PGresult_data;
73

Bruce Momjian's avatar
Bruce Momjian committed
74 75 76 77 78
union pgresult_data
{
	PGresult_data *next;		/* link to next block, or NULL */
	char		space[1];		/* dummy for accessing block as bytes */
};
79 80 81

/* Data about a single attribute (column) of a query result */

Bruce Momjian's avatar
Bruce Momjian committed
82 83
typedef struct pgresAttDesc
{
84 85 86 87
	char	   *name;			/* column name */
	Oid			tableid;		/* source table, if known */
	int			columnid;		/* source column, if known */
	int			format;			/* format code for value (text/binary) */
Bruce Momjian's avatar
Bruce Momjian committed
88 89 90
	Oid			typid;			/* type id */
	int			typlen;			/* type size */
	int			atttypmod;		/* type-specific modifier info */
91
} PGresAttDesc;
92

93 94 95 96 97 98 99
/*
 * Data for a single attribute of a single tuple
 *
 * We use char* for Attribute values.
 *
 * The value pointer always points to a null-terminated area; we add a
 * null (zero) byte after whatever the backend sends us.  This is only
100
 * particularly useful for text values ... with a binary value, the
101 102 103 104 105 106 107 108
 * value might have embedded nulls, so the application can't use C string
 * operators on it.  But we add a null anyway for consistency.
 * Note that the value itself does not contain a length word.
 *
 * A NULL attribute is a special case in two ways: its len field is NULL_LEN
 * and its value field points to null_field in the owning PGresult.  All the
 * NULL attributes in a query result point to the same place (there's no need
 * to store a null string separately for each one).
109 110 111 112
 */

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

Bruce Momjian's avatar
Bruce Momjian committed
113 114 115 116 117
typedef struct pgresAttValue
{
	int			len;			/* length in bytes of the value */
	char	   *value;			/* actual value, plus terminating zero
								 * byte */
118
} PGresAttValue;
Bruce Momjian's avatar
Bruce Momjian committed
119

120 121 122 123 124 125
/* Typedef for message-field list entries */
typedef struct pgMessageField
{
	struct pgMessageField *next;	/* list link */
	char		code;			/* field code */
	char		contents[1];	/* field value (VARIABLE LENGTH) */
126
} PGMessageField;
127 128 129 130

/* Fields needed for notice handling */
typedef struct
{
Bruce Momjian's avatar
Bruce Momjian committed
131
	PQnoticeReceiver noticeRec; /* notice message receiver */
132
	void	   *noticeRecArg;
Bruce Momjian's avatar
Bruce Momjian committed
133
	PQnoticeProcessor noticeProc;		/* notice message processor */
134
	void	   *noticeProcArg;
135
} PGNoticeHooks;
136

Bruce Momjian's avatar
Bruce Momjian committed
137 138 139 140 141 142
struct pg_result
{
	int			ntups;
	int			numAttributes;
	PGresAttDesc *attDescs;
	PGresAttValue **tuples;		/* each PGresTuple is an array of
143
								 * PGresAttValue's */
144
	int			tupArrSize;		/* allocated size of tuples array */
Bruce Momjian's avatar
Bruce Momjian committed
145 146
	ExecStatusType resultStatus;
	char		cmdStatus[CMDSTATUS_LEN];		/* cmd status from the
147
												 * query */
Bruce Momjian's avatar
Bruce Momjian committed
148
	int			binary;			/* binary tuple values if binary == 1,
149
								 * otherwise text */
150

151 152 153
	/*
	 * These fields are copied from the originating PGconn, so that
	 * operations on the PGresult don't have to reference the PGconn.
154
	 */
155
	PGNoticeHooks noticeHooks;
156
	int			client_encoding;	/* encoding id */
157

158 159 160
	/*
	 * Error information (all NULL if not an error result).  errMsg is the
	 * "overall" error message returned by PQresultErrorMessage.  If we
161
	 * have per-field info then it is stored in a linked list.
162
	 */
Bruce Momjian's avatar
Bruce Momjian committed
163
	char	   *errMsg;			/* error message, or NULL if no error */
164
	PGMessageField *errFields;	/* message broken into fields */
165

Bruce Momjian's avatar
Bruce Momjian committed
166 167 168 169
	/* All NULL attributes in the query result point to this null string */
	char		null_field[1];

	/*
170 171
	 * Space management information.  Note that attDescs and error stuff,
	 * if not null, point into allocated blocks.  But tuples points to a
Bruce Momjian's avatar
Bruce Momjian committed
172 173 174 175 176 177
	 * separately malloc'd block, so that we can realloc it.
	 */
	PGresult_data *curBlock;	/* most recently allocated block */
	int			curOffset;		/* start offset of free space in block */
	int			spaceLeft;		/* number of free bytes remaining in block */
};
178 179

/* PGAsyncStatusType defines the state of the query-execution state machine */
Bruce Momjian's avatar
Bruce Momjian committed
180 181
typedef enum
{
182 183 184 185 186
	PGASYNC_IDLE,				/* nothing's happening, dude */
	PGASYNC_BUSY,				/* query in progress */
	PGASYNC_READY,				/* result ready for PQgetResult */
	PGASYNC_COPY_IN,			/* Copy In data transfer in progress */
	PGASYNC_COPY_OUT			/* Copy Out data transfer in progress */
187
} PGAsyncStatusType;
188

189 190 191 192 193 194 195 196
/* PGQueryClass tracks which query protocol we are now executing */
typedef enum
{
	PGQUERY_SIMPLE,				/* simple Query protocol (PQexec) */
	PGQUERY_EXTENDED,			/* full Extended protocol (PQexecParams) */
	PGQUERY_PREPARE				/* Parse only (PQprepare) */
} PGQueryClass;

197 198 199 200 201 202 203 204 205 206 207
/* PGSetenvStatusType defines the state of the PQSetenv state machine */
/* (this is used only for 2.0-protocol connections) */
typedef enum
{
	SETENV_STATE_OPTION_SEND,	/* About to send an Environment Option */
	SETENV_STATE_OPTION_WAIT,	/* Waiting for above send to complete */
	SETENV_STATE_QUERY1_SEND,	/* About to send a status query */
	SETENV_STATE_QUERY1_WAIT,	/* Waiting for query to complete */
	SETENV_STATE_QUERY2_SEND,	/* About to send a status query */
	SETENV_STATE_QUERY2_WAIT,	/* Waiting for query to complete */
	SETENV_STATE_IDLE
208
} PGSetenvStatusType;
209 210 211 212 213 214

/* Typedef for the EnvironmentOptions[] array */
typedef struct PQEnvironmentOption
{
	const char *envName,		/* name of an environment variable */
			   *pgName;			/* name of corresponding SET variable */
215
} PQEnvironmentOption;
216 217 218 219

/* Typedef for parameter-status list entries */
typedef struct pgParameterStatus
{
Bruce Momjian's avatar
Bruce Momjian committed
220
	struct pgParameterStatus *next;		/* list link */
221 222 223
	char	   *name;			/* parameter name */
	char	   *value;			/* parameter value */
	/* Note: name and value are stored in same malloc block as struct is */
224
} pgParameterStatus;
225

226
/* large-object-access data ... allocated only if large-object code is used. */
Bruce Momjian's avatar
Bruce Momjian committed
227 228 229 230 231 232 233 234 235 236
typedef struct pgLobjfuncs
{
	Oid			fn_lo_open;		/* OID of backend function lo_open		*/
	Oid			fn_lo_close;	/* OID of backend function lo_close		*/
	Oid			fn_lo_creat;	/* OID of backend function lo_creat		*/
	Oid			fn_lo_unlink;	/* OID of backend function lo_unlink	*/
	Oid			fn_lo_lseek;	/* OID of backend function lo_lseek		*/
	Oid			fn_lo_tell;		/* OID of backend function lo_tell		*/
	Oid			fn_lo_read;		/* OID of backend function LOread		*/
	Oid			fn_lo_write;	/* OID of backend function LOwrite		*/
237
} PGlobjfuncs;
238

239 240
/*
 * PGconn stores all the state data associated with a single connection
241 242
 * to a backend.
 */
Bruce Momjian's avatar
Bruce Momjian committed
243 244 245 246
struct pg_conn
{
	/* Saved values of connection options */
	char	   *pghost;			/* the machine on which the server is
247
								 * running */
248
	char	   *pghostaddr;		/* the IPv4 address of the machine on
249 250
								 * which the server is running, in IPv4
								 * numbers-and-dots notation. Takes
251
								 * precedence over above. */
Bruce Momjian's avatar
Bruce Momjian committed
252
	char	   *pgport;			/* the server's communication port */
253 254 255
	char	   *pgunixsocket;	/* the Unix-domain socket that the server
								 * is listening on; if NULL, uses a
								 * default constructed from pgport */
Bruce Momjian's avatar
Bruce Momjian committed
256
	char	   *pgtty;			/* tty on which the backend messages is
257
								 * displayed (OBSOLETE, NOT USED) */
Bruce Momjian's avatar
Bruce Momjian committed
258
	char	   *connect_timeout;	/* connection timeout (numeric string) */
Bruce Momjian's avatar
Bruce Momjian committed
259 260 261 262
	char	   *pgoptions;		/* options to start the backend with */
	char	   *dbName;			/* database name */
	char	   *pguser;			/* Postgres username and password, if any */
	char	   *pgpass;
263
	char	   *sslmode;		/* SSL mode (require,prefer,allow,disable) */
Bruce Momjian's avatar
Bruce Momjian committed
264 265 266 267

	/* Optional file to write trace info to */
	FILE	   *Pfdebug;

268 269
	/* Callback procedures for notice message processing */
	PGNoticeHooks noticeHooks;
Bruce Momjian's avatar
Bruce Momjian committed
270 271 272 273

	/* Status indicators */
	ConnStatusType status;
	PGAsyncStatusType asyncStatus;
274 275
	PGTransactionStatusType xactStatus;
	/* note: xactStatus never changes to ACTIVE */
276
	PGQueryClass queryclass;
277 278
	bool		nonblocking;	/* whether this connection is using
								 * nonblock sending semantics */
Bruce Momjian's avatar
Bruce Momjian committed
279 280 281
	char		copy_is_binary; /* 1 = copy binary, 0 = copy text */
	int			copy_already_done;		/* # bytes already returned in
										 * COPY OUT */
282 283
	PGnotify   *notifyHead;		/* oldest unreported Notify msg */
	PGnotify   *notifyTail;		/* newest unreported Notify msg */
Bruce Momjian's avatar
Bruce Momjian committed
284 285 286 287 288

	/* Connection data */
	int			sock;			/* Unix FD for socket, -1 if not connected */
	SockAddr	laddr;			/* Local address */
	SockAddr	raddr;			/* Remote address */
289
	ProtocolVersion pversion;	/* FE/BE protocol version in use */
290
	int			sversion;		/* server version, e.g. 70401 for 7.4.1 */
291 292 293 294

	/* Transient state needed while establishing connection */
	struct addrinfo *addrlist;	/* list of possible backend addresses */
	struct addrinfo *addr_cur;	/* the one currently being tried */
Bruce Momjian's avatar
Bruce Momjian committed
295 296
	int			addrlist_family;	/* needed to know how to free addrlist */
	PGSetenvStatusType setenv_state;	/* for 2.0 protocol only */
297
	const PQEnvironmentOption *next_eo;
Bruce Momjian's avatar
Bruce Momjian committed
298 299 300 301

	/* Miscellaneous stuff */
	int			be_pid;			/* PID of backend --- needed for cancels */
	int			be_key;			/* key of backend --- needed for cancels */
302 303
	char		md5Salt[4];		/* password salt received from backend */
	char		cryptSalt[2];	/* password salt received from backend */
Bruce Momjian's avatar
Bruce Momjian committed
304 305 306
	pgParameterStatus *pstatus; /* ParameterStatus data */
	int			client_encoding;	/* encoding id */
	PGVerbosity verbosity;		/* error/notice message verbosity */
Bruce Momjian's avatar
Bruce Momjian committed
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
	PGlobjfuncs *lobjfuncs;		/* private state for large-object access
								 * fns */

	/* Buffer for data received from backend and not yet processed */
	char	   *inBuffer;		/* currently allocated buffer */
	int			inBufSize;		/* allocated size of buffer */
	int			inStart;		/* offset to first unconsumed data in
								 * buffer */
	int			inCursor;		/* next byte to tentatively consume */
	int			inEnd;			/* offset to first position after avail
								 * data */

	/* Buffer for data not yet sent to backend */
	char	   *outBuffer;		/* currently allocated buffer */
	int			outBufSize;		/* allocated size of buffer */
	int			outCount;		/* number of chars waiting in buffer */

324
	/* State for constructing messages in outBuffer */
Bruce Momjian's avatar
Bruce Momjian committed
325 326
	int			outMsgStart;	/* offset to msg start (length word); if
								 * -1, msg has no length word */
327 328
	int			outMsgEnd;		/* offset to msg end (so far) */

Bruce Momjian's avatar
Bruce Momjian committed
329 330 331 332
	/* Status for asynchronous result construction */
	PGresult   *result;			/* result being constructed */
	PGresAttValue *curTuple;	/* tuple currently being read */

333
#ifdef USE_SSL
334
	bool		allow_ssl_try;	/* Allowed to try SSL negotiation */
335
	bool		wait_ssl_try;	/* Delay SSL negotiation until after
336
								 * attempting normal connection */
337
	SSL		   *ssl;			/* SSL status, if have SSL connection */
Bruce Momjian's avatar
Bruce Momjian committed
338
	X509	   *peer;			/* X509 cert of server */
Bruce Momjian's avatar
Bruce Momjian committed
339 340
	char		peer_dn[256 + 1];		/* peer distinguished name */
	char		peer_cn[SM_USER + 1];	/* peer common name */
341 342
#endif

343
	/* Buffer for current error message */
344
	PQExpBufferData errorMessage;		/* expansible string */
345 346

	/* Buffer for receiving various parts of messages */
347
	PQExpBufferData workBuffer; /* expansible string */
Bruce Momjian's avatar
Bruce Momjian committed
348
};
349

350 351 352 353 354 355 356 357 358 359 360 361
/* PGcancel stores all data necessary to cancel a connection. A copy of this
 * data is required to safely cancel a connection running on a different
 * thread.
 */
struct pg_cancel
{
	SockAddr	raddr;			/* Remote address */
	int			be_pid;			/* PID of backend --- needed for cancels */
	int			be_key;			/* key of backend --- needed for cancels */
};


362 363 364 365 366
/* String descriptions of the ExecStatusTypes.
 * direct use of this array is deprecated; call PQresStatus() instead.
 */
extern char *const pgresStatus[];

367 368 369 370 371 372 373 374 375 376 377
/* ----------------
 * Internal functions of libpq
 * Functions declared here need to be visible across files of libpq,
 * but are not intended to be called by applications.  We use the
 * convention "pqXXX" for internal functions, vs. the "PQxxx" names
 * used for application-visible routines.
 * ----------------
 */

/* === in fe-connect.c === */

Bruce Momjian's avatar
Bruce Momjian committed
378 379
extern int pqPacketSend(PGconn *conn, char pack_type,
			 const void *buf, size_t buf_len);
380

381
#ifdef ENABLE_THREAD_SAFETY
382
extern pgthreadlock_t pg_g_threadlock;
Bruce Momjian's avatar
Bruce Momjian committed
383

384 385
#define pglock_thread()		pg_g_threadlock(true)
#define pgunlock_thread()	pg_g_threadlock(false)
386
#else
387 388
#define pglock_thread()		((void) 0)
#define pgunlock_thread()	((void) 0)
389
#endif
Bruce Momjian's avatar
Bruce Momjian committed
390

391

392 393
/* === in fe-exec.c === */

394
extern void pqSetResultError(PGresult *res, const char *msg);
395
extern void pqCatenateResultError(PGresult *res, const char *msg);
Bruce Momjian's avatar
Bruce Momjian committed
396
extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
Bruce Momjian's avatar
Bruce Momjian committed
397
extern char *pqResultStrdup(PGresult *res, const char *str);
398
extern void pqClearAsyncResult(PGconn *conn);
399 400
extern void pqSaveErrorResult(PGconn *conn);
extern PGresult *pqPrepareAsyncResult(PGconn *conn);
Bruce Momjian's avatar
Bruce Momjian committed
401
extern void
402
pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
403 404
/* This lets gcc check the format string for consistency. */
__attribute__((format(printf, 2, 3)));
405
extern int	pqAddTuple(PGresult *res, PGresAttValue *tup);
406
extern void pqSaveMessageField(PGresult *res, char code,
Bruce Momjian's avatar
Bruce Momjian committed
407
				   const char *value);
408
extern void pqSaveParameterStatus(PGconn *conn, const char *name,
Bruce Momjian's avatar
Bruce Momjian committed
409
					  const char *value);
410 411 412 413 414 415 416
extern void pqHandleSendFailure(PGconn *conn);

/* === in fe-protocol2.c === */

extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);

extern char *pqBuildStartupPacket2(PGconn *conn, int *packetlen,
417
					  const PQEnvironmentOption *options);
418
extern void pqParseInput2(PGconn *conn);
419
extern int	pqGetCopyData2(PGconn *conn, char **buffer, int async);
420 421 422 423
extern int	pqGetline2(PGconn *conn, char *s, int maxlen);
extern int	pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize);
extern int	pqEndcopy2(PGconn *conn);
extern PGresult *pqFunctionCall2(PGconn *conn, Oid fnid,
Bruce Momjian's avatar
Bruce Momjian committed
424 425 426
				int *result_buf, int *actual_result_len,
				int result_is_int,
				const PQArgBlock *args, int nargs);
427 428 429 430

/* === in fe-protocol3.c === */

extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
431
					  const PQEnvironmentOption *options);
432 433
extern void pqParseInput3(PGconn *conn);
extern int	pqGetErrorNotice3(PGconn *conn, bool isError);
434
extern int	pqGetCopyData3(PGconn *conn, char **buffer, int async);
435 436 437 438
extern int	pqGetline3(PGconn *conn, char *s, int maxlen);
extern int	pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
extern int	pqEndcopy3(PGconn *conn);
extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
Bruce Momjian's avatar
Bruce Momjian committed
439 440 441
				int *result_buf, int *actual_result_len,
				int result_is_int,
				const PQArgBlock *args, int nargs);
442 443 444

/* === in fe-misc.c === */

445 446 447 448 449
 /*
  * "Get" and "Put" routines return 0 if successful, EOF if not. Note that
  * for Get, EOF merely means the buffer is exhausted, not that there is
  * necessarily any error.
  */
450
extern int	pqCheckOutBufferSpace(int bytes_needed, PGconn *conn);
451
extern int	pqCheckInBufferSpace(int bytes_needed, PGconn *conn);
452
extern int	pqGetc(char *result, PGconn *conn);
453
extern int	pqPutc(char c, PGconn *conn);
454
extern int	pqGets(PQExpBuffer buf, PGconn *conn);
455
extern int	pqPuts(const char *s, PGconn *conn);
Bruce Momjian's avatar
Bruce Momjian committed
456 457 458 459
extern int	pqGetnchar(char *s, size_t len, PGconn *conn);
extern int	pqPutnchar(const char *s, size_t len, PGconn *conn);
extern int	pqGetInt(int *result, size_t bytes, PGconn *conn);
extern int	pqPutInt(int value, size_t bytes, PGconn *conn);
460
extern int	pqPutMsgStart(char msg_type, bool force_len, PGconn *conn);
461
extern int	pqPutMsgEnd(PGconn *conn);
462 463 464
extern int	pqReadData(PGconn *conn);
extern int	pqFlush(PGconn *conn);
extern int	pqWait(int forRead, int forWrite, PGconn *conn);
Bruce Momjian's avatar
Bruce Momjian committed
465 466
extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
			time_t finish_time);
467 468
extern int	pqReadReady(PGconn *conn);
extern int	pqWriteReady(PGconn *conn);
469

470 471
/* === in fe-secure.c === */

Bruce Momjian's avatar
Bruce Momjian committed
472
extern int	pqsecure_initialize(PGconn *);
473
extern void pqsecure_destroy(void);
474
extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
475 476 477
extern void pqsecure_close(PGconn *);
extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
Bruce Momjian's avatar
Bruce Momjian committed
478

479
#ifdef ENABLE_THREAD_SAFETY
480 481 482
extern int	pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
							 bool got_epipe);
483 484
#endif

485
/*
486
 * this is so that we can check if a connection is non-blocking internally
487 488
 * without the overhead of a function call
 */
489
#define pqIsnonblocking(conn)	((conn)->nonblocking)
490

491
#ifdef ENABLE_NLS
492 493
extern char *
libpq_gettext(const char *msgid)
494
__attribute__((format_arg(1)));
495

496 497 498
#else
#define libpq_gettext(x) (x)
#endif
499

500 501 502 503 504 505 506
/*
 * These macros are needed to let error-handling code be portable between
 * Unix and Windows.  (ugh)
 */
#ifdef WIN32
#define SOCK_ERRNO (WSAGetLastError())
#define SOCK_STRERROR winsock_strerror
507
#define SOCK_ERRNO_SET(e) WSASetLastError(e)
508 509
#else
#define SOCK_ERRNO errno
510
#define SOCK_STRERROR pqStrerror
511
#define SOCK_ERRNO_SET(e) (errno = (e))
512 513
#endif

514
#endif   /* LIBPQ_INT_H */