The main reason that libpq does not request protocol version 3.2 by
default is because other proxy/server implementations don't implement
the negotiation. This is a bit of a chicken and egg problem: We don't
bump the default version that libpq asks, but proxies will only
implement version negotation when their users run into issues. So I'm
proposing that we bump the default protocol version that libpq requests
on the master branch, so that users running the latest master against a
proxy that does not support the version negototian will be notified.
They can then push the author of the proxy to implement the
NegototiateProtocolVersion message.
Depending on how this works in practice we'll likely still want to
revert this change before we actually release PG19. If we do that before
19beta1 we still have roughly half a year where people will test the
ecosystem. I'd even suggest that we only revert before 19beta2, so that
people testing beta1 will also be testing the ecosystem for version
negotiation issues. In any case, the sooner we commit this the more
testing we get,
Note that users still have a way out to connect to the server by
manually setting max_protocol_version=3.0 in the connection string.
From 0486ee9f14dbfc4fb19d7716f2ce75d5fcbed2e5 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Thu, 23 Oct 2025 15:16:05 +0200
Subject: [PATCH v1 1/2] Add test for libpq its default protocol version

We did not test libpq its default protocol version. Defaults are
important so we should test them.
---
 .../modules/libpq_pipeline/libpq_pipeline.c   | 33 ++++++++++++++++---
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index b3af70fa09b..3af79e03d24 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -1328,7 +1328,7 @@ test_protocol_version(PGconn *conn)
 	int			nopts;
 	PQconninfoOption *opts = PQconninfo(conn);
 	int			protocol_version;
-	int			max_protocol_version_index;
+	int			max_protocol_version_index = -1;
 	int			i;
 
 	/*
@@ -1351,14 +1351,37 @@ test_protocol_version(PGconn *conn)
 		{
 			keywords[i] = opt->keyword;
 			vals[i] = opt->val;
+			if (strcmp(opt->keyword, "max_protocol_version") == 0)
+			{
+				max_protocol_version_index = i;
+			}
+
 			i++;
 		}
 	}
 
-	max_protocol_version_index = i;
-	keywords[i] = "max_protocol_version";	/* value is filled in below */
-	i++;
-	keywords[i] = vals[i] = NULL;
+	if (max_protocol_version_index == -1)
+	{
+		max_protocol_version_index = i;
+		keywords[i] = "max_protocol_version";	/* value is filled in below */
+		i++;
+	}
+
+	/*
+	 * Test default protocol_version
+	 */
+	vals[max_protocol_version_index] = "";
+	conn = PQconnectdbParams(keywords, vals, false);
+
+	if (PQstatus(conn) != CONNECTION_OK)
+		pg_fatal("Connection to database failed: %s",
+				 PQerrorMessage(conn));
+
+	protocol_version = PQfullProtocolVersion(conn);
+	if (protocol_version != 30000)
+		pg_fatal("expected 30000, got %d", protocol_version);
+
+	PQfinish(conn);
 
 	/*
 	 * Test max_protocol_version=3.0
-- 
2.51.1

From 57a89e1780bd721c721ee64a04ade165fd83a836 Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Thu, 23 Oct 2025 15:08:52 +0200
Subject: [PATCH v1 2/2] libpq: Bump default protocol version to 3.2

This bumps the default protocol version that libpq uses to connect to
servers. This will be reverted before we release 19beta2. The intent is
to stress test the ecosystem for servers that don't support protocol
version negotation, so that those servers can implement the negotation.

It's still possible for users to connect to servers that don't support
protocol negotation by using max_protocol_version=3.0 in their
connection string. Only the default connection behaviour is impacted.
---
 doc/src/sgml/libpq.sgml                          | 16 +++++++---------
 src/interfaces/libpq/fe-connect.c                | 12 ++++--------
 src/test/modules/libpq_pipeline/libpq_pipeline.c |  4 ++--
 3 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 5bf59a19855..686a473ccba 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2213,15 +2213,13 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       <listitem>
        <para>
         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-PQprotocolVersion"/> to
-        find out which exact protocol version was negotiated.
+        The default is to use the latest version supported by libpq, which is
+        currently <literal>3.2</literal>. 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-PQprotocolVersion"/> to find out which exact
+        protocol version was negotiated.
        </para>
 
        <para>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index a3d12931fff..0bd5ef22298 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2131,15 +2131,11 @@ pqConnectOptions2(PGconn *conn)
 	else
 	{
 		/*
-		 * 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.
+		 * Default to the latest protocol version. The server will
+		 * automatically downgrade via NegotiateProtocolVersion if it doesn't
+		 * support the requested version.
 		 */
-		if (conn->min_pversion > PG_PROTOCOL(3, 0))
-			conn->max_pversion = PG_PROTOCOL_LATEST;
-		else
-			conn->max_pversion = PG_PROTOCOL(3, 0);
+		conn->max_pversion = PG_PROTOCOL_LATEST;
 	}
 
 	if (conn->min_pversion > conn->max_pversion)
diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index 3af79e03d24..374917acacf 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -1378,8 +1378,8 @@ test_protocol_version(PGconn *conn)
 				 PQerrorMessage(conn));
 
 	protocol_version = PQfullProtocolVersion(conn);
-	if (protocol_version != 30000)
-		pg_fatal("expected 30000, got %d", protocol_version);
+	if (protocol_version != 30002)
+		pg_fatal("expected 30002, got %d", protocol_version);
 
 	PQfinish(conn);
 
-- 
2.51.1

Reply via email to