From 4ed03c6a73361b01610373267a843cbef110946d Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Fri, 21 Nov 2025 09:18:40 -0800
Subject: [PATCH] pqcomm.h: Explicitly reserve protocol v3.1

Document this unused version alongside the other special protocol
numbers.

Reviewed-by: Jelte Fennema-Nio <postgres@jeltef.nl>
---
 src/include/libpq/pqcomm.h          | 6 ++++++
 src/interfaces/libpq/fe-protocol3.c | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
index 6df6e0f902d..2e24083f462 100644
--- a/src/include/libpq/pqcomm.h
+++ b/src/include/libpq/pqcomm.h
@@ -98,6 +98,12 @@ is_unixsock_path(const char *path)
  * Reserved protocol numbers, which have special semantics:
  */
 
+/*
+ * 3.1 would have collided with old pgbouncer deployments, and was skipped. We
+ * neither emit it nor accept it on the wire.
+ */
+#define PG_PROTOCOL_RSRV31		PG_PROTOCOL(3,1)
+
 /*
  * 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-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 34518bbe6ea..2d67c496a3d 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1465,7 +1465,7 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
 	}
 
 	/* 3.1 never existed, we went straight from 3.0 to 3.2 */
-	if (their_version == PG_PROTOCOL(3, 1))
+	if (their_version == PG_PROTOCOL_RSRV31)
 	{
 		libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to non-existent 3.1 protocol version");
 		goto failure;
-- 
2.34.1

