postgres.git / summary / log / commit / refs
commit ef67d599eff86203371e38f2d08ec6fa6236b5b2
Author: Jacob Champion <jchampion@postgresql.org>
Date: Tue Sep 01 17:26:10 2026 +0000
libpq: Stop greasing protocol connections
This reverts commit 4966bd3ed95e0d02bf220c4bad2b292963827dd4, which
introduced the 19beta grease campaign, now that Beta 3 has been stamped.
(The reservation and documentation for the grease version code, done in
d8d7c5dc8f, remains.)
Discussion: https://postgr.es/m/CAOYmi%2Bkqt_gn-wvUjJG1j3MM4LDDsRMURSPz2eMxfABu0iGtpw%40mail.gmail.com
Backpatch-through: 19
doc/src/sgml/libpq.sgml | 17 --------
doc/src/sgml/protocol.sgml | 11 -----
src/interfaces/libpq/fe-connect.c | 51 ++++-------------------
src/interfaces/libpq/fe-misc.c | 18 --------
src/interfaces/libpq/fe-protocol3.c | 53 ++----------------------
src/interfaces/libpq/libpq-int.h | 1 -
src/test/modules/libpq_pipeline/libpq_pipeline.c | 6 +--
7 files changed, 16 insertions(+), 141 deletions(-)
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 7d3c3bb66d8..a1e82fea215 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2211,23 +2211,6 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
<varlistentry id="libpq-connect-max-protocol-version" xreflabel="max_protocol_version">
<term><literal>max_protocol_version</literal></term>
<listitem>
- <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>
Specifies the protocol version to request from the server.
The default is to use version <literal>3.0</literal> of the
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 49f81676712..89ac680efd5 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -198,17 +198,6 @@
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
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 38422becc48..ad8ae163699 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -91,9 +91,8 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* This is part of the protocol so just define it */
#define ERRCODE_INVALID_PASSWORD "28P01"
-/* These too */
+/* This too */
#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
-#define ERRCODE_PROTOCOL_VIOLATION "08P01"
/*
* Cope with the various platform-specific ways to spell TCP keepalive socket
@@ -2147,13 +2146,15 @@ pqConnectOptions2(PGconn *conn)
else
{
/*
- * 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.
+ * To not break connecting to older servers/poolers that do not yet
+ * support NegotiateProtocolVersion, default to the 3.0 protocol at
+ * least for a while longer. Except when min_protocol_version is set
+ * to something larger, then we might as well default to the latest.
*/
- conn->max_pversion = PG_PROTOCOL_GREASE;
+ if (conn->min_pversion > PG_PROTOCOL(3, 0))
+ conn->max_pversion = PG_PROTOCOL_LATEST;
+ else
+ conn->max_pversion = PG_PROTOCOL(3, 0);
}
if (conn->min_pversion > conn->max_pversion)
@@ -4159,32 +4160,6 @@ keep_going: /* We will come back to here until there is
/* Check to see if we should mention pgpassfile */
pgpassfileWarning(conn);
- /*
- * ...and whether we should mention grease. If the error
- * message contains the PG_PROTOCOL_GREASE number (in
- * major.minor, decimal, or hex format) or a complaint
- * about a protocol violation before we've even started an
- * authentication exchange, it's probably caused by a
- * grease interaction.
- */
- if (conn->max_pversion == PG_PROTOCOL_GREASE &&
- !conn->auth_req_received)
- {
- const char *sqlstate = PQresultErrorField(conn->result,
- PG_DIAG_SQLSTATE);
-
- if ((sqlstate &&
- strcmp(sqlstate, ERRCODE_PROTOCOL_VIOLATION) == 0) ||
- (conn->errorMessage.len > 0 &&
- (strstr(conn->errorMessage.data, "3.9999") ||
- strstr(conn->errorMessage.data, "206607") ||
- strstr(conn->errorMessage.data, "3270F") ||
- strstr(conn->errorMessage.data, "3270f"))))
- {
- libpq_append_grease_info(conn);
- }
- }
-
CONNECTION_FAILED();
}
/* Handle NegotiateProtocolVersion */
@@ -4415,14 +4390,6 @@ keep_going: /* We will come back to here until there is
goto error_return;
}
- if (conn->max_pversion == PG_PROTOCOL_GREASE &&
- conn->pversion == PG_PROTOCOL_GREASE)
- {
- libpq_append_conn_error(conn, "server incorrectly accepted \"grease\" protocol version 3.9999 without negotiation");
- libpq_append_grease_info(conn);
- goto error_return;
- }
-
/* Almost there now ... */
conn->status = CONNECTION_CHECK_TARGET;
goto keep_going;
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index f11b58bf9c7..35811a0e996 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -1567,21 +1567,3 @@ libpq_append_conn_error(PGconn *conn, const char *fmt, ...)
appendPQExpBufferChar(&conn->errorMessage, '\n');
}
-
-/*
- * For 19beta only, some protocol errors will have additional information
- * appended to help with the "grease" campaign.
- */
-void
-libpq_append_grease_info(PGconn *conn)
-{
- /* translator: %s is a URL */
- libpq_append_conn_error(conn,
- "\tThis indicates a bug in either the server being contacted\n"
- "\tor a proxy handling the connection. Please consider\n"
- "\treporting this to the maintainers of that software.\n"
- "\tFor more information, including instructions on how to\n"
- "\twork around this issue for now, visit\n"
- "\t\t%s",
- "https://wiki.postgresql.org/wiki/Grease");
-}
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index f807670409c..a94f926b3e7 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1445,15 +1445,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
{
int their_version;
int num;
- bool found_test_protocol_negotiation;
- bool expect_test_protocol_negotiation;
-
- /*
- * During 19beta only, if protocol grease is in use, assume that it's the
- * cause of any invalid messages encountered below. We'll print extra
- * information for the end user in that case.
- */
- bool need_grease_info = (conn->max_pversion == PG_PROTOCOL_GREASE);
if (pqGetInt(&their_version, 4, conn) != 0)
goto eof;
@@ -1514,7 +1505,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
PG_PROTOCOL_MAJOR(conn->min_pversion),
PG_PROTOCOL_MINOR(conn->min_pversion));
- need_grease_info = false; /* this is valid server behavior */
goto failure;
}
@@ -1522,12 +1512,9 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
conn->pversion = their_version;
/*
- * Check that all expected unsupported parameters are reported by the
- * server.
+ * We don't currently request any protocol extensions, so we don't expect
+ * the server to reply with any either.
*/
- found_test_protocol_negotiation = false;
- expect_test_protocol_negotiation = (conn->max_pversion == PG_PROTOCOL_GREASE);
-
for (int i = 0; i < num; i++)
{
if (pqGets(&conn->workBuffer, conn))
@@ -1539,30 +1526,8 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported unsupported parameter name without a \"%s\" prefix (\"%s\")", "_pq_.", conn->workBuffer.data);
goto failure;
}
-
- /* Check if this is the expected test parameter */
- 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);
- goto failure;
- }
- }
-
- /*
- * If we requested protocol grease, the server must report
- * _pq_.test_protocol_negotiation as unsupported. This ensures
- * comprehensive NegotiateProtocolVersion implementation.
- */
- if (expect_test_protocol_negotiation && !found_test_protocol_negotiation)
- {
- libpq_append_conn_error(conn, "server did not report the unsupported \"%s\" parameter in its protocol negotiation message",
- "_pq_.test_protocol_negotiation");
+ 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;
}
@@ -1571,8 +1536,6 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
eof:
libpq_append_conn_error(conn, "received invalid protocol negotiation message: message too short");
failure:
- if (need_grease_info)
- libpq_append_grease_info(conn);
conn->asyncStatus = PGASYNC_READY;
pqSaveErrorResult(conn);
return 1;
@@ -2540,14 +2503,6 @@ build_startup_packet(const PGconn *conn, char *packet,
if (conn->client_encoding_initial && conn->client_encoding_initial[0])
ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
- /*
- * 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", "");
-
/* Add any environment-driven GUC settings needed */
for (next_eo = options; next_eo->envName; next_eo++)
{
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3f921207a14..61b9d486d29 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -968,7 +968,6 @@ extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigne
extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt, ...) pg_attribute_printf(2, 3);
extern void libpq_append_conn_error(PGconn *conn, const char *fmt, ...) pg_attribute_printf(2, 3);
-extern void libpq_append_grease_info(PGconn *conn);
/*
* These macros are needed to let error-handling code be portable between
diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index ee3e2ec7570..b5241fc7b69 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -1363,7 +1363,7 @@ test_protocol_version(PGconn *conn)
Assert(max_protocol_version_index >= 0);
/*
- * Test default protocol_version (GREASE - should negotiate down to 3.2)
+ * Test default protocol_version
*/
vals[max_protocol_version_index] = "";
conn = PQconnectdbParams(keywords, vals, false);
@@ -1373,8 +1373,8 @@ test_protocol_version(PGconn *conn)
PQerrorMessage(conn));
protocol_version = PQfullProtocolVersion(conn);
- if (protocol_version != 30002)
- pg_fatal("expected 30002, got %d", protocol_version);
+ if (protocol_version != 30000)
+ pg_fatal("expected 30000, got %d", protocol_version);
PQfinish(conn);
[parent: 1956251afa8b]