since-v3.diff.txt
text/plain
Filename: since-v3.diff.txt
Type: text/plain
Part: 0
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index fb6ce177f0d..e08d46782cc 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2211,23 +2211,34 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
<varlistentry id="libpq-connect-max-protocol-version" xreflabel="max_protocol_version">
<term><literal>max_protocol_version</literal></term>
<listitem>
- <para>
- Specifies the protocol version to request from the server.
- During the PostgreSQL 19 beta period, the default is to use
- <literal>3.9999</literal>, a GREASE (Generate Random Extensions And
- Sustain Extensibility) value that tests proper protocol negotiation
- implementation. If the server does not support the protocol version
- requested by the client, the connection is automatically downgraded to
- a lower minor protocol version that the server supports. After the
- connection attempt has completed you can use
- <xref linkend="libpq-PQfullProtocolVersion"/> to find out which exact
- protocol version was negotiated.
- </para>
+ <note>
+ <para>
+ During the PostgreSQL 19 beta period, libpq connections that do not
+ specify a <literal>max_protocol_version</literal> will "grease" the
+ handshake by sending unsupported startup parameters, including version
+ <literal>3.9999</literal>, in order to identify software that does not
+ correctly negotiate the connection. This replaces the default behavior
+ described below.
+ </para>
+ <para>
+ If you know that a server doesn't properly implement protocol version
+ negotiation, you can set <literal>max_protocol_version=3.0</literal> to
+ revert to the standard behavior (preferably after notifying the server's
+ maintainers that their software needs to be fixed).
+ </para>
+ </note>
<para>
- For servers that don't properly implement protocol version negotiation,
- you can set <literal>max_protocol_version=3.0</literal> to connect
- successfully.
+ Specifies the protocol version to request from the server.
+ The default is to use version <literal>3.0</literal> of the
+ <productname>PostgreSQL</productname> protocol, unless the connection
+ string specifies a feature that relies on a higher protocol version,
+ in which case the latest version supported by libpq is used. If the
+ server does not support the protocol version requested by the client,
+ the connection is automatically downgraded to a lower minor protocol
+ version that the server supports. After the connection attempt has
+ completed you can use <xref linkend="libpq-PQfullProtocolVersion"/> to
+ find out which exact protocol version was negotiated.
</para>
<para>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index c61dd2bf948..45148a71d63 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -189,18 +189,26 @@
</sect2>
<sect2 id="protocol-versions">
- <title>Protocol Versions</title>
+ <title>Protocol Versions and Extensibility</title>
<para>
- The current, latest version of the protocol is version 3.2. During the
- PostgreSQL 19 beta period, libpq defaults to requesting protocol version
- 3.9999 to test that servers and middleware properly implement protocol
- version negotiation. Servers that support negotiation will automatically
- downgrade to version 3.2 or 3.0. For servers that don't support
- negotiation, users can connect by explicitly setting
- <literal>max_protocol_version=3.0</literal> in their connection string.
+ The current, latest version of the protocol is version 3.2. However, for
+ backwards compatibility with old server versions and middleware that don't
+ support the version negotiation yet, libpq still uses protocol version 3.0
+ by default.
</para>
+ <note>
+ <para>
+ During the PostgreSQL 19 beta period, libpq will instead default to
+ requesting protocol version 3.9999, to test that servers and middleware
+ properly implement protocol version negotiation. Servers that support
+ negotiation will automatically downgrade to version 3.2 or 3.0. Users can
+ bypass this beta-only behavior by explicitly setting
+ <literal>max_protocol_version=3.0</literal> in their connection string.
+ </para>
+ </note>
+
<para>
A single server can support multiple protocol versions. The initial
startup-request message tells the server which protocol version the client
@@ -226,10 +234,12 @@
<para>
<xref linkend="protocol-versions-table"/> shows the currently supported
protocol versions.
+ <xref linkend="other-protocol-versions-table"/>
+ documents protocol versions that are unsupported or otherwise reserved.
</para>
<table id="protocol-versions-table">
- <title>Protocol Versions</title>
+ <title>Supported Protocol Versions</title>
<tgroup cols="3">
<thead>
@@ -241,20 +251,6 @@
</thead>
<tbody>
- <row>
- <entry>3.9999</entry>
- <entry>-</entry>
- <entry>GREASE (Generate Random Extensions And Sustain Extensibility)
- version. This version number is intentionally reserved and will never
- be implemented. During the PostgreSQL 19 beta period, libpq requests
- this version by default to test that servers and middleware properly
- implement protocol version negotiation via
- <literal>NegotiateProtocolVersion</literal>. Servers should respond
- by downgrading to a supported version. This mechanism helps ensure
- the ecosystem is ready for future protocol versions. libpq will revert
- to defaulting to version 3.2 before the PostgreSQL 19 final release.
- </entry>
- </row>
<row>
<entry>3.2</entry>
<entry>PostgreSQL 18 and later</entry>
@@ -265,6 +261,39 @@
</entry>
</row>
<row>
+ <entry>3.0</entry>
+ <entry>PostgreSQL 7.4 and later</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table id="other-protocol-versions-table">
+ <title>Other Protocol Versions</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Version</entry>
+ <entry>Supported by</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>3.9999</entry>
+ <entry>-</entry>
+ <entry>Reserved for protocol greasing. libpq may use this version, which
+ is higher than any minor version the project ever expects to use, to
+ test that servers and middleware properly implement protocol version
+ negotiation. Servers <emphasis>must not</emphasis> add special-case
+ logic for this version; they should simply compare it to their latest
+ supported version (which will always be smaller) and downgrade via a
+ NegotiateProtocolVersion message.
+ </entry>
+ </row>
+ <row>
<entry>3.1</entry>
<entry>-</entry>
<entry>Reserved. Version 3.1 has not been used by any PostgreSQL
@@ -274,15 +303,93 @@
</entry>
</row>
<row>
- <entry>3.0</entry>
- <entry>PostgreSQL 7.4 and later</entry>
- </row>
- <row>
<entry>2.0</entry>
<entry>up to PostgreSQL 13</entry>
- <entry>See previous releases of
+ <entry>Obsolete. See previous releases of
the <productname>PostgreSQL</productname> documentation for
- details</entry>
+ details.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para id="protocol-extensions">
+ Servers and clients may additionally negotiate individual extensions to the
+ protocol version in use. These are offered by the client as specially-named
+ parameters in the startup message. Servers reject any unknown or unsupported
+ extensions by sending a NegotiateProtocolVersion message containing the list
+ of rejected parameter names, at which point the client may choose whether to
+ continue with the connection. <xref linkend="protocol-extensions-table"/>
+ shows the current list of protocol extension parameters.
+ </para>
+
+ <table id="protocol-extensions-table" rowheader="firstcol">
+ <title>Protocol Extensions</title>
+
+ <tgroup cols="5">
+ <!-- For spanning, below. -->
+ <colspec colname="first" colsep="0"/>
+ <colspec colname="name" colnum="2"/>
+ <colspec colname="vals" colnum="3"/>
+ <colspec colname="support" colnum="4"/>
+ <colspec colname="last" colnum="5"/>
+
+ <!--
+ "all" spans the width of the table; it is used for the section headers.
+ "reserved" spans the Values and Supported columns, for the Reserved
+ names which define neither.
+ -->
+ <spanspec spanname="all" namest="first" nameend="last"/>
+ <spanspec spanname="reserved" namest="vals" nameend="support"/>
+
+ <thead>
+ <row>
+ <!--
+ Row header. Use namest="name" to skip to the next column.
+ XXX this causes a thin "indent" effect for the other rows
+ -->
+ <entry/>
+
+ <entry>Parameter Name</entry>
+ <entry>Values</entry>
+ <entry>Supported by</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row><entry spanname="all">Defined</entry></row>
+
+ <row>
+ <entry namest="last" align="center" valign="middle">
+ <emphasis>(No supported protocol extensions are currently defined.)</emphasis>
+ </entry>
+ </row>
+
+ <row><entry spanname="all">Reserved</entry></row>
+
+ <row>
+ <entry namest="name"><literal>_pq_.<replaceable>[name]</replaceable></literal></entry>
+ <entry spanname="reserved">-</entry>
+ <entry>Any other parameter names beginning with <literal>_pq_.</literal>,
+ that are not defined above, are reserved for future protocol expansion.
+ Servers <emphasis>must</emphasis> reject any that are received from a
+ client, by sending a NegotiateProtocolVersion message during the
+ <link linkend="protocol-flow-start-up">startup flow</link>, and should
+ otherwise continue the connection.
+ </entry>
+ </row>
+
+ <row>
+ <entry namest="name"><literal>_pq_.test_protocol_negotiation</literal></entry>
+ <entry spanname="reserved">-</entry>
+ <entry>Reserved for protocol greasing. libpq may send this extension to
+ test that servers and middleware properly implement protocol extension
+ negotiation. Servers <emphasis>must not</emphasis> add special-case
+ logic for this parameter; they should simply send the list of all
+ unsupported options (including this one) via a NegotiateProtocolVersion
+ message.
+ </entry>
</row>
</tbody>
</tgroup>
@@ -312,8 +419,8 @@
To begin a session, a frontend opens a connection to the server and sends
a startup message. This message includes the names of the user and of the
database the user wants to connect to; it also identifies the particular
- protocol version to be used. (Optionally, the startup message can include
- additional settings for run-time parameters.)
+ protocol version to be used. (Optionally, the startup message can request
+ protocol extensions and include additional settings for run-time parameters.)
The server then uses this information and
the contents of its configuration files (such as
<filename>pg_hba.conf</filename>) to determine
@@ -6164,29 +6271,13 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
</para>
</listitem>
</varlistentry>
- <varlistentry>
- <term><literal>_pq_.test_protocol_negotiation</literal></term>
- <listitem>
- <para>
- A reserved protocol extension requested by libpq during the
- PostgreSQL 19 beta period to test that servers properly implement
- protocol version negotiation. When the client requests the GREASE
- protocol version (3.9999), this parameter is automatically
- included in the startup packet too. Servers should report it as
- unsupported in their <literal>NegotiateProtocolVersion</literal>
- response. In GREASE mode the connection will fail if the server
- doesn't report this parameter as unsupported, ensuring
- comprehensive implementation of protocol negotiation. This
- parameter is reserved and will never actually be implemented by a
- server.
- </para>
- </listitem>
- </varlistentry>
</variablelist>
In addition to the above, other parameters may be listed.
Parameter names beginning with <literal>_pq_.</literal> are
- reserved for use as protocol extensions, while others are
+ reserved for use as
+ <link linkend="protocol-extensions">protocol extensions</link>,
+ while others are
treated as run-time parameters to be set at backend start
time. Such settings will be applied during backend start
(after parsing the command-line arguments if any) and will
diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
index 0c3583ce4d9..a29c9c94d79 100644
--- a/src/include/libpq/pqcomm.h
+++ b/src/include/libpq/pqcomm.h
@@ -90,16 +90,9 @@ is_unixsock_path(const char *path)
/*
* The earliest and latest frontend/backend protocol version supported.
- *
- * PG_PROTOCOL_GREASE is an intentionally unsupported protocol version used
- * for GREASE (Generate Random Extensions And Sustain Extensibility). This
- * helps ensure that servers properly implement protocol version negotiation
- * via NegotiateProtocolVersion. Version 3.9999 was chosen to be safely within
- * the valid range but unlikely to ever be implemented.
*/
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(3,0)
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,2)
-#define PG_PROTOCOL_GREASE PG_PROTOCOL(3,9999)
/*
* Reserved protocol numbers, which have special semantics:
@@ -111,6 +104,16 @@ is_unixsock_path(const char *path)
*/
#define PG_PROTOCOL_RESERVED_31 PG_PROTOCOL(3,1)
+/*
+ * PG_PROTOCOL_GREASE is an intentionally unsupported protocol version used
+ * for "greasing" (the practice of sending valid, but extraneous or otherwise
+ * unusual, messages to keep peer implementations honest). This helps ensure
+ * that servers properly implement protocol version negotiation. Version 3.9999
+ * was chosen since it is safely within the valid range, it is representable
+ * via PQfullProtocolVersion, and it is unlikely to ever be needed in practice.
+ */
+#define PG_PROTOCOL_GREASE PG_PROTOCOL(3,9999)
+
/*
* A client can send a cancel-current-operation request to the postmaster.
* This is uglier than sending it directly to the client's backend, but it
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 9fcf094a36f..c42f38cbc99 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2142,10 +2142,11 @@ pqConnectOptions2(PGconn *conn)
else
{
/*
- * Default to the GREASE protocol version to test that servers
- * properly implement NegotiateProtocolVersion. The server will
- * automatically downgrade to a supported version. This will be
- * changed to a supported version before the PG19 release.
+ * Default to PG_PROTOCOL_GREASE, which is larger than all real
+ * versions, to test negotiation. The server should automatically
+ * downgrade to a supported version.
+ *
+ * This behavior is for 19beta only. It will be reverted before RC1.
*/
conn->max_pversion = PG_PROTOCOL_GREASE;
}
@@ -4386,7 +4387,7 @@ keep_going: /* We will come back to here until there is
if (conn->max_pversion == PG_PROTOCOL_GREASE &&
conn->pversion == PG_PROTOCOL_GREASE)
{
- libpq_append_conn_error(conn, "server incorrectly accepted reserved GREASE protocol version 3.9999 without negotiation");
+ libpq_append_conn_error(conn, "server incorrectly accepted \"grease\" protocol version 3.9999 without negotiation");
goto error_return;
}
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 4f78b88b3a8..fc011e89450 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1453,7 +1453,19 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
if (pqGetInt(&num, 4, conn) != 0)
goto eof;
- /* Check the protocol version */
+ /*
+ * Check the protocol version.
+ *
+ * PG_PROTOCOL_GREASE is intentionally unsupported and reserved. It's
+ * higher than any real version, so check for that first, to get the most
+ * specific error message. Then check the upper and lower bounds.
+ */
+ if (their_version == PG_PROTOCOL_GREASE)
+ {
+ libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested \"grease\" protocol version 3.9999");
+ goto failure;
+ }
+
if (their_version > conn->pversion)
{
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to a higher-numbered version");
@@ -1473,13 +1485,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
goto failure;
}
- /* The GREASE protocol version is intentionally unsupported and reserved */
- if (their_version == PG_PROTOCOL_GREASE)
- {
- libpq_append_conn_error(conn, "received invalid protocol negotiation message: server claimed to support reserved GREASE protocol version 3.9999");
- goto failure;
- }
-
if (num < 0)
{
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported negative number of unsupported parameters");
@@ -1527,19 +1532,21 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
}
/* Check if this is the expected test parameter */
- if (expect_test_protocol_negotiation && strcmp(conn->workBuffer.data, "_pq_.test_protocol_negotiation") == 0)
+ if (expect_test_protocol_negotiation &&
+ strcmp(conn->workBuffer.data, "_pq_.test_protocol_negotiation") == 0)
{
found_test_protocol_negotiation = true;
}
else
{
- libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")", conn->workBuffer.data);
+ libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")",
+ conn->workBuffer.data);
goto failure;
}
}
/*
- * If we requested the GREASE protocol version, the server must report
+ * If we requested protocol grease, the server must report
* _pq_.test_protocol_negotiation as unsupported. This ensures
* comprehensive NegotiateProtocolVersion implementation.
*/
@@ -2497,9 +2504,9 @@ build_startup_packet(const PGconn *conn, char *packet,
ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
/*
- * Add the test protocol negotiation option if we're using the GREASE
- * protocol version. This tests that servers properly report unsupported
- * protocol options in their NegotiateProtocolVersion response.
+ * Add the test_protocol_negotiation option when greasing, to test that
+ * servers properly report unsupported protocol options in addition to
+ * unsupported minor versions.
*/
if (conn->pversion == PG_PROTOCOL_GREASE)
ADD_STARTUP_OPTION("_pq_.test_protocol_negotiation", "");