#include "access/printsimple.h"
#include "catalog/pg_type.h"
+#include "libpq/protocol.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
StringInfoData buf;
int i;
- pq_beginmessage(&buf, 'T'); /* RowDescription */
+ pq_beginmessage(&buf, PqMsg_RowDescription);
pq_sendint16(&buf, tupdesc->natts);
for (i = 0; i < tupdesc->natts; ++i)
slot_getallattrs(slot);
/* Prepare and send message */
- pq_beginmessage(&buf, 'D');
+ pq_beginmessage(&buf, PqMsg_DataRow);
pq_sendint16(&buf, tupdesc->natts);
for (i = 0; i < tupdesc->natts; ++i)
switch (msgtype)
{
- case 'K': /* BackendKeyData */
+ case PqMsg_BackendKeyData:
{
int32 pid = pq_getmsgint(msg, 4);
break;
}
- case 'E': /* ErrorResponse */
- case 'N': /* NoticeResponse */
+ case PqMsg_ErrorResponse:
+ case PqMsg_NoticeResponse:
{
ErrorData edata;
ErrorContextCallback *save_error_context_stack;
break;
}
- case 'A': /* NotifyResponse */
+ case PqMsg_NotificationResponse:
{
/* Propagate NotifyResponse. */
int32 pid;
break;
}
- case 'X': /* Terminate, indicating clean exit */
+ case PqMsg_Terminate:
{
shm_mq_detach(pcxt->worker[i].error_mqh);
pcxt->worker[i].error_mqh = NULL;
* protocol message is defined, but it won't actually be used for anything
* in this case.
*/
- pq_beginmessage(&msgbuf, 'K');
+ pq_beginmessage(&msgbuf, PqMsg_BackendKeyData);
pq_sendint32(&msgbuf, (int32) MyProcPid);
pq_sendint32(&msgbuf, (int32) MyCancelKey);
pq_endmessage(&msgbuf);
DetachSession();
/* Report success. */
- pq_putmessage('X', NULL, 0);
+ pq_putmessage(PqMsg_Terminate, NULL, 0);
}
/*
SendTablespaceList(state->tablespaces);
/* Send a CommandComplete message */
- pq_puttextmessage('C', "SELECT");
+ pq_puttextmessage(PqMsg_CommandComplete, "SELECT");
/* Begin COPY stream. This will be used for all archives + manifest. */
SendCopyOutResponse();
StringInfoData buf;
ti = list_nth(state->tablespaces, state->tablespace_num);
- pq_beginmessage(&buf, 'd'); /* CopyData */
+ pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'n'); /* New archive */
pq_sendstring(&buf, archive_name);
pq_sendstring(&buf, ti->path == NULL ? "" : ti->path);
{
mysink->last_progress_report_time = now;
- pq_beginmessage(&buf, 'd'); /* CopyData */
+ pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'p'); /* Progress report */
pq_sendint64(&buf, state->bytes_done);
pq_endmessage(&buf);
mysink->bytes_done_at_last_time_check = state->bytes_done;
mysink->last_progress_report_time = GetCurrentTimestamp();
- pq_beginmessage(&buf, 'd'); /* CopyData */
+ pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'p'); /* Progress report */
pq_sendint64(&buf, state->bytes_done);
pq_endmessage(&buf);
{
StringInfoData buf;
- pq_beginmessage(&buf, 'd'); /* CopyData */
+ pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'm'); /* Manifest */
pq_endmessage(&buf);
}
{
StringInfoData buf;
- pq_beginmessage(&buf, 'H');
+ pq_beginmessage(&buf, PqMsg_CopyOutResponse);
pq_sendbyte(&buf, 0); /* overall format */
pq_sendint16(&buf, 0); /* natts */
pq_endmessage(&buf);
static void
SendCopyDone(void)
{
- pq_putemptymessage('c');
+ pq_putemptymessage(PqMsg_CopyDone);
}
/*
end_tup_output(tstate);
/* Send a CommandComplete message */
- pq_puttextmessage('C', "SELECT");
+ pq_puttextmessage(PqMsg_CommandComplete, "SELECT");
}
/*
{
StringInfoData buf;
- pq_beginmessage(&buf, 'A');
+ pq_beginmessage(&buf, PqMsg_NotificationResponse);
pq_sendint32(&buf, srcPid);
pq_sendstring(&buf, channel);
pq_sendstring(&buf, payload);
int16 format = (cstate->opts.binary ? 1 : 0);
int i;
- pq_beginmessage(&buf, 'G');
+ pq_beginmessage(&buf, PqMsg_CopyInResponse);
pq_sendbyte(&buf, format); /* overall format */
pq_sendint16(&buf, natts);
for (i = 0; i < natts; i++)
/* Validate message type and set packet size limit */
switch (mtype)
{
- case 'd': /* CopyData */
+ case PqMsg_CopyData:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
break;
- case 'c': /* CopyDone */
- case 'f': /* CopyFail */
- case 'H': /* Flush */
- case 'S': /* Sync */
+ case PqMsg_CopyDone:
+ case PqMsg_CopyFail:
+ case PqMsg_Flush:
+ case PqMsg_Sync:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
break;
default:
/* ... and process it */
switch (mtype)
{
- case 'd': /* CopyData */
+ case PqMsg_CopyData:
break;
- case 'c': /* CopyDone */
+ case PqMsg_CopyDone:
/* COPY IN correctly terminated by frontend */
cstate->raw_reached_eof = true;
return bytesread;
- case 'f': /* CopyFail */
+ case PqMsg_CopyFail:
ereport(ERROR,
(errcode(ERRCODE_QUERY_CANCELED),
errmsg("COPY from stdin failed: %s",
pq_getmsgstring(cstate->fe_msgbuf))));
break;
- case 'H': /* Flush */
- case 'S': /* Sync */
+ case PqMsg_Flush:
+ case PqMsg_Sync:
/*
* Ignore Flush/Sync for the convenience of client
int16 format = (cstate->opts.binary ? 1 : 0);
int i;
- pq_beginmessage(&buf, 'H');
+ pq_beginmessage(&buf, PqMsg_CopyOutResponse);
pq_sendbyte(&buf, format); /* overall format */
pq_sendint16(&buf, natts);
for (i = 0; i < natts; i++)
/* Shouldn't have any unsent data */
Assert(cstate->fe_msgbuf->len == 0);
/* Send Copy Done message */
- pq_putemptymessage('c');
+ pq_putemptymessage(PqMsg_CopyDone);
}
/*----------
CopySendChar(cstate, '\n');
/* Dump the accumulated row as one CopyData message */
- (void) pq_putmessage('d', fe_msgbuf->data, fe_msgbuf->len);
+ (void) pq_putmessage(PqMsg_CopyData, fe_msgbuf->data, fe_msgbuf->len);
break;
case COPY_CALLBACK:
cstate->data_dest_cb(fe_msgbuf->data, fe_msgbuf->len);
{
pq_startmsgread();
mtype = pq_getbyte();
- if (mtype != 'p')
+ if (mtype != PqMsg_SASLResponse)
{
/* Only log error if client didn't disconnect. */
if (mtype != EOF)
CHECK_FOR_INTERRUPTS();
- pq_beginmessage(&buf, 'R');
+ pq_beginmessage(&buf, PqMsg_AuthenticationRequest);
pq_sendint32(&buf, (int32) areq);
if (extralen > 0)
pq_sendbytes(&buf, extradata, extralen);
/* Expect 'p' message type */
mtype = pq_getbyte();
- if (mtype != 'p')
+ if (mtype != PqMsg_PasswordMessage)
{
/*
* If the client just disconnects without offering a password, don't
CHECK_FOR_INTERRUPTS();
mtype = pq_getbyte();
- if (mtype != 'p')
+ if (mtype != PqMsg_GSSResponse)
{
/* Only log error if client didn't disconnect. */
if (mtype != EOF)
{
pq_startmsgread();
mtype = pq_getbyte();
- if (mtype != 'p')
+ if (mtype != PqMsg_GSSResponse)
{
if (sspictx != NULL)
{
StringInfoData buf;
ListCell *lc;
- pq_beginmessage(&buf, 'v'); /* NegotiateProtocolVersion */
+ pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion);
pq_sendint32(&buf, PG_PROTOCOL_LATEST);
pq_sendint32(&buf, list_length(unrecognized_protocol_options));
foreach(lc, unrecognized_protocol_options)
dest->rStartup(dest, CMD_SELECT, tupdesc);
/* Send a DataRow message */
- pq_beginmessage(&buf, 'D');
+ pq_beginmessage(&buf, PqMsg_DataRow);
pq_sendint16(&buf, 2); /* # of columns */
len = strlen(histfname);
pq_sendint32(&buf, len); /* col1 len */
WalSndSetState(WALSNDSTATE_CATCHUP);
/* Send a CopyBothResponse message, and start streaming */
- pq_beginmessage(&buf, 'W');
+ pq_beginmessage(&buf, PqMsg_CopyBothResponse);
pq_sendbyte(&buf, 0);
pq_sendint16(&buf, 0);
pq_endmessage(&buf);
WalSndSetState(WALSNDSTATE_CATCHUP);
/* Send a CopyBothResponse message, and start streaming */
- pq_beginmessage(&buf, 'W');
+ pq_beginmessage(&buf, PqMsg_CopyBothResponse);
pq_sendbyte(&buf, 0);
pq_sendint16(&buf, 0);
pq_endmessage(&buf);
/* Validate message type and set packet size limit */
switch (firstchar)
{
- case 'd':
+ case PqMsg_CopyData:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
break;
- case 'c':
- case 'X':
+ case PqMsg_CopyDone:
+ case PqMsg_Terminate:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
break;
default:
/*
* 'd' means a standby reply wrapped in a CopyData packet.
*/
- case 'd':
+ case PqMsg_CopyData:
ProcessStandbyMessage();
received = true;
break;
* CopyDone means the standby requested to finish streaming.
* Reply with CopyDone, if we had not sent that already.
*/
- case 'c':
+ case PqMsg_CopyDone:
if (!streamingDoneSending)
{
pq_putmessage_noblock('c', NULL, 0);
/*
* 'X' means that the standby is closing down the socket.
*/
- case 'X':
+ case PqMsg_Terminate:
proc_exit(0);
default:
len = BuildQueryCompletionString(completionTag, qc,
force_undecorated_output);
- pq_putmessage('C', completionTag, len + 1);
+ pq_putmessage(PqMsg_Close, completionTag, len + 1);
case DestNone:
case DestDebug:
void
EndReplicationCommand(const char *commandTag)
{
- pq_putmessage('C', commandTag, strlen(commandTag) + 1);
+ pq_putmessage(PqMsg_Close, commandTag, strlen(commandTag) + 1);
}
/* ----------------
case DestRemoteSimple:
/* Tell the FE that we saw an empty query string */
- pq_putemptymessage('I');
+ pq_putemptymessage(PqMsg_EmptyQueryResponse);
break;
case DestNone:
{
StringInfoData buf;
- pq_beginmessage(&buf, 'Z');
+ pq_beginmessage(&buf, PqMsg_ReadyForQuery);
pq_sendbyte(&buf, TransactionBlockStatusCode());
pq_endmessage(&buf);
}
{
StringInfoData buf;
- pq_beginmessage(&buf, 'V');
+ pq_beginmessage(&buf, PqMsg_FunctionCallResponse);
if (isnull)
{
*/
switch (qtype)
{
- case 'Q': /* simple query */
+ case PqMsg_Query:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
doing_extended_query_message = false;
break;
- case 'F': /* fastpath function call */
+ case PqMsg_FunctionCall:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
doing_extended_query_message = false;
break;
- case 'X': /* terminate */
+ case PqMsg_Terminate:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
doing_extended_query_message = false;
ignore_till_sync = false;
break;
- case 'B': /* bind */
- case 'P': /* parse */
+ case PqMsg_Bind:
+ case PqMsg_Parse:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
doing_extended_query_message = true;
break;
- case 'C': /* close */
- case 'D': /* describe */
- case 'E': /* execute */
- case 'H': /* flush */
+ case PqMsg_Close:
+ case PqMsg_Describe:
+ case PqMsg_Execute:
+ case PqMsg_Flush:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
doing_extended_query_message = true;
break;
- case 'S': /* sync */
+ case PqMsg_Sync:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
/* stop any active skip-till-Sync */
ignore_till_sync = false;
doing_extended_query_message = false;
break;
- case 'd': /* copy data */
+ case PqMsg_CopyData:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
doing_extended_query_message = false;
break;
- case 'c': /* copy done */
- case 'f': /* copy fail */
+ case PqMsg_CopyDone:
+ case PqMsg_CopyFail:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
doing_extended_query_message = false;
break;
* Send ParseComplete.
*/
if (whereToSendOutput == DestRemote)
- pq_putemptymessage('1');
+ pq_putemptymessage(PqMsg_ParseComplete);
/*
* Emit duration logging if appropriate.
* Send BindComplete.
*/
if (whereToSendOutput == DestRemote)
- pq_putemptymessage('2');
+ pq_putemptymessage(PqMsg_BindComplete);
/*
* Emit duration logging if appropriate.
{
/* Portal run not complete, so send PortalSuspended */
if (whereToSendOutput == DestRemote)
- pq_putemptymessage('s');
+ pq_putemptymessage(PqMsg_PortalSuspended);
/*
* Set XACT_FLAGS_PIPELINING whenever we suspend an Execute message,
NULL);
}
else
- pq_putemptymessage('n'); /* NoData */
+ pq_putemptymessage(PqMsg_NoData);
}
/*
FetchPortalTargetList(portal),
portal->formats);
else
- pq_putemptymessage('n'); /* NoData */
+ pq_putemptymessage(PqMsg_NoData);
}
{
StringInfoData buf;
- pq_beginmessage(&buf, 'K');
+ pq_beginmessage(&buf, PqMsg_BackendKeyData);
pq_sendint32(&buf, (int32) MyProcPid);
pq_sendint32(&buf, (int32) MyCancelKey);
pq_endmessage(&buf);
switch (firstchar)
{
- case 'Q': /* simple query */
+ case PqMsg_Query:
{
const char *query_string;
}
break;
- case 'P': /* parse */
+ case PqMsg_Parse:
{
const char *stmt_name;
const char *query_string;
}
break;
- case 'B': /* bind */
+ case PqMsg_Bind:
forbidden_in_wal_sender(firstchar);
/* Set statement_timestamp() */
/* exec_bind_message does valgrind_report_error_query */
break;
- case 'E': /* execute */
+ case PqMsg_Execute:
{
const char *portal_name;
int max_rows;
}
break;
- case 'F': /* fastpath function call */
+ case PqMsg_FunctionCall:
forbidden_in_wal_sender(firstchar);
/* Set statement_timestamp() */
send_ready_for_query = true;
break;
- case 'C': /* close */
+ case PqMsg_Close:
{
int close_type;
const char *close_target;
}
if (whereToSendOutput == DestRemote)
- pq_putemptymessage('3'); /* CloseComplete */
+ pq_putemptymessage(PqMsg_CloseComplete);
valgrind_report_error_query("CLOSE message");
}
break;
- case 'D': /* describe */
+ case PqMsg_Describe:
{
int describe_type;
const char *describe_target;
}
break;
- case 'H': /* flush */
+ case PqMsg_Flush:
pq_getmsgend(&input_message);
if (whereToSendOutput == DestRemote)
pq_flush();
break;
- case 'S': /* sync */
+ case PqMsg_Sync:
pq_getmsgend(&input_message);
finish_xact_command();
valgrind_report_error_query("SYNC message");
/* FALLTHROUGH */
- case 'X':
+ case PqMsg_Terminate:
/*
* Reset whereToSendOutput to prevent ereport from attempting
*/
proc_exit(0);
- case 'd': /* copy data */
- case 'c': /* copy done */
- case 'f': /* copy fail */
+ case PqMsg_CopyData:
+ case PqMsg_CopyDone:
+ case PqMsg_CopyFail:
/*
* Accept but ignore these messages, per protocol spec; we
{
if (am_walsender)
{
- if (firstchar == 'F')
+ if (firstchar == PqMsg_FunctionCall)
ereport(ERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("fastpath function calls not supported in a replication connection")));
char tbuf[12];
/* 'N' (Notice) is for nonfatal conditions, 'E' is for errors */
- pq_beginmessage(&msgbuf, (edata->elevel < ERROR) ? 'N' : 'E');
+ if (edata->elevel < ERROR)
+ pq_beginmessage(&msgbuf, PqMsg_NoticeResponse);
+ else
+ pq_beginmessage(&msgbuf, PqMsg_ErrorResponse);
sev = error_severity(edata->elevel);
pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
{
StringInfoData msgbuf;
- pq_beginmessage(&msgbuf, 'S');
+ pq_beginmessage(&msgbuf, PqMsg_ParameterStatus);
pq_sendstring(&msgbuf, record->name);
pq_sendstring(&msgbuf, val);
pq_endmessage(&msgbuf);
$(INSTALL_DATA) $(srcdir)/port.h '$(DESTDIR)$(includedir_internal)'
$(INSTALL_DATA) $(srcdir)/postgres_fe.h '$(DESTDIR)$(includedir_internal)'
$(INSTALL_DATA) $(srcdir)/libpq/pqcomm.h '$(DESTDIR)$(includedir_internal)/libpq'
+ $(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
# These headers are needed for server-side development
$(INSTALL_DATA) pg_config.h '$(DESTDIR)$(includedir_server)'
$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
uninstall:
rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
- rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h)
+ rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
# heuristic...
rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
#include <netdb.h>
#include <netinet/in.h>
+/*
+ * The definitions for the request/response codes are kept in a separate file
+ * for ease of use in third party programs.
+ */
+#include "libpq/protocol.h"
+
typedef struct
{
struct sockaddr_storage addr;
#define MAX_STARTUP_PACKET_LENGTH 10000
-/* These are the authentication request codes sent by the backend. */
-
-#define AUTH_REQ_OK 0 /* User is authenticated */
-#define AUTH_REQ_KRB4 1 /* Kerberos V4. Not supported any more. */
-#define AUTH_REQ_KRB5 2 /* Kerberos V5. Not supported any more. */
-#define AUTH_REQ_PASSWORD 3 /* Password */
-#define AUTH_REQ_CRYPT 4 /* crypt password. Not supported any more. */
-#define AUTH_REQ_MD5 5 /* md5 password */
-/* 6 is available. It was used for SCM creds, not supported any more. */
-#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */
-#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */
-#define AUTH_REQ_SSPI 9 /* SSPI negotiate without wrap() */
-#define AUTH_REQ_SASL 10 /* Begin SASL authentication */
-#define AUTH_REQ_SASL_CONT 11 /* Continue SASL authentication */
-#define AUTH_REQ_SASL_FIN 12 /* Final SASL message */
-#define AUTH_REQ_MAX AUTH_REQ_SASL_FIN /* maximum AUTH_REQ_* value */
-
typedef uint32 AuthRequest;
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * protocol.h
+ * Definitions of the request/response codes for the wire protocol.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/protocol.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+/* These are the request codes sent by the frontend. */
+
+#define PqMsg_Bind 'B'
+#define PqMsg_Close 'C'
+#define PqMsg_Describe 'D'
+#define PqMsg_Execute 'E'
+#define PqMsg_FunctionCall 'F'
+#define PqMsg_Flush 'H'
+#define PqMsg_Parse 'P'
+#define PqMsg_Query 'Q'
+#define PqMsg_Sync 'S'
+#define PqMsg_Terminate 'X'
+#define PqMsg_CopyFail 'f'
+#define PqMsg_GSSResponse 'p'
+#define PqMsg_PasswordMessage 'p'
+#define PqMsg_SASLInitialResponse 'p'
+#define PqMsg_SASLResponse 'p'
+
+
+/* These are the response codes sent by the backend. */
+
+#define PqMsg_ParseComplete '1'
+#define PqMsg_BindComplete '2'
+#define PqMsg_CloseComplete '3'
+#define PqMsg_NotificationResponse 'A'
+#define PqMsg_CommandComplete 'C'
+#define PqMsg_DataRow 'D'
+#define PqMsg_ErrorResponse 'E'
+#define PqMsg_CopyInResponse 'G'
+#define PqMsg_CopyOutResponse 'H'
+#define PqMsg_EmptyQueryResponse 'I'
+#define PqMsg_BackendKeyData 'K'
+#define PqMsg_NoticeResponse 'N'
+#define PqMsg_AuthenticationRequest 'R'
+#define PqMsg_ParameterStatus 'S'
+#define PqMsg_RowDescription 'T'
+#define PqMsg_FunctionCallResponse 'V'
+#define PqMsg_CopyBothResponse 'W'
+#define PqMsg_ReadyForQuery 'Z'
+#define PqMsg_NoData 'n'
+#define PqMsg_PortalSuspended 's'
+#define PqMsg_ParameterDescription 't'
+#define PqMsg_NegotiateProtocolVersion 'v'
+
+
+/* These are the codes sent by both the frontend and backend. */
+
+#define PqMsg_CopyDone 'c'
+#define PqMsg_CopyData 'd'
+
+
+/* These are the authentication request codes sent by the backend. */
+
+#define AUTH_REQ_OK 0 /* User is authenticated */
+#define AUTH_REQ_KRB4 1 /* Kerberos V4. Not supported any more. */
+#define AUTH_REQ_KRB5 2 /* Kerberos V5. Not supported any more. */
+#define AUTH_REQ_PASSWORD 3 /* Password */
+#define AUTH_REQ_CRYPT 4 /* crypt password. Not supported any more. */
+#define AUTH_REQ_MD5 5 /* md5 password */
+/* 6 is available. It was used for SCM creds, not supported any more. */
+#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */
+#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */
+#define AUTH_REQ_SSPI 9 /* SSPI negotiate without wrap() */
+#define AUTH_REQ_SASL 10 /* Begin SASL authentication */
+#define AUTH_REQ_SASL_CONT 11 /* Continue SASL authentication */
+#define AUTH_REQ_SASL_FIN 12 /* Final SASL message */
+#define AUTH_REQ_MAX AUTH_REQ_SASL_FIN /* maximum AUTH_REQ_* value */
+
+#endif /* PROTOCOL_H */
install_headers(
'libpq/pqcomm.h',
+ 'libpq/protocol.h',
install_dir: dir_include_internal / 'libpq',
)
/*
* Build a SASLInitialResponse message, and send it.
*/
- if (pqPutMsgStart('p', conn))
+ if (pqPutMsgStart(PqMsg_SASLInitialResponse, conn))
goto error;
if (pqPuts(selected_mechanism, conn))
goto error;
* Anything else probably means it's not Postgres on the other
* end at all.
*/
- if (!(beresp == 'R' || beresp == 'v' || beresp == 'E'))
+ if (beresp != PqMsg_AuthenticationRequest &&
+ beresp != PqMsg_ErrorResponse &&
+ beresp != PqMsg_NegotiateProtocolVersion)
{
libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
beresp);
* version 14, the server also used the old protocol for
* errors that happened before processing the startup packet.)
*/
- if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
+ if (beresp == PqMsg_AuthenticationRequest &&
+ (msgLength < 8 || msgLength > 2000))
{
libpq_append_conn_error(conn, "received invalid authentication request");
goto error_return;
}
- if (beresp == 'v' && (msgLength < 8 || msgLength > 2000))
+ if (beresp == PqMsg_NegotiateProtocolVersion &&
+ (msgLength < 8 || msgLength > 2000))
{
libpq_append_conn_error(conn, "received invalid protocol negotiation message");
goto error_return;
}
#define MAX_ERRLEN 30000
- if (beresp == 'E' && (msgLength < 8 || msgLength > MAX_ERRLEN))
+ if (beresp == PqMsg_ErrorResponse &&
+ (msgLength < 8 || msgLength > MAX_ERRLEN))
{
/* Handle error from a pre-3.0 server */
conn->inCursor = conn->inStart + 1; /* reread data */
}
/* Handle errors. */
- if (beresp == 'E')
+ if (beresp == PqMsg_ErrorResponse)
{
if (pqGetErrorNotice3(conn, true))
{
goto error_return;
}
- else if (beresp == 'v')
+ else if (beresp == PqMsg_NegotiateProtocolVersion)
{
if (pqGetNegotiateProtocolVersion3(conn))
{
* Try to send "close connection" message to backend. Ignore any
* error.
*/
- pqPutMsgStart('X', conn);
+ pqPutMsgStart(PqMsg_Terminate, conn);
pqPutMsgEnd(conn);
(void) pqFlush(conn);
}
/* Send the query message(s) */
/* construct the outgoing Query message */
- if (pqPutMsgStart('Q', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Query, conn) < 0 ||
pqPuts(query, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
{
return 0; /* error msg already set */
/* construct the Parse message */
- if (pqPutMsgStart('P', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
pqPuts(stmtName, conn) < 0 ||
pqPuts(query, conn) < 0)
goto sendFailed;
/* Add a Sync, unless in pipeline mode. */
if (conn->pipelineStatus == PQ_PIPELINE_OFF)
{
- if (pqPutMsgStart('S', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
goto sendFailed;
}
if (command)
{
/* construct the Parse message */
- if (pqPutMsgStart('P', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Parse, conn) < 0 ||
pqPuts(stmtName, conn) < 0 ||
pqPuts(command, conn) < 0)
goto sendFailed;
}
/* Construct the Bind message */
- if (pqPutMsgStart('B', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Bind, conn) < 0 ||
pqPuts("", conn) < 0 ||
pqPuts(stmtName, conn) < 0)
goto sendFailed;
goto sendFailed;
/* construct the Describe Portal message */
- if (pqPutMsgStart('D', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Describe, conn) < 0 ||
pqPutc('P', conn) < 0 ||
pqPuts("", conn) < 0 ||
pqPutMsgEnd(conn) < 0)
goto sendFailed;
/* construct the Execute message */
- if (pqPutMsgStart('E', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Execute, conn) < 0 ||
pqPuts("", conn) < 0 ||
pqPutInt(0, 4, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
/* construct the Sync message if not in pipeline mode */
if (conn->pipelineStatus == PQ_PIPELINE_OFF)
{
- if (pqPutMsgStart('S', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
goto sendFailed;
}
{
if (!PQexecStart(conn))
return NULL;
- if (!PQsendTypedCommand(conn, 'D', 'S', stmt))
+ if (!PQsendTypedCommand(conn, PqMsg_Describe, 'S', stmt))
return NULL;
return PQexecFinish(conn);
}
{
if (!PQexecStart(conn))
return NULL;
- if (!PQsendTypedCommand(conn, 'D', 'P', portal))
+ if (!PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal))
return NULL;
return PQexecFinish(conn);
}
int
PQsendDescribePrepared(PGconn *conn, const char *stmt)
{
- return PQsendTypedCommand(conn, 'D', 'S', stmt);
+ return PQsendTypedCommand(conn, PqMsg_Describe, 'S', stmt);
}
/*
int
PQsendDescribePortal(PGconn *conn, const char *portal)
{
- return PQsendTypedCommand(conn, 'D', 'P', portal);
+ return PQsendTypedCommand(conn, PqMsg_Describe, 'P', portal);
}
/*
{
if (!PQexecStart(conn))
return NULL;
- if (!PQsendTypedCommand(conn, 'C', 'S', stmt))
+ if (!PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt))
return NULL;
return PQexecFinish(conn);
}
{
if (!PQexecStart(conn))
return NULL;
- if (!PQsendTypedCommand(conn, 'C', 'P', portal))
+ if (!PQsendTypedCommand(conn, PqMsg_Close, 'P', portal))
return NULL;
return PQexecFinish(conn);
}
int
PQsendClosePrepared(PGconn *conn, const char *stmt)
{
- return PQsendTypedCommand(conn, 'C', 'S', stmt);
+ return PQsendTypedCommand(conn, PqMsg_Close, 'S', stmt);
}
/*
int
PQsendClosePortal(PGconn *conn, const char *portal)
{
- return PQsendTypedCommand(conn, 'C', 'P', portal);
+ return PQsendTypedCommand(conn, PqMsg_Close, 'P', portal);
}
/*
* Common code to send a Describe or Close command
*
* Available options for "command" are
- * 'C' for Close; or
- * 'D' for Describe.
+ * PqMsg_Close for Close; or
+ * PqMsg_Describe for Describe.
*
* Available options for "type" are
* 'S' to run a command on a prepared statement; or
/* construct the Sync message */
if (conn->pipelineStatus == PQ_PIPELINE_OFF)
{
- if (pqPutMsgStart('S', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
goto sendFailed;
}
/* remember if we are doing a Close or a Describe */
- if (command == 'C')
+ if (command == PqMsg_Close)
{
entry->queryclass = PGQUERY_CLOSE;
}
- else if (command == 'D')
+ else if (command == PqMsg_Describe)
{
entry->queryclass = PGQUERY_DESCRIBE;
}
return pqIsnonblocking(conn) ? 0 : -1;
}
/* Send the data (too simple to delegate to fe-protocol files) */
- if (pqPutMsgStart('d', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_CopyData, conn) < 0 ||
pqPutnchar(buffer, nbytes, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
return -1;
if (errormsg)
{
/* Send COPY FAIL */
- if (pqPutMsgStart('f', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_CopyFail, conn) < 0 ||
pqPuts(errormsg, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
return -1;
else
{
/* Send COPY DONE */
- if (pqPutMsgStart('c', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
return -1;
}
if (conn->cmd_queue_head &&
conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
{
- if (pqPutMsgStart('S', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
return -1;
}
entry->query = NULL;
/* construct the Sync message */
- if (pqPutMsgStart('S', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
goto sendFailed;
return 0;
}
- if (pqPutMsgStart('H', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Flush, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
{
return 0;
* than a couple of kilobytes).
*/
#define VALID_LONG_MESSAGE_TYPE(id) \
- ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
- (id) == 'E' || (id) == 'N' || (id) == 'A')
+ ((id) == PqMsg_CopyData || \
+ (id) == PqMsg_DataRow || \
+ (id) == PqMsg_ErrorResponse || \
+ (id) == PqMsg_FunctionCallResponse || \
+ (id) == PqMsg_NoticeResponse || \
+ (id) == PqMsg_NotificationResponse || \
+ (id) == PqMsg_RowDescription)
static void handleSyncLoss(PGconn *conn, char id, int msgLength);
* from config file due to SIGHUP), but otherwise we hold off until
* BUSY state.
*/
- if (id == 'A')
+ if (id == PqMsg_NotificationResponse)
{
if (getNotify(conn))
return;
}
- else if (id == 'N')
+ else if (id == PqMsg_NoticeResponse)
{
if (pqGetErrorNotice3(conn, false))
return;
* it is about to close the connection, so we don't want to just
* discard it...)
*/
- if (id == 'E')
+ if (id == PqMsg_ErrorResponse)
{
if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
return;
}
- else if (id == 'S')
+ else if (id == PqMsg_ParameterStatus)
{
if (getParameterStatus(conn))
return;
*/
switch (id)
{
- case 'C': /* command complete */
+ case PqMsg_CommandComplete:
if (pqGets(&conn->workBuffer, conn))
return;
if (!pgHavePendingResult(conn))
CMDSTATUS_LEN);
conn->asyncStatus = PGASYNC_READY;
break;
- case 'E': /* error return */
+ case PqMsg_ErrorResponse:
if (pqGetErrorNotice3(conn, true))
return;
conn->asyncStatus = PGASYNC_READY;
break;
- case 'Z': /* sync response, backend is ready for new
- * query */
+ case PqMsg_ReadyForQuery:
if (getReadyForQuery(conn))
return;
if (conn->pipelineStatus != PQ_PIPELINE_OFF)
conn->asyncStatus = PGASYNC_IDLE;
}
break;
- case 'I': /* empty query */
+ case PqMsg_EmptyQueryResponse:
if (!pgHavePendingResult(conn))
{
conn->result = PQmakeEmptyPGresult(conn,
}
conn->asyncStatus = PGASYNC_READY;
break;
- case '1': /* Parse Complete */
+ case PqMsg_ParseComplete:
/* If we're doing PQprepare, we're done; else ignore */
if (conn->cmd_queue_head &&
conn->cmd_queue_head->queryclass == PGQUERY_PREPARE)
conn->asyncStatus = PGASYNC_READY;
}
break;
- case '2': /* Bind Complete */
+ case PqMsg_BindComplete:
/* Nothing to do for this message type */
break;
- case '3': /* Close Complete */
+ case PqMsg_CloseComplete:
/* If we're doing PQsendClose, we're done; else ignore */
if (conn->cmd_queue_head &&
conn->cmd_queue_head->queryclass == PGQUERY_CLOSE)
conn->asyncStatus = PGASYNC_READY;
}
break;
- case 'S': /* parameter status */
+ case PqMsg_ParameterStatus:
if (getParameterStatus(conn))
return;
break;
- case 'K': /* secret key data from the backend */
+ case PqMsg_BackendKeyData:
/*
* This is expected only during backend startup, but it's
if (pqGetInt(&(conn->be_key), 4, conn))
return;
break;
- case 'T': /* Row Description */
+ case PqMsg_RowDescription:
if (conn->error_result ||
(conn->result != NULL &&
conn->result->resultStatus == PGRES_FATAL_ERROR))
return;
}
break;
- case 'n': /* No Data */
+ case PqMsg_NoData:
/*
* NoData indicates that we will not be seeing a
conn->asyncStatus = PGASYNC_READY;
}
break;
- case 't': /* Parameter Description */
+ case PqMsg_ParameterDescription:
if (getParamDescriptions(conn, msgLength))
return;
break;
- case 'D': /* Data Row */
+ case PqMsg_DataRow:
if (conn->result != NULL &&
conn->result->resultStatus == PGRES_TUPLES_OK)
{
conn->inCursor += msgLength;
}
break;
- case 'G': /* Start Copy In */
+ case PqMsg_CopyInResponse:
if (getCopyStart(conn, PGRES_COPY_IN))
return;
conn->asyncStatus = PGASYNC_COPY_IN;
break;
- case 'H': /* Start Copy Out */
+ case PqMsg_CopyOutResponse:
if (getCopyStart(conn, PGRES_COPY_OUT))
return;
conn->asyncStatus = PGASYNC_COPY_OUT;
conn->copy_already_done = 0;
break;
- case 'W': /* Start Copy Both */
+ case PqMsg_CopyBothResponse:
if (getCopyStart(conn, PGRES_COPY_BOTH))
return;
conn->asyncStatus = PGASYNC_COPY_BOTH;
conn->copy_already_done = 0;
break;
- case 'd': /* Copy Data */
+ case PqMsg_CopyData:
/*
* If we see Copy Data, just silently drop it. This would
*/
conn->inCursor += msgLength;
break;
- case 'c': /* Copy Done */
+ case PqMsg_CopyDone:
/*
* If we see Copy Done, just silently drop it. This is
*/
switch (id)
{
- case 'A': /* NOTIFY */
+ case PqMsg_NotificationResponse:
if (getNotify(conn))
return 0;
break;
- case 'N': /* NOTICE */
+ case PqMsg_NoticeResponse:
if (pqGetErrorNotice3(conn, false))
return 0;
break;
- case 'S': /* ParameterStatus */
+ case PqMsg_ParameterStatus:
if (getParameterStatus(conn))
return 0;
break;
- case 'd': /* Copy Data, pass it back to caller */
+ case PqMsg_CopyData:
return msgLength;
- case 'c':
+ case PqMsg_CopyDone:
/*
* If this is a CopyDone message, exit COPY_OUT mode and let
if (conn->asyncStatus == PGASYNC_COPY_IN ||
conn->asyncStatus == PGASYNC_COPY_BOTH)
{
- if (pqPutMsgStart('c', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
return 1;
if (conn->cmd_queue_head &&
conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
{
- if (pqPutMsgStart('S', conn) < 0 ||
+ if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
pqPutMsgEnd(conn) < 0)
return 1;
}
/* PQfn already validated connection state */
- if (pqPutMsgStart('F', conn) < 0 || /* function call msg */
+ if (pqPutMsgStart(PqMsg_FunctionCall, conn) < 0 ||
pqPutInt(fnid, 4, conn) < 0 || /* function id */
pqPutInt(1, 2, conn) < 0 || /* # of format codes */
pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
switch (id)
{
- case '1':
+ case PqMsg_ParseComplete:
fprintf(conn->Pfdebug, "ParseComplete");
/* No message content */
break;
- case '2':
+ case PqMsg_BindComplete:
fprintf(conn->Pfdebug, "BindComplete");
/* No message content */
break;
- case '3':
+ case PqMsg_CloseComplete:
fprintf(conn->Pfdebug, "CloseComplete");
/* No message content */
break;
- case 'A': /* Notification Response */
+ case PqMsg_NotificationResponse:
pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
break;
- case 'B': /* Bind */
+ case PqMsg_Bind:
pqTraceOutputB(conn->Pfdebug, message, &logCursor);
break;
- case 'c':
+ case PqMsg_CopyDone:
fprintf(conn->Pfdebug, "CopyDone");
/* No message content */
break;
- case 'C': /* Close(F) or Command Complete(B) */
+ case PqMsg_CommandComplete:
+ /* Close(F) and CommandComplete(B) use the same identifier. */
+ Assert(PqMsg_Close == PqMsg_CommandComplete);
pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
break;
- case 'd': /* Copy Data */
+ case PqMsg_CopyData:
/* Drop COPY data to reduce the overhead of logging. */
break;
- case 'D': /* Describe(F) or Data Row(B) */
+ case PqMsg_Describe:
+ /* Describe(F) and DataRow(B) use the same identifier. */
+ Assert(PqMsg_Describe == PqMsg_DataRow);
pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
break;
- case 'E': /* Execute(F) or Error Response(B) */
+ case PqMsg_Execute:
+ /* Execute(F) and ErrorResponse(B) use the same identifier. */
+ Assert(PqMsg_Execute == PqMsg_ErrorResponse);
pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
regress);
break;
- case 'f': /* Copy Fail */
+ case PqMsg_CopyFail:
pqTraceOutputf(conn->Pfdebug, message, &logCursor);
break;
- case 'F': /* Function Call */
+ case PqMsg_FunctionCall:
pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
break;
- case 'G': /* Start Copy In */
+ case PqMsg_CopyInResponse:
pqTraceOutputG(conn->Pfdebug, message, &logCursor);
break;
- case 'H': /* Flush(F) or Start Copy Out(B) */
+ case PqMsg_Flush:
+ /* Flush(F) and CopyOutResponse(B) use the same identifier */
+ Assert(PqMsg_CopyOutResponse == PqMsg_Flush);
if (!toServer)
pqTraceOutputH(conn->Pfdebug, message, &logCursor);
else
fprintf(conn->Pfdebug, "Flush"); /* no message content */
break;
- case 'I':
+ case PqMsg_EmptyQueryResponse:
fprintf(conn->Pfdebug, "EmptyQueryResponse");
/* No message content */
break;
- case 'K': /* secret key data from the backend */
+ case PqMsg_BackendKeyData:
pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
break;
- case 'n':
+ case PqMsg_NoData:
fprintf(conn->Pfdebug, "NoData");
/* No message content */
break;
- case 'N':
+ case PqMsg_NoticeResponse:
pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
&logCursor, regress);
break;
- case 'P': /* Parse */
+ case PqMsg_Parse:
pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
break;
- case 'Q': /* Query */
+ case PqMsg_Query:
pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
break;
- case 'R': /* Authentication */
+ case PqMsg_AuthenticationRequest:
pqTraceOutputR(conn->Pfdebug, message, &logCursor);
break;
- case 's':
+ case PqMsg_PortalSuspended:
fprintf(conn->Pfdebug, "PortalSuspended");
/* No message content */
break;
- case 'S': /* Parameter Status(B) or Sync(F) */
+ case PqMsg_Sync:
+ /* Parameter Status(B) and Sync(F) use the same identifier */
+ Assert(PqMsg_ParameterStatus == PqMsg_Sync);
if (!toServer)
pqTraceOutputS(conn->Pfdebug, message, &logCursor);
else
fprintf(conn->Pfdebug, "Sync"); /* no message content */
break;
- case 't': /* Parameter Description */
+ case PqMsg_ParameterDescription:
pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
break;
- case 'T': /* Row Description */
+ case PqMsg_RowDescription:
pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
break;
- case 'v': /* Negotiate Protocol Version */
+ case PqMsg_NegotiateProtocolVersion:
pqTraceOutputv(conn->Pfdebug, message, &logCursor);
break;
- case 'V': /* Function Call response */
+ case PqMsg_FunctionCallResponse:
pqTraceOutputV(conn->Pfdebug, message, &logCursor);
break;
- case 'W': /* Start Copy Both */
+ case PqMsg_CopyBothResponse:
pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
break;
- case 'X':
+ case PqMsg_Terminate:
fprintf(conn->Pfdebug, "Terminate");
/* No message content */
break;
- case 'Z': /* Ready For Query */
+ case PqMsg_ReadyForQuery:
pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
break;
default:
'src/include/', 'c.h', 'port.h', 'postgres_fe.h');
lcopy('src/include/libpq/pqcomm.h', $target . '/include/internal/libpq/')
|| croak 'Could not copy pqcomm.h';
+ lcopy('src/include/libpq/protocol.h', $target . '/include/internal/libpq/')
+ || croak 'Could not copy protocol.h';
CopyFiles(
'Server headers',